Flatten conditional registration

This allows us to pass a precomputed, flat list of requirements when registering a language feature
This commit is contained in:
Matt Bierner 2020-07-16 11:33:44 -07:00
parent 740e2d3602
commit 16c6b81b3e
15 changed files with 161 additions and 130 deletions

View file

@ -3,15 +3,15 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { ITypeScriptServiceClient } from '../typescriptService';
import * as typeConverters from '../utils/typeConverters';
import API from '../utils/api';
import { VersionDependentRegistration } from '../utils/dependentRegistration';
import type * as Proto from '../protocol';
import * as path from 'path'; import * as path from 'path';
import * as vscode from 'vscode';
import type * as Proto from '../protocol';
import * as PConst from '../protocol.const'; import * as PConst from '../protocol.const';
import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api';
import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import { parseKindModifier } from '../utils/modifiers'; import { parseKindModifier } from '../utils/modifiers';
import * as typeConverters from '../utils/typeConverters';
namespace Experimental { namespace Experimental {
export interface CallHierarchyItem extends Proto.CallHierarchyItem { export interface CallHierarchyItem extends Proto.CallHierarchyItem {
@ -120,7 +120,10 @@ export function register(
selector: vscode.DocumentSelector, selector: vscode.DocumentSelector,
client: ITypeScriptServiceClient client: ITypeScriptServiceClient
) { ) {
return new VersionDependentRegistration(client, TypeScriptCallHierarchySupport.minVersion, return conditionalRegistration([
() => vscode.languages.registerCallHierarchyProvider(selector, requireMinVersion(client, TypeScriptCallHierarchySupport.minVersion),
new TypeScriptCallHierarchySupport(client))); ], () => {
return vscode.languages.registerCallHierarchyProvider(selector,
new TypeScriptCallHierarchySupport(client));
});
} }

View file

@ -12,14 +12,14 @@ import API from '../utils/api';
import { nulToken } from '../utils/cancellation'; import { nulToken } from '../utils/cancellation';
import { applyCodeAction } from '../utils/codeAction'; import { applyCodeAction } from '../utils/codeAction';
import { Command, CommandManager } from '../utils/commandManager'; import { Command, CommandManager } from '../utils/commandManager';
import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireConfiguration } from '../utils/dependentRegistration';
import { parseKindModifier } from '../utils/modifiers';
import * as Previewer from '../utils/previewer'; import * as Previewer from '../utils/previewer';
import { snippetForFunctionCall } from '../utils/snippetForFunctionCall'; import { snippetForFunctionCall } from '../utils/snippetForFunctionCall';
import { TelemetryReporter } from '../utils/telemetry'; import { TelemetryReporter } from '../utils/telemetry';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
import TypingsStatus from '../utils/typingsStatus'; import TypingsStatus from '../utils/typingsStatus';
import FileConfigurationManager from './fileConfigurationManager'; import FileConfigurationManager from './fileConfigurationManager';
import { parseKindModifier } from '../utils/modifiers';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@ -804,8 +804,11 @@ export function register(
telemetryReporter: TelemetryReporter, telemetryReporter: TelemetryReporter,
onCompletionAccepted: (item: vscode.CompletionItem) => void onCompletionAccepted: (item: vscode.CompletionItem) => void
) { ) {
return new ConfigurationDependentRegistration(modeId, 'suggest.enabled', () => return conditionalRegistration([
vscode.languages.registerCompletionItemProvider(selector, requireConfiguration(modeId, 'suggest.enabled'),
], () => {
return vscode.languages.registerCompletionItemProvider(selector,
new TypeScriptCompletionItemProvider(client, modeId, typingsStatus, fileConfigurationManager, commandManager, telemetryReporter, onCompletionAccepted), new TypeScriptCompletionItemProvider(client, modeId, typingsStatus, fileConfigurationManager, commandManager, telemetryReporter, onCompletionAccepted),
...TypeScriptCompletionItemProvider.triggerCharacters)); ...TypeScriptCompletionItemProvider.triggerCharacters);
});
} }

View file

@ -8,7 +8,7 @@ import * as nls from 'vscode-nls';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import * as errorCodes from '../utils/errorCodes'; import * as errorCodes from '../utils/errorCodes';
import * as fixNames from '../utils/fixNames'; import * as fixNames from '../utils/fixNames';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
@ -254,7 +254,9 @@ export function register(
fileConfigurationManager: FileConfigurationManager, fileConfigurationManager: FileConfigurationManager,
diagnosticsManager: DiagnosticsManager, diagnosticsManager: DiagnosticsManager,
) { ) {
return new VersionDependentRegistration(client, API.v300, () => { return conditionalRegistration([
requireMinVersion(client, API.v300)
], () => {
const provider = new TypeScriptAutoFixProvider(client, fileConfigurationManager, diagnosticsManager); const provider = new TypeScriptAutoFixProvider(client, fileConfigurationManager, diagnosticsManager);
return vscode.languages.registerCodeActionsProvider(selector, provider, provider.metadata); return vscode.languages.registerCodeActionsProvider(selector, provider, provider.metadata);
}); });

View file

@ -8,7 +8,7 @@ import type * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { coalesce } from '../utils/arrays'; import { coalesce } from '../utils/arrays';
import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
class TypeScriptFoldingProvider implements vscode.FoldingRangeProvider { class TypeScriptFoldingProvider implements vscode.FoldingRangeProvider {
@ -76,7 +76,9 @@ export function register(
selector: vscode.DocumentSelector, selector: vscode.DocumentSelector,
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
): vscode.Disposable { ): vscode.Disposable {
return new VersionDependentRegistration(client, TypeScriptFoldingProvider.minVersion, () => { return conditionalRegistration([
requireMinVersion(client, TypeScriptFoldingProvider.minVersion),
], () => {
return vscode.languages.registerFoldingRangeProvider(selector, return vscode.languages.registerFoldingRangeProvider(selector,
new TypeScriptFoldingProvider(client)); new TypeScriptFoldingProvider(client));
}); });

View file

@ -6,7 +6,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireConfiguration } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
import FileConfigurationManager from './fileConfigurationManager'; import FileConfigurationManager from './fileConfigurationManager';
@ -89,7 +89,9 @@ export function register(
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
fileConfigurationManager: FileConfigurationManager fileConfigurationManager: FileConfigurationManager
) { ) {
return new ConfigurationDependentRegistration(modeId, 'format.enable', () => { return conditionalRegistration([
requireConfiguration(modeId, 'format.enable'),
], () => {
const formattingProvider = new TypeScriptFormattingProvider(client, fileConfigurationManager); const formattingProvider = new TypeScriptFormattingProvider(client, fileConfigurationManager);
return vscode.Disposable.from( return vscode.Disposable.from(
vscode.languages.registerOnTypeFormattingEditProvider(selector, formattingProvider, ';', '}', '\n'), vscode.languages.registerOnTypeFormattingEditProvider(selector, formattingProvider, ';', '}', '\n'),

View file

@ -8,7 +8,7 @@ import * as nls from 'vscode-nls';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import * as PConst from '../protocol.const'; import * as PConst from '../protocol.const';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireConfiguration } from '../utils/dependentRegistration';
import { TypeScriptBaseCodeLensProvider, ReferencesCodeLens, getSymbolRange } from './baseCodeLensProvider'; import { TypeScriptBaseCodeLensProvider, ReferencesCodeLens, getSymbolRange } from './baseCodeLensProvider';
import { CachedResponse } from '../tsServer/cachedResponse'; import { CachedResponse } from '../tsServer/cachedResponse';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
@ -94,7 +94,9 @@ export function register(
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
cachedResponse: CachedResponse<Proto.NavTreeResponse>, cachedResponse: CachedResponse<Proto.NavTreeResponse>,
) { ) {
return new ConfigurationDependentRegistration(modeId, 'implementationsCodeLens.enabled', () => { return conditionalRegistration([
requireConfiguration(modeId, 'implementationsCodeLens.enabled'),
], () => {
return vscode.languages.registerCodeLensProvider(selector, return vscode.languages.registerCodeLensProvider(selector,
new TypeScriptImplementationsCodeLensProvider(client, cachedResponse)); new TypeScriptImplementationsCodeLensProvider(client, cachedResponse));
}); });

View file

@ -6,7 +6,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireConfiguration } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
@ -114,7 +114,9 @@ export function register(
modeId: string, modeId: string,
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
): vscode.Disposable { ): vscode.Disposable {
return new ConfigurationDependentRegistration(modeId, 'suggest.completeJSDocs', () => { return conditionalRegistration([
requireConfiguration(modeId, 'suggest.completeJSDocs')
], () => {
return vscode.languages.registerCompletionItemProvider(selector, return vscode.languages.registerCompletionItemProvider(selector,
new JsDocCompletionProvider(client), new JsDocCompletionProvider(client),
'*'); '*');

View file

@ -8,12 +8,12 @@ import * as nls from 'vscode-nls';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { nulToken } from '../utils/cancellation';
import { Command, CommandManager } from '../utils/commandManager'; import { Command, CommandManager } from '../utils/commandManager';
import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import { TelemetryReporter } from '../utils/telemetry';
import * as typeconverts from '../utils/typeConverters'; import * as typeconverts from '../utils/typeConverters';
import FileConfigurationManager from './fileConfigurationManager'; import FileConfigurationManager from './fileConfigurationManager';
import { TelemetryReporter } from '../utils/telemetry';
import { nulToken } from '../utils/cancellation';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@ -105,7 +105,9 @@ export function register(
fileConfigurationManager: FileConfigurationManager, fileConfigurationManager: FileConfigurationManager,
telemetryReporter: TelemetryReporter, telemetryReporter: TelemetryReporter,
) { ) {
return new VersionDependentRegistration(client, OrganizeImportsCodeActionProvider.minVersion, () => { return conditionalRegistration([
requireMinVersion(client, OrganizeImportsCodeActionProvider.minVersion)
], () => {
const organizeImportsProvider = new OrganizeImportsCodeActionProvider(client, commandManager, fileConfigurationManager, telemetryReporter); const organizeImportsProvider = new OrganizeImportsCodeActionProvider(client, commandManager, fileConfigurationManager, telemetryReporter);
return vscode.languages.registerCodeActionsProvider(selector, return vscode.languages.registerCodeActionsProvider(selector,
organizeImportsProvider, organizeImportsProvider,

View file

@ -11,7 +11,7 @@ import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { nulToken } from '../utils/cancellation'; import { nulToken } from '../utils/cancellation';
import { Command, CommandManager } from '../utils/commandManager'; import { Command, CommandManager } from '../utils/commandManager';
import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import * as fileSchemes from '../utils/fileSchemes'; import * as fileSchemes from '../utils/fileSchemes';
import { TelemetryReporter } from '../utils/telemetry'; import { TelemetryReporter } from '../utils/telemetry';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
@ -402,7 +402,9 @@ export function register(
commandManager: CommandManager, commandManager: CommandManager,
telemetryReporter: TelemetryReporter, telemetryReporter: TelemetryReporter,
) { ) {
return new VersionDependentRegistration(client, TypeScriptRefactorProvider.minVersion, () => { return conditionalRegistration([
requireMinVersion(client, TypeScriptRefactorProvider.minVersion)
], () => {
return vscode.languages.registerCodeActionsProvider(selector, return vscode.languages.registerCodeActionsProvider(selector,
new TypeScriptRefactorProvider(client, formattingOptionsManager, commandManager, telemetryReporter), new TypeScriptRefactorProvider(client, formattingOptionsManager, commandManager, telemetryReporter),
TypeScriptRefactorProvider.metadata); TypeScriptRefactorProvider.metadata);

View file

@ -9,7 +9,7 @@ import type * as Proto from '../protocol';
import * as PConst from '../protocol.const'; import * as PConst from '../protocol.const';
import { CachedResponse } from '../tsServer/cachedResponse'; import { CachedResponse } from '../tsServer/cachedResponse';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireConfiguration } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
import { getSymbolRange, ReferencesCodeLens, TypeScriptBaseCodeLensProvider } from './baseCodeLensProvider'; import { getSymbolRange, ReferencesCodeLens, TypeScriptBaseCodeLensProvider } from './baseCodeLensProvider';
@ -127,7 +127,9 @@ export function register(
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
cachedResponse: CachedResponse<Proto.NavTreeResponse>, cachedResponse: CachedResponse<Proto.NavTreeResponse>,
) { ) {
return new ConfigurationDependentRegistration(modeId, 'referencesCodeLens.enabled', () => { return conditionalRegistration([
requireConfiguration(modeId, 'referencesCodeLens.enabled')
], () => {
return vscode.languages.registerCodeLensProvider(selector, return vscode.languages.registerCodeLensProvider(selector,
new TypeScriptReferencesCodeLensProvider(client, cachedResponse, modeId)); new TypeScriptReferencesCodeLensProvider(client, cachedResponse, modeId));
}); });

View file

@ -3,14 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { ITypeScriptServiceClient, ExecConfig, ServerResponse } from '../typescriptService';
import * as Proto from '../protocol';
import { VersionDependentRegistration } from '../utils/dependentRegistration';
import API from '../utils/api';
// all constants are const // all constants are const
import { TokenType, TokenModifier, TokenEncodingConsts, VersionRequirement } from 'typescript-vscode-sh-plugin/lib/constants'; import { TokenEncodingConsts, TokenModifier, TokenType, VersionRequirement } from 'typescript-vscode-sh-plugin/lib/constants';
import * as vscode from 'vscode';
import * as Proto from '../protocol';
import { ExecConfig, ITypeScriptServiceClient, ServerResponse } from '../typescriptService';
import API from '../utils/api';
import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
const minTypeScriptVersion = API.fromVersionString(`${VersionRequirement.major}.${VersionRequirement.minor}`); const minTypeScriptVersion = API.fromVersionString(`${VersionRequirement.major}.${VersionRequirement.minor}`);
@ -18,7 +18,9 @@ const minTypeScriptVersion = API.fromVersionString(`${VersionRequirement.major}.
const CONTENT_LENGTH_LIMIT = 100000; const CONTENT_LENGTH_LIMIT = 100000;
export function register(selector: vscode.DocumentSelector, client: ITypeScriptServiceClient) { export function register(selector: vscode.DocumentSelector, client: ITypeScriptServiceClient) {
return new VersionDependentRegistration(client, minTypeScriptVersion, () => { return conditionalRegistration([
requireMinVersion(client, minTypeScriptVersion),
], () => {
const provider = new DocumentSemanticTokensProvider(client); const provider = new DocumentSemanticTokensProvider(client);
return vscode.Disposable.from( return vscode.Disposable.from(
// register only as a range provider // register only as a range provider

View file

@ -7,7 +7,7 @@ import * as vscode from 'vscode';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
class SmartSelection implements vscode.SelectionRangeProvider { class SmartSelection implements vscode.SelectionRangeProvider {
@ -52,6 +52,9 @@ export function register(
selector: vscode.DocumentSelector, selector: vscode.DocumentSelector,
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
) { ) {
return new VersionDependentRegistration(client, SmartSelection.minVersion, () => return conditionalRegistration([
vscode.languages.registerSelectionRangeProvider(selector, new SmartSelection(client))); requireMinVersion(client, SmartSelection.minVersion),
], () => {
return vscode.languages.registerSelectionRangeProvider(selector, new SmartSelection(client));
});
} }

View file

@ -7,7 +7,7 @@ import * as vscode from 'vscode';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService'; import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { ConditionalRegistration, ConfigurationDependentRegistration, VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion, requireConfiguration, Condition } from '../utils/dependentRegistration';
import { Disposable } from '../utils/dispose'; import { Disposable } from '../utils/dispose';
import * as typeConverters from '../utils/typeConverters'; import * as typeConverters from '../utils/typeConverters';
@ -135,32 +135,19 @@ class TagClosing extends Disposable {
} }
} }
export class ActiveDocumentDependentRegistration extends Disposable { function requireActiveDocument(
private readonly _registration: ConditionalRegistration; selector: vscode.DocumentSelector
) {
constructor( return new Condition(
private readonly selector: vscode.DocumentSelector, () => {
register: () => vscode.Disposable, const editor = vscode.window.activeTextEditor;
) { return !!(editor && vscode.languages.match(selector, editor.document));
super(); },
this._registration = this._register(new ConditionalRegistration(register)); handler => {
vscode.window.onDidChangeActiveTextEditor(this.update, this, this._disposables); return vscode.Disposable.from(
vscode.workspace.onDidOpenTextDocument(this.onDidOpenDocument, this, this._disposables); vscode.window.onDidChangeActiveTextEditor(handler),
this.update(); vscode.workspace.onDidOpenTextDocument(handler));
} });
private update() {
const editor = vscode.window.activeTextEditor;
const enabled = !!(editor && vscode.languages.match(this.selector, editor.document));
this._registration.update(enabled);
}
private onDidOpenDocument(openedDocument: vscode.TextDocument) {
if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document === openedDocument) {
// The active document's language may have changed
this.update();
}
}
} }
export function register( export function register(
@ -168,8 +155,9 @@ export function register(
modeId: string, modeId: string,
client: ITypeScriptServiceClient, client: ITypeScriptServiceClient,
) { ) {
return new VersionDependentRegistration(client, TagClosing.minVersion, () => return conditionalRegistration([
new ConfigurationDependentRegistration(modeId, 'autoClosingTags', () => requireMinVersion(client, TagClosing.minVersion),
new ActiveDocumentDependentRegistration(selector, () => requireConfiguration(modeId, 'autoClosingTags'),
new TagClosing(client)))); requireActiveDocument(selector)
], () => new TagClosing(client));
} }

View file

@ -11,7 +11,7 @@ import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api'; import API from '../utils/api';
import { Delayer } from '../utils/async'; import { Delayer } from '../utils/async';
import { nulToken } from '../utils/cancellation'; import { nulToken } from '../utils/cancellation';
import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { conditionalRegistration, requireMinVersion } from '../utils/dependentRegistration';
import { Disposable } from '../utils/dispose'; import { Disposable } from '../utils/dispose';
import * as fileSchemes from '../utils/fileSchemes'; import * as fileSchemes from '../utils/fileSchemes';
import { doesResourceLookLikeATypeScriptFile } from '../utils/languageDescription'; import { doesResourceLookLikeATypeScriptFile } from '../utils/languageDescription';
@ -294,6 +294,9 @@ export function register(
fileConfigurationManager: FileConfigurationManager, fileConfigurationManager: FileConfigurationManager,
handles: (uri: vscode.Uri) => Promise<boolean>, handles: (uri: vscode.Uri) => Promise<boolean>,
) { ) {
return new VersionDependentRegistration(client, UpdateImportsOnFileRenameHandler.minVersion, () => return conditionalRegistration([
new UpdateImportsOnFileRenameHandler(client, fileConfigurationManager, handles)); requireMinVersion(client, UpdateImportsOnFileRenameHandler.minVersion),
], () => {
return new UpdateImportsOnFileRenameHandler(client, fileConfigurationManager, handles);
});
} }

View file

@ -8,24 +8,54 @@ import { ITypeScriptServiceClient } from '../typescriptService';
import API from './api'; import API from './api';
import { Disposable } from './dispose'; import { Disposable } from './dispose';
export class ConditionalRegistration { export class Condition extends Disposable {
private _value: boolean;
constructor(
private readonly getValue: () => boolean,
onUpdate: (handler: () => void) => void,
) {
super();
this._value = this.getValue();
onUpdate(() => {
const newValue = this.getValue();
if (newValue !== this._value) {
this._value = newValue;
this._onDidChange.fire();
}
});
}
public get value(): boolean { return this._value; }
private readonly _onDidChange = this._register(new vscode.EventEmitter<void>());
public readonly onDidChange = this._onDidChange.event;
}
class ConditionalRegistration {
private registration: vscode.Disposable | undefined = undefined; private registration: vscode.Disposable | undefined = undefined;
public constructor( public constructor(
private readonly _doRegister: () => vscode.Disposable private readonly conditions: readonly Condition[],
) { } private readonly doRegister: () => vscode.Disposable
) {
public dispose() { for (const condition of conditions) {
if (this.registration) { condition.onDidChange(() => this.update());
this.registration.dispose();
this.registration = undefined;
} }
this.update();
} }
public update(enabled: boolean) { public dispose() {
this.registration?.dispose();
this.registration = undefined;
}
private update() {
const enabled = this.conditions.every(condition => condition.value);
if (enabled) { if (enabled) {
if (!this.registration) { if (!this.registration) {
this.registration = this._doRegister(); this.registration = this.doRegister();
} }
} else { } else {
if (this.registration) { if (this.registration) {
@ -36,49 +66,32 @@ export class ConditionalRegistration {
} }
} }
export class VersionDependentRegistration extends Disposable { export function conditionalRegistration(
private readonly _registration: ConditionalRegistration; conditions: readonly Condition[],
doRegister: () => vscode.Disposable,
constructor( ): vscode.Disposable {
private readonly client: ITypeScriptServiceClient, return new ConditionalRegistration(conditions, doRegister);
private readonly minVersion: API,
register: () => vscode.Disposable,
) {
super();
this._registration = this._register(new ConditionalRegistration(register));
this._register(this.client.onTsServerStarted(() => {
this.update(this.client.apiVersion);
}));
this.update(client.apiVersion);
}
private update(api: API) {
this._registration.update(api.gte(this.minVersion));
}
} }
export function requireMinVersion(
export class ConfigurationDependentRegistration extends Disposable { client: ITypeScriptServiceClient,
private readonly _registration: ConditionalRegistration; minVersion: API,
) {
constructor( return new Condition(
private readonly language: string, () => client.apiVersion.gte(minVersion),
private readonly configValue: string, client.onTsServerStarted
register: () => vscode.Disposable, );
) { }
super();
this._registration = this._register(new ConditionalRegistration(register)); export function requireConfiguration(
language: string,
this._register(vscode.workspace.onDidChangeConfiguration(this.update, this)); configValue: string,
) {
this.update(); return new Condition(
} () => {
const config = vscode.workspace.getConfiguration(language, null);
private update() { return !!config.get<boolean>(configValue);
const config = vscode.workspace.getConfiguration(this.language, null); },
this._registration.update(!!config.get<boolean>(this.configValue)); vscode.workspace.onDidChangeConfiguration
} );
} }