Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/codeAction/browser/codeActionCommands.ts
5226 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { HierarchicalKind } from '../../../../base/common/hierarchicalKind.js';
7
import { IJSONSchema, TypeFromJsonSchema } from '../../../../base/common/jsonSchema.js';
8
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
9
import { escapeRegExpCharacters } from '../../../../base/common/strings.js';
10
import { ICodeEditor } from '../../../browser/editorBrowser.js';
11
import { EditorAction, EditorAction2, EditorCommand, ServicesAccessor } from '../../../browser/editorExtensions.js';
12
import { EditorContextKeys } from '../../../common/editorContextKeys.js';
13
import { autoFixCommandId, codeActionCommandId, fixAllCommandId, organizeImportsCommandId, quickFixCommandId, refactorCommandId, sourceActionCommandId } from './codeAction.js';
14
import * as nls from '../../../../nls.js';
15
import { MenuId } from '../../../../platform/actions/common/actions.js';
16
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
17
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
18
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionFilter, CodeActionKind, CodeActionTriggerSource } from '../common/types.js';
19
import { CodeActionController } from './codeActionController.js';
20
import { SUPPORTED_CODE_ACTIONS } from './codeActionModel.js';
21
import { Codicon } from '../../../../base/common/codicons.js';
22
23
function contextKeyForSupportedActions(kind: HierarchicalKind) {
24
return ContextKeyExpr.regex(
25
SUPPORTED_CODE_ACTIONS.keys()[0],
26
new RegExp('(\\s|^)' + escapeRegExpCharacters(kind.value) + '\\b'));
27
}
28
29
const argsSchema = {
30
type: 'object',
31
defaultSnippets: [{ body: { kind: '' } }],
32
properties: {
33
'kind': {
34
type: 'string',
35
description: nls.localize('args.schema.kind', "Kind of the code action to run."),
36
},
37
'apply': {
38
type: 'string',
39
description: nls.localize('args.schema.apply', "Controls when the returned actions are applied."),
40
default: CodeActionAutoApply.IfSingle,
41
enum: [CodeActionAutoApply.First, CodeActionAutoApply.IfSingle, CodeActionAutoApply.Never],
42
enumDescriptions: [
43
nls.localize('args.schema.apply.first', "Always apply the first returned code action."),
44
nls.localize('args.schema.apply.ifSingle', "Apply the first returned code action if it is the only one."),
45
nls.localize('args.schema.apply.never', "Do not apply the returned code actions."),
46
]
47
},
48
'preferred': {
49
type: 'boolean',
50
default: false,
51
description: nls.localize('args.schema.preferred', "Controls if only preferred code actions should be returned."),
52
}
53
}
54
} as const satisfies IJSONSchema;
55
56
function triggerCodeActionsForEditorSelection(
57
editor: ICodeEditor,
58
notAvailableMessage: string,
59
filter: CodeActionFilter | undefined,
60
autoApply: CodeActionAutoApply | undefined,
61
triggerAction: CodeActionTriggerSource = CodeActionTriggerSource.Default
62
): void {
63
if (editor.hasModel()) {
64
const controller = CodeActionController.get(editor);
65
controller?.manualTriggerAtCurrentPosition(notAvailableMessage, triggerAction, filter, autoApply);
66
}
67
}
68
69
export class QuickFixAction extends EditorAction2 {
70
71
constructor() {
72
super({
73
id: quickFixCommandId,
74
title: nls.localize2('quickfix.trigger.label', "Quick Fix..."),
75
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
76
icon: Codicon.lightBulb,
77
f1: true,
78
keybinding: {
79
when: EditorContextKeys.textInputFocus,
80
primary: KeyMod.CtrlCmd | KeyCode.Period,
81
weight: KeybindingWeight.EditorContrib
82
},
83
menu: {
84
id: MenuId.InlineChatEditorAffordance,
85
group: '0_quickfix',
86
order: 0,
87
when: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider)
88
}
89
});
90
}
91
92
override runEditorCommand(_accessor: ServicesAccessor, editor: ICodeEditor): void {
93
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), undefined, undefined, CodeActionTriggerSource.QuickFix);
94
}
95
}
96
97
export class CodeActionCommand extends EditorCommand {
98
99
constructor() {
100
super({
101
id: codeActionCommandId,
102
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
103
metadata: {
104
description: 'Trigger a code action',
105
args: [{ name: 'args', schema: argsSchema, }]
106
}
107
});
108
}
109
110
public runEditorCommand(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs?: TypeFromJsonSchema<typeof argsSchema>): void {
111
const args = CodeActionCommandArgs.fromUser(userArgs, {
112
kind: HierarchicalKind.Empty,
113
apply: CodeActionAutoApply.IfSingle,
114
});
115
return triggerCodeActionsForEditorSelection(editor,
116
typeof userArgs?.kind === 'string'
117
? args.preferred
118
? nls.localize('editor.action.codeAction.noneMessage.preferred.kind', "No preferred code actions for '{0}' available", userArgs.kind)
119
: nls.localize('editor.action.codeAction.noneMessage.kind', "No code actions for '{0}' available", userArgs.kind)
120
: args.preferred
121
? nls.localize('editor.action.codeAction.noneMessage.preferred', "No preferred code actions available")
122
: nls.localize('editor.action.codeAction.noneMessage', "No code actions available"),
123
{
124
include: args.kind,
125
includeSourceActions: true,
126
onlyIncludePreferredActions: args.preferred,
127
},
128
args.apply);
129
}
130
}
131
132
133
export class RefactorAction extends EditorAction {
134
135
constructor() {
136
super({
137
id: refactorCommandId,
138
label: nls.localize2('refactor.label', "Refactor..."),
139
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
140
kbOpts: {
141
kbExpr: EditorContextKeys.textInputFocus,
142
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyR,
143
mac: {
144
primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KeyR
145
},
146
weight: KeybindingWeight.EditorContrib
147
},
148
contextMenuOpts: {
149
group: '1_modification',
150
order: 2,
151
when: ContextKeyExpr.and(
152
EditorContextKeys.writable,
153
contextKeyForSupportedActions(CodeActionKind.Refactor)),
154
},
155
metadata: {
156
description: 'Refactor...',
157
args: [{ name: 'args', schema: argsSchema }]
158
}
159
});
160
}
161
162
public run(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs?: TypeFromJsonSchema<typeof argsSchema>): void {
163
const args = CodeActionCommandArgs.fromUser(userArgs, {
164
kind: CodeActionKind.Refactor,
165
apply: CodeActionAutoApply.Never
166
});
167
return triggerCodeActionsForEditorSelection(editor,
168
typeof userArgs?.kind === 'string'
169
? args.preferred
170
? nls.localize('editor.action.refactor.noneMessage.preferred.kind', "No preferred refactorings for '{0}' available", userArgs.kind)
171
: nls.localize('editor.action.refactor.noneMessage.kind', "No refactorings for '{0}' available", userArgs.kind)
172
: args.preferred
173
? nls.localize('editor.action.refactor.noneMessage.preferred', "No preferred refactorings available")
174
: nls.localize('editor.action.refactor.noneMessage', "No refactorings available"),
175
{
176
include: CodeActionKind.Refactor.contains(args.kind) ? args.kind : HierarchicalKind.None,
177
onlyIncludePreferredActions: args.preferred
178
},
179
args.apply, CodeActionTriggerSource.Refactor);
180
}
181
}
182
183
export class SourceAction extends EditorAction {
184
185
constructor() {
186
super({
187
id: sourceActionCommandId,
188
label: nls.localize2('source.label', "Source Action..."),
189
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
190
contextMenuOpts: {
191
group: '1_modification',
192
order: 2.1,
193
when: ContextKeyExpr.and(
194
EditorContextKeys.writable,
195
contextKeyForSupportedActions(CodeActionKind.Source)),
196
},
197
metadata: {
198
description: 'Source Action...',
199
args: [{ name: 'args', schema: argsSchema }]
200
}
201
});
202
}
203
204
public run(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs?: TypeFromJsonSchema<typeof argsSchema>): void {
205
const args = CodeActionCommandArgs.fromUser(userArgs, {
206
kind: CodeActionKind.Source,
207
apply: CodeActionAutoApply.Never
208
});
209
return triggerCodeActionsForEditorSelection(editor,
210
typeof userArgs?.kind === 'string'
211
? args.preferred
212
? nls.localize('editor.action.source.noneMessage.preferred.kind', "No preferred source actions for '{0}' available", userArgs.kind)
213
: nls.localize('editor.action.source.noneMessage.kind', "No source actions for '{0}' available", userArgs.kind)
214
: args.preferred
215
? nls.localize('editor.action.source.noneMessage.preferred', "No preferred source actions available")
216
: nls.localize('editor.action.source.noneMessage', "No source actions available"),
217
{
218
include: CodeActionKind.Source.contains(args.kind) ? args.kind : HierarchicalKind.None,
219
includeSourceActions: true,
220
onlyIncludePreferredActions: args.preferred,
221
},
222
args.apply, CodeActionTriggerSource.SourceAction);
223
}
224
}
225
226
export class OrganizeImportsAction extends EditorAction {
227
228
constructor() {
229
super({
230
id: organizeImportsCommandId,
231
label: nls.localize2('organizeImports.label', "Organize Imports"),
232
precondition: ContextKeyExpr.and(
233
EditorContextKeys.writable,
234
contextKeyForSupportedActions(CodeActionKind.SourceOrganizeImports)),
235
kbOpts: {
236
kbExpr: EditorContextKeys.textInputFocus,
237
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KeyO,
238
weight: KeybindingWeight.EditorContrib
239
},
240
metadata: {
241
description: nls.localize2('organizeImports.description', "Organize imports in the current file. Also called 'Optimize Imports' by some tools")
242
}
243
});
244
}
245
246
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
247
return triggerCodeActionsForEditorSelection(editor,
248
nls.localize('editor.action.organize.noneMessage', "No organize imports action available"),
249
{ include: CodeActionKind.SourceOrganizeImports, includeSourceActions: true },
250
CodeActionAutoApply.IfSingle, CodeActionTriggerSource.OrganizeImports);
251
}
252
}
253
254
export class FixAllAction extends EditorAction {
255
256
constructor() {
257
super({
258
id: fixAllCommandId,
259
label: nls.localize2('fixAll.label', "Fix All"),
260
precondition: ContextKeyExpr.and(
261
EditorContextKeys.writable,
262
contextKeyForSupportedActions(CodeActionKind.SourceFixAll))
263
});
264
}
265
266
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
267
return triggerCodeActionsForEditorSelection(editor,
268
nls.localize('fixAll.noneMessage', "No fix all action available"),
269
{ include: CodeActionKind.SourceFixAll, includeSourceActions: true },
270
CodeActionAutoApply.IfSingle, CodeActionTriggerSource.FixAll);
271
}
272
}
273
274
export class AutoFixAction extends EditorAction {
275
276
constructor() {
277
super({
278
id: autoFixCommandId,
279
label: nls.localize2('autoFix.label', "Auto Fix..."),
280
precondition: ContextKeyExpr.and(
281
EditorContextKeys.writable,
282
contextKeyForSupportedActions(CodeActionKind.QuickFix)),
283
kbOpts: {
284
kbExpr: EditorContextKeys.textInputFocus,
285
primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Period,
286
mac: {
287
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Period
288
},
289
weight: KeybindingWeight.EditorContrib
290
}
291
});
292
}
293
294
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
295
return triggerCodeActionsForEditorSelection(editor,
296
nls.localize('editor.action.autoFix.noneMessage', "No auto fixes available"),
297
{
298
include: CodeActionKind.QuickFix,
299
onlyIncludePreferredActions: true
300
},
301
CodeActionAutoApply.IfSingle, CodeActionTriggerSource.AutoFix);
302
}
303
}
304
305