Move TS/JS to use organize imports codeAction instead of command (#47850)

* Move TS/JS to use organize imports code action

Fixes #47845
Fixes #46647

- Defines a new standard `SourceOrganizeImports` `CodeActionKind` to be used to implement organize imports in a consistent way.
- Add a new `Organize imports` command and keybinding that executes these actions.
- Move over the existing js/ts organize imports command to use the new code action kind

* Use supportedCodeActions context key

* Document code action kind values

* Fix regular expression

Make sure we only match whole scopes and not `unicorn.source.organizeImports`
This commit is contained in:
Matt Bierner
2018-04-18 10:51:33 -07:00
committed by GitHub
parent 6c76080362
commit 2fadb90198
11 changed files with 95 additions and 137 deletions

View File

@@ -19,7 +19,6 @@ import ManagedFileContextManager from './utils/managedFileContext';
import { lazy, Lazy } from './utils/lazy';
import * as fileSchemes from './utils/fileSchemes';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import { OrganizeImportsCommand, OrganizeImportsContextManager } from './features/organizeImports';
export function activate(
context: vscode.ExtensionContext
@@ -74,11 +73,6 @@ function createLazyClientHost(
context.subscriptions.push(clientHost);
const organizeImportsContext = new OrganizeImportsContextManager();
clientHost.serviceClient.onTsServerStarted(api => {
organizeImportsContext.onDidChangeApiVersion(api);
}, null, context.subscriptions);
clientHost.serviceClient.onReady(() => {
context.subscriptions.push(
ProjectStatus.create(
@@ -103,7 +97,6 @@ function registerCommands(
commandManager.register(new commands.RestartTsServerCommand(lazyClientHost));
commandManager.register(new commands.TypeScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new commands.JavaScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new OrganizeImportsCommand(lazyClientHost));
}
function isSupportedDocument(

View File

@@ -4,37 +4,27 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import * as Proto from '../protocol';
import { Command } from '../utils/commandManager';
import { ITypeScriptServiceClient } from '../typescriptService';
import { Command, CommandManager } from '../utils/commandManager';
import { isSupportedLanguageMode } from '../utils/languageModeIds';
import * as typeconverts from '../utils/typeConverters';
import { isSupportedLanguageMode } from '../utils/languageModeIds';
import API from '../utils/api';
import { Lazy } from '../utils/lazy';
import TypeScriptServiceClientHost from '../typeScriptServiceClientHost';
import { ITypeScriptServiceClient } from '../typescriptService';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export class OrganizeImportsCommand implements Command {
public static readonly Ids = ['javascript.organizeImports', 'typescript.organizeImports'];
class OrganizeImportsCommand implements Command {
public static readonly Id = '_typescript.organizeImports';
public readonly id = OrganizeImportsCommand.Ids;
public readonly id = OrganizeImportsCommand.Id;
constructor(
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
private readonly client: ITypeScriptServiceClient
) { }
public async execute(): Promise<boolean> {
// Don't force activation
if (!this.lazyClientHost.hasValue) {
return false;
}
const client = this.lazyClientHost.value.serviceClient;
if (!client.apiVersion.has280Features()) {
if (!this.client.apiVersion.has280Features()) {
return false;
}
@@ -43,7 +33,7 @@ export class OrganizeImportsCommand implements Command {
return false;
}
const file = client.normalizePath(editor.document.uri);
const file = this.client.normalizePath(editor.document.uri);
if (!file) {
return false;
}
@@ -56,67 +46,42 @@ export class OrganizeImportsCommand implements Command {
}
}
};
const response = await client.execute('organizeImports', args);
const response = await this.client.execute('organizeImports', args);
if (!response || !response.success) {
return false;
}
const edits = typeconverts.WorkspaceEdit.fromFromFileCodeEdits(client, response.body);
const edits = typeconverts.WorkspaceEdit.fromFromFileCodeEdits(this.client, response.body);
return await vscode.workspace.applyEdit(edits);
}
}
/**
* When clause context set when the ts version supports organize imports.
*/
const contextName = 'typescript.canOrganizeImports';
export class OrganizeImportsContextManager {
private currentValue: boolean = false;
public onDidChangeApiVersion(apiVersion: API): any {
this.updateContext(apiVersion.has280Features());
}
private updateContext(newValue: boolean) {
if (newValue === this.currentValue) {
return;
}
vscode.commands.executeCommand('setContext', contextName, newValue);
this.currentValue = newValue;
}
}
export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvider {
private static readonly organizeImportsKind = vscode.CodeActionKind.Source.append('organizeImports');
public constructor(
private readonly client: ITypeScriptServiceClient
) { }
private readonly client: ITypeScriptServiceClient,
commandManager: CommandManager
) {
commandManager.register(new OrganizeImportsCommand(client));
}
public readonly metadata: vscode.CodeActionProviderMetadata = {
providedCodeActionKinds: [OrganizeImportsCodeActionProvider.organizeImportsKind]
providedCodeActionKinds: [vscode.CodeActionKind.SourceOrganizeImports]
};
public provideCodeActions(
document: vscode.TextDocument,
_document: vscode.TextDocument,
_range: vscode.Range,
_context: vscode.CodeActionContext,
_token: vscode.CancellationToken
): vscode.CodeAction[] {
if (!isSupportedLanguageMode(document)) {
return [];
}
if (!this.client.apiVersion.has280Features()) {
return [];
}
const action = new vscode.CodeAction(localize('oraganizeImportsAction.title', "Organize Imports"), OrganizeImportsCodeActionProvider.organizeImportsKind);
action.command = { title: '', command: OrganizeImportsCommand.Ids[0] };
const action = new vscode.CodeAction(
localize('oraganizeImportsAction.title', "Organize Imports"),
vscode.CodeActionKind.SourceOrganizeImports);
action.command = { title: '', command: OrganizeImportsCommand.Id };
return [action];
}
}

View File

@@ -43,7 +43,7 @@ export default class LanguageProvider {
constructor(
private readonly client: TypeScriptServiceClient,
private readonly description: LanguageDescription,
commandManager: CommandManager,
private readonly commandManager: CommandManager,
typingsStatus: TypingsStatus
) {
this.formattingOptionsManager = new FormattingConfigurationManager(client);
@@ -123,9 +123,6 @@ export default class LanguageProvider {
const refactorProvider = new (await import('./features/refactorProvider')).default(client, this.formattingOptionsManager, commandManager);
this.disposables.push(languages.registerCodeActionsProvider(selector, refactorProvider, refactorProvider.metadata));
const organizeImportsProvider = new (await import('./features/organizeImports')).OrganizeImportsCodeActionProvider(client);
this.disposables.push(languages.registerCodeActionsProvider(selector, organizeImportsProvider, organizeImportsProvider.metadata));
await this.initFoldingProvider();
this.disposables.push(workspace.onDidChangeConfiguration(c => {
if (c.affectsConfiguration(foldingSetting)) {
@@ -247,6 +244,11 @@ export default class LanguageProvider {
if (this.client.apiVersion.has213Features()) {
this.versionDependentDisposables.push(languages.registerTypeDefinitionProvider(selector, new (await import('./features/typeDefinitionProvider')).default(this.client)));
}
if (this.client.apiVersion.has280Features()) {
const organizeImportsProvider = new (await import('./features/organizeImports')).OrganizeImportsCodeActionProvider(this.client, this.commandManager);
this.versionDependentDisposables.push(languages.registerCodeActionsProvider(selector, organizeImportsProvider, organizeImportsProvider.metadata));
}
}
public triggerAllDiagnostics(): void {