Merge pull request #152383 from justschen/justin/CodeAction-Telemetry

Adding additional telemetry on CodeActions (trigger reasons)
This commit is contained in:
Justin Chen
2022-06-23 11:06:21 -07:00
committed by GitHub
11 changed files with 98 additions and 51 deletions
@@ -16,7 +16,7 @@ import * as languages from 'vs/editor/common/languages';
import { IModelService } from 'vs/editor/common/services/model';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IProgress, Progress } from 'vs/platform/progress/common/progress';
import { CodeActionFilter, CodeActionKind, CodeActionTrigger, filtersAction, mayIncludeActionsOfKind } from './types';
import { CodeActionFilter, CodeActionKind, CodeActionTrigger, CodeActionTriggerSource, filtersAction, mayIncludeActionsOfKind } from './types';
import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
@@ -224,7 +224,6 @@ function getDocumentation(
}
}
}
return undefined;
}
@@ -254,7 +253,7 @@ CommandsRegistry.registerCommand('_executeCodeActionProvider', async function (a
codeActionProvider,
model,
validatedRangeOrSelection,
{ type: languages.CodeActionTriggerType.Invoke, filter: { includeSourceActions: true, include } },
{ type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default, filter: { includeSourceActions: true, include } },
Progress.None,
CancellationToken.None);
@@ -31,7 +31,7 @@ import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CodeActionModel, CodeActionsState, SUPPORTED_CODE_ACTIONS } from './codeActionModel';
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionFilter, CodeActionKind, CodeActionTrigger } from './types';
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionFilter, CodeActionKind, CodeActionTrigger, CodeActionTriggerSource } from './types';
function contextKeyForSupportedActions(kind: CodeActionKind) {
return ContextKeyExpr.regex(
@@ -39,7 +39,7 @@ function contextKeyForSupportedActions(kind: CodeActionKind) {
new RegExp('(\\s|^)' + escapeRegExpCharacters(kind.value) + '\\b'));
}
function RefactorTrigger(editor: ICodeEditor, userArgs: any, preview: boolean) {
function refactorTrigger(editor: ICodeEditor, userArgs: any, preview: boolean, codeActionFrom: CodeActionTriggerSource) {
const args = CodeActionCommandArgs.fromUser(userArgs, {
kind: CodeActionKind.Refactor,
apply: CodeActionAutoApply.Never
@@ -56,7 +56,7 @@ function RefactorTrigger(editor: ICodeEditor, userArgs: any, preview: boolean) {
include: CodeActionKind.Refactor.contains(args.kind) ? args.kind : CodeActionKind.None,
onlyIncludePreferredActions: args.preferred
},
args.apply, preview);
args.apply, preview, codeActionFrom);
}
const argsSchema: IJSONSchema = {
@@ -120,7 +120,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
await this._applyCodeAction(action, preview);
} finally {
if (retrigger) {
this._trigger({ type: CodeActionTriggerType.Auto, filter: {} });
this._trigger({ type: CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.QuickFix, filter: {} });
}
}
}
@@ -133,14 +133,16 @@ export class QuickFixController extends Disposable implements IEditorContributio
}
public showCodeActions(trigger: CodeActionTrigger, actions: CodeActionSet, at: IAnchor | IPosition) {
return this._ui.getValue().showCodeActionList(trigger, actions, at, { includeDisabledActions: false });
return this._ui.getValue().showCodeActionList(trigger, actions, at, { includeDisabledActions: false, fromLightbulb: false });
}
public manualTriggerAtCurrentPosition(
notAvailableMessage: string,
triggerAction: CodeActionTriggerSource,
filter?: CodeActionFilter,
autoApply?: CodeActionAutoApply,
preview?: boolean
preview?: boolean,
): void {
if (!this._editor.hasModel()) {
return;
@@ -148,7 +150,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
MessageController.get(this._editor)?.closeMessage();
const triggerPosition = this._editor.getPosition();
this._trigger({ type: CodeActionTriggerType.Invoke, filter, autoApply, context: { notAvailableMessage, position: triggerPosition }, preview });
this._trigger({ type: CodeActionTriggerType.Invoke, triggerAction, filter, autoApply, context: { notAvailableMessage, position: triggerPosition }, preview });
}
private _trigger(trigger: CodeActionTrigger) {
@@ -166,6 +168,7 @@ export enum ApplyCodeActionReason {
FromCodeActions = 'fromCodeActions'
}
export async function applyCodeAction(
accessor: ServicesAccessor,
item: CodeActionItem,
@@ -181,13 +184,13 @@ export async function applyCodeAction(
codeActionTitle: string;
codeActionKind: string | undefined;
codeActionIsPreferred: boolean;
reason?: ApplyCodeActionReason;
reason: ApplyCodeActionReason;
};
type ApplyCodeEventClassification = {
codeActionTitle: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The display label of the applied code action' };
codeActionKind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The kind (refactor, quickfix) of the applied code action' };
codeActionIsPreferred: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Was the code action marked as being a preferred action?' };
reason?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The kind of action used to trigger apply code action.' };
reason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The kind of action used to trigger apply code action.' };
owner: 'mjbvz';
comment: 'Event used to gain insights into which code actions are being triggered';
};
@@ -196,7 +199,7 @@ export async function applyCodeAction(
codeActionTitle: item.action.title,
codeActionKind: item.action.kind,
codeActionIsPreferred: !!item.action.isPreferred,
reason: codeActionReason
reason: codeActionReason,
});
await item.resolve(CancellationToken.None);
@@ -240,11 +243,12 @@ function triggerCodeActionsForEditorSelection(
notAvailableMessage: string,
filter: CodeActionFilter | undefined,
autoApply: CodeActionAutoApply | undefined,
preview: boolean = false
preview: boolean = false,
triggerAction: CodeActionTriggerSource = CodeActionTriggerSource.Default
): void {
if (editor.hasModel()) {
const controller = QuickFixController.get(editor);
controller?.manualTriggerAtCurrentPosition(notAvailableMessage, filter, autoApply, preview);
controller?.manualTriggerAtCurrentPosition(notAvailableMessage, triggerAction, filter, autoApply, preview);
}
}
@@ -267,7 +271,7 @@ export class QuickFixAction extends EditorAction {
}
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), undefined, undefined);
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), undefined, undefined, false, CodeActionTriggerSource.QuickFix);
}
}
@@ -338,7 +342,7 @@ export class RefactorAction extends EditorAction {
}
public run(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs: any): void {
return RefactorTrigger(editor, userArgs, false);
return refactorTrigger(editor, userArgs, false, CodeActionTriggerSource.Refactor);
}
}
@@ -358,7 +362,7 @@ export class RefactorPreview extends EditorAction {
}
public run(_accessor: ServicesAccessor, editor: ICodeEditor, userArgs: any): void {
return RefactorTrigger(editor, userArgs, true);
return refactorTrigger(editor, userArgs, true, CodeActionTriggerSource.RefactorPreview);
}
}
@@ -402,7 +406,7 @@ export class SourceAction extends EditorAction {
includeSourceActions: true,
onlyIncludePreferredActions: args.preferred,
},
args.apply);
args.apply, undefined, CodeActionTriggerSource.SourceAction);
}
}
@@ -428,7 +432,7 @@ export class OrganizeImportsAction extends EditorAction {
return triggerCodeActionsForEditorSelection(editor,
nls.localize('editor.action.organize.noneMessage', "No organize imports action available"),
{ include: CodeActionKind.SourceOrganizeImports, includeSourceActions: true },
CodeActionAutoApply.IfSingle);
CodeActionAutoApply.IfSingle, undefined, CodeActionTriggerSource.OrganizeImports);
}
}
@@ -449,7 +453,7 @@ export class FixAllAction extends EditorAction {
return triggerCodeActionsForEditorSelection(editor,
nls.localize('fixAll.noneMessage', "No fix all action available"),
{ include: CodeActionKind.SourceFixAll, includeSourceActions: true },
CodeActionAutoApply.IfSingle);
CodeActionAutoApply.IfSingle, undefined, CodeActionTriggerSource.FixAll);
}
}
@@ -483,6 +487,6 @@ export class AutoFixAction extends EditorAction {
include: CodeActionKind.QuickFix,
onlyIncludePreferredActions: true
},
CodeActionAutoApply.IfSingle);
CodeActionAutoApply.IfSingle, undefined, CodeActionTriggerSource.AutoFix);
}
}
@@ -17,10 +17,11 @@ import { ScrollType } from 'vs/editor/common/editorCommon';
import { CodeAction, Command } from 'vs/editor/common/languages';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { codeActionCommandId, CodeActionItem, CodeActionSet, fixAllCommandId, organizeImportsCommandId, refactorCommandId, sourceActionCommandId } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionKind, CodeActionTrigger } from 'vs/editor/contrib/codeAction/browser/types';
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionKind, CodeActionTrigger, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/browser/types';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
interface CodeActionWidgetDelegate {
onSelectCodeAction: (action: CodeActionItem, trigger: CodeActionTrigger) => Promise<any>;
@@ -47,6 +48,7 @@ function stripNewlines(str: string): string {
export interface CodeActionShowOptions {
readonly includeDisabledActions: boolean;
readonly fromLightbulb?: boolean;
}
export class CodeActionMenu extends Disposable {
@@ -62,6 +64,7 @@ export class CodeActionMenu extends Disposable {
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
@IKeybindingService keybindingService: IKeybindingService,
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
@ITelemetryService private readonly _telemetryService: ITelemetryService
) {
super();
@@ -101,7 +104,30 @@ export class CodeActionMenu extends Disposable {
domForShadowRoot: useShadowDOM ? this._editor.getDomNode()! : undefined,
getAnchor: () => anchor,
getActions: () => menuActions,
onHide: () => {
onHide: (didCancel) => {
const openedFromString = (options.fromLightbulb) ? CodeActionTriggerSource.Lightbulb : trigger.triggerAction;
type ApplyCodeActionEvent = {
codeActionFrom: CodeActionTriggerSource;
validCodeActions: number;
cancelled: boolean;
};
type ApplyCodeEventClassification = {
codeActionFrom: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The kind of action used to opened the code action.' };
validCodeActions: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The total number of valid actions that are highlighted and can be used.' };
cancelled: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The indicator if the menu was selected or cancelled.' };
owner: 'mjbvz';
comment: 'Event used to gain insights into how code actions are being triggered';
};
this._telemetryService.publicLog2<ApplyCodeActionEvent, ApplyCodeEventClassification>('codeAction.applyCodeAction', {
codeActionFrom: openedFromString,
validCodeActions: codeActions.validActions.length,
cancelled: didCancel,
});
this._visible = false;
this._editor.focus();
},
@@ -116,7 +142,6 @@ export class CodeActionMenu extends Disposable {
documentation: readonly Command[]
): IAction[] {
const toCodeActionAction = (item: CodeActionItem): CodeActionAction => new CodeActionAction(item.action, () => this._delegate.onSelectCodeAction(item, trigger));
const result: IAction[] = actionsToShow
.map(toCodeActionAction);
@@ -20,7 +20,7 @@ import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/cont
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEditorProgressService, Progress } from 'vs/platform/progress/common/progress';
import { CodeActionSet, getCodeActions } from './codeAction';
import { CodeActionTrigger } from './types';
import { CodeActionTrigger, CodeActionTriggerSource } from './types';
export const SUPPORTED_CODE_ACTIONS = new RawContextKey<string>('supportedCodeAction', '');
@@ -58,14 +58,14 @@ class CodeActionOracle extends Disposable {
if (resources.some(resource => isEqual(resource, model.uri))) {
this._autoTriggerTimer.cancelAndSet(() => {
this.trigger({ type: CodeActionTriggerType.Auto });
this.trigger({ type: CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default });
}, this._delay);
}
}
private _onCursorChange(): void {
this._autoTriggerTimer.cancelAndSet(() => {
this.trigger({ type: CodeActionTriggerType.Auto });
this.trigger({ type: CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default });
}, this._delay);
}
@@ -256,7 +256,7 @@ export class CodeActionModel extends Disposable {
this.setState(new CodeActionsState.Triggered(trigger.trigger, trigger.selection, trigger.position, actions));
}, undefined);
this._codeActionOracle.value.trigger({ type: CodeActionTriggerType.Auto });
this._codeActionOracle.value.trigger({ type: CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default });
} else {
this._supportedCodeActions.reset();
}
@@ -47,7 +47,7 @@ export class CodeActionUi extends Disposable {
this._lightBulbWidget = new Lazy(() => {
const widget = this._register(instantiationService.createInstance(LightBulbWidget, this._editor, quickFixActionId, preferredFixActionId));
this._register(widget.onClick(e => this.showCodeActionList(e.trigger, e.actions, e, { includeDisabledActions: false })));
this._register(widget.onClick(e => this.showCodeActionList(e.trigger, e.actions, e, { includeDisabledActions: false, fromLightbulb: true })));
return widget;
});
}
@@ -114,7 +114,7 @@ export class CodeActionUi extends Disposable {
}
this._activeCodeActions.value = actions;
this._codeActionWidget.getValue().show(newState.trigger, actions, newState.position, { includeDisabledActions });
this._codeActionWidget.getValue().show(newState.trigger, actions, newState.position, { includeDisabledActions, fromLightbulb: false });
} else {
// auto magically triggered
if (this._codeActionWidget.getValue().isVisible) {
@@ -44,6 +44,21 @@ export const enum CodeActionAutoApply {
Never = 'never',
}
export enum CodeActionTriggerSource {
Refactor = 'refactor',
RefactorPreview = 'refactor preview',
Lightbulb = 'lightbulb',
Default = 'other (default)',
SourceAction = 'source action',
QuickFix = 'quick fix action',
FixAll = 'fix all',
OrganizeImports = 'organize imports',
AutoFix = 'auto fix',
QuickFixHover = 'quick fix hover window',
OnSave = 'save participants',
ProblemsView = 'problems view'
}
export interface CodeActionFilter {
readonly include?: CodeActionKind;
readonly excludes?: readonly CodeActionKind[];
@@ -116,6 +131,7 @@ function excludesAction(providedKind: CodeActionKind, exclude: CodeActionKind, i
export interface CodeActionTrigger {
readonly type: CodeActionTriggerType;
readonly triggerAction: CodeActionTriggerSource;
readonly filter?: CodeActionFilter;
readonly autoApply?: CodeActionAutoApply;
readonly context?: {
@@ -11,7 +11,7 @@ import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistr
import * as languages from 'vs/editor/common/languages';
import { TextModel } from 'vs/editor/common/model/textModel';
import { CodeActionItem, getCodeActions } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/browser/types';
import { CodeActionKind, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/browser/types';
import { createTextModel } from 'vs/editor/test/common/testTextModel';
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { Progress } from 'vs/platform/progress/common/progress';
@@ -130,7 +130,7 @@ suite('CodeAction', () => {
new CodeActionItem(testData.tsLint.abc, provider)
];
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Invoke }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 6);
assert.deepStrictEqual(actions, expected);
});
@@ -145,20 +145,20 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider));
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 2);
assert.strictEqual(actions[0].action.title, 'a');
assert.strictEqual(actions[1].action.title, 'a.b');
}
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b') } }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a.b') } }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a.b');
}
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b.c') } }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a.b.c') } }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 0);
}
});
@@ -177,7 +177,7 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider));
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a');
});
@@ -191,13 +191,13 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider));
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.SourceAction }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'b');
}
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a');
}
@@ -214,7 +214,7 @@ suite('CodeAction', () => {
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), {
type: languages.CodeActionTriggerType.Auto, filter: {
type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.SourceAction, filter: {
include: CodeActionKind.Source.append('test'),
excludes: [CodeActionKind.Source],
includeSourceActions: true,
@@ -251,7 +251,7 @@ suite('CodeAction', () => {
{
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), {
type: languages.CodeActionTriggerType.Auto, filter: {
type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Refactor, filter: {
include: baseType,
excludes: [subType],
}
@@ -276,7 +276,7 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider));
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), {
type: languages.CodeActionTriggerType.Auto,
type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Refactor,
filter: {
include: CodeActionKind.QuickFix
}
@@ -17,7 +17,7 @@ import { CodeActionTriggerType } from 'vs/editor/common/languages';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markerDecorations';
import { CodeActionSet, getCodeActions } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { QuickFixAction, QuickFixController } from 'vs/editor/contrib/codeAction/browser/codeActionCommands';
import { CodeActionKind, CodeActionTrigger } from 'vs/editor/contrib/codeAction/browser/types';
import { CodeActionKind, CodeActionTrigger, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/browser/types';
import { MarkerController, NextMarkerAction } from 'vs/editor/contrib/gotoError/browser/gotoError';
import { HoverAnchor, HoverAnchorType, IEditorHoverParticipant, IEditorHoverRenderContext, IHoverPart } from 'vs/editor/contrib/hover/browser/hoverTypes';
import * as nls from 'vs/nls';
@@ -50,7 +50,8 @@ export class MarkerHover implements IHoverPart {
const markerCodeActionTrigger: CodeActionTrigger = {
type: CodeActionTriggerType.Invoke,
filter: { include: CodeActionKind.QuickFix }
filter: { include: CodeActionKind.QuickFix },
triggerAction: CodeActionTriggerSource.QuickFixHover
};
export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHover> {
@@ -53,6 +53,7 @@ import { URITransformerService } from 'vs/workbench/api/common/extHostUriTransfo
import { OutlineModel } from 'vs/editor/contrib/documentSymbols/browser/outlineModel';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService';
import { CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/browser/types';
suite('ExtHostLanguageFeatures', function () {
@@ -628,7 +629,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.QuickFix }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 2);
const [first, second] = actions;
assert.strictEqual(first.action.title, 'Testing1');
@@ -652,7 +653,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
const [first] = actions;
assert.strictEqual(first.action.title, 'Testing1');
@@ -675,7 +676,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
});
@@ -693,7 +694,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke }, Progress.None, CancellationToken.None);
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.QuickFix }, Progress.None, CancellationToken.None);
assert.strictEqual(actions.length, 1);
});
@@ -16,7 +16,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { CodeActionTriggerType, CodeActionProvider } from 'vs/editor/common/languages';
import { getCodeActions } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { applyCodeAction, ApplyCodeActionReason } from 'vs/editor/contrib/codeAction/browser/codeActionCommands';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/browser/types';
import { CodeActionKind, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/browser/types';
import { formatDocumentRangesWithSelectedProvider, formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/browser/format';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { localize } from 'vs/nls';
@@ -375,6 +375,7 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant {
private getActionsToRun(model: ITextModel, codeActionKind: CodeActionKind, excludes: readonly CodeActionKind[], progress: IProgress<CodeActionProvider>, token: CancellationToken) {
return getCodeActions(this.languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), {
type: CodeActionTriggerType.Auto,
triggerAction: CodeActionTriggerSource.OnSave,
filter: { include: codeActionKind, excludes: excludes, includeSourceActions: true },
}, progress, token);
}
@@ -34,7 +34,7 @@ import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/com
import { IModelService } from 'vs/editor/common/services/model';
import { Range } from 'vs/editor/common/core/range';
import { getCodeActions, CodeActionSet } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/browser/types';
import { CodeActionKind, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/browser/types';
import { ITextModel } from 'vs/editor/common/model';
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { applyCodeAction, ApplyCodeActionReason } from 'vs/editor/contrib/codeAction/browser/codeActionCommands';
@@ -627,7 +627,7 @@ export class MarkerViewModel extends Disposable {
if (!this.codeActionsPromise) {
this.codeActionsPromise = createCancelablePromise(cancellationToken => {
return getCodeActions(this.languageFeaturesService.codeActionProvider, model, new Range(this.marker.range.startLineNumber, this.marker.range.startColumn, this.marker.range.endLineNumber, this.marker.range.endColumn), {
type: CodeActionTriggerType.Invoke, filter: { include: CodeActionKind.QuickFix }
type: CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.ProblemsView, filter: { include: CodeActionKind.QuickFix }
}, Progress.None, cancellationToken).then(actions => {
return this._register(actions);
});