From a8216d42a4c12e072d26611b1281ae03cdee7f38 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 11 Feb 2019 14:05:10 -0800 Subject: [PATCH] Make the typescript plugins contribution point dynamic Part of #67575 --- .../src/typescriptServiceClient.ts | 4 ++ .../src/utils/plugins.ts | 71 ++++++++++++++----- 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index 134942e4696..3af65af48e0 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -166,6 +166,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType this._register(this.pluginManager.onDidUpdateConfig(update => { this.configurePlugin(update.pluginId, update.config); })); + + this._register(this.pluginManager.onDidChangePlugins(() => { + this.restartTsServer(); + })); } public get configuration() { diff --git a/extensions/typescript-language-features/src/utils/plugins.ts b/extensions/typescript-language-features/src/utils/plugins.ts index 3b0cf217b92..71ce2430cb8 100644 --- a/extensions/typescript-language-features/src/utils/plugins.ts +++ b/extensions/typescript-language-features/src/utils/plugins.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import * as arrays from './arrays'; import { Disposable } from './dispose'; -import { memoize } from './memoize'; export interface TypeScriptServerPlugin { readonly path: string; @@ -14,28 +14,45 @@ export interface TypeScriptServerPlugin { readonly languages: ReadonlyArray; } +namespace TypeScriptServerPlugin { + export function equals(a: TypeScriptServerPlugin, b: TypeScriptServerPlugin): boolean { + return a.path === b.path + && a.name === b.name + && a.enableForWorkspaceTypeScriptVersions === b.enableForWorkspaceTypeScriptVersions + && arrays.equals(a.languages, b.languages); + } +} + export class PluginManager extends Disposable { private readonly _pluginConfigurations = new Map(); - @memoize - public get plugins(): ReadonlyArray { - const plugins: TypeScriptServerPlugin[] = []; - for (const extension of vscode.extensions.all) { - const pack = extension.packageJSON; - if (pack.contributes && Array.isArray(pack.contributes.typescriptServerPlugins)) { - for (const plugin of pack.contributes.typescriptServerPlugins) { - plugins.push({ - name: plugin.name, - enableForWorkspaceTypeScriptVersions: !!plugin.enableForWorkspaceTypeScriptVersions, - path: extension.extensionPath, - languages: Array.isArray(plugin.languages) ? plugin.languages : [], - }); - } + private _plugins: Map> | undefined; + + constructor() { + super(); + + vscode.extensions.onDidChange(() => { + if (!this._plugins) { + return; } + const newPlugins = this.readPlugins(); + if (!arrays.equals(arrays.flatten(Array.from(this._plugins.values())), arrays.flatten(Array.from(newPlugins.values())), TypeScriptServerPlugin.equals)) { + this._plugins = newPlugins; + this._onDidUpdatePlugins.fire(this); + } + }, undefined, this._disposables); + } + + public get plugins(): ReadonlyArray { + if (!this._plugins) { + this._plugins = this.readPlugins(); } - return plugins; + return arrays.flatten(Array.from(this._plugins.values())); } + private readonly _onDidUpdatePlugins = this._register(new vscode.EventEmitter()); + public readonly onDidChangePlugins = this._onDidUpdatePlugins.event; + private readonly _onDidUpdateConfig = this._register(new vscode.EventEmitter<{ pluginId: string, config: {} }>()); public readonly onDidUpdateConfig = this._onDidUpdateConfig.event; @@ -47,4 +64,26 @@ export class PluginManager extends Disposable { public configurations(): IterableIterator<[string, {}]> { return this._pluginConfigurations.entries(); } + + private readPlugins() { + const pluginMap = new Map>(); + for (const extension of vscode.extensions.all) { + const pack = extension.packageJSON; + if (pack.contributes && Array.isArray(pack.contributes.typescriptServerPlugins)) { + const plugins: TypeScriptServerPlugin[] = []; + for (const plugin of pack.contributes.typescriptServerPlugins) { + plugins.push({ + name: plugin.name, + enableForWorkspaceTypeScriptVersions: !!plugin.enableForWorkspaceTypeScriptVersions, + path: extension.extensionPath, + languages: Array.isArray(plugin.languages) ? plugin.languages : [], + }); + } + if (plugins.length) { + pluginMap.set(extension.id, plugins); + } + } + } + return pluginMap; + } } \ No newline at end of file -- GitLab