Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Actions - Add fix all support #6310

Merged
merged 10 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@
"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",
"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.",
Expand Down
74 changes: 74 additions & 0 deletions src/lsptoolshost/fixAllCodeAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------------------------
* 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,
outputChannel: vscode.OutputChannel
) {
context.subscriptions.push(
vscode.commands.registerCommand(
'roslyn.client.fixAllCodeAction',
async (request): Promise<void> => registerFixAllResolveCodeAction(languageServer, request, outputChannel)
)
);
}

async function registerFixAllResolveCodeAction(
languageServer: RoslynLanguageServer,
codeActionData: any,
outputChannel: vscode.OutputChannel
) {
if (codeActionData) {
const data = <LSPAny>codeActionData;
const result = await vscode.window.showQuickPick(data.FixAllFlavors, {
placeHolder: vscode.l10n.t('Pick a fix all scope'),
});

await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: vscode.l10n.t('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);
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.');
}
}
}
}
);
}
}
3 changes: 3 additions & 0 deletions src/lsptoolshost/roslynLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { RoslynLanguageServerEvents } from './languageServerEvents';
import { registerShowToastNotification } from './showToastNotification';
import { registerRazorCommands } from './razorCommands';
import { registerOnAutoInsert } from './onAutoInsert';
import { registerCodeActionFixAllCommands } from './fixAllCodeAction';
import { commonOptions, languageServerOptions, omnisharpOptions } from '../shared/options';
import { NamedPipeInformation } from './roslynProtocol';
import { IDisposable } from '../disposable';
Expand Down Expand Up @@ -862,6 +863,8 @@ export async function activateRoslynLanguageServer(
// Register any commands that need to be handled by the extension.
registerCommands(context, languageServer, hostExecutableResolver, _channel);

registerCodeActionFixAllCommands(context, languageServer, _channel);

registerRazorCommands(context, languageServer);

registerUnitTestingCommands(context, languageServer, dotnetTestChannel);
Expand Down
11 changes: 11 additions & 0 deletions src/lsptoolshost/roslynProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { Command } from 'vscode';
import * as lsp from 'vscode-languageserver-protocol';
import { CodeAction } from 'vscode-languageserver-protocol';
import { ProjectConfigurationMessage } from '../shared/projectConfiguration';

export interface WorkspaceDebugConfigurationParams {
Expand Down Expand Up @@ -141,6 +142,10 @@ export interface BuildOnlyDiagnosticIdsResult {
ids: string[];
}

export interface RoslynFixAllCodeAction extends CodeAction {
scope: string;
}

export interface NamedPipeInformation {
pipeName: string;
}
Expand Down Expand Up @@ -218,3 +223,9 @@ export namespace BuildOnlyDiagnosticIdsRequest {
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.RequestType0<BuildOnlyDiagnosticIdsResult, void>(method);
}

export namespace CodeActionFixAllResolveRequest {
export const method = 'codeAction/resolveFixAll';
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.RequestType<RoslynFixAllCodeAction, RoslynFixAllCodeAction, void>(method);
}
Loading