Skip to content

Commit

Permalink
[plugin] activate dependencies before activating a plugin
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <[email protected]>
  • Loading branch information
akosyakov authored and benoitf committed Jul 17, 2019
1 parent 82068d4 commit 6021d79
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Breaking changes:
- [plugin] added basic support of activation events [#5622](https://github.com/theia-ide/theia/pull/5622)
- `HostedPluginSupport` is refactored to support multiple `PluginManagerExt` properly
- [plugin] added support of `workspaceContains` activation events [#5649](https://github.com/theia-ide/theia/pull/5649)
- [plugin] activate dependencies before activating a plugin [#5661](https://github.com/theia-ide/theia/pull/5661)

## v0.8.0

Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-ext-vscode/src/node/scanner-vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export class VsCodePluginScanner extends TheiaPluginScanner implements PluginSca

getModel(plugin: PluginPackage): PluginModel {
const result: PluginModel = {
id: `${plugin.publisher}.${plugin.name}`,
// see id definition: https://github.com/microsoft/vscode/blob/15916055fe0cb9411a5f36119b3b012458fe0a1d/src/vs/platform/extensions/common/extensions.ts#L167-L169
id: `${plugin.publisher.toLowerCase()}.${plugin.name.toLowerCase()}`,
name: plugin.name,
publisher: plugin.publisher,
version: plugin.version,
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-ext/src/common/plugin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface PluginPackage {
contributes?: PluginPackageContribution;
packagePath: string;
activationEvents?: string[];
extensionDependencies?: string[];
}
export namespace PluginPackage {
export function toPluginUrl(pck: PluginPackage, relativePath: string): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export class TheiaPluginScanner implements PluginScanner {

getModel(plugin: PluginPackage): PluginModel {
const result: PluginModel = {
id: `${plugin.publisher}.${plugin.name}`,
// see id definition: https://github.com/microsoft/vscode/blob/15916055fe0cb9411a5f36119b3b012458fe0a1d/src/vs/platform/extensions/common/extensions.ts#L167-L169
id: `${plugin.publisher.toLowerCase()}.${plugin.name.toLowerCase()}`,
name: plugin.name,
publisher: plugin.publisher,
version: plugin.version,
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ export function createAPIFactory(
},
// tslint:disable-next-line:no-any
getPlugin(pluginId: string): theia.Plugin<any> | undefined {
const plg = pluginManager.getPluginById(pluginId);
const plg = pluginManager.getPluginById(pluginId.toLowerCase());
if (plg) {
return new Plugin(pluginManager, plg);
}
Expand Down
42 changes: 30 additions & 12 deletions packages/plugin-ext/src/plugin/plugin-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {

private readonly registry = new Map<string, Plugin>();
private readonly activations = new Map<string, (() => Promise<void>)[] | undefined>();
private readonly loadedPlugins = new Set<string>();
private readonly loadedPlugins = new Map<string, Promise<void>>();
private readonly activatedPlugins = new Map<string, ActivatedPlugin>();
private pluginActivationPromises = new Map<string, Deferred<void>>();
private pluginContextsMap: Map<string, theia.PluginContext> = new Map();
Expand Down Expand Up @@ -143,7 +143,6 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
for (const activationEvent of pluginInit.activationEvents) {
await this.$activateByEvent(activationEvent);
}
// TODO eager activate by `workspaceContains`

if (this.host.loadTests) {
return this.host.loadTests();
Expand All @@ -167,7 +166,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
} else {
for (let activationEvent of plugin.rawModel.activationEvents) {
if (activationEvent === 'onUri') {
activationEvent = `onUri:theia://${plugin.model.publisher.toLowerCase()}.${plugin.model.name.toLowerCase()}`;
activationEvent = `onUri:theia://${plugin.model.id}`;
}
this.setActivation(activationEvent, activation);
}
Expand All @@ -180,19 +179,38 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
this.activations.set(activationEvent, activations);
}

protected async loadPlugin(plugin: Plugin, configStorage: ConfigStorage): Promise<void> {
if (this.loadedPlugins.has(plugin.model.id)) {
protected async loadPlugin(plugin: Plugin, configStorage: ConfigStorage, visited = new Set<string>()): Promise<void> {
// in order to break cycles
if (visited.has(plugin.model.id)) {
return;
}
this.loadedPlugins.add(plugin.model.id);
visited.add(plugin.model.id);

let loading = this.loadedPlugins.get(plugin.model.id);
if (!loading) {
loading = (async () => {
if (plugin.rawModel.extensionDependencies) {
for (const dependencyId of plugin.rawModel.extensionDependencies) {
const dependency = this.registry.get(dependencyId);
if (dependency) {
await this.loadPlugin(dependency, configStorage, visited);
} else {
console.warn(`cannot find a dependency to '${dependencyId}' for '${plugin.model.id}' plugin`);
}
}
}

const pluginMain = this.host.loadPlugin(plugin);
// able to load the plug-in ?
if (pluginMain !== undefined) {
await this.startPlugin(plugin, configStorage, pluginMain);
} else {
console.error(`Unable to load a plugin from "${plugin.pluginPath}"`);
const pluginMain = this.host.loadPlugin(plugin);
// able to load the plug-in ?
if (pluginMain !== undefined) {
await this.startPlugin(plugin, configStorage, pluginMain);
} else {
console.error(`Unable to load a plugin from "${plugin.pluginPath}"`);
}
})();
}
this.loadedPlugins.set(plugin.model.id, loading);
return loading;
}

$updateStoragePath(path: string | undefined): PromiseLike<void> {
Expand Down

0 comments on commit 6021d79

Please sign in to comment.