Command enablement not enforced for TreeItems (#157642)

* Command enablement not enforced for TreeItems
Fixes #157493

* missed a spot
This commit is contained in:
Alex Ross
2022-08-09 16:06:09 +02:00
committed by GitHub
parent 596b8f9da9
commit 532560f5f5
3 changed files with 22 additions and 17 deletions
@@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { DataTransferDTO, ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions } from 'vs/workbench/common/views';
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions, TreeCommand } from 'vs/workbench/common/views';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
import { asPromise } from 'vs/base/common/async';
import { TreeItemCollapsibleState, ThemeIcon, MarkdownString as MarkdownStringType, TreeItem } from 'vs/workbench/api/common/extHostTypes';
@@ -22,7 +22,6 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
import { MarkdownString, ViewBadge, DataTransfer } from 'vs/workbench/api/common/extHostTypeConverters';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Command } from 'vs/editor/common/languages';
import { ITreeViewsService, TreeviewsService } from 'vs/workbench/services/views/common/treeViewsService';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
@@ -696,7 +695,7 @@ class ExtHostTreeView<T> extends Disposable {
return tooltip;
}
private getCommand(disposable: DisposableStore, command?: vscode.Command): Command & { originalId: string } | undefined {
private getCommand(disposable: DisposableStore, command?: vscode.Command): TreeCommand | undefined {
return command ? { ...this.commands.toInternal(command, disposable), originalId: command.command } : undefined;
}
@@ -32,7 +32,6 @@ import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import 'vs/css!./media/views';
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import { Command } from 'vs/editor/common/languages';
import { localize } from 'vs/nls';
import { createActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { Action2, IMenu, IMenuService, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
@@ -60,7 +59,7 @@ import { API_OPEN_DIFF_EDITOR_COMMAND_ID, API_OPEN_EDITOR_COMMAND_ID } from 'vs/
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { Extensions, ITreeItem, ITreeItemLabel, ITreeView, ITreeViewDataProvider, ITreeViewDescriptor, ITreeViewDragAndDropController, IViewBadge, IViewDescriptorService, IViewsRegistry, ResolvableTreeItem, TreeItemCollapsibleState, TreeViewItemHandleArg, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
import { Extensions, ITreeItem, ITreeItemLabel, ITreeView, ITreeViewDataProvider, ITreeViewDescriptor, ITreeViewDragAndDropController, IViewBadge, IViewDescriptorService, IViewsRegistry, ResolvableTreeItem, TreeCommand, TreeItemCollapsibleState, TreeViewItemHandleArg, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
@@ -153,6 +152,18 @@ class Root implements ITreeItem {
children: ITreeItem[] | undefined = undefined;
}
function isTreeCommandEnabled(treeCommand: TreeCommand, contextKeyService: IContextKeyService): boolean {
const command = CommandsRegistry.getCommand(treeCommand.originalId ? treeCommand.originalId : treeCommand.id);
if (command) {
const commandAction = MenuRegistry.getCommand(command.id);
const precondition = commandAction && commandAction.precondition;
if (precondition) {
return contextKeyService.contextMatchesRules(precondition);
}
}
return true;
}
const noDataProviderMessage = localize('no-dataprovider', "There is no data provider registered that can provide view data.");
export const RawCustomTreeViewContextKey = new RawContextKey<boolean>('customTreeView', false);
@@ -225,7 +236,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
@INotificationService private readonly notificationService: INotificationService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IHoverService private readonly hoverService: IHoverService,
@IContextKeyService contextKeyService: IContextKeyService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IActivityService private readonly activityService: IActivityService,
@ILogService private readonly logService: ILogService
) {
@@ -617,7 +628,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
const selection = this.tree!.getSelection();
const command = await this.resolveCommand(selection.length === 1 ? selection[0] : undefined);
if (command) {
if (command && isTreeCommandEnabled(command, this.contextKeyService)) {
let args = command.arguments || [];
if (command.id === API_OPEN_EDITOR_COMMAND_ID || command.id === API_OPEN_DIFF_EDITOR_COMMAND_ID) {
// Some commands owned by us should receive the
@@ -632,7 +643,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
this._register(treeMenus.onDidChange((changed) => this.tree?.rerender(changed)));
}
private async resolveCommand(element: ITreeItem | undefined): Promise<Command | undefined> {
private async resolveCommand(element: ITreeItem | undefined): Promise<TreeCommand | undefined> {
let command = element?.command;
if (element && !command) {
if ((element instanceof ResolvableTreeItem) && element.hasResolve) {
@@ -1032,14 +1043,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
let commandEnabled = true;
if (node.command) {
const command = CommandsRegistry.getCommand(node.command.originalId ? node.command.originalId : node.command.id);
if (command) {
const commandAction = MenuRegistry.getCommand(command.id);
const precondition = commandAction && commandAction.precondition;
if (precondition) {
commandEnabled = this.contextKeyService.contextMatchesRules(precondition);
}
}
commandEnabled = isTreeCommandEnabled(node.command, this.contextKeyService);
}
if (resource) {
+3 -1
View File
@@ -731,6 +731,8 @@ export interface ITreeItemLabel {
}
export type TreeCommand = Command & { originalId?: string };
export interface ITreeItem {
handle: string;
@@ -755,7 +757,7 @@ export interface ITreeItem {
contextValue?: string;
command?: Command & { originalId?: string };
command?: TreeCommand;
children?: ITreeItem[];