Path: blob/main/src/vs/editor/contrib/codeAction/browser/codeActionCommands.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { HierarchicalKind } from '../../../../base/common/hierarchicalKind.js';6import { IJSONSchema } from '../../../../base/common/jsonSchema.js';7import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';8import { escapeRegExpCharacters } from '../../../../base/common/strings.js';9import { ICodeEditor } from '../../../browser/editorBrowser.js';10import { EditorAction, EditorCommand, ServicesAccessor } from '../../../browser/editorExtensions.js';11import { EditorContextKeys } from '../../../common/editorContextKeys.js';12import { autoFixCommandId, codeActionCommandId, fixAllCommandId, organizeImportsCommandId, quickFixCommandId, refactorCommandId, sourceActionCommandId } from './codeAction.js';13import * as nls from '../../../../nls.js';14import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';15import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';16import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionFilter, CodeActionKind, CodeActionTriggerSource } from '../common/types.js';17import { CodeActionController } from './codeActionController.js';18import { SUPPORTED_CODE_ACTIONS } from './codeActionModel.js';1920function contextKeyForSupportedActions(kind: HierarchicalKind) {21return ContextKeyExpr.regex(22SUPPORTED_CODE_ACTIONS.keys()[0],23new RegExp('(\\s|^)' + escapeRegExpCharacters(kind.value) + '\\b'));24}2526const argsSchema: IJSONSchema = {27type: 'object',28defaultSnippets: [{ body: { kind: '' } }],29properties: {30'kind': {31type: 'string',32description: nls.localize('args.schema.kind', "Kind of the code action to run."),33},34'apply': {35type: 'string',36description: nls.localize('args.schema.apply', "Controls when the returned actions are applied."),37default: CodeActionAutoApply.IfSingle,38enum: [CodeActionAutoApply.First, CodeActionAutoApply.IfSingle, CodeActionAutoApply.Never],39enumDescriptions: [40nls.localize('args.schema.apply.first', "Always apply the first returned code action."),41nls.localize('args.schema.apply.ifSingle', "Apply the first returned code action if it is the only one."),42nls.localize('args.schema.apply.never', "Do not apply the returned code actions."),43]44},45'preferred': {46type: 'boolean',47default: false,48description: nls.localize('args.schema.preferred', "Controls if only preferred code actions should be returned."),49}50}51};5253function triggerCodeActionsForEditorSelection(54editor: ICodeEditor,55notAvailableMessage: string,56filter: CodeActionFilter | undefined,57autoApply: CodeActionAutoApply | undefined,58triggerAction: CodeActionTriggerSource = CodeActionTriggerSource.Default59): void {60if (editor.hasModel()) {61const controller = CodeActionController.get(editor);62controller?.manualTriggerAtCurrentPosition(notAvailableMessage, triggerAction, filter, autoApply);63}64}6566export class QuickFixAction extends EditorAction {6768constructor() {69super({70id: quickFixCommandId,71label: nls.localize2('quickfix.trigger.label', "Quick Fix..."),72precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),73kbOpts: {74kbExpr: EditorContextKeys.textInputFocus,75primary: KeyMod.CtrlCmd | KeyCode.Period,76weight: KeybindingWeight.EditorContrib77}78});79}8081public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {82return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), undefined, undefined, CodeActionTriggerSource.QuickFix);83}84}8586export class CodeActionCommand extends EditorCommand {8788constructor() {89super({90id: codeActionCommandId,91precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),92metadata: {93description: 'Trigger a code action',94args: [{ name: 'args', schema: argsSchema, }]95}96});97}9899public runEditorCommand(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs: any) {100const args = CodeActionCommandArgs.fromUser(userArgs, {101kind: HierarchicalKind.Empty,102apply: CodeActionAutoApply.IfSingle,103});104return triggerCodeActionsForEditorSelection(editor,105typeof userArgs?.kind === 'string'106? args.preferred107? nls.localize('editor.action.codeAction.noneMessage.preferred.kind', "No preferred code actions for '{0}' available", userArgs.kind)108: nls.localize('editor.action.codeAction.noneMessage.kind', "No code actions for '{0}' available", userArgs.kind)109: args.preferred110? nls.localize('editor.action.codeAction.noneMessage.preferred', "No preferred code actions available")111: nls.localize('editor.action.codeAction.noneMessage', "No code actions available"),112{113include: args.kind,114includeSourceActions: true,115onlyIncludePreferredActions: args.preferred,116},117args.apply);118}119}120121122export class RefactorAction extends EditorAction {123124constructor() {125super({126id: refactorCommandId,127label: nls.localize2('refactor.label', "Refactor..."),128precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),129kbOpts: {130kbExpr: EditorContextKeys.textInputFocus,131primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyR,132mac: {133primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KeyR134},135weight: KeybindingWeight.EditorContrib136},137contextMenuOpts: {138group: '1_modification',139order: 2,140when: ContextKeyExpr.and(141EditorContextKeys.writable,142contextKeyForSupportedActions(CodeActionKind.Refactor)),143},144metadata: {145description: 'Refactor...',146args: [{ name: 'args', schema: argsSchema }]147}148});149}150151public run(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs: any): void {152const args = CodeActionCommandArgs.fromUser(userArgs, {153kind: CodeActionKind.Refactor,154apply: CodeActionAutoApply.Never155});156return triggerCodeActionsForEditorSelection(editor,157typeof userArgs?.kind === 'string'158? args.preferred159? nls.localize('editor.action.refactor.noneMessage.preferred.kind', "No preferred refactorings for '{0}' available", userArgs.kind)160: nls.localize('editor.action.refactor.noneMessage.kind', "No refactorings for '{0}' available", userArgs.kind)161: args.preferred162? nls.localize('editor.action.refactor.noneMessage.preferred', "No preferred refactorings available")163: nls.localize('editor.action.refactor.noneMessage', "No refactorings available"),164{165include: CodeActionKind.Refactor.contains(args.kind) ? args.kind : HierarchicalKind.None,166onlyIncludePreferredActions: args.preferred167},168args.apply, CodeActionTriggerSource.Refactor);169}170}171172export class SourceAction extends EditorAction {173174constructor() {175super({176id: sourceActionCommandId,177label: nls.localize2('source.label', "Source Action..."),178precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),179contextMenuOpts: {180group: '1_modification',181order: 2.1,182when: ContextKeyExpr.and(183EditorContextKeys.writable,184contextKeyForSupportedActions(CodeActionKind.Source)),185},186metadata: {187description: 'Source Action...',188args: [{ name: 'args', schema: argsSchema }]189}190});191}192193public run(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs: any): void {194const args = CodeActionCommandArgs.fromUser(userArgs, {195kind: CodeActionKind.Source,196apply: CodeActionAutoApply.Never197});198return triggerCodeActionsForEditorSelection(editor,199typeof userArgs?.kind === 'string'200? args.preferred201? nls.localize('editor.action.source.noneMessage.preferred.kind', "No preferred source actions for '{0}' available", userArgs.kind)202: nls.localize('editor.action.source.noneMessage.kind', "No source actions for '{0}' available", userArgs.kind)203: args.preferred204? nls.localize('editor.action.source.noneMessage.preferred', "No preferred source actions available")205: nls.localize('editor.action.source.noneMessage', "No source actions available"),206{207include: CodeActionKind.Source.contains(args.kind) ? args.kind : HierarchicalKind.None,208includeSourceActions: true,209onlyIncludePreferredActions: args.preferred,210},211args.apply, CodeActionTriggerSource.SourceAction);212}213}214215export class OrganizeImportsAction extends EditorAction {216217constructor() {218super({219id: organizeImportsCommandId,220label: nls.localize2('organizeImports.label', "Organize Imports"),221precondition: ContextKeyExpr.and(222EditorContextKeys.writable,223contextKeyForSupportedActions(CodeActionKind.SourceOrganizeImports)),224kbOpts: {225kbExpr: EditorContextKeys.textInputFocus,226primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KeyO,227weight: KeybindingWeight.EditorContrib228},229metadata: {230description: nls.localize2('organizeImports.description', "Organize imports in the current file. Also called 'Optimize Imports' by some tools")231}232});233}234235public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {236return triggerCodeActionsForEditorSelection(editor,237nls.localize('editor.action.organize.noneMessage', "No organize imports action available"),238{ include: CodeActionKind.SourceOrganizeImports, includeSourceActions: true },239CodeActionAutoApply.IfSingle, CodeActionTriggerSource.OrganizeImports);240}241}242243export class FixAllAction extends EditorAction {244245constructor() {246super({247id: fixAllCommandId,248label: nls.localize2('fixAll.label', "Fix All"),249precondition: ContextKeyExpr.and(250EditorContextKeys.writable,251contextKeyForSupportedActions(CodeActionKind.SourceFixAll))252});253}254255public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {256return triggerCodeActionsForEditorSelection(editor,257nls.localize('fixAll.noneMessage', "No fix all action available"),258{ include: CodeActionKind.SourceFixAll, includeSourceActions: true },259CodeActionAutoApply.IfSingle, CodeActionTriggerSource.FixAll);260}261}262263export class AutoFixAction extends EditorAction {264265constructor() {266super({267id: autoFixCommandId,268label: nls.localize2('autoFix.label', "Auto Fix..."),269precondition: ContextKeyExpr.and(270EditorContextKeys.writable,271contextKeyForSupportedActions(CodeActionKind.QuickFix)),272kbOpts: {273kbExpr: EditorContextKeys.textInputFocus,274primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Period,275mac: {276primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Period277},278weight: KeybindingWeight.EditorContrib279}280});281}282283public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {284return triggerCodeActionsForEditorSelection(editor,285nls.localize('editor.action.autoFix.noneMessage', "No auto fixes available"),286{287include: CodeActionKind.QuickFix,288onlyIncludePreferredActions: true289},290CodeActionAutoApply.IfSingle, CodeActionTriggerSource.AutoFix);291}292}293294295