diff --git a/src/vs/editor/contrib/inlayHints/inlayHintsController.ts b/src/vs/editor/contrib/inlayHints/inlayHintsController.ts index f8eb34909b3..78df5d4d66f 100644 --- a/src/vs/editor/contrib/inlayHints/inlayHintsController.ts +++ b/src/vs/editor/contrib/inlayHints/inlayHintsController.ts @@ -258,13 +258,12 @@ export class InlayHintsController implements IEditorContribution { const label = this._getInlayHintLabelPart(e); if (label) { const part = label.part; - if (languages.Command.is(part.command)) { - // command -> execute it - this._commandService.executeCommand(part.command.id, ...(part.command.arguments ?? [])).catch(err => this._notificationService.error(err)); - - } else if (part.location) { + if (part.location) { // location -> execute go to def this._instaService.invokeFunction(goToDefinitionWithLocation, e, this._editor as IActiveCodeEditor, part.location); + } else if (languages.Command.is(part.command)) { + // command -> execute it + this._commandService.executeCommand(part.command.id, ...(part.command.arguments ?? [])).catch(err => this._notificationService.error(err)); } } }); diff --git a/src/vs/editor/contrib/inlayHints/inlayHintsLocations.ts b/src/vs/editor/contrib/inlayHints/inlayHintsLocations.ts index 356863216f8..c7f94c1b7ab 100644 --- a/src/vs/editor/contrib/inlayHints/inlayHintsLocations.ts +++ b/src/vs/editor/contrib/inlayHints/inlayHintsLocations.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as dom from 'vs/base/browser/dom'; -import { Action, IAction } from 'vs/base/common/actions'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; @@ -17,6 +17,7 @@ import { ClickLinkMouseEvent } from 'vs/editor/contrib/gotoSymbol/link/clickLink import { RenderedInlayHintLabelPart } from 'vs/editor/contrib/inlayHints/inlayHintsController'; import { PeekContext } from 'vs/editor/contrib/peekView/peekView'; import { isIMenuItem, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { ICommandService } from 'vs/platform/commands/common/commands'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -25,6 +26,7 @@ export async function showGoToContextMenu(accessor: ServicesAccessor, editor: IC const resolverService = accessor.get(ITextModelService); const contextMenuService = accessor.get(IContextMenuService); + const commandService = accessor.get(ICommandService); const instaService = accessor.get(IInstantiationService); await part.item.resolve(CancellationToken.None); @@ -55,6 +57,14 @@ export async function showGoToContextMenu(accessor: ServicesAccessor, editor: IC } } + if (part.part.command) { + const { command } = part.part; + menuActions.push(new Separator()); + menuActions.push(new Action(command.id, command.title, undefined, true, () => { + commandService.executeCommand(command.id, ...(command.arguments ?? [])); + })); + } + // show context menu const useShadowDOM = editor.getOption(EditorOption.useShadowDOM); contextMenuService.showContextMenu({ diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 7c474d77838..b4d4b0a5100 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -346,21 +346,6 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry { } }; -export class ExecuteCommandAction extends Action { - - constructor( - id: string, - label: string, - @ICommandService private readonly _commandService: ICommandService) { - - super(id, label); - } - - override run(...args: any[]): Promise { - return this._commandService.executeCommand(this.id, ...args); - } -} - export class SubmenuItemAction extends SubmenuAction { constructor( diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index f2a995969b8..2e12e01b631 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -1271,7 +1271,8 @@ class InlayHintsAdapter { result.tooltip = part.tooltip && typeConvert.MarkdownString.from(part.tooltip); if (Location.isLocation(part.location)) { result.location = typeConvert.location.from(part.location); - } else if (part.command) { + } + if (part.command) { result.command = this._commands.toInternal(part.command, disposables); } return result; diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 89a97e68756..f62f5c69bb8 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1174,7 +1174,8 @@ export namespace InlayHintLabelPart { : part.tooltip; if (modes.Command.is(part.command)) { result.command = converter.fromInternal(part.command); - } else if (part.location) { + } + if (part.location) { result.location = location.to(part.location); } return result; diff --git a/src/vscode-dts/vscode.proposed.inlayHints.d.ts b/src/vscode-dts/vscode.proposed.inlayHints.d.ts index 8510c247135..34c7e2581c8 100644 --- a/src/vscode-dts/vscode.proposed.inlayHints.d.ts +++ b/src/vscode-dts/vscode.proposed.inlayHints.d.ts @@ -49,9 +49,29 @@ declare module 'vscode' { */ tooltip?: string | MarkdownString | undefined; - // invokes provider + /** + * An optional {@link Location source code location} that represents this label + * part. + * + * The editor will use this location for the hover and for code navigation features: This + * part will become a clickable link that resolves to the definition of the symbol at the + * given location (not neccessarily the location itself), it shows the hover that shows at + * the given location, and it shows a context menu with further code navigation commands. + * + * *Note* that this property can be set late during + * {@link InlayHintsProvider.resolveInlayHint resolving} of inlay hints. + */ location?: Location | undefined; + /** + * An optional command for this label part. + * + * The editor renders parts with commands as clickable links. The command is added to the context menu + * when a label part defines {@link InlayHintLabelPart.location location} and {@link InlayHintLabelPart.command command} . + * + * *Note* that this property can be set late during + * {@link InlayHintsProvider.resolveInlayHint resolving} of inlay hints. + */ command?: Command | undefined; // todo@api