Adding a command helper class to start cleaning up command registration

This commit is contained in:
Matt Bierner
2017-11-07 15:29:56 -08:00
parent 2aa8096972
commit dc2d3b1de3
5 changed files with 75 additions and 30 deletions

View File

@@ -3,13 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands } from 'vscode';
import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command } from 'vscode';
import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import { vsRangeToTsFileRange } from '../utils/convert';
import FormattingConfigurationManager from './formattingConfigurationManager';
import { applyCodeAction } from '../utils/codeAction';
import { CommandManager } from '../utils/commandManager';
interface NumberSet {
[key: number]: boolean;
@@ -23,10 +24,11 @@ export default class TypeScriptCodeActionProvider implements CodeActionProvider
constructor(
private readonly client: ITypeScriptServiceClient,
private readonly formattingConfigurationManager: FormattingConfigurationManager,
mode: string
mode: string,
commandManager: CommandManager
) {
this.commandId = `_typescript.applyCodeAction.${mode}`;
commands.registerCommand(this.commandId, this.onCodeAction, this);
commandManager.registerCommand(this.commandId, this.onCodeAction, this);
}
public async provideCodeActions(

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CompletionItem, TextDocument, Position, CompletionItemKind, CompletionItemProvider, CancellationToken, TextEdit, Range, SnippetString, workspace, ProviderResult, CompletionContext, commands, Uri, MarkdownString } from 'vscode';
import { CompletionItem, TextDocument, Position, CompletionItemKind, CompletionItemProvider, CancellationToken, TextEdit, Range, SnippetString, workspace, ProviderResult, CompletionContext, Uri, MarkdownString } from 'vscode';
import { ITypeScriptServiceClient } from '../typescriptService';
import TypingsStatus from '../utils/typingsStatus';
@@ -16,6 +16,7 @@ import { tsTextSpanToVsRange, vsPositionToTsFileLocation } from '../utils/conver
import * as nls from 'vscode-nls';
import { applyCodeAction } from '../utils/codeAction';
import * as languageModeIds from '../utils/languageModeIds';
import { CommandManager } from '../utils/commandManager';
let localize = nls.loadMessageBundle();
@@ -146,10 +147,11 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
constructor(
private client: ITypeScriptServiceClient,
mode: string,
private typingsStatus: TypingsStatus
private readonly typingsStatus: TypingsStatus,
commandManager: CommandManager
) {
this.commandId = `_typescript.applyCompletionCodeAction.${mode}`;
commands.registerCommand(this.commandId, this.applyCompletionCodeAction, this);
commandManager.registerCommand(this.commandId, this.applyCompletionCodeAction, this);
}
public async provideCompletionItems(

View File

@@ -11,6 +11,7 @@ import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import { tsTextSpanToVsRange, vsRangeToTsFileRange, tsLocationToVsPosition } from '../utils/convert';
import FormattingOptionsManager from './formattingConfigurationManager';
import { CommandManager } from '../utils/commandManager';
export default class TypeScriptRefactorProvider implements CodeActionProvider {
private doRefactorCommandId: string;
@@ -19,13 +20,14 @@ export default class TypeScriptRefactorProvider implements CodeActionProvider {
constructor(
private readonly client: ITypeScriptServiceClient,
private formattingOptionsManager: FormattingOptionsManager,
mode: string
mode: string,
commandManager: CommandManager
) {
this.doRefactorCommandId = `_typescript.applyRefactoring.${mode}`;
this.selectRefactorCommandId = `_typescript.selectRefactoring.${mode}`;
commands.registerCommand(this.doRefactorCommandId, this.doRefactoring, this);
commands.registerCommand(this.selectRefactorCommandId, this.selectRefactoring, this);
commandManager.registerCommand(this.doRefactorCommandId, this.doRefactoring, this);
commandManager.registerCommand(this.selectRefactorCommandId, this.selectRefactoring, this);
}
public async provideCodeActions(

View File

@@ -36,6 +36,7 @@ import { openOrCreateConfigFile, isImplicitProjectConfigFile } from './utils/tsc
import { tsLocationToVsPosition } from './utils/convert';
import FormattingConfigurationManager from './features/formattingConfigurationManager';
import * as languageModeIds from './utils/languageModeIds';
import { CommandManager } from './utils/commandManager';
interface LanguageDescription {
id: string;
@@ -62,11 +63,14 @@ const standardLanguageDescriptions: LanguageDescription[] = [
export function activate(context: ExtensionContext): void {
const plugins = getContributedTypeScriptServerPlugins();
const commandManager = new CommandManager();
context.subscriptions.push(commandManager);
const lazyClientHost = (() => {
let clientHost: TypeScriptServiceClientHost | undefined;
return () => {
if (!clientHost) {
clientHost = new TypeScriptServiceClientHost(standardLanguageDescriptions, context.workspaceState, plugins);
clientHost = new TypeScriptServiceClientHost(standardLanguageDescriptions, context.workspaceState, plugins, commandManager);
context.subscriptions.push(clientHost);
const host = clientHost;
@@ -83,25 +87,25 @@ export function activate(context: ExtensionContext): void {
})();
context.subscriptions.push(commands.registerCommand('typescript.reloadProjects', () => {
commandManager.registerCommand('typescript.reloadProjects', () => {
lazyClientHost().reloadProjects();
}));
});
context.subscriptions.push(commands.registerCommand('javascript.reloadProjects', () => {
commandManager.registerCommand('javascript.reloadProjects', () => {
lazyClientHost().reloadProjects();
}));
});
context.subscriptions.push(commands.registerCommand('typescript.selectTypeScriptVersion', () => {
commandManager.registerCommand('typescript.selectTypeScriptVersion', () => {
lazyClientHost().serviceClient.onVersionStatusClicked();
}));
});
context.subscriptions.push(commands.registerCommand('typescript.openTsServerLog', () => {
commandManager.registerCommand('typescript.openTsServerLog', () => {
lazyClientHost().serviceClient.openTsServerLogFile();
}));
});
context.subscriptions.push(commands.registerCommand('typescript.restartTsServer', () => {
commandManager.registerCommand('typescript.restartTsServer', () => {
lazyClientHost().serviceClient.restartTsServer();
}));
});
context.subscriptions.push(new TypeScriptTaskProviderManager(() => lazyClientHost().serviceClient));
@@ -111,11 +115,11 @@ export function activate(context: ExtensionContext): void {
lazyClientHost().goToProjectConfig(isTypeScript, editor.document.uri);
}
};
context.subscriptions.push(commands.registerCommand('typescript.goToProjectConfig', goToProjectConfig.bind(null, true)));
context.subscriptions.push(commands.registerCommand('javascript.goToProjectConfig', goToProjectConfig.bind(null, false)));
commandManager.registerCommand('typescript.goToProjectConfig', goToProjectConfig.bind(null, true));
commandManager.registerCommand('javascript.goToProjectConfig', goToProjectConfig.bind(null, false));
const jsDocCompletionCommand = new TryCompleteJsDocCommand(() => lazyClientHost().serviceClient);
context.subscriptions.push(commands.registerCommand(TryCompleteJsDocCommand.COMMAND_NAME, jsDocCompletionCommand.tryCompleteJsDoc, jsDocCompletionCommand));
commandManager.registerCommand(TryCompleteJsDocCommand.COMMAND_NAME, jsDocCompletionCommand.tryCompleteJsDoc, jsDocCompletionCommand);
const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
@@ -177,7 +181,8 @@ class LanguageProvider {
constructor(
private readonly client: TypeScriptServiceClient,
private readonly description: LanguageDescription
private readonly description: LanguageDescription,
private readonly commandManager: CommandManager
) {
this.formattingOptionsManager = new FormattingConfigurationManager(client);
this.bufferSyncSupport = new BufferSyncSupport(client, description.modeIds, {
@@ -228,7 +233,7 @@ class LanguageProvider {
const selector = this.description.modeIds;
const config = workspace.getConfiguration(this.id);
const completionItemProvider = new (await import('./features/completionItemProvider')).default(client, this.description.id, this.typingsStatus);
const completionItemProvider = new (await import('./features/completionItemProvider')).default(client, this.description.id, this.typingsStatus, this.commandManager);
this.disposables.push(languages.registerCompletionItemProvider(selector, completionItemProvider, '.', '"', '\'', '/', '@'));
this.disposables.push(languages.registerCompletionItemProvider(selector, new (await import('./features/directiveCommentCompletionProvider')).default(client), '@'));
@@ -251,8 +256,8 @@ class LanguageProvider {
this.disposables.push(languages.registerDocumentSymbolProvider(selector, new (await import('./features/documentSymbolProvider')).default(client)));
this.disposables.push(languages.registerSignatureHelpProvider(selector, new (await import('./features/signatureHelpProvider')).default(client), '(', ','));
this.disposables.push(languages.registerRenameProvider(selector, new (await import('./features/renameProvider')).default(client)));
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/codeActionProvider')).default(client, this.formattingOptionsManager, this.description.id)));
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/refactorProvider')).default(client, this.formattingOptionsManager, this.description.id)));
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/codeActionProvider')).default(client, this.formattingOptionsManager, this.description.id, this.commandManager)));
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/refactorProvider')).default(client, this.formattingOptionsManager, this.description.id, this.commandManager)));
this.registerVersionDependentProviders();
for (const modeId of this.description.modeIds) {
@@ -432,7 +437,8 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
constructor(
descriptions: LanguageDescription[],
workspaceState: Memento,
plugins: TypeScriptServerPlugin[]
plugins: TypeScriptServerPlugin[],
private commandManager: CommandManager
) {
const handleProjectCreateOrDelete = () => {
this.client.execute('reloadProjects', null, false);
@@ -457,7 +463,7 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
this.languagePerId = new Map();
for (const description of descriptions) {
const manager = new LanguageProvider(this.client, description);
const manager = new LanguageProvider(this.client, description, this.commandManager);
this.languages.push(manager);
this.disposables.push(manager);
this.languagePerId.set(description.id, manager);
@@ -481,7 +487,7 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
diagnosticSource: 'ts-plugins',
isExternal: true
};
const manager = new LanguageProvider(this.client, description);
const manager = new LanguageProvider(this.client, description, this.commandManager);
this.languages.push(manager);
this.disposables.push(manager);
this.languagePerId.set(description.id, manager);

View File

@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
export interface Command {
readonly id: string;
execute(...args: any[]): void;
}
export class CommandManager {
private readonly commands: vscode.Disposable[] = [];
public dispose() {
while (this.commands.length) {
const obj = this.commands.pop();
if (obj) {
obj.dispose();
}
}
}
public registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) {
this.commands.push(vscode.commands.registerCommand(id, impl, thisArg));
}
public register(command: Command) {
this.registerCommand(command.id, command.execute, command);
}
}