123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
- var __param = (this && this.__param) || function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- import { getDomNodePagePosition } from '../../../base/browser/dom.js';
- import { Action, Separator } from '../../../base/common/actions.js';
- import { canceled } from '../../../base/common/errors.js';
- import { Lazy } from '../../../base/common/lazy.js';
- import { Disposable, MutableDisposable } from '../../../base/common/lifecycle.js';
- import { Position } from '../../common/core/position.js';
- import { CodeActionProviderRegistry } from '../../common/modes.js';
- import { codeActionCommandId, CodeActionItem, fixAllCommandId, organizeImportsCommandId, refactorCommandId, sourceActionCommandId } from './codeAction.js';
- import { CodeActionCommandArgs, CodeActionKind } from './types.js';
- import { IContextMenuService } from '../../../platform/contextview/browser/contextView.js';
- import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';
- class CodeActionAction extends Action {
- constructor(action, callback) {
- super(action.command ? action.command.id : action.title, stripNewlines(action.title), undefined, !action.disabled, callback);
- this.action = action;
- }
- }
- function stripNewlines(str) {
- return str.replace(/\r\n|\r|\n/g, ' ');
- }
- let CodeActionMenu = class CodeActionMenu extends Disposable {
- constructor(_editor, _delegate, _contextMenuService, keybindingService) {
- super();
- this._editor = _editor;
- this._delegate = _delegate;
- this._contextMenuService = _contextMenuService;
- this._visible = false;
- this._showingActions = this._register(new MutableDisposable());
- this._keybindingResolver = new CodeActionKeybindingResolver({
- getKeybindings: () => keybindingService.getKeybindings()
- });
- }
- get isVisible() {
- return this._visible;
- }
- show(trigger, codeActions, at, options) {
- return __awaiter(this, void 0, void 0, function* () {
- const actionsToShow = options.includeDisabledActions ? codeActions.allActions : codeActions.validActions;
- if (!actionsToShow.length) {
- this._visible = false;
- return;
- }
- if (!this._editor.getDomNode()) {
- // cancel when editor went off-dom
- this._visible = false;
- throw canceled();
- }
- this._visible = true;
- this._showingActions.value = codeActions;
- const menuActions = this.getMenuActions(trigger, actionsToShow, codeActions.documentation);
- const anchor = Position.isIPosition(at) ? this._toCoords(at) : at || { x: 0, y: 0 };
- const resolver = this._keybindingResolver.getResolver();
- const useShadowDOM = this._editor.getOption(114 /* useShadowDOM */);
- this._contextMenuService.showContextMenu({
- domForShadowRoot: useShadowDOM ? this._editor.getDomNode() : undefined,
- getAnchor: () => anchor,
- getActions: () => menuActions,
- onHide: () => {
- this._visible = false;
- this._editor.focus();
- },
- autoSelectFirstItem: true,
- getKeyBinding: action => action instanceof CodeActionAction ? resolver(action.action) : undefined,
- });
- });
- }
- getMenuActions(trigger, actionsToShow, documentation) {
- var _a, _b;
- const toCodeActionAction = (item) => new CodeActionAction(item.action, () => this._delegate.onSelectCodeAction(item));
- const result = actionsToShow
- .map(toCodeActionAction);
- const allDocumentation = [...documentation];
- const model = this._editor.getModel();
- if (model && result.length) {
- for (const provider of CodeActionProviderRegistry.all(model)) {
- if (provider._getAdditionalMenuItems) {
- allDocumentation.push(...provider._getAdditionalMenuItems({ trigger: trigger.type, only: (_b = (_a = trigger.filter) === null || _a === void 0 ? void 0 : _a.include) === null || _b === void 0 ? void 0 : _b.value }, actionsToShow.map(item => item.action)));
- }
- }
- }
- if (allDocumentation.length) {
- result.push(new Separator(), ...allDocumentation.map(command => toCodeActionAction(new CodeActionItem({
- title: command.title,
- command: command,
- }, undefined))));
- }
- return result;
- }
- _toCoords(position) {
- if (!this._editor.hasModel()) {
- return { x: 0, y: 0 };
- }
- this._editor.revealPosition(position, 1 /* Immediate */);
- this._editor.render();
- // Translate to absolute editor position
- const cursorCoords = this._editor.getScrolledVisiblePosition(position);
- const editorCoords = getDomNodePagePosition(this._editor.getDomNode());
- const x = editorCoords.left + cursorCoords.left;
- const y = editorCoords.top + cursorCoords.top + cursorCoords.height;
- return { x, y };
- }
- };
- CodeActionMenu = __decorate([
- __param(2, IContextMenuService),
- __param(3, IKeybindingService)
- ], CodeActionMenu);
- export { CodeActionMenu };
- export class CodeActionKeybindingResolver {
- constructor(_keybindingProvider) {
- this._keybindingProvider = _keybindingProvider;
- }
- getResolver() {
- // Lazy since we may not actually ever read the value
- const allCodeActionBindings = new Lazy(() => this._keybindingProvider.getKeybindings()
- .filter(item => CodeActionKeybindingResolver.codeActionCommands.indexOf(item.command) >= 0)
- .filter(item => item.resolvedKeybinding)
- .map((item) => {
- // Special case these commands since they come built-in with VS Code and don't use 'commandArgs'
- let commandArgs = item.commandArgs;
- if (item.command === organizeImportsCommandId) {
- commandArgs = { kind: CodeActionKind.SourceOrganizeImports.value };
- }
- else if (item.command === fixAllCommandId) {
- commandArgs = { kind: CodeActionKind.SourceFixAll.value };
- }
- return Object.assign({ resolvedKeybinding: item.resolvedKeybinding }, CodeActionCommandArgs.fromUser(commandArgs, {
- kind: CodeActionKind.None,
- apply: "never" /* Never */
- }));
- }));
- return (action) => {
- if (action.kind) {
- const binding = this.bestKeybindingForCodeAction(action, allCodeActionBindings.getValue());
- return binding === null || binding === void 0 ? void 0 : binding.resolvedKeybinding;
- }
- return undefined;
- };
- }
- bestKeybindingForCodeAction(action, candidates) {
- if (!action.kind) {
- return undefined;
- }
- const kind = new CodeActionKind(action.kind);
- return candidates
- .filter(candidate => candidate.kind.contains(kind))
- .filter(candidate => {
- if (candidate.preferred) {
- // If the candidate keybinding only applies to preferred actions, the this action must also be preferred
- return action.isPreferred;
- }
- return true;
- })
- .reduceRight((currentBest, candidate) => {
- if (!currentBest) {
- return candidate;
- }
- // Select the more specific binding
- return currentBest.kind.contains(candidate.kind) ? candidate : currentBest;
- }, undefined);
- }
- }
- CodeActionKeybindingResolver.codeActionCommands = [
- refactorCommandId,
- codeActionCommandId,
- sourceActionCommandId,
- organizeImportsCommandId,
- fixAllCommandId
- ];
|