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