From 536e04656c97ec221be705fccd602ac2cde49577 Mon Sep 17 00:00:00 2001 From: akhera99 Date: Thu, 31 Aug 2023 16:15:19 -0700 Subject: [PATCH 1/6] wip --- src/lsptoolshost/roslynLanguageServer.ts | 27 ++++++++++++++++++++++++ src/lsptoolshost/roslynProtocol.ts | 11 ++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 6884c8650..57af273f8 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -168,6 +168,33 @@ export class RoslynLanguageServer { workspace: { configuration: (params) => readConfigurations(params), }, + resolveCodeAction: async (codeAction, token, next) => { + const lspCodeAction = codeAction; + const data = lspCodeAction.data; + if (data.FixAllFlavors) { + const result = await vscode.window.showQuickPick(data.FixAllFlavors, { + placeHolder: 'Pick a fix all scope', + }); + + if (result) { + const fixAllCodeAction: RoslynProtocol.RoslynFixAllCodeAction = { + title: lspCodeAction.title, + edit: lspCodeAction.edit, + data: data, + scope: result, + }; + + const response = await _languageServer.sendRequest( + RoslynProtocol.CodeActionFixAllResolveRequest.type, + fixAllCodeAction, + token + ); + console.log(response); + } + } else { + return await next(codeAction, token); + } + }, }, }; diff --git a/src/lsptoolshost/roslynProtocol.ts b/src/lsptoolshost/roslynProtocol.ts index ec53f7ddc..e3654e4f2 100644 --- a/src/lsptoolshost/roslynProtocol.ts +++ b/src/lsptoolshost/roslynProtocol.ts @@ -5,6 +5,7 @@ import { Command } from 'vscode'; import * as lsp from 'vscode-languageserver-protocol'; +import { CodeAction } from 'vscode-languageserver-protocol'; export interface WorkspaceDebugConfigurationParams { /** @@ -135,6 +136,10 @@ export interface BuildOnlyDiagnosticIdsResult { ids: string[]; } +export interface RoslynFixAllCodeAction extends CodeAction { + scope: string; +} + export namespace WorkspaceDebugConfigurationRequest { export const method = 'workspace/debugConfiguration'; export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer; @@ -202,3 +207,9 @@ export namespace BuildOnlyDiagnosticIdsRequest { export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer; export const type = new lsp.RequestType0(method); } + +export namespace CodeActionFixAllResolveRequest { + export const method = 'codeAction/resolveFixAll'; + export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer; + export const type = new lsp.RequestType(method); +} From e5af714e75f4d72ce40fd96c87fb9058bea047c6 Mon Sep 17 00:00:00 2001 From: akhera99 Date: Thu, 7 Sep 2023 14:10:38 -0700 Subject: [PATCH 2/6] wip --- src/lsptoolshost/roslynLanguageServer.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 9f0ee479d..e3947fae0 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -68,6 +68,7 @@ import { getDotnetInfo } from '../shared/utils/getDotnetInfo'; import { registerLanguageServerOptionChanges } from './optionChanges'; import { Observable } from 'rxjs'; import { DotnetInfo } from '../shared/utils/dotnetInfo'; +import { URIConverter, createConverter } from 'vscode-languageclient/lib/common/protocolConverter'; let _languageServer: RoslynLanguageServer; let _channel: vscode.OutputChannel; @@ -192,6 +193,19 @@ export class RoslynLanguageServer { fixAllCodeAction, token ); + + if (response.edit) { + const uriConverter: URIConverter = (value: string): vscode.Uri => + UriConverter.deserialize(value); + const protocolConverter = createConverter(uriConverter, true, true); + const result = await protocolConverter.asWorkspaceEdit(response.edit); + + if (!(await vscode.workspace.applyEdit(result))) { + throw new Error( + 'Tried to insert multiple code action edits, but an error occurred.' + ); + } + } console.log(response); } } else { From c29e0e0ebbfa041ba76a76cce81fdc85ccf7fa8f Mon Sep 17 00:00:00 2001 From: akhera99 Date: Tue, 19 Sep 2023 16:36:11 -0700 Subject: [PATCH 3/6] feedback --- l10n/bundle.l10n.json | 1 + src/lsptoolshost/fixAllCodeAction.ts | 67 ++++++++++++++++++ src/lsptoolshost/roslynLanguageServer.ts | 87 ++++++++++++------------ 3 files changed, 110 insertions(+), 45 deletions(-) create mode 100644 src/lsptoolshost/fixAllCodeAction.ts diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index e7ee67d46..7fcdd0bac 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -127,6 +127,7 @@ "Choose and set default": "Choose and set default", "Do not load any": "Do not load any", "C# configuration has changed. Would you like to reload the window to apply your changes?": "C# configuration has changed. Would you like to reload the window to apply your changes?", + "Pick a fix all scope": "Pick a fix all scope", "pipeArgs must be a string or a string array type": "pipeArgs must be a string or a string array type", "Name not defined in current configuration.": "Name not defined in current configuration.", "Configuration \"{0}\" in launch.json does not have a {1} argument with {2} for remote process listing.": "Configuration \"{0}\" in launch.json does not have a {1} argument with {2} for remote process listing.", diff --git a/src/lsptoolshost/fixAllCodeAction.ts b/src/lsptoolshost/fixAllCodeAction.ts new file mode 100644 index 000000000..c0c321ec6 --- /dev/null +++ b/src/lsptoolshost/fixAllCodeAction.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; +import * as RoslynProtocol from './roslynProtocol'; +import { LSPAny } from 'vscode-languageserver-protocol'; +import { RoslynLanguageServer } from './roslynLanguageServer'; +import { URIConverter, createConverter } from 'vscode-languageclient/lib/common/protocolConverter'; +import { UriConverter } from './uriConverter'; + +export function registerCodeActionFixAllCommands( + context: vscode.ExtensionContext, + languageServer: RoslynLanguageServer +) { + context.subscriptions.push( + vscode.commands.registerCommand( + 'roslyn.client.fixAllCodeAction', + async (request): Promise => registerFixAllResolveCodeAction(languageServer, request) + ) + ); +} + +async function registerFixAllResolveCodeAction(languageServer: RoslynLanguageServer, codeActionData: any) { + if (codeActionData) { + const data = codeActionData; + const result = await vscode.window.showQuickPick(data.FixAllFlavors, { + placeHolder: vscode.l10n.t('Pick a fix all scope'), + }); + + let fixAllEdit = new vscode.WorkspaceEdit(); + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: 'Fix All Code Action', + cancellable: true, + }, + async (_, token) => { + if (result) { + const fixAllCodeAction: RoslynProtocol.RoslynFixAllCodeAction = { + title: data.UniqueIdentifier, + data: data, + scope: result, + }; + + const response = await languageServer.sendRequest( + RoslynProtocol.CodeActionFixAllResolveRequest.type, + fixAllCodeAction, + token + ); + + if (response.edit) { + const uriConverter: URIConverter = (value: string): vscode.Uri => + UriConverter.deserialize(value); + const protocolConverter = createConverter(uriConverter, true, true); + fixAllEdit = await protocolConverter.asWorkspaceEdit(response.edit); + } + } + } + ); + + if (!(await vscode.workspace.applyEdit(fixAllEdit))) { + throw new Error('Tried to insert multiple code action edits, but an error occurred.'); + } + } +} diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 0c4059426..476cda605 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -21,7 +21,6 @@ import { RequestType0, PartialResultParams, ProtocolRequestType, - CodeAction, } from 'vscode-languageclient/node'; import { PlatformInformation } from '../shared/platform'; import { readConfigurations } from './configurationMiddleware'; @@ -46,13 +45,12 @@ import { getDotnetInfo } from '../shared/utils/getDotnetInfo'; import { registerLanguageServerOptionChanges } from './optionChanges'; import { Observable } from 'rxjs'; import { DotnetInfo } from '../shared/utils/dotnetInfo'; -import { URIConverter, createConverter } from 'vscode-languageclient/lib/common/protocolConverter'; import { RoslynLanguageServerEvents } from './languageServerEvents'; import { registerShowToastNotification } from './showToastNotification'; import { registerRazorCommands } from './razorCommands'; import { registerOnAutoInsert } from './onAutoInsert'; +import { registerCodeActionFixAllCommands } from './fixAllCodeAction'; -let _languageServer: RoslynLanguageServer; let _channel: vscode.OutputChannel; let _traceChannel: vscode.OutputChannel; @@ -205,46 +203,46 @@ export class RoslynLanguageServer { workspace: { configuration: (params) => readConfigurations(params), }, - resolveCodeAction: async (codeAction, token, next) => { - const lspCodeAction = codeAction; - const data = lspCodeAction.data; - if (data.FixAllFlavors) { - const result = await vscode.window.showQuickPick(data.FixAllFlavors, { - placeHolder: 'Pick a fix all scope', - }); - - if (result) { - const fixAllCodeAction: RoslynProtocol.RoslynFixAllCodeAction = { - title: lspCodeAction.title, - edit: lspCodeAction.edit, - data: data, - scope: result, - }; - - const response = await _languageServer.sendRequest( - RoslynProtocol.CodeActionFixAllResolveRequest.type, - fixAllCodeAction, - token - ); - - if (response.edit) { - const uriConverter: URIConverter = (value: string): vscode.Uri => - UriConverter.deserialize(value); - const protocolConverter = createConverter(uriConverter, true, true); - const result = await protocolConverter.asWorkspaceEdit(response.edit); - - if (!(await vscode.workspace.applyEdit(result))) { - throw new Error( - 'Tried to insert multiple code action edits, but an error occurred.' - ); - } - } - console.log(response); - } - } else { - return await next(codeAction, token); - } - }, + // resolveCodeAction: async (codeAction, token, next) => { + // const lspCodeAction = codeAction; + // const data = lspCodeAction.data; + // if (data.FixAllFlavors) { + // const result = await vscode.window.showQuickPick(data.FixAllFlavors, { + // placeHolder: 'Pick a fix all scope', + // }); + + // if (result) { + // const fixAllCodeAction: RoslynProtocol.RoslynFixAllCodeAction = { + // title: lspCodeAction.title, + // edit: lspCodeAction.edit, + // data: data, + // scope: result, + // }; + + // const response = await _languageServer.sendRequest( + // RoslynProtocol.CodeActionFixAllResolveRequest.type, + // fixAllCodeAction, + // token + // ); + + // if (response.edit) { + // const uriConverter: URIConverter = (value: string): vscode.Uri => + // UriConverter.deserialize(value); + // const protocolConverter = createConverter(uriConverter, true, true); + // const result = await protocolConverter.asWorkspaceEdit(response.edit); + + // if (!(await vscode.workspace.applyEdit(result))) { + // throw new Error( + // 'Tried to insert multiple code action edits, but an error occurred.' + // ); + // } + // } + // console.log(response); + // } + // } else { + // return await next(codeAction, token); + // } + // }, }, }; @@ -267,7 +265,6 @@ export class RoslynLanguageServer { languageServerEvents ); - _languageServer = server; // Start the client. This will also launch the server process. await client.start(); return server; @@ -789,7 +786,7 @@ export async function activateRoslynLanguageServer( // Register any commands that need to be handled by the extension. registerCommands(context, languageServer, optionProvider, hostExecutableResolver, _channel); - + registerCodeActionFixAllCommands(context, languageServer); registerRazorCommands(context, languageServer); registerUnitTestingCommands(context, languageServer, dotnetTestChannel); From 2f685978319b24cebf5ebd7007909933699c4ca7 Mon Sep 17 00:00:00 2001 From: akhera99 Date: Tue, 19 Sep 2023 17:29:57 -0700 Subject: [PATCH 4/6] remove comment --- src/lsptoolshost/fixAllCodeAction.ts | 2 +- src/lsptoolshost/roslynLanguageServer.ts | 40 ------------------------ 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/src/lsptoolshost/fixAllCodeAction.ts b/src/lsptoolshost/fixAllCodeAction.ts index c0c321ec6..7447b9059 100644 --- a/src/lsptoolshost/fixAllCodeAction.ts +++ b/src/lsptoolshost/fixAllCodeAction.ts @@ -33,7 +33,7 @@ async function registerFixAllResolveCodeAction(languageServer: RoslynLanguageSer await vscode.window.withProgress( { location: vscode.ProgressLocation.Notification, - title: 'Fix All Code Action', + title: vscode.l10n.t('Fix All Code Action'), cancellable: true, }, async (_, token) => { diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 476cda605..ff13f308d 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -203,46 +203,6 @@ export class RoslynLanguageServer { workspace: { configuration: (params) => readConfigurations(params), }, - // resolveCodeAction: async (codeAction, token, next) => { - // const lspCodeAction = codeAction; - // const data = lspCodeAction.data; - // if (data.FixAllFlavors) { - // const result = await vscode.window.showQuickPick(data.FixAllFlavors, { - // placeHolder: 'Pick a fix all scope', - // }); - - // if (result) { - // const fixAllCodeAction: RoslynProtocol.RoslynFixAllCodeAction = { - // title: lspCodeAction.title, - // edit: lspCodeAction.edit, - // data: data, - // scope: result, - // }; - - // const response = await _languageServer.sendRequest( - // RoslynProtocol.CodeActionFixAllResolveRequest.type, - // fixAllCodeAction, - // token - // ); - - // if (response.edit) { - // const uriConverter: URIConverter = (value: string): vscode.Uri => - // UriConverter.deserialize(value); - // const protocolConverter = createConverter(uriConverter, true, true); - // const result = await protocolConverter.asWorkspaceEdit(response.edit); - - // if (!(await vscode.workspace.applyEdit(result))) { - // throw new Error( - // 'Tried to insert multiple code action edits, but an error occurred.' - // ); - // } - // } - // console.log(response); - // } - // } else { - // return await next(codeAction, token); - // } - // }, }, }; From 6fe55e72737f831b45a184f27ecfdd7b057cf530 Mon Sep 17 00:00:00 2001 From: akhera99 Date: Tue, 19 Sep 2023 17:30:51 -0700 Subject: [PATCH 5/6] comments --- src/lsptoolshost/fixAllCodeAction.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/lsptoolshost/fixAllCodeAction.ts b/src/lsptoolshost/fixAllCodeAction.ts index 7447b9059..4b8013bbe 100644 --- a/src/lsptoolshost/fixAllCodeAction.ts +++ b/src/lsptoolshost/fixAllCodeAction.ts @@ -29,7 +29,6 @@ async function registerFixAllResolveCodeAction(languageServer: RoslynLanguageSer placeHolder: vscode.l10n.t('Pick a fix all scope'), }); - let fixAllEdit = new vscode.WorkspaceEdit(); await vscode.window.withProgress( { location: vscode.ProgressLocation.Notification, @@ -54,14 +53,13 @@ async function registerFixAllResolveCodeAction(languageServer: RoslynLanguageSer const uriConverter: URIConverter = (value: string): vscode.Uri => UriConverter.deserialize(value); const protocolConverter = createConverter(uriConverter, true, true); - fixAllEdit = await protocolConverter.asWorkspaceEdit(response.edit); + const fixAllEdit = await protocolConverter.asWorkspaceEdit(response.edit); + if (!(await vscode.workspace.applyEdit(fixAllEdit))) { + throw new Error('Tried to insert multiple code action edits, but an error occurred.'); + } } } } ); - - if (!(await vscode.workspace.applyEdit(fixAllEdit))) { - throw new Error('Tried to insert multiple code action edits, but an error occurred.'); - } } } From ee1eea2f2099b591a3f601fbb2b4aeb2784e1606 Mon Sep 17 00:00:00 2001 From: akhera99 Date: Wed, 20 Sep 2023 16:03:34 -0700 Subject: [PATCH 6/6] comments --- l10n/bundle.l10n.json | 1 + src/lsptoolshost/fixAllCodeAction.ts | 15 ++++++++++++--- src/lsptoolshost/roslynLanguageServer.ts | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 7fcdd0bac..9baff8cd5 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -128,6 +128,7 @@ "Do not load any": "Do not load any", "C# configuration has changed. Would you like to reload the window to apply your changes?": "C# configuration has changed. Would you like to reload the window to apply your changes?", "Pick a fix all scope": "Pick a fix all scope", + "Fix All Code Action": "Fix All Code Action", "pipeArgs must be a string or a string array type": "pipeArgs must be a string or a string array type", "Name not defined in current configuration.": "Name not defined in current configuration.", "Configuration \"{0}\" in launch.json does not have a {1} argument with {2} for remote process listing.": "Configuration \"{0}\" in launch.json does not have a {1} argument with {2} for remote process listing.", diff --git a/src/lsptoolshost/fixAllCodeAction.ts b/src/lsptoolshost/fixAllCodeAction.ts index 4b8013bbe..aa133d73a 100644 --- a/src/lsptoolshost/fixAllCodeAction.ts +++ b/src/lsptoolshost/fixAllCodeAction.ts @@ -12,17 +12,22 @@ import { UriConverter } from './uriConverter'; export function registerCodeActionFixAllCommands( context: vscode.ExtensionContext, - languageServer: RoslynLanguageServer + languageServer: RoslynLanguageServer, + outputChannel: vscode.OutputChannel ) { context.subscriptions.push( vscode.commands.registerCommand( 'roslyn.client.fixAllCodeAction', - async (request): Promise => registerFixAllResolveCodeAction(languageServer, request) + async (request): Promise => registerFixAllResolveCodeAction(languageServer, request, outputChannel) ) ); } -async function registerFixAllResolveCodeAction(languageServer: RoslynLanguageServer, codeActionData: any) { +async function registerFixAllResolveCodeAction( + languageServer: RoslynLanguageServer, + codeActionData: any, + outputChannel: vscode.OutputChannel +) { if (codeActionData) { const data = codeActionData; const result = await vscode.window.showQuickPick(data.FixAllFlavors, { @@ -55,6 +60,10 @@ async function registerFixAllResolveCodeAction(languageServer: RoslynLanguageSer const protocolConverter = createConverter(uriConverter, true, true); const fixAllEdit = await protocolConverter.asWorkspaceEdit(response.edit); if (!(await vscode.workspace.applyEdit(fixAllEdit))) { + const componentName = '[roslyn.client.fixAllCodeAction]'; + const errorMessage = 'Failed to make a fix all edit for completion.'; + outputChannel.show(); + outputChannel.appendLine(`${componentName} ${errorMessage}`); throw new Error('Tried to insert multiple code action edits, but an error occurred.'); } } diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index f79888735..0bdd2f593 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -805,7 +805,7 @@ export async function activateRoslynLanguageServer( // Register any commands that need to be handled by the extension. registerCommands(context, languageServer, hostExecutableResolver, _channel); - registerCodeActionFixAllCommands(context, languageServer); + registerCodeActionFixAllCommands(context, languageServer, _channel); registerRazorCommands(context, languageServer);