Skip to content

Commit

Permalink
Prototype auto fixable quick fixes
Browse files Browse the repository at this point in the history
Part of microsoft#62110

- Adds a new field `canAutoApply` to code actions. This field indicates that a code action can be applied without additional user input. For quick fixes, this should be set if the fix properly addresses the error

- Enable auto fixes for TS spelling errors

- Added a `editor.action.autoFix` command to triggers auto fixes at the current cursor position
  • Loading branch information
mjbvz committed Jan 17, 2019
1 parent b76ea57 commit 1904cd8
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider {

const results = new CodeActionSet();
for (const tsCodeFix of response.body) {
this.addAllFixesForTsCodeAction(results, document, file, diagnostic, tsCodeFix);
this.addAllFixesForTsCodeAction(results, document, file, diagnostic, tsCodeFix as Proto.CodeFixAction);
}
return results.values;
}
Expand All @@ -250,7 +250,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider {
document: vscode.TextDocument,
file: string,
diagnostic: vscode.Diagnostic,
tsAction: Proto.CodeAction
tsAction: Proto.CodeFixAction
): CodeActionSet {
results.addAction(this.getSingleFixForTsCodeAction(diagnostic, tsAction));
this.addFixAllForTsCodeAction(results, document, file, diagnostic, tsAction as Proto.CodeFixAction);
Expand All @@ -259,7 +259,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider {

private getSingleFixForTsCodeAction(
diagnostic: vscode.Diagnostic,
tsAction: Proto.CodeAction
tsAction: Proto.CodeFixAction
): vscode.CodeAction {
const codeAction = new vscode.CodeAction(tsAction.description, vscode.CodeActionKind.QuickFix);
codeAction.edit = getEditForCodeAction(this.client, tsAction);
Expand All @@ -269,6 +269,9 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider {
arguments: [tsAction],
title: ''
};
if (tsAction.fixName === 'spelling') {
codeAction.canAutoApply = true;
}
return codeAction;
}

Expand Down
1 change: 1 addition & 0 deletions src/vs/editor/common/modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ export interface CodeAction {
edit?: WorkspaceEdit;
diagnostics?: IMarkerData[];
kind?: string;
canAutoApply?: boolean;
}

/**
Expand Down
11 changes: 9 additions & 2 deletions src/vs/editor/contrib/codeAction/codeAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import { CodeAction, CodeActionContext, CodeActionProviderRegistry, CodeActionTr
import { IModelService } from 'vs/editor/common/services/modelService';
import { CodeActionFilter, CodeActionKind, CodeActionTrigger } from './codeActionTrigger';

export function getCodeActions(model: ITextModel, rangeOrSelection: Range | Selection, trigger?: CodeActionTrigger, token: CancellationToken = CancellationToken.None): Promise<CodeAction[]> {
export function getCodeActions(
model: ITextModel,
rangeOrSelection: Range | Selection,
trigger?: CodeActionTrigger,
token: CancellationToken = CancellationToken.None
): Promise<CodeAction[]> {
const codeActionContext: CodeActionContext = {
only: trigger && trigger.filter && trigger.filter.kind ? trigger.filter.kind.value : undefined,
trigger: trigger && trigger.type === 'manual' ? CodeActionTriggerKind.Manual : CodeActionTriggerKind.Automatic
Expand Down Expand Up @@ -65,7 +70,9 @@ export function getCodeActions(model: ITextModel, rangeOrSelection: Range | Sele
}

function isValidAction(filter: CodeActionFilter | undefined, action: CodeAction): boolean {
return action && isValidActionKind(filter, action.kind);
return action
&& isValidActionKind(filter, action.kind)
&& (filter && filter.autoFixesOnly ? !!action.canAutoApply : true);
}

function isValidActionKind(filter: CodeActionFilter | undefined, kind: string | undefined): boolean {
Expand Down
28 changes: 28 additions & 0 deletions src/vs/editor/contrib/codeAction/codeActionCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,3 +358,31 @@ export class OrganizeImportsAction extends EditorAction {
CodeActionAutoApply.IfSingle);
}
}

export class AutoFixAction extends EditorAction {

static readonly Id = 'editor.action.autoFix';

constructor() {
super({
id: AutoFixAction.Id,
label: nls.localize('autoFix.label', "Auto Fix"),
alias: 'Auto Fix',
precondition: ContextKeyExpr.and(
EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.QuickFix)),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_DOT,
weight: KeybindingWeight.EditorContrib
}
});
}

public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
return showCodeActionsForEditorSelection(editor,
nls.localize('editor.action.autoFix.noneMessage', "No auto fixes available"),
{ kind: CodeActionKind.QuickFix, autoFixesOnly: true },
CodeActionAutoApply.IfSingle);
}
}
3 changes: 2 additions & 1 deletion src/vs/editor/contrib/codeAction/codeActionContributions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
*--------------------------------------------------------------------------------------------*/

import { registerEditorAction, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { CodeActionCommand, OrganizeImportsAction, QuickFixAction, QuickFixController, RefactorAction, SourceAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
import { CodeActionCommand, OrganizeImportsAction, QuickFixAction, QuickFixController, RefactorAction, SourceAction, AutoFixAction } from 'vs/editor/contrib/codeAction/codeActionCommands';


registerEditorContribution(QuickFixController);
registerEditorAction(QuickFixAction);
registerEditorAction(RefactorAction);
registerEditorAction(SourceAction);
registerEditorAction(OrganizeImportsAction);
registerEditorAction(AutoFixAction);
registerEditorCommand(new CodeActionCommand());
1 change: 1 addition & 0 deletions src/vs/editor/contrib/codeAction/codeActionTrigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const enum CodeActionAutoApply {
export interface CodeActionFilter {
readonly kind?: CodeActionKind;
readonly includeSourceActions?: boolean;
readonly autoFixesOnly?: boolean;
}

export interface CodeActionTrigger {
Expand Down
1 change: 1 addition & 0 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4848,6 +4848,7 @@ declare namespace monaco.languages {
edit?: WorkspaceEdit;
diagnostics?: editor.IMarkerData[];
kind?: string;
canAutoApply?: boolean;
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1098,4 +1098,17 @@ declare module 'vscode' {
readonly activeSignatureHelp?: SignatureHelp;
}
//#endregion

//#region CodeAction.canAutoApply - mjbvz
export interface CodeAction {
/**
* If the action can be safely automatically applied without the user selecting it from a list.
*
* Set this on quick fixes to indicate that the fix properly addresses the underlying error.
*/
canAutoApply?: boolean;
}
//#endregion


}
1 change: 1 addition & 0 deletions src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ export interface CodeActionDto {
diagnostics?: IMarkerData[];
command?: modes.Command;
kind?: string;
canAutoApply?: boolean;
}

export interface ExtHostLanguageFeaturesShape {
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/node/extHostLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ class CodeActionAdapter {
command: candidate.command && this._commands.toInternal(candidate.command),
diagnostics: candidate.diagnostics && candidate.diagnostics.map(typeConvert.Diagnostic.from),
edit: candidate.edit && typeConvert.WorkspaceEdit.from(candidate.edit),
kind: candidate.kind && candidate.kind.value
kind: candidate.kind && candidate.kind.value,
canAutoApply: candidate.canAutoApply,
});
}
}
Expand Down

0 comments on commit 1904cd8

Please sign in to comment.