Action Widget won't show label for edits in hover when no edits are available (#192238)

* initial working version v1

* cleanup and fixed error in terminal quick fix

* code cleanup, making onFocus optional, removing terminal quickfix edits

* added logic for cancellation v1 and removing extra call to rerender

* registered cancellable tokens and added better checks onFocus

* code cleanup
This commit is contained in:
Justin Chen
2023-09-14 23:22:16 +01:00
committed by GitHub
parent 153335bd06
commit 9c12e02b7b
3 changed files with 29 additions and 4 deletions
@@ -30,6 +30,7 @@ import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { CodeActionAutoApply, CodeActionFilter, CodeActionItem, CodeActionSet, CodeActionTrigger, CodeActionTriggerSource } from '../common/types';
import { CodeActionModel, CodeActionsState } from './codeActionModel';
import { CancellationToken } from 'vs/base/common/cancellation';
interface IActionShowOptions {
@@ -251,6 +252,13 @@ export class CodeActionController extends Disposable implements IEditorContribut
},
onHide: () => {
this._editor?.focus();
},
onFocus: async (action: CodeActionItem, token: CancellationToken) => {
await action.resolve(token);
if (token.isCancellationRequested) {
return;
}
return { canPreview: !!action.action.edit?.edits.length };
}
};
@@ -44,7 +44,8 @@ export function toMenuItems(
item: action,
group: uncategorizedCodeActionGroup,
disabled: !!action.action.disabled,
label: action.action.disabled || action.action.title
label: action.action.disabled || action.action.title,
canPreview: !!action.action.edit?.edits.length,
};
});
}
@@ -6,6 +6,7 @@ import * as dom from 'vs/base/browser/dom';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
import { IListEvent, IListMouseEvent, IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Codicon } from 'vs/base/common/codicons';
import { ResolvedKeybinding } from 'vs/base/common/keybindings';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -24,6 +25,7 @@ export const previewSelectedActionCommand = 'previewSelectedCodeAction';
export interface IActionListDelegate<T> {
onHide(didCancel?: boolean): void;
onSelect(action: T, preview?: boolean): void;
onFocus?(action: T, cancellationToken: CancellationToken): Promise<{ canPreview: boolean } | void>;
}
export interface IActionListItem<T> {
@@ -32,8 +34,8 @@ export interface IActionListItem<T> {
readonly group?: { kind?: any; icon?: ThemeIcon; title: string };
readonly disabled?: boolean;
readonly label?: string;
readonly keybinding?: ResolvedKeybinding;
canPreview?: boolean | undefined;
}
interface IActionMenuTemplateData {
@@ -126,7 +128,7 @@ class ActionItemRenderer<T> implements IListRenderer<IActionListItem<T>, IAction
if (element.disabled) {
data.container.title = element.label;
} else if (actionTitle && previewTitle) {
if (this._supportsPreview) {
if (this._supportsPreview && element.canPreview) {
data.container.title = localize({ key: 'label-preview', comment: ['placeholders are keybindings, e.g "F2 to apply, Shift+F2 to preview"'] }, "{0} to apply, {1} to preview", actionTitle, previewTitle);
} else {
data.container.title = localize({ key: 'label', comment: ['placeholder is a keybinding, e.g "F2 to apply"'] }, "{0} to apply", actionTitle);
@@ -168,6 +170,8 @@ export class ActionList<T> extends Disposable {
private readonly _allMenuItems: readonly IActionListItem<T>[];
private readonly cts = this._register(new CancellationTokenSource());
constructor(
user: string,
preview: boolean,
@@ -230,6 +234,7 @@ export class ActionList<T> extends Disposable {
hide(didCancel?: boolean): void {
this._delegate.onHide(didCancel);
this.cts.cancel();
this._contextViewService.hideContextView();
}
@@ -302,7 +307,18 @@ export class ActionList<T> extends Disposable {
}
}
private onListHover(e: IListMouseEvent<IActionListItem<T>>): void {
private async onListHover(e: IListMouseEvent<IActionListItem<T>>) {
const element = e.element;
if (element && element.item && this.focusCondition(element)) {
if (this._delegate.onFocus && !element.disabled && element.kind === ActionListItemKind.Action) {
const result = await this._delegate.onFocus(element.item, this.cts.token);
element.canPreview = result ? result.canPreview : undefined;
}
if (e.index) {
this._list.splice(e.index, 1, [element]);
}
}
this._list.setFocus(typeof e.index === 'number' ? [e.index] : []);
}