From fd968feeea7e0136278d915fbcdc3503fe6aadf0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 11 Nov 2020 10:02:21 +0100 Subject: [PATCH 1/2] wip --- src/vs/workbench/api/common/apiCommands.ts | 19 ++++++++++++++++++- .../contrib/views/browser/treeView.ts | 10 ++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/common/apiCommands.ts b/src/vs/workbench/api/common/apiCommands.ts index eaf1c90ec2d2d..d91c593cfa49c 100644 --- a/src/vs/workbench/api/common/apiCommands.ts +++ b/src/vs/workbench/api/common/apiCommands.ts @@ -7,7 +7,7 @@ import type * as vscode from 'vscode'; import { URI } from 'vs/base/common/uri'; import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands'; -import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -17,6 +17,7 @@ import { Schemas } from 'vs/base/common/network'; import { ILogService } from 'vs/platform/log/common/log'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IViewDescriptorService, IViewsService, ViewVisibilityState } from 'vs/workbench/common/views'; +import { SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; // ----------------------------------------------------------------- // The following commands are registered on both sides separately. @@ -113,6 +114,19 @@ CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand export class OpenAPICommand { public static readonly ID = 'vscode.open'; public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions, label?: string): Promise { + const internalTypes = OpenAPICommand._toInternalTypes(columnOrOptions); + + return OpenAPICommand._doExecute(executor, resource, internalTypes.options, internalTypes.position, label); + } + public static executeWithContext(executor: ICommandsExecutor, context: { editorOptions: IEditorOptions; sideBySide: boolean }, resource: URI, columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions, label?: string): Promise { + const internalTypes = OpenAPICommand._toInternalTypes(columnOrOptions); + + const options = { ...(internalTypes.options ?? Object.create(null)), ...context.editorOptions }; + const position = context.sideBySide ? SIDE_GROUP : internalTypes.position; + + return OpenAPICommand._doExecute(executor, resource, options, position, label); + } + private static _toInternalTypes(columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions): { position: number | undefined, options: ITextEditorOptions | undefined } { let options: ITextEditorOptions | undefined; let position: EditorViewColumn | undefined; @@ -125,6 +139,9 @@ export class OpenAPICommand { } } + return { position, options }; + } + private static _doExecute(executor: ICommandsExecutor, resource: URI, options: ITextEditorOptions | undefined, position: number | undefined, label: string | undefined): Promise { return executor.executeCommand('_workbench.open', [ resource, options, diff --git a/src/vs/workbench/contrib/views/browser/treeView.ts b/src/vs/workbench/contrib/views/browser/treeView.ts index 1f03a2b9bbca1..c6cb6be9edefa 100644 --- a/src/vs/workbench/contrib/views/browser/treeView.ts +++ b/src/vs/workbench/contrib/views/browser/treeView.ts @@ -45,6 +45,7 @@ import { IHoverDelegate, IHoverDelegateOptions } from 'vs/base/browser/ui/iconLa import { IMarkdownString } from 'vs/base/common/htmlContent'; import { IIconLabelMarkdownString } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer'; +import { OpenAPICommand } from 'vs/workbench/api/common/apiCommands'; class Root implements ITreeItem { label = { label: 'root' }; @@ -462,8 +463,13 @@ export class TreeView extends Disposable implements ITreeView { return; } const selection = this.tree!.getSelection(); - if ((selection.length === 1) && selection[0].command) { - this.commandService.executeCommand(selection[0].command.id, ...(selection[0].command.arguments || [])); + const command = selection[0].command; + if ((selection.length === 1) && command) { + if (command.id === OpenAPICommand.ID) { + OpenAPICommand.executeWithContext(this.commandService, e, command.arguments?.[0], command.arguments?.[1], command.arguments?.[2]); + } else { + this.commandService.executeCommand(command.id, ...(command.arguments || [])); + } } })); From 27f7f712d97bea2eafabcabd07c1eb06c177dee9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 11 Nov 2020 15:46:01 +0100 Subject: [PATCH 2/2] allow certain commands to pass --- src/vs/workbench/api/common/apiCommands.ts | 10 ++--- .../workbench/api/common/extHostCommands.ts | 37 ++++++++++++------- .../api/common/extHostTypeConverters.ts | 6 ++- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/api/common/apiCommands.ts b/src/vs/workbench/api/common/apiCommands.ts index d91c593cfa49c..3bee9cc09c5a6 100644 --- a/src/vs/workbench/api/common/apiCommands.ts +++ b/src/vs/workbench/api/common/apiCommands.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import type * as vscode from 'vscode'; -import { URI } from 'vs/base/common/uri'; +import { URI, UriComponents } from 'vs/base/common/uri'; import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands'; import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; @@ -113,12 +113,12 @@ CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand export class OpenAPICommand { public static readonly ID = 'vscode.open'; - public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions, label?: string): Promise { + public static execute(executor: ICommandsExecutor, resource: UriComponents, columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions, label?: string): Promise { const internalTypes = OpenAPICommand._toInternalTypes(columnOrOptions); return OpenAPICommand._doExecute(executor, resource, internalTypes.options, internalTypes.position, label); } - public static executeWithContext(executor: ICommandsExecutor, context: { editorOptions: IEditorOptions; sideBySide: boolean }, resource: URI, columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions, label?: string): Promise { + public static executeWithContext(executor: ICommandsExecutor, context: { editorOptions: IEditorOptions; sideBySide: boolean }, resource: UriComponents, columnOrOptions?: vscode.ViewColumn | typeConverters.TextEditorOpenOptions, label?: string): Promise { const internalTypes = OpenAPICommand._toInternalTypes(columnOrOptions); const options = { ...(internalTypes.options ?? Object.create(null)), ...context.editorOptions }; @@ -141,9 +141,9 @@ export class OpenAPICommand { return { position, options }; } - private static _doExecute(executor: ICommandsExecutor, resource: URI, options: ITextEditorOptions | undefined, position: number | undefined, label: string | undefined): Promise { + private static _doExecute(executor: ICommandsExecutor, resource: UriComponents, options: ITextEditorOptions | undefined, position: number | undefined, label: string | undefined): Promise { return executor.executeCommand('_workbench.open', [ - resource, + URI.revive(resource), options, position, label diff --git a/src/vs/workbench/api/common/extHostCommands.ts b/src/vs/workbench/api/common/extHostCommands.ts index c20a7a42ba7aa..521661bf6c20a 100644 --- a/src/vs/workbench/api/common/extHostCommands.ts +++ b/src/vs/workbench/api/common/extHostCommands.ts @@ -20,6 +20,7 @@ import { URI } from 'vs/base/common/uri'; import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; +import { DiffAPICommand, OpenAPICommand } from 'vs/workbench/api/common/apiCommands'; interface CommandHandler { callback: Function; @@ -247,20 +248,28 @@ export class CommandsConverter { if (command.command && isNonEmptyArray(command.arguments)) { // we have a contributed command with arguments. that - // means we don't want to send the arguments around - - const id = ++this._cachIdPool; - this._cache.set(id, command); - disposables.add(toDisposable(() => { - this._cache.delete(id); - this._logService.trace('CommandsConverter#DISPOSE', id); - })); - result.$ident = id; - - result.id = this._delegatingCommandId; - result.arguments = [id]; - - this._logService.trace('CommandsConverter#CREATE', command.command, id); + // means we don't want to send the arguments around unless + // we know exactly that the arguments are serializable + + if (command.command === OpenAPICommand.ID || command.command === DiffAPICommand.ID) { + // this enables `vscode.open` and `vscode.diff` to benefit + // from the actual editor options to use based on the context + // (e.g. invocation from a custom tree view) + result.arguments = command.arguments; + } else { + const id = ++this._cachIdPool; + this._cache.set(id, command); + disposables.add(toDisposable(() => { + this._cache.delete(id); + this._logService.trace('CommandsConverter#DISPOSE', id); + })); + result.$ident = id; + + result.id = this._delegatingCommandId; + result.arguments = [id]; + + this._logService.trace('CommandsConverter#CREATE', command.command, id); + } } return result; diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index ee870895848c5..b7f3f388790eb 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -85,6 +85,10 @@ export namespace Range { }; } + export function fromPositions(positions: PositionLike[]): editorRange.IRange { + return from({ start: positions[0], end: positions[1] }); + } + export function to(range: undefined): types.Range; export function to(range: editorRange.IRange): types.Range; export function to(range: editorRange.IRange | undefined): types.Range | undefined; @@ -1194,7 +1198,7 @@ export namespace TextEditorOpenOptions { pinned: typeof options.preview === 'boolean' ? !options.preview : undefined, inactive: options.background, preserveFocus: options.preserveFocus, - selection: typeof options.selection === 'object' ? Range.from(options.selection) : undefined, + selection: Array.isArray(options.selection) ? Range.fromPositions(options.selection) : typeof options.selection === 'object' ? Range.from(options.selection) : undefined, override: typeof options.override === 'boolean' ? false : undefined }; }