Skip to content

Commit 50a85fa

Browse files
committed
Working on re-structuring code action logic:
- The oracle should only handle triggering - The model should manage code action requests - The controller should handle presenting data from the model
1 parent 729943d commit 50a85fa

5 files changed

Lines changed: 128 additions & 112 deletions

File tree

src/vs/editor/contrib/codeAction/codeActionCommands.ts

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { CancelablePromise } from 'vs/base/common/async';
76
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
87
import { Disposable, dispose } from 'vs/base/common/lifecycle';
98
import { escapeRegExpCharacters } from 'vs/base/common/strings';
@@ -22,7 +21,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
2221
import { IMarkerService } from 'vs/platform/markers/common/markers';
2322
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
2423
import { CodeActionModel, SUPPORTED_CODE_ACTIONS, CodeActionsState } from './codeActionModel';
25-
import { CodeActionAutoApply, CodeActionFilter, CodeActionKind } from './codeActionTrigger';
24+
import { CodeActionAutoApply, CodeActionFilter, CodeActionKind, CodeActionTrigger } from './codeActionTrigger';
2625
import { CodeActionWidget } from './codeActionWidget';
2726
import { LightBulbWidget } from './lightBulbWidget';
2827
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -49,8 +48,6 @@ export class QuickFixController extends Disposable implements IEditorContributio
4948
private readonly _lightBulbWidget: LightBulbWidget;
5049
private _currentCodeActions: CodeActionSet | undefined;
5150

52-
private _activeRequest: CancelablePromise<CodeActionSet> | undefined;
53-
5451
constructor(
5552
editor: ICodeEditor,
5653
@IMarkerService markerService: IMarkerService,
@@ -68,9 +65,10 @@ export class QuickFixController extends Disposable implements IEditorContributio
6865
this._codeActionWidget = new CodeActionWidget(editor, contextMenuService, {
6966
onSelectCodeAction: async (action) => {
7067
try {
71-
await this._onApplyCodeAction(action);
68+
await this._applyCodeAction(action);
7269
} finally {
73-
this._model.trigger({ type: 'auto', filter: {} });
70+
// Retrigger
71+
this._trigger({ type: 'auto', filter: {} });
7472
}
7573
}
7674
});
@@ -79,7 +77,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
7977
this._updateLightBulbTitle();
8078

8179
this._register(this._lightBulbWidget.onClick(this._handleLightBulbSelect, this));
82-
this._register(this._model.onDidChangeState(e => this._onDidChangeCodeActionsState(e)));
80+
this._register(this._model.onDidChangeState((newState) => this._onDidChangeCodeActionsState(newState)));
8381
this._register(this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this));
8482
}
8583

@@ -89,26 +87,23 @@ export class QuickFixController extends Disposable implements IEditorContributio
8987
}
9088

9189
private _onDidChangeCodeActionsState(newState: CodeActionsState.State): void {
92-
if (this._activeRequest) {
93-
this._activeRequest.cancel();
94-
this._activeRequest = undefined;
95-
}
96-
9790
if (newState.type === CodeActionsState.Type.Triggered) {
98-
this._activeRequest = newState.actions;
99-
10091
newState.actions.then(actions => {
10192
dispose(this._currentCodeActions);
10293
this._currentCodeActions = actions;
94+
95+
if (!actions.actions.length && newState.trigger.context) {
96+
MessageController.get(this._editor).showMessage(newState.trigger.context.notAvailableMessage, newState.trigger.context.position);
97+
}
10398
});
10499

105100
if (newState.trigger.filter && newState.trigger.filter.kind) {
106101
// Triggered for specific scope
107-
newState.actions.then(fixes => {
108-
if (fixes.actions.length > 0) {
102+
newState.actions.then(codeActions => {
103+
if (codeActions.actions.length > 0) {
109104
// Apply if we only have one action or requested autoApply
110-
if (newState.trigger.autoApply === CodeActionAutoApply.First || (newState.trigger.autoApply === CodeActionAutoApply.IfSingle && fixes.actions.length === 1)) {
111-
this._onApplyCodeAction(fixes.actions[0]);
105+
if (newState.trigger.autoApply === CodeActionAutoApply.First || (newState.trigger.autoApply === CodeActionAutoApply.IfSingle && codeActions.actions.length === 1)) {
106+
this._applyCodeAction(codeActions.actions[0]);
112107
return;
113108
}
114109
}
@@ -138,12 +133,26 @@ export class QuickFixController extends Disposable implements IEditorContributio
138133
return QuickFixController.ID;
139134
}
140135

141-
private _handleLightBulbSelect(e: { x: number, y: number, state: CodeActionsState.Triggered }): void {
142-
this._codeActionWidget.show(e.state.actions, e);
136+
public triggerForCurrentSelection(
137+
notAvailableMessage: string,
138+
filter?: CodeActionFilter,
139+
autoApply?: CodeActionAutoApply
140+
): void {
141+
if (!this._editor.hasModel()) {
142+
return;
143+
}
144+
145+
MessageController.get(this._editor).closeMessage();
146+
const triggerPosition = this._editor.getPosition();
147+
this._trigger({ type: 'manual', filter, autoApply, context: { notAvailableMessage, position: triggerPosition } });
143148
}
144149

145-
public triggerFromEditorSelection(filter?: CodeActionFilter, autoApply?: CodeActionAutoApply): Promise<CodeActionSet | undefined> {
146-
return this._model.trigger({ type: 'manual', filter, autoApply });
150+
private _trigger(trigger: CodeActionTrigger) {
151+
return this._model.trigger(trigger);
152+
}
153+
154+
private _handleLightBulbSelect(e: { x: number, y: number, state: CodeActionsState.Triggered }): void {
155+
this._codeActionWidget.show(e.state.actions, e);
147156
}
148157

149158
private _updateLightBulbTitle(): void {
@@ -157,7 +166,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
157166
this._lightBulbWidget.title = title;
158167
}
159168

160-
private _onApplyCodeAction(action: CodeAction): Promise<void> {
169+
private _applyCodeAction(action: CodeAction): Promise<void> {
161170
return applyCodeAction(action, this._bulkEditService, this._commandService, this._editor);
162171
}
163172
}
@@ -176,28 +185,18 @@ export async function applyCodeAction(
176185
}
177186
}
178187

179-
function showCodeActionsForEditorSelection(
188+
function triggerCodeActionsForEditorSelection(
180189
editor: ICodeEditor,
181190
notAvailableMessage: string,
182-
filter?: CodeActionFilter,
183-
autoApply?: CodeActionAutoApply
184-
) {
185-
if (!editor.hasModel()) {
186-
return;
187-
}
188-
189-
const controller = QuickFixController.get(editor);
190-
if (!controller) {
191-
return;
192-
}
193-
194-
MessageController.get(editor).closeMessage();
195-
const pos = editor.getPosition();
196-
controller.triggerFromEditorSelection(filter, autoApply).then(codeActions => {
197-
if (!codeActions || !codeActions.actions.length) {
198-
MessageController.get(editor).showMessage(notAvailableMessage, pos);
191+
filter: CodeActionFilter | undefined,
192+
autoApply: CodeActionAutoApply | undefined
193+
): void {
194+
if (editor.hasModel()) {
195+
const controller = QuickFixController.get(editor);
196+
if (controller) {
197+
controller.triggerForCurrentSelection(notAvailableMessage, filter, autoApply);
199198
}
200-
});
199+
}
201200
}
202201

203202
export class QuickFixAction extends EditorAction {
@@ -219,7 +218,7 @@ export class QuickFixAction extends EditorAction {
219218
}
220219

221220
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
222-
return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"));
221+
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), undefined, undefined);
223222
}
224223
}
225224

@@ -299,7 +298,7 @@ export class CodeActionCommand extends EditorCommand {
299298
kind: CodeActionKind.Empty,
300299
apply: CodeActionAutoApply.IfSingle,
301300
});
302-
return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"),
301+
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"),
303302
{
304303
kind: args.kind,
305304
includeSourceActions: true,
@@ -362,7 +361,7 @@ export class RefactorAction extends EditorAction {
362361
kind: CodeActionKind.Refactor,
363362
apply: CodeActionAutoApply.Never
364363
});
365-
return showCodeActionsForEditorSelection(editor,
364+
return triggerCodeActionsForEditorSelection(editor,
366365
nls.localize('editor.action.refactor.noneMessage', "No refactorings available"),
367366
{
368367
kind: CodeActionKind.Refactor.contains(args.kind) ? args.kind : CodeActionKind.Empty,
@@ -417,7 +416,7 @@ export class SourceAction extends EditorAction {
417416
kind: CodeActionKind.Source,
418417
apply: CodeActionAutoApply.Never
419418
});
420-
return showCodeActionsForEditorSelection(editor,
419+
return triggerCodeActionsForEditorSelection(editor,
421420
nls.localize('editor.action.source.noneMessage', "No source actions available"),
422421
{
423422
kind: CodeActionKind.Source.contains(args.kind) ? args.kind : CodeActionKind.Empty,
@@ -449,7 +448,7 @@ export class OrganizeImportsAction extends EditorAction {
449448
}
450449

451450
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
452-
return showCodeActionsForEditorSelection(editor,
451+
return triggerCodeActionsForEditorSelection(editor,
453452
nls.localize('editor.action.organize.noneMessage', "No organize imports action available"),
454453
{ kind: CodeActionKind.SourceOrganizeImports, includeSourceActions: true },
455454
CodeActionAutoApply.IfSingle);
@@ -472,7 +471,7 @@ export class FixAllAction extends EditorAction {
472471
}
473472

474473
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
475-
return showCodeActionsForEditorSelection(editor,
474+
return triggerCodeActionsForEditorSelection(editor,
476475
nls.localize('fixAll.noneMessage', "No fix all action available"),
477476
{ kind: CodeActionKind.SourceFixAll, includeSourceActions: true },
478477
CodeActionAutoApply.IfSingle);
@@ -503,7 +502,7 @@ export class AutoFixAction extends EditorAction {
503502
}
504503

505504
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
506-
return showCodeActionsForEditorSelection(editor,
505+
return triggerCodeActionsForEditorSelection(editor,
507506
nls.localize('editor.action.autoFix.noneMessage', "No auto fixes available"),
508507
{
509508
kind: CodeActionKind.QuickFix,

0 commit comments

Comments
 (0)