提交 41050913 编写于 作者: M Matt Bierner

Add base Disposable class to help manage disposables

上级 f97c7435
......@@ -4,12 +4,12 @@
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import { CancellationTokenSource, Disposable, EventEmitter, TextDocument, TextDocumentChangeEvent, TextDocumentContentChangeEvent, Uri, workspace } from 'vscode';
import { CancellationTokenSource, EventEmitter, TextDocument, TextDocumentChangeEvent, TextDocumentContentChangeEvent, Uri, workspace } from 'vscode';
import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api';
import { Delayer } from '../utils/async';
import { disposeAll } from '../utils/dispose';
import { Disposable } from '../utils/dispose';
import * as languageModeIds from '../utils/languageModeIds';
import { ResourceMap } from '../utils/resourceMap';
import * as typeConverters from '../utils/typeConverters';
......@@ -168,14 +168,13 @@ class GetErrRequest {
}
}
export default class BufferSyncSupport {
export default class BufferSyncSupport extends Disposable {
private readonly client: ITypeScriptServiceClient;
private _validateJavaScript: boolean = true;
private _validateTypeScript: boolean = true;
private readonly modeIds: Set<string>;
private readonly disposables: Disposable[] = [];
private readonly syncedBuffers: SyncedBufferMap;
private readonly pendingDiagnostics: PendingDiagnostics;
private readonly diagnosticDelayer: Delayer<any>;
......@@ -186,6 +185,7 @@ export default class BufferSyncSupport {
client: ITypeScriptServiceClient,
modeIds: string[]
) {
super();
this.client = client;
this.modeIds = new Set<string>(modeIds);
......@@ -196,10 +196,10 @@ export default class BufferSyncSupport {
this.pendingDiagnostics = new PendingDiagnostics(pathNormalizer);
this.updateConfiguration();
workspace.onDidChangeConfiguration(this.updateConfiguration, this, this.disposables);
workspace.onDidChangeConfiguration(this.updateConfiguration, this, this._disposables);
}
private readonly _onDelete = new EventEmitter<Uri>();
private readonly _onDelete = this._register(new EventEmitter<Uri>());
public readonly onDelete = this._onDelete.event;
public listen(): void {
......@@ -207,9 +207,9 @@ export default class BufferSyncSupport {
return;
}
this.listening = true;
workspace.onDidOpenTextDocument(this.openTextDocument, this, this.disposables);
workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, this.disposables);
workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, this.disposables);
workspace.onDidOpenTextDocument(this.openTextDocument, this, this._disposables);
workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, this._disposables);
workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, this._disposables);
workspace.textDocuments.forEach(this.openTextDocument, this);
}
......@@ -231,11 +231,6 @@ export default class BufferSyncSupport {
}
}
public dispose(): void {
disposeAll(this.disposables);
this._onDelete.dispose();
}
public openTextDocument(document: TextDocument): void {
if (!this.modeIds.has(document.languageId)) {
return;
......
......@@ -9,7 +9,7 @@
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { disposeAll } from '../utils/dispose';
import { Disposable } from '../utils/dispose';
import * as languageModeIds from '../utils/languageModeIds';
const jsTsLanguageConfiguration: vscode.LanguageConfiguration = {
......@@ -64,10 +64,10 @@ const jsxTagsLanguageConfiguration: vscode.LanguageConfiguration = {
],
};
export class LanguageConfigurationManager {
private readonly _registrations: vscode.Disposable[] = [];
export class LanguageConfigurationManager extends Disposable {
constructor() {
super();
const standardLanguages = [
languageModeIds.javascript,
languageModeIds.javascriptreact,
......@@ -82,10 +82,6 @@ export class LanguageConfigurationManager {
}
private registerConfiguration(language: string, config: vscode.LanguageConfiguration) {
this._registrations.push(vscode.languages.setLanguageConfiguration(language, config));
}
dispose() {
disposeAll(this._registrations);
this._register(vscode.languages.setLanguageConfiguration(language, config));
}
}
......@@ -8,19 +8,19 @@ import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api';
import { ConditionalRegistration, ConfigurationDependentRegistration, VersionDependentRegistration } from '../utils/dependentRegistration';
import { disposeAll } from '../utils/dispose';
import { Disposable } from '../utils/dispose';
import * as typeConverters from '../utils/typeConverters';
class TagClosing {
class TagClosing extends Disposable {
private _disposed = false;
private _timeout: NodeJS.Timer | undefined = undefined;
private _cancel: vscode.CancellationTokenSource | undefined = undefined;
private readonly _disposables: vscode.Disposable[] = [];
constructor(
private readonly client: ITypeScriptServiceClient
) {
super();
vscode.workspace.onDidChangeTextDocument(
event => this.onDidChangeTextDocument(event.document, event.contentChanges),
null,
......@@ -28,10 +28,9 @@ class TagClosing {
}
public dispose() {
super.dispose();
this._disposed = true;
disposeAll(this._disposables);
if (this._timeout) {
clearTimeout(this._timeout);
this._timeout = undefined;
......@@ -136,24 +135,19 @@ class TagClosing {
}
}
export class ActiveDocumentDependentRegistration {
export class ActiveDocumentDependentRegistration extends Disposable {
private readonly _registration: ConditionalRegistration;
private readonly _disposables: vscode.Disposable[] = [];
constructor(
private readonly selector: vscode.DocumentSelector,
register: () => vscode.Disposable,
) {
this._registration = new ConditionalRegistration(register);
super();
this._registration = this._register(new ConditionalRegistration(register));
vscode.window.onDidChangeActiveTextEditor(this.update, this, this._disposables);
this.update();
}
public dispose() {
disposeAll(this._disposables);
this._registration.dispose();
}
private update() {
const editor = vscode.window.activeTextEditor;
const enabled = !!(editor && vscode.languages.match(this.selector, editor.document));
......
......@@ -10,7 +10,7 @@ import { DiagnosticKind } from './features/diagnostics';
import FileConfigurationManager from './features/fileConfigurationManager';
import TypeScriptServiceClient from './typescriptServiceClient';
import { CommandManager } from './utils/commandManager';
import { disposeAll } from './utils/dispose';
import { Disposable } from './utils/dispose';
import * as fileSchemes from './utils/fileSchemes';
import { LanguageDescription } from './utils/languageDescription';
import { memoize } from './utils/memoize';
......@@ -21,8 +21,7 @@ import TypingsStatus from './utils/typingsStatus';
const validateSetting = 'validate.enable';
const suggestionSetting = 'suggestionActions.enabled';
export default class LanguageProvider {
private readonly disposables: vscode.Disposable[] = [];
export default class LanguageProvider extends Disposable {
constructor(
private readonly client: TypeScriptServiceClient,
......@@ -32,7 +31,8 @@ export default class LanguageProvider {
private readonly typingsStatus: TypingsStatus,
private readonly fileConfigurationManager: FileConfigurationManager
) {
vscode.workspace.onDidChangeConfiguration(this.configurationChanged, this, this.disposables);
super();
vscode.workspace.onDidChangeConfiguration(this.configurationChanged, this, this._disposables);
this.configurationChanged();
client.onReady(async () => {
......@@ -40,9 +40,6 @@ export default class LanguageProvider {
});
}
public dispose(): void {
disposeAll(this.disposables);
}
@memoize
private get documentSelector(): vscode.DocumentFilter[] {
......@@ -60,27 +57,27 @@ export default class LanguageProvider {
const cachedResponse = new CachedNavTreeResponse();
this.disposables.push((await import('./features/completions')).register(selector, this.client, this.typingsStatus, this.fileConfigurationManager, this.commandManager));
this.disposables.push((await import('./features/definitions')).register(selector, this.client));
this.disposables.push((await import('./features/directiveCommentCompletions')).register(selector, this.client));
this.disposables.push((await import('./features/documentHighlight')).register(selector, this.client));
this.disposables.push((await import('./features/documentSymbol')).register(selector, this.client));
this.disposables.push((await import('./features/folding')).register(selector, this.client));
this.disposables.push((await import('./features/formatting')).register(selector, this.description.id, this.client, this.fileConfigurationManager));
this.disposables.push((await import('./features/hover')).register(selector, this.client));
this.disposables.push((await import('./features/implementations')).register(selector, this.client));
this.disposables.push((await import('./features/implementationsCodeLens')).register(selector, this.description.id, this.client, cachedResponse));
this.disposables.push((await import('./features/jsDocCompletions')).register(selector, this.client, this.commandManager));
this.disposables.push((await import('./features/organizeImports')).register(selector, this.client, this.commandManager, this.fileConfigurationManager, this.telemetryReporter));
this.disposables.push((await import('./features/quickFix')).register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.client.diagnosticsManager, this.telemetryReporter));
this.disposables.push((await import('./features/refactor')).register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.telemetryReporter));
this.disposables.push((await import('./features/references')).register(selector, this.client));
this.disposables.push((await import('./features/referencesCodeLens')).register(selector, this.description.id, this.client, cachedResponse));
this.disposables.push((await import('./features/rename')).register(selector, this.client));
this.disposables.push((await import('./features/signatureHelp')).register(selector, this.client));
this.disposables.push((await import('./features/tagClosing')).register(selector, this.description.id, this.client));
this.disposables.push((await import('./features/typeDefinitions')).register(selector, this.client));
this.disposables.push((await import('./features/workspaceSymbols')).register(this.client, this.description.modeIds));
this._register((await import('./features/completions')).register(selector, this.client, this.typingsStatus, this.fileConfigurationManager, this.commandManager));
this._register((await import('./features/definitions')).register(selector, this.client));
this._register((await import('./features/directiveCommentCompletions')).register(selector, this.client));
this._register((await import('./features/documentHighlight')).register(selector, this.client));
this._register((await import('./features/documentSymbol')).register(selector, this.client));
this._register((await import('./features/folding')).register(selector, this.client));
this._register((await import('./features/formatting')).register(selector, this.description.id, this.client, this.fileConfigurationManager));
this._register((await import('./features/hover')).register(selector, this.client));
this._register((await import('./features/implementations')).register(selector, this.client));
this._register((await import('./features/implementationsCodeLens')).register(selector, this.description.id, this.client, cachedResponse));
this._register((await import('./features/jsDocCompletions')).register(selector, this.client, this.commandManager));
this._register((await import('./features/organizeImports')).register(selector, this.client, this.commandManager, this.fileConfigurationManager, this.telemetryReporter));
this._register((await import('./features/quickFix')).register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.client.diagnosticsManager, this.telemetryReporter));
this._register((await import('./features/refactor')).register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.telemetryReporter));
this._register((await import('./features/references')).register(selector, this.client));
this._register((await import('./features/referencesCodeLens')).register(selector, this.description.id, this.client, cachedResponse));
this._register((await import('./features/rename')).register(selector, this.client));
this._register((await import('./features/signatureHelp')).register(selector, this.client));
this._register((await import('./features/tagClosing')).register(selector, this.description.id, this.client));
this._register((await import('./features/typeDefinitions')).register(selector, this.client));
this._register((await import('./features/workspaceSymbols')).register(this.client, this.description.modeIds));
}
private configurationChanged(): void {
......
......@@ -8,7 +8,7 @@
* https://github.com/Microsoft/TypeScript-Sublime-Plugin/blob/master/TypeScript%20Indent.tmPreferences
* ------------------------------------------------------------------------------------------ */
import { Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Disposable, Memento, Range, Uri, workspace } from 'vscode';
import { Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Memento, Range, Uri, workspace } from 'vscode';
import { DiagnosticKind } from './features/diagnostics';
import FileConfigurationManager from './features/fileConfigurationManager';
import { register as registerUpdatePathsOnRename } from './features/updatePathsOnRename';
......@@ -18,7 +18,7 @@ import * as PConst from './protocol.const';
import TypeScriptServiceClient from './typescriptServiceClient';
import API from './utils/api';
import { CommandManager } from './utils/commandManager';
import { disposeAll } from './utils/dispose';
import { Disposable } from './utils/dispose';
import { LanguageDescription, DiagnosticLanguage } from './utils/languageDescription';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import { TypeScriptServerPlugin } from './utils/plugins';
......@@ -36,13 +36,11 @@ const styleCheckDiagnostics = [
7030 // not all code paths return a value
];
export default class TypeScriptServiceClientHost {
private readonly ataProgressReporter: AtaProgressReporter;
export default class TypeScriptServiceClientHost extends Disposable {
private readonly typingsStatus: TypingsStatus;
private readonly client: TypeScriptServiceClient;
private readonly languages: LanguageProvider[] = [];
private readonly languagePerId = new Map<string, LanguageProvider>();
private readonly disposables: Disposable[] = [];
private readonly versionStatus: VersionStatus;
private readonly fileConfigurationManager: FileConfigurationManager;
......@@ -55,6 +53,7 @@ export default class TypeScriptServiceClientHost {
private readonly commandManager: CommandManager,
logDirectoryProvider: LogDirectoryProvider
) {
super();
const handleProjectCreateOrDelete = () => {
this.client.execute('reloadProjects', null, false);
this.triggerAllDiagnostics();
......@@ -65,10 +64,10 @@ export default class TypeScriptServiceClientHost {
}, 1500);
};
const configFileWatcher = workspace.createFileSystemWatcher('**/[tj]sconfig.json');
this.disposables.push(configFileWatcher);
configFileWatcher.onDidCreate(handleProjectCreateOrDelete, this, this.disposables);
configFileWatcher.onDidDelete(handleProjectCreateOrDelete, this, this.disposables);
configFileWatcher.onDidChange(handleProjectChange, this, this.disposables);
this._register(configFileWatcher);
configFileWatcher.onDidCreate(handleProjectCreateOrDelete, this, this._disposables);
configFileWatcher.onDidDelete(handleProjectCreateOrDelete, this, this._disposables);
configFileWatcher.onDidChange(handleProjectChange, this, this._disposables);
const allModeIds = this.getAllModeIds(descriptions);
this.client = new TypeScriptServiceClient(
......@@ -77,30 +76,30 @@ export default class TypeScriptServiceClientHost {
plugins,
logDirectoryProvider,
allModeIds);
this.disposables.push(this.client);
this._register(this.client);
this.client.onDiagnosticsReceived(({ kind, resource, diagnostics }) => {
this.diagnosticsReceived(kind, resource, diagnostics);
}, null, this.disposables);
}, null, this._disposables);
this.client.onConfigDiagnosticsReceived(diag => this.configFileDiagnosticsReceived(diag), null, this.disposables);
this.client.onResendModelsRequested(() => this.populateService(), null, this.disposables);
this.client.onConfigDiagnosticsReceived(diag => this.configFileDiagnosticsReceived(diag), null, this._disposables);
this.client.onResendModelsRequested(() => this.populateService(), null, this._disposables);
this.versionStatus = new VersionStatus(resource => this.client.toPath(resource));
this.disposables.push(this.versionStatus);
this._register(this.versionStatus);
this.typingsStatus = new TypingsStatus(this.client);
this.ataProgressReporter = new AtaProgressReporter(this.client);
this.fileConfigurationManager = new FileConfigurationManager(this.client);
this._register(new AtaProgressReporter(this.client));
this.typingsStatus = this._register(new TypingsStatus(this.client));
this.fileConfigurationManager = this._register(new FileConfigurationManager(this.client));
for (const description of descriptions) {
const manager = new LanguageProvider(this.client, description, this.commandManager, this.client.telemetryReporter, this.typingsStatus, this.fileConfigurationManager);
this.languages.push(manager);
this.disposables.push(manager);
this._register(manager);
this.languagePerId.set(description.id, manager);
}
this.disposables.push(registerUpdatePathsOnRename(this.client, this.fileConfigurationManager, uri => this.handles(uri)));
this._register(registerUpdatePathsOnRename(this.client, this.fileConfigurationManager, uri => this.handles(uri)));
this.client.ensureServiceStarted();
this.client.onReady(() => {
......@@ -125,7 +124,7 @@ export default class TypeScriptServiceClientHost {
};
const manager = new LanguageProvider(this.client, description, this.commandManager, this.client.telemetryReporter, this.typingsStatus, this.fileConfigurationManager);
this.languages.push(manager);
this.disposables.push(manager);
this._register(manager);
this.languagePerId.set(description.id, manager);
}
});
......@@ -134,7 +133,7 @@ export default class TypeScriptServiceClientHost {
this.triggerAllDiagnostics();
});
workspace.onDidChangeConfiguration(this.configurationChanged, this, this.disposables);
workspace.onDidChangeConfiguration(this.configurationChanged, this, this._disposables);
this.configurationChanged();
}
......@@ -146,13 +145,6 @@ export default class TypeScriptServiceClientHost {
return allModeIds;
}
public dispose(): void {
disposeAll(this.disposables);
this.typingsStatus.dispose();
this.ataProgressReporter.dispose();
this.fileConfigurationManager.dispose();
}
public get serviceClient(): TypeScriptServiceClient {
return this.client;
}
......
......@@ -6,7 +6,7 @@
import * as cp from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { CancellationToken, commands, Disposable, env, EventEmitter, Memento, MessageItem, Uri, window, workspace } from 'vscode';
import { CancellationToken, commands, env, EventEmitter, Memento, MessageItem, Uri, window, workspace } from 'vscode';
import * as nls from 'vscode-nls';
import BufferSyncSupport from './features/bufferSyncSupport';
import { DiagnosticKind, DiagnosticsManager } from './features/diagnostics';
......@@ -14,7 +14,7 @@ import * as Proto from './protocol';
import { ITypeScriptServiceClient } from './typescriptService';
import API from './utils/api';
import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration';
import { disposeAll } from './utils/dispose';
import { Disposable } from './utils/dispose';
import * as electron from './utils/electron';
import * as fileSchemes from './utils/fileSchemes';
import * as is from './utils/is';
......@@ -30,9 +30,6 @@ import { TypeScriptVersion, TypeScriptVersionProvider } from './utils/versionPro
import { ICallback, Reader } from './utils/wireProtocol';
const localize = nls.loadMessageBundle();
interface CallbackItem {
......@@ -159,7 +156,7 @@ export interface TsDiagnostics {
readonly diagnostics: Proto.Diagnostic[];
}
export default class TypeScriptServiceClient implements ITypeScriptServiceClient {
export default class TypeScriptServiceClient extends Disposable implements ITypeScriptServiceClient {
private static readonly WALK_THROUGH_SNIPPET_SCHEME_COLON = `${fileSchemes.walkThroughSnippet}:`;
private pathSeparator: string;
......@@ -194,8 +191,6 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
*/
private _tsserverVersion: string | undefined;
private readonly disposables: Disposable[] = [];
public readonly bufferSyncSupport: BufferSyncSupport;
public readonly diagnosticsManager: DiagnosticsManager;
......@@ -206,6 +201,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
private readonly logDirectoryProvider: LogDirectoryProvider,
allModeIds: string[]
) {
super();
this.pathSeparator = path.sep;
this.lastStart = Date.now();
......@@ -235,7 +231,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
this.diagnosticsManager = new DiagnosticsManager('typescript');
this.bufferSyncSupport.onDelete(resource => {
this.diagnosticsManager.delete(resource);
}, null, this.disposables);
}, null, this._disposables);
workspace.onDidChangeConfiguration(() => {
const oldConfiguration = this._configuration;
......@@ -256,9 +252,9 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
this.restartTsServer();
}
}
}, this, this.disposables);
}, this, this._disposables);
this.telemetryReporter = new TelemetryReporter(() => this._tsserverVersion || this._apiVersion.versionString);
this.disposables.push(this.telemetryReporter);
this._register(this.telemetryReporter);
}
public get configuration() {
......@@ -266,22 +262,15 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
}
public dispose() {
super.dispose();
this.bufferSyncSupport.dispose();
this._onTsServerStarted.dispose();
this._onDidBeginInstallTypings.dispose();
this._onDidEndInstallTypings.dispose();
this._onTypesInstallerInitializationFailed.dispose();
if (this.servicePromise) {
this.servicePromise.then(childProcess => {
childProcess.kill();
}).then(undefined, () => void 0);
}
disposeAll(this.disposables);
this._onDiagnosticsReceived.dispose();
this._onConfigDiagnosticsReceived.dispose();
this._onResendModelsRequested.dispose();
}
public restartTsServer(): void {
......@@ -302,28 +291,28 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
}
}
private readonly _onTsServerStarted = new EventEmitter<API>();
private readonly _onTsServerStarted = this._register(new EventEmitter<API>());
public readonly onTsServerStarted = this._onTsServerStarted.event;
private readonly _onDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
private readonly _onDiagnosticsReceived = this._register(new EventEmitter<TsDiagnostics>());
public readonly onDiagnosticsReceived = this._onDiagnosticsReceived.event;
private readonly _onConfigDiagnosticsReceived = new EventEmitter<Proto.ConfigFileDiagnosticEvent>();
private readonly _onConfigDiagnosticsReceived = this._register(new EventEmitter<Proto.ConfigFileDiagnosticEvent>());
public readonly onConfigDiagnosticsReceived = this._onConfigDiagnosticsReceived.event;
private readonly _onResendModelsRequested = new EventEmitter<void>();
private readonly _onResendModelsRequested = this._register(new EventEmitter<void>());
public readonly onResendModelsRequested = this._onResendModelsRequested.event;
private readonly _onProjectLanguageServiceStateChanged = new EventEmitter<Proto.ProjectLanguageServiceStateEventBody>();
private readonly _onProjectLanguageServiceStateChanged = this._register(new EventEmitter<Proto.ProjectLanguageServiceStateEventBody>());
public readonly onProjectLanguageServiceStateChanged = this._onProjectLanguageServiceStateChanged.event;
private readonly _onDidBeginInstallTypings = new EventEmitter<Proto.BeginInstallTypesEventBody>();
private readonly _onDidBeginInstallTypings = this._register(new EventEmitter<Proto.BeginInstallTypesEventBody>());
public readonly onDidBeginInstallTypings = this._onDidBeginInstallTypings.event;
private readonly _onDidEndInstallTypings = new EventEmitter<Proto.EndInstallTypesEventBody>();
private readonly _onDidEndInstallTypings = this._register(new EventEmitter<Proto.EndInstallTypesEventBody>());
public readonly onDidEndInstallTypings = this._onDidEndInstallTypings.event;
private readonly _onTypesInstallerInitializationFailed = new EventEmitter<Proto.TypesInstallerInitializationFailedEventBody>();
private readonly _onTypesInstallerInitializationFailed = this._register(new EventEmitter<Proto.TypesInstallerInitializationFailedEventBody>());
public readonly onTypesInstallerInitializationFailed = this._onTypesInstallerInitializationFailed.event;
public get apiVersion(): API {
......
......@@ -6,7 +6,7 @@
import * as vscode from 'vscode';
import { ITypeScriptServiceClient } from '../typescriptService';
import API from './api';
import { disposeAll } from './dispose';
import { Disposable } from './dispose';
export class ConditionalRegistration {
private registration: vscode.Disposable | undefined = undefined;
......@@ -36,15 +36,15 @@ export class ConditionalRegistration {
}
}
export class VersionDependentRegistration {
export class VersionDependentRegistration extends Disposable {
private readonly _registration: ConditionalRegistration;
private readonly _disposables: vscode.Disposable[] = [];
constructor(
private readonly client: ITypeScriptServiceClient,
private readonly minVersion: API,
register: () => vscode.Disposable,
) {
super();
this._registration = new ConditionalRegistration(register);
this.update(client.apiVersion);
......@@ -55,7 +55,7 @@ export class VersionDependentRegistration {
}
public dispose() {
disposeAll(this._disposables);
super.dispose();
this._registration.dispose();
}
......@@ -65,22 +65,22 @@ export class VersionDependentRegistration {
}
export class ConfigurationDependentRegistration {
export class ConfigurationDependentRegistration extends Disposable {
private readonly _registration: ConditionalRegistration;
private readonly _disposables: vscode.Disposable[] = [];
constructor(
private readonly language: string,
private readonly configValue: string,
register: () => vscode.Disposable,
) {
super();
this._registration = new ConditionalRegistration(register);
this.update();
vscode.workspace.onDidChangeConfiguration(this.update, this, this._disposables);
}
public dispose() {
disposeAll(this._disposables);
super.dispose();
this._registration.dispose();
}
......
......@@ -5,7 +5,7 @@
import * as vscode from 'vscode';
export function disposeAll(disposables: vscode.Disposable[]) {
function disposeAll(disposables: vscode.Disposable[]) {
while (disposables.length) {
const item = disposables.pop();
if (item) {
......@@ -13,3 +13,26 @@ export function disposeAll(disposables: vscode.Disposable[]) {
}
}
}
export abstract class Disposable {
private _isDisposed = false;
protected _disposables: vscode.Disposable[] = [];
public dispose(): any {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
disposeAll(this._disposables);
}
protected _register<T extends vscode.Disposable>(value: T): T {
if (this._isDisposed) {
value.dispose();
} else {
this._disposables.push(value);
}
return value;
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册