Skip to content

Commit 1d7163f

Browse files
authored
Add support for SnippetTextEdit in code actions (#3730)
- Add snippetEditSupport extended client capability from JDT-LS - Handle possible code action conversion (LSP to VS Code) in middleware.resolveCodeAction
1 parent e3bc9b5 commit 1d7163f

File tree

1 file changed

+57
-5
lines changed

1 file changed

+57
-5
lines changed

src/extension.ts

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import * as fse from 'fs-extra';
66
import * as os from 'os';
77
import * as path from 'path';
88
import * as semver from 'semver';
9-
import { CodeActionContext, commands, CompletionItem, ConfigurationTarget, Diagnostic, env, EventEmitter, ExtensionContext, extensions, IndentAction, InputBoxOptions, languages, MarkdownString, QuickPickItemKind, RelativePattern, TextDocument, TextEditorRevealType, UIKind, Uri, ViewColumn, window, workspace, WorkspaceConfiguration } from 'vscode';
10-
import { CancellationToken, CodeActionParams, CodeActionRequest, Command, CompletionRequest, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient';
9+
import { CodeActionContext, commands, CompletionItem, ConfigurationTarget, Diagnostic, env, EventEmitter, ExtensionContext, extensions, IndentAction, InputBoxOptions, languages, MarkdownString, QuickPickItemKind, Range, RelativePattern, SnippetString, SnippetTextEdit, TextDocument, TextEditorRevealType, UIKind, Uri, ViewColumn, window, workspace, WorkspaceConfiguration, WorkspaceEdit } from 'vscode';
10+
import { CancellationToken, CodeActionParams, CodeActionRequest, CodeActionResolveRequest, Command, CompletionRequest, DidChangeConfigurationNotification, ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient';
1111
import { LanguageClient } from 'vscode-languageclient/node';
1212
import { apiManager } from './apiManager';
1313
import { ClientErrorHandler } from './clientErrorHandler';
@@ -235,6 +235,7 @@ export async function activate(context: ExtensionContext): Promise<ExtensionAPI>
235235
extractInterfaceSupport: true,
236236
advancedUpgradeGradleSupport: true,
237237
executeClientCommandSupport: true,
238+
snippetEditSupport: true,
238239
},
239240
triggerFiles,
240241
},
@@ -303,7 +304,60 @@ export async function activate(context: ExtensionContext): Promise<ExtensionAPI>
303304
}, (error) => {
304305
return client.handleFailedRequest(CodeActionRequest.type, token, error, []);
305306
});
306-
}
307+
},
308+
309+
resolveCodeAction: async (item, token, next) => {
310+
const client: LanguageClient = standardClient.getClient();
311+
const documentUris = [];
312+
const snippetEdits = [];
313+
const resolveCodeAction = async (item, token) => {
314+
return client.sendRequest(CodeActionResolveRequest.type, client.code2ProtocolConverter.asCodeActionSync(item), token).then(async (result) => {
315+
if (token.isCancellationRequested) {
316+
return item;
317+
}
318+
const docChanges = result.edit !== undefined ? result.edit.documentChanges : undefined;
319+
if (docChanges !== undefined) {
320+
for (const docChange of docChanges) {
321+
if ("textDocument" in docChange) {
322+
for (const edit of docChange.edits) {
323+
if ("snippet" in edit) {
324+
documentUris.push(docChange.textDocument.uri);
325+
snippetEdits.push(new SnippetTextEdit(client.protocol2CodeConverter.asRange((edit as any).range), new SnippetString((edit as any).snippet.value)));
326+
}
327+
}
328+
}
329+
}
330+
const codeAction = await client.protocol2CodeConverter.asCodeAction(result, token);
331+
const docEdits = codeAction.edit !== undefined? codeAction.edit.entries() : [];
332+
for (const docEdit of docEdits) {
333+
const uri = docEdit[0];
334+
if (documentUris.includes(uri.toString())) {
335+
const editList = [];
336+
for (const edit of docEdit[1]) {
337+
let isSnippet = false;
338+
snippetEdits.forEach((snippet, index) => {
339+
if (edit.range.isEqual(snippet.range) && documentUris[index] === uri.toString()) {
340+
editList.push(snippet);
341+
isSnippet = true;
342+
}
343+
});
344+
if (!isSnippet) {
345+
editList.push(edit);
346+
}
347+
}
348+
codeAction.edit.set(uri, null);
349+
codeAction.edit.set(uri, editList);
350+
}
351+
}
352+
return codeAction;
353+
}
354+
return await client.protocol2CodeConverter.asCodeAction(result, token);
355+
}, (error) => {
356+
return client.handleFailedRequest(CodeActionResolveRequest.type, token, error, item);
357+
});
358+
};
359+
return resolveCodeAction(item, token);
360+
},
307361
},
308362
revealOutputChannelOn: RevealOutputChannelOn.Never,
309363
errorHandler: new ClientErrorHandler(extensionName),
@@ -1189,5 +1243,3 @@ function registerRestartJavaLanguageServerCommand(context: ExtensionContext) {
11891243
}
11901244
}));
11911245
}
1192-
1193-

0 commit comments

Comments
 (0)