From f9943473daa142728f4794cfbc80ff76a6df6096 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 23 Sep 2022 16:30:33 -0700 Subject: [PATCH 1/6] Add `removeUnusedImports` command --- .../src/languageFeatures/organizeImports.ts | 29 ++++++++++++++----- .../src/protocol.const.ts | 6 ++++ .../src/utils/api.ts | 2 ++ .../src/utils/typeConverters.ts | 11 +++++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts index cd1aeffa823ee..1326079b909bd 100644 --- a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts +++ b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts @@ -7,6 +7,7 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { Command, CommandManager } from '../commands/commandManager'; import type * as Proto from '../protocol'; +import { OrganizeImportsMode } from '../protocol.const'; import { ClientCapability, ITypeScriptServiceClient } from '../typescriptService'; import API from '../utils/api'; import { nulToken } from '../utils/cancellation'; @@ -29,7 +30,7 @@ class OrganizeImportsCommand implements Command { private readonly telemetryReporter: TelemetryReporter, ) { } - public async execute(file: string, sortOnly = false): Promise { + public async execute(file: string, mode?: OrganizeImportsMode): Promise { /* __GDPR__ "organizeImports.execute" : { "owner": "mjbvz", @@ -47,7 +48,8 @@ class OrganizeImportsCommand implements Command { file } }, - skipDestructiveCodeActions: sortOnly, + // @ts-expect-error until 4.9 + mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(mode), }; const response = await this.client.interruptGetErr(() => this.client.execute('organizeImports', args, nulToken)); if (response.type !== 'response' || !response.body) { @@ -68,7 +70,7 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider { minVersion: API, kind: vscode.CodeActionKind, title: string, - sortOnly: boolean, + mode: OrganizeImportsMode, commandManager: CommandManager, fileConfigurationManager: FileConfigurationManager, telemetryReporter: TelemetryReporter, @@ -78,7 +80,7 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider { requireMinVersion(client, minVersion), requireSomeCapability(client, ClientCapability.Semantic), ], () => { - const provider = new ImportsCodeActionProvider(client, kind, title, sortOnly, commandManager, fileConfigurationManager, telemetryReporter); + const provider = new ImportsCodeActionProvider(client, kind, title, mode, commandManager, fileConfigurationManager, telemetryReporter); return vscode.languages.registerCodeActionsProvider(selector.semantic, provider, { providedCodeActionKinds: [kind] }); @@ -89,7 +91,7 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider { private readonly client: ITypeScriptServiceClient, private readonly kind: vscode.CodeActionKind, private readonly title: string, - private readonly sortOnly: boolean, + private readonly mode: OrganizeImportsMode, commandManager: CommandManager, private readonly fileConfigManager: FileConfigurationManager, telemetryReporter: TelemetryReporter, @@ -115,7 +117,7 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider { this.fileConfigManager.ensureConfigurationForDocument(document, token); const action = new vscode.CodeAction(this.title, this.kind); - action.command = { title: '', command: OrganizeImportsCommand.Id, arguments: [file, this.sortOnly] }; + action.command = { title: '', command: OrganizeImportsCommand.Id, arguments: [file, this.mode] }; return [action]; } } @@ -133,7 +135,7 @@ export function register( API.v280, vscode.CodeActionKind.SourceOrganizeImports, localize('organizeImportsAction.title', "Organize Imports"), - false, + OrganizeImportsMode.All, commandManager, fileConfigurationManager, telemetryReporter, @@ -144,7 +146,18 @@ export function register( API.v430, vscode.CodeActionKind.Source.append('sortImports'), localize('sortImportsAction.title', "Sort Imports"), - true, + OrganizeImportsMode.SortAndCombine, + commandManager, + fileConfigurationManager, + telemetryReporter, + selector + ), + ImportsCodeActionProvider.register( + client, + API.v490, + vscode.CodeActionKind.Source.append('removeUnusedImports'), + localize('removeUnusedImportsAction.title', "Remove Unused Imports"), + OrganizeImportsMode.RemoveUnused, commandManager, fileConfigurationManager, telemetryReporter, diff --git a/extensions/typescript-language-features/src/protocol.const.ts b/extensions/typescript-language-features/src/protocol.const.ts index 9571d1c0e63c2..deb3357e6ae30 100644 --- a/extensions/typescript-language-features/src/protocol.const.ts +++ b/extensions/typescript-language-features/src/protocol.const.ts @@ -89,3 +89,9 @@ export enum EventName { projectLoadingStart = 'projectLoadingStart', projectLoadingFinish = 'projectLoadingFinish', } + +export enum OrganizeImportsMode { + All = 'All', + SortAndCombine = 'SortAndCombine', + RemoveUnused = 'RemoveUnused', +} diff --git a/extensions/typescript-language-features/src/utils/api.ts b/extensions/typescript-language-features/src/utils/api.ts index e9e85091fa44e..4af828ed45af3 100644 --- a/extensions/typescript-language-features/src/utils/api.ts +++ b/extensions/typescript-language-features/src/utils/api.ts @@ -40,6 +40,8 @@ export default class API { public static readonly v440 = API.fromSimpleString('4.4.0'); public static readonly v460 = API.fromSimpleString('4.6.0'); public static readonly v470 = API.fromSimpleString('4.7.0'); + public static readonly v480 = API.fromSimpleString('4.8.0'); + public static readonly v490 = API.fromSimpleString('4.9.0'); public static fromVersionString(versionString: string): API { let version = semver.valid(versionString); diff --git a/extensions/typescript-language-features/src/utils/typeConverters.ts b/extensions/typescript-language-features/src/utils/typeConverters.ts index 1e81c133262d5..e776c540cf19f 100644 --- a/extensions/typescript-language-features/src/utils/typeConverters.ts +++ b/extensions/typescript-language-features/src/utils/typeConverters.ts @@ -136,3 +136,14 @@ export namespace CompletionTriggerKind { } } } + +export namespace OrganizeImportsMode { + // @ts-expect-error until 4.9 + export function toProtocolOrganizeImportsMode(mode: PConst.OrganizeImportsMode): Proto.OrganizeImportsMode { + switch (mode) { + case PConst.OrganizeImportsMode.All: return 'All'; + case PConst.OrganizeImportsMode.SortAndCombine: return 'SortAndCombine'; + case PConst.OrganizeImportsMode.RemoveUnused: return 'RemoveUnused'; + } + } +} From 34a07c5eef1c024278b952a7f4496bee643677f2 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 26 Sep 2022 09:47:07 -0700 Subject: [PATCH 2/6] Continue to send `skipDestructiveCodeActions` for older TS versions --- .../src/languageFeatures/organizeImports.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts index 1326079b909bd..b292c6e769400 100644 --- a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts +++ b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts @@ -48,6 +48,8 @@ class OrganizeImportsCommand implements Command { file } }, + // Deprecated in 4.9; `mode` takes priority + skipDestructiveCodeActions: mode === OrganizeImportsMode.SortAndCombine, // @ts-expect-error until 4.9 mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(mode), }; From 113513ecf75ed300a09f53433e2bf3e622ab871e Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 30 Sep 2022 09:47:10 -0700 Subject: [PATCH 3/6] Expose Sort Imports and Remove Unused Imports commands --- .../typescript-language-features/package.json | 36 ++++++ .../package.nls.json | 4 +- .../src/languageFeatures/organizeImports.ts | 107 +++++++++++++----- 3 files changed, 118 insertions(+), 29 deletions(-) diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index d050a4a931fcb..4223567a2e586 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -1273,6 +1273,26 @@ "command": "typescript.goToSourceDefinition", "title": "%typescript.goToSourceDefinition%", "category": "TypeScript" + }, + { + "command": "typescript.sortImports", + "title": "%typescript.sortImports%", + "category": "TypeScript" + }, + { + "command": "javascript.sortImports", + "title": "%typescript.sortImports%", + "category": "JavaScript" + }, + { + "command": "typescript.removeUnusedImports", + "title": "%typescript.removeUnusedImports%", + "category": "TypeScript" + }, + { + "command": "javascript.removeUnusedImports", + "title": "%typescript.removeUnusedImports%", + "category": "JavaScript" } ], "menus": { @@ -1328,6 +1348,22 @@ { "command": "typescript.goToSourceDefinition", "when": "tsSupportsSourceDefinition && typescript.isManagedFile" + }, + { + "command": "typescript.sortImports", + "when": "tsSupportsSortImports && editorLangId =~ /^typescript(react)?$/" + }, + { + "command": "javascript.sortImports", + "when": "tsSupportsSortImports && editorLangId =~ /^javascript(react)?$/" + }, + { + "command": "typescript.removeUnusedImports", + "when": "tsSupportsRemoveUnusedImports && editorLangId =~ /^typescript(react)?$/" + }, + { + "command": "javascript.removeUnusedImports", + "when": "tsSupportsRemoveUnusedImports && editorLangId =~ /^javascript(react)?$/" } ], "editor/context": [ diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index 49291d123ba35..1b787edebe732 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -187,7 +187,9 @@ "codeActions.refactor.rewrite.parameters.toDestructured.title": "Convert parameters to destructured object", "codeActions.refactor.rewrite.property.generateAccessors.title": "Generate accessors", "codeActions.refactor.rewrite.property.generateAccessors.description": "Generate 'get' and 'set' accessors", - "codeActions.source.organizeImports.title": "Organize imports", + "codeActions.source.organizeImports.title": "Organize Imports", + "typescript.sortImports": "Sort Imports", + "typescript.removeUnusedImports": "Remove Unused Imports", "typescript.findAllFileReferences": "Find File References", "typescript.goToSourceDefinition": "Go to Source Definition", "configuration.suggest.classMemberSnippets.enabled": "Enable/disable snippet completions for class members. Requires using TypeScript 4.5+ in the workspace", diff --git a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts index b292c6e769400..e30dc1b870b3d 100644 --- a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts +++ b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts @@ -20,17 +20,16 @@ import FileConfigurationManager from './fileConfigurationManager'; const localize = nls.loadMessageBundle(); -class OrganizeImportsCommand implements Command { - public static readonly Id = '_typescript.organizeImports'; - - public readonly id = OrganizeImportsCommand.Id; +abstract class BaseOrganizeImportsCommand implements Command { + protected abstract readonly mode: OrganizeImportsMode; constructor( + public id: string, private readonly client: ITypeScriptServiceClient, private readonly telemetryReporter: TelemetryReporter, ) { } - public async execute(file: string, mode?: OrganizeImportsMode): Promise { + public async execute(file?: string): Promise { /* __GDPR__ "organizeImports.execute" : { "owner": "mjbvz", @@ -40,6 +39,23 @@ class OrganizeImportsCommand implements Command { } */ this.telemetryReporter.logTelemetry('organizeImports.execute', {}); + if (!file) { + const activeEditor = vscode.window.activeTextEditor; + if (!activeEditor) { + vscode.window.showErrorMessage(localize('error.noResource', "Organize Imports failed. No resource provided.")); + return; + } + + const resource = activeEditor.document.uri; + const document = await vscode.workspace.openTextDocument(resource); + const openedFiledPath = this.client.toOpenedFilePath(document); + if (!openedFiledPath) { + vscode.window.showErrorMessage(localize('error.unknownFile', "Organize Imports failed. Unknown file type.")); + return; + } + + file = openedFiledPath; + } const args: Proto.OrganizeImportsRequestArgs = { scope: { @@ -49,9 +65,9 @@ class OrganizeImportsCommand implements Command { } }, // Deprecated in 4.9; `mode` takes priority - skipDestructiveCodeActions: mode === OrganizeImportsMode.SortAndCombine, + skipDestructiveCodeActions: this.mode === OrganizeImportsMode.SortAndCombine, // @ts-expect-error until 4.9 - mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(mode), + mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(this.mode), }; const response = await this.client.interruptGetErr(() => this.client.execute('organizeImports', args, nulToken)); if (response.type !== 'response' || !response.body) { @@ -65,24 +81,53 @@ class OrganizeImportsCommand implements Command { } } +class OrganizeImportsCommand extends BaseOrganizeImportsCommand { + public static readonly id = 'organizeImports'; + public static minVersion = API.v280; + public static title = localize('organizeImportsAction.title', "Organize Imports"); + public readonly mode = OrganizeImportsMode.All; +} + +class SortImportsCommand extends BaseOrganizeImportsCommand { + public static readonly id = 'sortImports'; + public static minVersion = API.v430; + public static title = localize('sortImportsAction.title', "Sort Imports"); + public readonly mode = OrganizeImportsMode.SortAndCombine; + public static context = 'tsSupportsSortImports'; +} + +class RemoveUnusedImportsCommand extends BaseOrganizeImportsCommand { + public static readonly id = 'removeUnusedImports'; + public static minVersion = API.v490; + public static title = localize('removeUnusedImportsAction.title', "Remove Unused Imports"); + public readonly mode = OrganizeImportsMode.RemoveUnused; + public static context = 'tsSupportsRemoveUnusedImports'; +} + +interface OrganizeImportsCommandClass { + readonly id: string; + readonly title: string; + readonly context?: string; + readonly minVersion: API; + new(id: string, client: ITypeScriptServiceClient, telemetryReporter: TelemetryReporter): BaseOrganizeImportsCommand; +} + class ImportsCodeActionProvider implements vscode.CodeActionProvider { static register( client: ITypeScriptServiceClient, - minVersion: API, kind: vscode.CodeActionKind, - title: string, - mode: OrganizeImportsMode, + Command: OrganizeImportsCommandClass, commandManager: CommandManager, fileConfigurationManager: FileConfigurationManager, telemetryReporter: TelemetryReporter, selector: DocumentSelector ): vscode.Disposable { return conditionalRegistration([ - requireMinVersion(client, minVersion), + requireMinVersion(client, Command.minVersion), requireSomeCapability(client, ClientCapability.Semantic), ], () => { - const provider = new ImportsCodeActionProvider(client, kind, title, mode, commandManager, fileConfigurationManager, telemetryReporter); + const provider = new ImportsCodeActionProvider(client, kind, Command, commandManager, fileConfigurationManager, telemetryReporter); return vscode.languages.registerCodeActionsProvider(selector.semantic, provider, { providedCodeActionKinds: [kind] }); @@ -92,13 +137,25 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider { public constructor( private readonly client: ITypeScriptServiceClient, private readonly kind: vscode.CodeActionKind, - private readonly title: string, - private readonly mode: OrganizeImportsMode, + private readonly Command: OrganizeImportsCommandClass, commandManager: CommandManager, private readonly fileConfigManager: FileConfigurationManager, telemetryReporter: TelemetryReporter, ) { - commandManager.register(new OrganizeImportsCommand(client, telemetryReporter)); + commandManager.register(new Command(`typescript.${Command.id}`, client, telemetryReporter)); + if (Command !== OrganizeImportsCommand) { + // The non-built-in variants have get duplicated with javascript-specific ids + // can show "JavasScript" as the category + commandManager.register(new Command(`javascript.${Command.id}`, client, telemetryReporter)); + } + + if (Command.context) { + updateContext(); + client.onTsServerStarted(() => updateContext()); + function updateContext() { + vscode.commands.executeCommand('setContext', Command.context, client.apiVersion.gte(Command.minVersion)); + } + } } public provideCodeActions( @@ -118,8 +175,8 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider { this.fileConfigManager.ensureConfigurationForDocument(document, token); - const action = new vscode.CodeAction(this.title, this.kind); - action.command = { title: '', command: OrganizeImportsCommand.Id, arguments: [file, this.mode] }; + const action = new vscode.CodeAction(this.Command.title, this.kind); + action.command = { title: '', command: this.Command.id, arguments: [file] }; return [action]; } } @@ -134,10 +191,8 @@ export function register( return vscode.Disposable.from( ImportsCodeActionProvider.register( client, - API.v280, vscode.CodeActionKind.SourceOrganizeImports, - localize('organizeImportsAction.title', "Organize Imports"), - OrganizeImportsMode.All, + OrganizeImportsCommand, commandManager, fileConfigurationManager, telemetryReporter, @@ -145,10 +200,8 @@ export function register( ), ImportsCodeActionProvider.register( client, - API.v430, - vscode.CodeActionKind.Source.append('sortImports'), - localize('sortImportsAction.title', "Sort Imports"), - OrganizeImportsMode.SortAndCombine, + vscode.CodeActionKind.Source.append(SortImportsCommand.id), + SortImportsCommand, commandManager, fileConfigurationManager, telemetryReporter, @@ -156,10 +209,8 @@ export function register( ), ImportsCodeActionProvider.register( client, - API.v490, - vscode.CodeActionKind.Source.append('removeUnusedImports'), - localize('removeUnusedImportsAction.title', "Remove Unused Imports"), - OrganizeImportsMode.RemoveUnused, + vscode.CodeActionKind.Source.append(RemoveUnusedImportsCommand.id), + RemoveUnusedImportsCommand, commandManager, fileConfigurationManager, telemetryReporter, From f5006788813591c5ec8dca1a2176d0ca9031b7d6 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 13 Oct 2022 14:24:42 -0700 Subject: [PATCH 4/6] Update localization keys --- .../src/languageFeatures/organizeImports.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts index e30dc1b870b3d..f2c2f1f75a7de 100644 --- a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts +++ b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts @@ -42,7 +42,7 @@ abstract class BaseOrganizeImportsCommand implements Command { if (!file) { const activeEditor = vscode.window.activeTextEditor; if (!activeEditor) { - vscode.window.showErrorMessage(localize('error.noResource', "Organize Imports failed. No resource provided.")); + vscode.window.showErrorMessage(localize('error.organizeImports.noResource', "Organize Imports failed. No resource provided.")); return; } @@ -50,7 +50,7 @@ abstract class BaseOrganizeImportsCommand implements Command { const document = await vscode.workspace.openTextDocument(resource); const openedFiledPath = this.client.toOpenedFilePath(document); if (!openedFiledPath) { - vscode.window.showErrorMessage(localize('error.unknownFile', "Organize Imports failed. Unknown file type.")); + vscode.window.showErrorMessage(localize('error.organizeImports.unknownFile', "Organize Imports failed. Unknown file type.")); return; } From 631da000182575fc22ce73aa925cb7e9ac6e22fa Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 17 Oct 2022 08:59:21 -0700 Subject: [PATCH 5/6] Update for 4.9 protocol --- .../src/languageFeatures/organizeImports.ts | 1 - .../src/utils/typeConverters.ts | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts index f2c2f1f75a7de..4abcabf9de217 100644 --- a/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts +++ b/extensions/typescript-language-features/src/languageFeatures/organizeImports.ts @@ -66,7 +66,6 @@ abstract class BaseOrganizeImportsCommand implements Command { }, // Deprecated in 4.9; `mode` takes priority skipDestructiveCodeActions: this.mode === OrganizeImportsMode.SortAndCombine, - // @ts-expect-error until 4.9 mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(this.mode), }; const response = await this.client.interruptGetErr(() => this.client.execute('organizeImports', args, nulToken)); diff --git a/extensions/typescript-language-features/src/utils/typeConverters.ts b/extensions/typescript-language-features/src/utils/typeConverters.ts index e776c540cf19f..b15d59371ddc1 100644 --- a/extensions/typescript-language-features/src/utils/typeConverters.ts +++ b/extensions/typescript-language-features/src/utils/typeConverters.ts @@ -8,7 +8,7 @@ */ import * as vscode from 'vscode'; -import type * as Proto from '../protocol'; +import * as Proto from '../protocol'; import * as PConst from '../protocol.const'; import { ITypeScriptServiceClient } from '../typescriptService'; @@ -138,12 +138,11 @@ export namespace CompletionTriggerKind { } export namespace OrganizeImportsMode { - // @ts-expect-error until 4.9 export function toProtocolOrganizeImportsMode(mode: PConst.OrganizeImportsMode): Proto.OrganizeImportsMode { switch (mode) { - case PConst.OrganizeImportsMode.All: return 'All'; - case PConst.OrganizeImportsMode.SortAndCombine: return 'SortAndCombine'; - case PConst.OrganizeImportsMode.RemoveUnused: return 'RemoveUnused'; + case PConst.OrganizeImportsMode.All: return Proto.OrganizeImportsMode.All; + case PConst.OrganizeImportsMode.SortAndCombine: return Proto.OrganizeImportsMode.SortAndCombine; + case PConst.OrganizeImportsMode.RemoveUnused: return Proto.OrganizeImportsMode.RemoveUnused; } } } From ebb0612564c65e9dfd777938cd370aa811446141 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 17 Oct 2022 11:24:08 -0700 Subject: [PATCH 6/6] Proto must be type only import? --- .../src/utils/typeConverters.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/typescript-language-features/src/utils/typeConverters.ts b/extensions/typescript-language-features/src/utils/typeConverters.ts index b15d59371ddc1..2574fae406475 100644 --- a/extensions/typescript-language-features/src/utils/typeConverters.ts +++ b/extensions/typescript-language-features/src/utils/typeConverters.ts @@ -8,7 +8,7 @@ */ import * as vscode from 'vscode'; -import * as Proto from '../protocol'; +import type * as Proto from '../protocol'; import * as PConst from '../protocol.const'; import { ITypeScriptServiceClient } from '../typescriptService'; @@ -140,9 +140,9 @@ export namespace CompletionTriggerKind { export namespace OrganizeImportsMode { export function toProtocolOrganizeImportsMode(mode: PConst.OrganizeImportsMode): Proto.OrganizeImportsMode { switch (mode) { - case PConst.OrganizeImportsMode.All: return Proto.OrganizeImportsMode.All; - case PConst.OrganizeImportsMode.SortAndCombine: return Proto.OrganizeImportsMode.SortAndCombine; - case PConst.OrganizeImportsMode.RemoveUnused: return Proto.OrganizeImportsMode.RemoveUnused; + case PConst.OrganizeImportsMode.All: return 'All' as Proto.OrganizeImportsMode.All; + case PConst.OrganizeImportsMode.SortAndCombine: return 'SortAndCombine' as Proto.OrganizeImportsMode.SortAndCombine; + case PConst.OrganizeImportsMode.RemoveUnused: return 'RemoveUnused' as Proto.OrganizeImportsMode.RemoveUnused; } } }