Skip to content

Commit 9d2deb6

Browse files
authored
Use resolveCodeAction for organize imports (microsoft#210418)
For microsoft#210171
1 parent 4555840 commit 9d2deb6

File tree

1 file changed

+56
-57
lines changed

1 file changed

+56
-57
lines changed

extensions/typescript-language-features/src/languageFeatures/organizeImports.ts

Lines changed: 56 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,26 @@ import { conditionalRegistration, requireMinVersion, requireSomeCapability } fro
1818

1919

2020
interface OrganizeImportsCommandMetadata {
21-
readonly ids: readonly string[];
2221
readonly title: string;
2322
readonly minVersion?: API;
2423
readonly kind: vscode.CodeActionKind;
2524
readonly mode: OrganizeImportsMode;
2625
}
2726

2827
const organizeImportsCommand: OrganizeImportsCommandMetadata = {
29-
ids: ['typescript.organizeImports'],
3028
title: vscode.l10n.t("Organize Imports"),
3129
kind: vscode.CodeActionKind.SourceOrganizeImports,
3230
mode: OrganizeImportsMode.All,
3331
};
3432

3533
const sortImportsCommand: OrganizeImportsCommandMetadata = {
36-
ids: ['typescript.sortImports', 'javascript.sortImports'],
3734
minVersion: API.v430,
3835
title: vscode.l10n.t("Sort Imports"),
3936
kind: vscode.CodeActionKind.Source.append('sortImports'),
4037
mode: OrganizeImportsMode.SortAndCombine,
4138
};
4239

4340
const removeUnusedImportsCommand: OrganizeImportsCommandMetadata = {
44-
ids: ['typescript.removeUnusedImports', 'javascript.removeUnusedImports'],
4541
minVersion: API.v490,
4642
title: vscode.l10n.t("Remove Unused Imports"),
4743
kind: vscode.CodeActionKind.Source.append('removeUnusedImports'),
@@ -50,14 +46,14 @@ const removeUnusedImportsCommand: OrganizeImportsCommandMetadata = {
5046

5147
class OrganizeImportsCommand implements Command {
5248

49+
public static readonly ID = '_typescript.organizeImports';
50+
public readonly id = OrganizeImportsCommand.ID;
51+
5352
constructor(
54-
public readonly id: string,
55-
private readonly commandMetadata: OrganizeImportsCommandMetadata,
56-
private readonly client: ITypeScriptServiceClient,
5753
private readonly telemetryReporter: TelemetryReporter,
5854
) { }
5955

60-
public async execute(file?: string): Promise<any> {
56+
public async execute(): Promise<any> {
6157
/* __GDPR__
6258
"organizeImports.execute" : {
6359
"owner": "mjbvz",
@@ -67,48 +63,20 @@ class OrganizeImportsCommand implements Command {
6763
}
6864
*/
6965
this.telemetryReporter.logTelemetry('organizeImports.execute', {});
70-
if (!file) {
71-
const activeEditor = vscode.window.activeTextEditor;
72-
if (!activeEditor) {
73-
vscode.window.showErrorMessage(vscode.l10n.t("Organize Imports failed. No resource provided."));
74-
return;
75-
}
76-
77-
const resource = activeEditor.document.uri;
78-
const document = await vscode.workspace.openTextDocument(resource);
79-
const openedFiledPath = this.client.toOpenTsFilePath(document);
80-
if (!openedFiledPath) {
81-
vscode.window.showErrorMessage(vscode.l10n.t("Organize Imports failed. Unknown file type."));
82-
return;
83-
}
84-
85-
file = openedFiledPath;
86-
}
87-
88-
const args: Proto.OrganizeImportsRequestArgs = {
89-
scope: {
90-
type: 'file',
91-
args: {
92-
file
93-
}
94-
},
95-
// Deprecated in 4.9; `mode` takes priority
96-
skipDestructiveCodeActions: this.commandMetadata.mode === OrganizeImportsMode.SortAndCombine,
97-
mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(this.commandMetadata.mode),
98-
};
99-
const response = await this.client.interruptGetErr(() => this.client.execute('organizeImports', args, nulToken));
100-
if (response.type !== 'response' || !response.body) {
101-
return;
102-
}
66+
}
67+
}
10368

104-
if (response.body.length) {
105-
const edits = typeConverters.WorkspaceEdit.fromFileCodeEdits(this.client, response.body);
106-
return vscode.workspace.applyEdit(edits);
107-
}
69+
class ImportCodeAction extends vscode.CodeAction {
70+
constructor(
71+
title: string,
72+
kind: vscode.CodeActionKind,
73+
public readonly document: vscode.TextDocument,
74+
) {
75+
super(title, kind);
10876
}
10977
}
11078

111-
class ImportsCodeActionProvider implements vscode.CodeActionProvider {
79+
class ImportsCodeActionProvider implements vscode.CodeActionProvider<ImportCodeAction> {
11280

11381
constructor(
11482
private readonly client: ITypeScriptServiceClient,
@@ -117,31 +85,62 @@ class ImportsCodeActionProvider implements vscode.CodeActionProvider {
11785
private readonly fileConfigManager: FileConfigurationManager,
11886
telemetryReporter: TelemetryReporter,
11987
) {
120-
for (const id of commandMetadata.ids) {
121-
commandManager.register(new OrganizeImportsCommand(id, commandMetadata, client, telemetryReporter));
122-
}
88+
commandManager.register(new OrganizeImportsCommand(telemetryReporter));
12389
}
12490

12591
public provideCodeActions(
12692
document: vscode.TextDocument,
12793
_range: vscode.Range,
12894
context: vscode.CodeActionContext,
129-
token: vscode.CancellationToken
130-
): vscode.CodeAction[] {
95+
_token: vscode.CancellationToken
96+
): ImportCodeAction[] {
97+
if (!context.only?.contains(this.commandMetadata.kind)) {
98+
return [];
99+
}
100+
131101
const file = this.client.toOpenTsFilePath(document);
132102
if (!file) {
133103
return [];
134104
}
135105

136-
if (!context.only?.contains(this.commandMetadata.kind)) {
137-
return [];
106+
return [new ImportCodeAction(this.commandMetadata.title, this.commandMetadata.kind, document)];
107+
}
108+
109+
async resolveCodeAction(codeAction: ImportCodeAction, token: vscode.CancellationToken): Promise<ImportCodeAction | undefined> {
110+
const response = await this.client.interruptGetErr(async () => {
111+
await this.fileConfigManager.ensureConfigurationForDocument(codeAction.document, token);
112+
if (token.isCancellationRequested) {
113+
return;
114+
}
115+
116+
const file = this.client.toOpenTsFilePath(codeAction.document);
117+
if (!file) {
118+
return;
119+
}
120+
121+
const args: Proto.OrganizeImportsRequestArgs = {
122+
scope: {
123+
type: 'file',
124+
args: { file }
125+
},
126+
// Deprecated in 4.9; `mode` takes priority
127+
skipDestructiveCodeActions: this.commandMetadata.mode === OrganizeImportsMode.SortAndCombine,
128+
mode: typeConverters.OrganizeImportsMode.toProtocolOrganizeImportsMode(this.commandMetadata.mode),
129+
};
130+
131+
return this.client.execute('organizeImports', args, nulToken);
132+
});
133+
if (response?.type !== 'response' || !response.body || token.isCancellationRequested) {
134+
return;
135+
}
136+
137+
if (response.body.length) {
138+
codeAction.edit = typeConverters.WorkspaceEdit.fromFileCodeEdits(this.client, response.body);
138139
}
139140

140-
this.fileConfigManager.ensureConfigurationForDocument(document, token);
141+
codeAction.command = { command: OrganizeImportsCommand.ID, title: '', arguments: [] };
141142

142-
const action = new vscode.CodeAction(this.commandMetadata.title, this.commandMetadata.kind);
143-
action.command = { title: '', command: this.commandMetadata.ids[0], arguments: [file] };
144-
return [action];
143+
return codeAction;
145144
}
146145
}
147146

0 commit comments

Comments
 (0)