From 821b9dc27653ea971f77e2b1f3771b7a4e44b1e0 Mon Sep 17 00:00:00 2001 From: Sven Efftinge Date: Mon, 30 Sep 2019 08:46:53 +0000 Subject: [PATCH] [plugin] support `vscode.executeDocumentSymbol` command. Signed-off-by: Sven Efftinge --- packages/monaco/src/browser/monaco-command.ts | 43 ++++++++++++++---- packages/monaco/src/typings/monaco/index.d.ts | 6 +++ .../plugin-vscode-commands-contribution.ts | 44 ++++++++++++++----- .../plugin-ext/src/plugin/type-converters.ts | 11 +++++ 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/packages/monaco/src/browser/monaco-command.ts b/packages/monaco/src/browser/monaco-command.ts index 6ba4815402801..7d120c345dae8 100644 --- a/packages/monaco/src/browser/monaco-command.ts +++ b/packages/monaco/src/browser/monaco-command.ts @@ -17,7 +17,7 @@ import { injectable, inject } from 'inversify'; import { ProtocolToMonacoConverter } from 'monaco-languageclient/lib'; import { Position, Location } from '@theia/languages/lib/browser'; -import { Command, CommandContribution } from '@theia/core'; +import { Command, CommandContribution, CommandRegistry } from '@theia/core'; import { CommonCommands } from '@theia/core/lib/browser'; import { QuickOpenService } from '@theia/core/lib/browser/quick-open/quick-open-service'; import { QuickOpenItem, QuickOpenMode } from '@theia/core/lib/browser/quick-open/quick-open-model'; @@ -91,7 +91,10 @@ export namespace MonacoCommands { export class MonacoEditorCommandHandlers implements CommandContribution { @inject(MonacoCommandRegistry) - protected readonly registry: MonacoCommandRegistry; + protected readonly monacoCommandRegistry: MonacoCommandRegistry; + + @inject(CommandRegistry) + protected readonly commandRegistry: CommandRegistry; @inject(ProtocolToMonacoConverter) protected readonly p2m: ProtocolToMonacoConverter; @@ -103,6 +106,28 @@ export class MonacoEditorCommandHandlers implements CommandContribution { this.registerCommonCommandHandlers(); this.registerEditorCommandHandlers(); this.registerMonacoActionCommands(); + this.registerInternalLanguageServiceCommands(); + } + + protected registerInternalLanguageServiceCommands(): void { + const instantiationService = monaco.services.StaticServices.instantiationService.get(); + const monacoCommands = monaco.commands.CommandsRegistry.getCommands(); + for (const command of monacoCommands.keys()) { + if (command.startsWith('_execute')) { + this.commandRegistry.registerCommand( + { + id: MonacoCommandRegistry.MONACO_COMMAND_PREFIX + command + }, + { + // tslint:disable-next-line:no-any + execute: (...args: any) => instantiationService.invokeFunction( + monacoCommands.get(command)!.handler, + ...args + ) + } + ); + } + } } protected registerCommonCommandHandlers(): void { @@ -110,7 +135,7 @@ export class MonacoEditorCommandHandlers implements CommandContribution { for (const action in MonacoCommands.COMMON_ACTIONS) { const command = MonacoCommands.COMMON_ACTIONS[action]; const handler = this.newCommonActionHandler(action); - this.registry.registerHandler(command, handler); + this.monacoCommandRegistry.registerHandler(command, handler); } } protected newCommonActionHandler(action: string): MonacoEditorCommandHandler { @@ -121,11 +146,11 @@ export class MonacoEditorCommandHandlers implements CommandContribution { } protected registerEditorCommandHandlers(): void { - this.registry.registerHandler(EditorCommands.SHOW_REFERENCES.id, this.newShowReferenceHandler()); - this.registry.registerHandler(EditorCommands.CONFIG_INDENTATION.id, this.newConfigIndentationHandler()); - this.registry.registerHandler(EditorCommands.CONFIG_EOL.id, this.newConfigEolHandler()); - this.registry.registerHandler(EditorCommands.INDENT_USING_SPACES.id, this.newConfigTabSizeHandler(true)); - this.registry.registerHandler(EditorCommands.INDENT_USING_TABS.id, this.newConfigTabSizeHandler(false)); + this.monacoCommandRegistry.registerHandler(EditorCommands.SHOW_REFERENCES.id, this.newShowReferenceHandler()); + this.monacoCommandRegistry.registerHandler(EditorCommands.CONFIG_INDENTATION.id, this.newConfigIndentationHandler()); + this.monacoCommandRegistry.registerHandler(EditorCommands.CONFIG_EOL.id, this.newConfigEolHandler()); + this.monacoCommandRegistry.registerHandler(EditorCommands.INDENT_USING_SPACES.id, this.newConfigTabSizeHandler(true)); + this.monacoCommandRegistry.registerHandler(EditorCommands.INDENT_USING_TABS.id, this.newConfigTabSizeHandler(false)); } protected newShowReferenceHandler(): MonacoEditorCommandHandler { @@ -241,7 +266,7 @@ export class MonacoEditorCommandHandlers implements CommandContribution { protected registerMonacoActionCommands(): void { for (const action of MonacoCommands.ACTIONS.values()) { const handler = this.newMonacoActionHandler(action); - this.registry.registerCommand(action, handler); + this.monacoCommandRegistry.registerCommand(action, handler); } } protected newMonacoActionHandler(action: MonacoCommand): MonacoEditorCommandHandler { diff --git a/packages/monaco/src/typings/monaco/index.d.ts b/packages/monaco/src/typings/monaco/index.d.ts index 9de50f9529a9c..06b57aa101b69 100644 --- a/packages/monaco/src/typings/monaco/index.d.ts +++ b/packages/monaco/src/typings/monaco/index.d.ts @@ -19,6 +19,7 @@ declare module monaco.instantiation { export interface IInstantiationService { + invokeFunction: (fn: any, ...args: any) => any } } @@ -273,6 +274,10 @@ declare module monaco.editor { declare module monaco.commands { + export const CommandsRegistry: { + getCommands(): Map any }>; + }; + export interface ICommandEvent { commandId: string; } @@ -514,6 +519,7 @@ declare module monaco.services { export const codeEditorService: LazyStaticService; export const configurationService: LazyStaticService; export const resourcePropertiesService: LazyStaticService; + export const instantiationService: LazyStaticService; } } diff --git a/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts b/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts index a545f59d2b996..352b039696d05 100644 --- a/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts +++ b/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts @@ -14,24 +14,23 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { injectable, inject } from 'inversify'; -import { CommandContribution, CommandRegistry, Command } from '@theia/core'; +import { Command, CommandContribution, CommandRegistry, ResourceProvider } from '@theia/core'; +import { ApplicationShell, NavigatableWidget, open, OpenerService, Saveable } from '@theia/core/lib/browser'; +import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; +import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker'; import { CommandService } from '@theia/core/lib/common/command'; import TheiaURI from '@theia/core/lib/common/uri'; -import URI from 'vscode-uri'; -import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; -import { DiffService } from '@theia/workspace/lib/browser/diff-service'; import { EditorManager } from '@theia/editor/lib/browser'; +import { TextDocumentShowOptions } from '@theia/plugin-ext/lib/common/plugin-api-rpc-model'; +import { DocumentsMainImpl } from '@theia/plugin-ext/lib/main/browser/documents-main'; +import { createUntitledResource } from '@theia/plugin-ext/lib/main/browser/editor/untitled-resource'; import { WebviewWidget } from '@theia/plugin-ext/lib/main/browser/webview/webview'; -import { ApplicationShell, NavigatableWidget, OpenerService, open, Saveable } from '@theia/core/lib/browser'; -import { ResourceProvider } from '@theia/core'; +import { fromViewColumn, toDocumentSymbol } from '@theia/plugin-ext/lib/plugin/type-converters'; import { ViewColumn } from '@theia/plugin-ext/lib/plugin/types-impl'; -import { TextDocumentShowOptions } from '@theia/plugin-ext/lib/common/plugin-api-rpc-model'; -import { fromViewColumn } from '@theia/plugin-ext/lib/plugin/type-converters'; import { WorkspaceCommands } from '@theia/workspace/lib/browser'; -import { createUntitledResource } from '@theia/plugin-ext/lib/main/browser/editor/untitled-resource'; -import { DocumentsMainImpl } from '@theia/plugin-ext/lib/main/browser/documents-main'; -import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker'; +import { DiffService } from '@theia/workspace/lib/browser/diff-service'; +import { inject, injectable } from 'inversify'; +import URI from 'vscode-uri'; export namespace VscodeCommands { export const OPEN: Command = { @@ -315,6 +314,27 @@ export class PluginVscodeCommandsContribution implements CommandContribution { * Show Opened File in New Window workbench.action.files.showOpenedFileInNewWindow * Compare Opened File With workbench.files.action.compareFileWith */ + + // Register built-in language service commands + // see https://code.visualstudio.com/api/references/commands + // tslint:disable: no-any + commands.registerCommand( + { + id: 'vscode.executeDocumentSymbolProvider' + }, + { + execute: (resource: URI) => commands.executeCommand('monaco._executeDocumentSymbolProvider', + { resource: monaco.Uri.parse(resource.toString()) } + ).then((value: any) => { + if (!Array.isArray(value) || value === undefined) { + return undefined; + } + return value.map(loc => toDocumentSymbol(loc)); + }) + } + ); + // TODO register other `vscode.execute...` commands. + // see https://github.com/microsoft/vscode/blob/master/src/vs/workbench/api/common/extHostApiCommands.ts } private getHtml(body: String): string { diff --git a/packages/plugin-ext/src/plugin/type-converters.ts b/packages/plugin-ext/src/plugin/type-converters.ts index d171652c580ab..3034c5654e722 100644 --- a/packages/plugin-ext/src/plugin/type-converters.ts +++ b/packages/plugin-ext/src/plugin/type-converters.ts @@ -642,6 +642,17 @@ export function fromDocumentSymbol(info: theia.DocumentSymbol): model.DocumentSy return result; } +export function toDocumentSymbol(symbol: model.DocumentSymbol): theia.DocumentSymbol { + return { + name: symbol.name, + detail: symbol.detail, + range: toRange(symbol.range)!, + selectionRange: toRange(symbol.selectionRange)!, + children: symbol.children ? symbol.children.map(toDocumentSymbol) : [], + kind: SymbolKind.toSymbolKind(symbol.kind) + }; +} + export function toWorkspaceFolder(folder: model.WorkspaceFolder): theia.WorkspaceFolder { return { uri: URI.revive(folder.uri),