Skip to content

Commit

Permalink
Support 'logUri' and 'extension' (partially) to PluginContext (eclips…
Browse files Browse the repository at this point in the history
…e-theia#10650)

* Support 'logUri' and 'extension' (partially) to PluginContext

- Ensure 'logUri' and 'extension' property are present in context
- 'extension' currently has always theia.Plugin type, even in vscode

Fixes eclipse-theia#10033

* Move VSCode extension mapping directly into Plugin creation

* Fix conversion with correct fields

* Incorporate feedback about naming and exports
  • Loading branch information
martin-fleck-at authored and mcgordonite committed May 13, 2022
1 parent fd754da commit 1aa8dd1
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 21 deletions.
18 changes: 3 additions & 15 deletions packages/plugin-ext-vscode/src/node/plugin-vscode-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ export enum ExtensionKind {
export const doInitialization: BackendInitializationFn = (apiFactory: PluginAPIFactory, plugin: Plugin) => {
const vscode = Object.assign(apiFactory(plugin), { ExtensionKind });

// use Theia plugin api instead vscode extensions
// use Theia plugin api to implement vscode extensions api
(<any>vscode).extensions = {
get all(): any[] {
return vscode.plugins.all.map(p => asExtension(p));
return vscode.plugins.all;
},
getExtension(pluginId: string): any | undefined {
return asExtension(vscode.plugins.getPlugin(pluginId));
return vscode.plugins.getPlugin(pluginId);
},
get onDidChange(): theia.Event<void> {
return vscode.plugins.onDidChange;
Expand Down Expand Up @@ -95,15 +95,3 @@ function overrideInternalLoad(): void {
function findPlugin(filePath: string): Plugin | undefined {
return plugins.find(plugin => filePath.startsWith(plugin.pluginFolder));
}

function asExtension(plugin: any | undefined): any | undefined {
if (!plugin) {
return plugin;
}
if (plugin.pluginPath) {
plugin.extensionPath = plugin.pluginPath;
}
// stub as a local VS Code extension (not running on a remote workspace)
plugin.extensionKind = ExtensionKind.UI;
return plugin;
}
66 changes: 61 additions & 5 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (C) 2018 Red Hat, Inc. and others.
* Copyright (C) 2018-2022 Red Hat, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -720,13 +720,13 @@ export function createAPIFactory(
const plugins: typeof theia.plugins = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get all(): theia.Plugin<any>[] {
return pluginManager.getAllPlugins().map(plg => new Plugin(pluginManager, plg));
return pluginManager.getAllPlugins().map(plg => new PluginExt(pluginManager, plg));
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getPlugin(pluginId: string): theia.Plugin<any> | undefined {
const plg = pluginManager.getPluginById(pluginId.toLowerCase());
if (plg) {
return new Plugin(pluginManager, plg);
return new PluginExt(pluginManager, plg);
}
return undefined;
},
Expand Down Expand Up @@ -954,14 +954,44 @@ export function createAPIFactory(
};
}

class Plugin<T> implements theia.Plugin<T> {
export enum ExtensionKind {
UI = 1,
Workspace = 2
}

/**
* Represents a Theia plugin as well as a VSCode extension.
*/
export interface ExtensionPlugin<T> extends theia.Plugin<T> {
/**
* The uri of the directory containing the extension. Same as {@linkcode theia.Plugin.pluginUri}.
*/
readonly extensionUri: theia.Uri;

/**
* The absolute file path of the directory containing this extension.
* Same as {@linkcode theia.Plugin.pluginPath}.
*/
readonly extensionPath: string;

/**
* The extension kind describes if an extension runs where the UI runs
* or if an extension runs where the remote extension host runs. The extension kind
* is defined in the `package.json`-file of extensions. When no remote extension host exists,
* the value is {@linkcode ExtensionKind.UI}.
*/
extensionKind: ExtensionKind;
}

export class Plugin<T> implements theia.Plugin<T> {
id: string;
pluginPath: string;
pluginUri: URI;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
packageJSON: any;
pluginType: theia.PluginType;
constructor(private readonly pluginManager: PluginManager, plugin: InternalPlugin) {

constructor(protected readonly pluginManager: PluginManager, plugin: InternalPlugin) {
this.id = plugin.model.id;
this.pluginPath = plugin.pluginFolder;
this.pluginUri = URI.file(plugin.pluginFolder);
Expand All @@ -981,3 +1011,29 @@ class Plugin<T> implements theia.Plugin<T> {
return this.pluginManager.activatePlugin(this.id).then(() => this.exports);
}
}

export class PluginExt<T> extends Plugin<T> implements ExtensionPlugin<T> {
extensionPath: string;
extensionUri: theia.Uri;
extensionKind: ExtensionKind;

constructor(protected readonly pluginManager: PluginManager, plugin: InternalPlugin) {
super(pluginManager, plugin);

this.extensionPath = this.pluginPath;
this.extensionUri = this.pluginUri;
this.extensionKind = ExtensionKind.UI; // stub as a local extension (not running on a remote workspace)
}

get isActive(): boolean {
return this.pluginManager.isActive(this.id);
}

get exports(): T {
return <T>this.pluginManager.getPluginExport(this.id);
}

activate(): PromiseLike<T> {
return this.pluginManager.activatePlugin(this.id).then(() => this.exports);
}
}
6 changes: 5 additions & 1 deletion packages/plugin-ext/src/plugin/plugin-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { RPCProtocol } from '../common/rpc-protocol';
import { Emitter } from '@theia/core/lib/common/event';
import { WebviewsExtImpl } from './webviews';
import { URI as Uri } from './types-impl';
import { PluginExt } from './plugin-context';

export interface PluginHost {

Expand Down Expand Up @@ -357,7 +358,10 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
storageUri: storagePath ? Uri.file(storagePath) : undefined,
globalStoragePath: globalStoragePath,
globalStorageUri: Uri.file(globalStoragePath),
environmentVariableCollection: this.terminalService.getEnvironmentVariableCollection(plugin.model.id)
environmentVariableCollection: this.terminalService.getEnvironmentVariableCollection(plugin.model.id),
extensionMode: 1, // @todo: implement proper `extensionMode`.
extension: new PluginExt(this, plugin),
logUri: Uri.file(logPath)
};
this.pluginContextsMap.set(plugin.model.id, pluginContext);

Expand Down
20 changes: 20 additions & 0 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3190,6 +3190,26 @@ declare module '@theia/plugin' {
* the parent directory is guaranteed to be existent.
*/
readonly logPath: string;

/**
* The mode the extension is running in. This is specific to the current
* extension. One extension may be in `ExtensionMode.Development` while
* other extensions in the host run in `ExtensionMode.Release`.
*/
readonly extensionMode: ExtensionMode;

/**
* The current extension instance.
*/
readonly extension: Plugin<any> | undefined;

/**
* The uri of a directory in which the extension can create log files. The directory might
* not exist on disk and creation is up to the extension. However, the parent directory is
* guaranteed to be existent.
* see - workspace.fs for how to read and write files and folders from an uri.
*/
readonly logUri: Uri;
}

/**
Expand Down

0 comments on commit 1aa8dd1

Please sign in to comment.