diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index 6d9a372c6149798cb4ccac7540bca9878932603f..3f191cfe3b20e1d740fb2b67f2435a35e886a805 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import type * as vscode from 'vscode'; import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import * as types from 'vs/workbench/api/common/extHostTypes'; @@ -12,7 +12,7 @@ import { IRawColorInfo, IWorkspaceEditDto, ICallHierarchyItemDto, IIncomingCallD import * as modes from 'vs/editor/common/modes'; import * as search from 'vs/workbench/contrib/search/common/search'; import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; -import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; +import { ApiCommand, ApiCommandArgument, ApiCommandResult, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { CustomCodeAction } from 'vs/workbench/api/common/extHostLanguageFeatures'; import { ICommandsExecutor, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand, OpenIssueReporter, OpenIssueReporterArgs } from './apiCommands'; import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -20,73 +20,9 @@ import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { IRange } from 'vs/editor/common/core/range'; import { IPosition } from 'vs/editor/common/core/position'; import { TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { ISelection } from 'vs/editor/common/core/selection'; //#region --- NEW world -export class ApiCommandArgument { - - static readonly Uri = new ApiCommandArgument('uri', 'Uri of a text document', v => URI.isUri(v), v => v); - static readonly Position = new ApiCommandArgument('position', 'A position in a text document', v => types.Position.isPosition(v), typeConverters.Position.from); - static readonly Range = new ApiCommandArgument('range', 'A range in a text document', v => types.Range.isRange(v), typeConverters.Range.from); - static readonly Selection = new ApiCommandArgument('selection', 'A selection in a text document', v => types.Selection.isSelection(v), typeConverters.Selection.from); - - static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof types.CallHierarchyItem, typeConverters.CallHierarchyItem.to); - - constructor( - readonly name: string, - readonly description: string, - readonly validate: (v: V) => boolean, - readonly convert: (v: V) => O - ) { } -} - -export class ApiCommandResult { - - constructor( - readonly description: string, - readonly convert: (v: V, apiArgs: any[], cmdConverter: CommandsConverter) => O - ) { } -} - -export class ApiCommand { - - constructor( - readonly id: string, - readonly internalId: string, - readonly description: string, - readonly args: ApiCommandArgument[], - readonly result: ApiCommandResult - ) { } - - register(commands: ExtHostCommands): IDisposable { - - return commands.registerCommand(false, this.id, async (...apiArgs) => { - - const internalArgs = this.args.map((arg, i) => { - if (!arg.validate(apiArgs[i])) { - throw new Error(`Invalid argument '${arg.name}' when running '${this.id}', receieved: ${apiArgs[i]}`); - } - return arg.convert(apiArgs[i]); - }); - - const internalResult = await commands.executeCommand(this.internalId, ...internalArgs); - return this.result.convert(internalResult, apiArgs, commands.converter); - }, undefined, this._getCommandHandlerDesc()); - } - - private _getCommandHandlerDesc(): ICommandHandlerDescription { - return { - description: this.description, - args: this.args, - returns: this.result.description - }; - } -} - - - - const newCommands: ApiCommand[] = [ // -- document highlights new ApiCommand( @@ -372,7 +308,7 @@ const newCommands: ApiCommand[] = [ export class ExtHostApiCommands { static register(commands: ExtHostCommands) { - newCommands.forEach(command => command.register(commands)); + newCommands.forEach(commands.registerApiCommand, commands); return new ExtHostApiCommands(commands).registerCommands(); } diff --git a/src/vs/workbench/api/common/extHostCommands.ts b/src/vs/workbench/api/common/extHostCommands.ts index 423169b484bbd09a0f5368b0c17bdca6c13f6677..f2ea5a89eb0047c405d2df4af0ebfe31feae49fe 100644 --- a/src/vs/workbench/api/common/extHostCommands.ts +++ b/src/vs/workbench/api/common/extHostCommands.ts @@ -14,13 +14,14 @@ import * as modes from 'vs/editor/common/modes'; import type * as vscode from 'vscode'; import { ILogService } from 'vs/platform/log/common/log'; import { revive } from 'vs/base/common/marshalling'; -import { Range } from 'vs/editor/common/core/range'; -import { Position } from 'vs/editor/common/core/position'; +import { IRange, Range } from 'vs/editor/common/core/range'; +import { IPosition, Position } from 'vs/editor/common/core/position'; 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, ICommandsExecutor, OpenAPICommand } from 'vs/workbench/api/common/apiCommands'; +import { ISelection } from 'vs/editor/common/core/selection'; interface CommandHandler { callback: Function; @@ -83,6 +84,26 @@ export class ExtHostCommands implements ExtHostCommandsShape { this._argumentProcessors.push(processor); } + registerApiCommand(apiCommand: ApiCommand): extHostTypes.Disposable { + + return this.registerCommand(false, apiCommand.id, async (...apiArgs) => { + + const internalArgs = apiCommand.args.map((arg, i) => { + if (!arg.validate(apiArgs[i])) { + throw new Error(`Invalid argument '${arg.name}' when running '${apiCommand.id}', receieved: ${apiArgs[i]}`); + } + return arg.convert(apiArgs[i]); + }); + + const internalResult = await this.executeCommand(apiCommand.internalId, ...internalArgs); + return apiCommand.result.convert(internalResult, apiArgs, this.converter); + }, undefined, { + description: apiCommand.description, + args: apiCommand.args, + returns: apiCommand.result.description + }); + } + registerCommand(global: boolean, id: string, callback: (...args: any[]) => T | Thenable, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable { this._logService.trace('ExtHostCommands#registerCommand', id); @@ -212,6 +233,8 @@ export class ExtHostCommands implements ExtHostCommandsShape { } } +export interface IExtHostCommands extends ExtHostCommands { } +export const IExtHostCommands = createDecorator('IExtHostCommands'); export class CommandsConverter { @@ -308,5 +331,39 @@ export class CommandsConverter { } -export interface IExtHostCommands extends ExtHostCommands { } -export const IExtHostCommands = createDecorator('IExtHostCommands'); + +export class ApiCommandArgument { + + static readonly Uri = new ApiCommandArgument('uri', 'Uri of a text document', v => URI.isUri(v), v => v); + static readonly Position = new ApiCommandArgument('position', 'A position in a text document', v => extHostTypes.Position.isPosition(v), extHostTypeConverter.Position.from); + static readonly Range = new ApiCommandArgument('range', 'A range in a text document', v => extHostTypes.Range.isRange(v), extHostTypeConverter.Range.from); + static readonly Selection = new ApiCommandArgument('selection', 'A selection in a text document', v => extHostTypes.Selection.isSelection(v), extHostTypeConverter.Selection.from); + + static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof extHostTypes.CallHierarchyItem, extHostTypeConverter.CallHierarchyItem.to); + + constructor( + readonly name: string, + readonly description: string, + readonly validate: (v: V) => boolean, + readonly convert: (v: V) => O + ) { } +} + +export class ApiCommandResult { + + constructor( + readonly description: string, + readonly convert: (v: V, apiArgs: any[], cmdConverter: CommandsConverter) => O + ) { } +} + +export class ApiCommand { + + constructor( + readonly id: string, + readonly internalId: string, + readonly description: string, + readonly args: ApiCommandArgument[], + readonly result: ApiCommandResult + ) { } +}