diff --git a/docs/Extensions.md b/docs/Extensions.md index bb7fb59e..ccf4e714 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -39,4 +39,10 @@ You can see the [vscode-xml-maven](https://github.com/angelozerr/vscode-xml-mave ## XML extension API (TypeScript) -See [PR 292](https://github.com/redhat-developer/vscode-xml/pull/292) \ No newline at end of file +See [PR 292](https://github.com/redhat-developer/vscode-xml/pull/292) + +### Commands + +`xml.workspace.executeCommand` - command registered on VSCode client (via **vscode-xml** extension) to let other extensions execute commands on XML Language server + +`xml/executeClientCommand` - XML Language server LSP extension to let XML LS extenders execute commands on the client. The command is made available via `IXMLCommandService` on the server side. See [XML LS extensions docs](https://github.com/eclipse/lemminx/blob/master/docs/LemMinX-Extensions.md#xml-language-server-services-available-for-extensions) diff --git a/src/commands.ts b/src/commands.ts index 2202cf4b..7668ef03 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -50,4 +50,9 @@ export namespace Commands { export const OPEN_DOCS = "xml.open.docs"; export const OPEN_DOCS_HOME = "xml.open.docs.home"; + + /** + * VSCode client command to executes an LSP command on the XML Language Server + */ + export const EXECUTE_WORKSPACE_COMMAND = "xml.workspace.executeCommand"; } \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 4bf4c9b1..97a95589 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,7 +11,22 @@ */ import { prepareExecutable } from './javaServerStarter'; -import { LanguageClientOptions, RevealOutputChannelOn, LanguageClient, DidChangeConfigurationNotification, RequestType, TextDocumentPositionParams, ReferencesRequest, NotificationType, MessageType, ConfigurationRequest, ConfigurationParams } from 'vscode-languageclient'; +import { + LanguageClientOptions, + RevealOutputChannelOn, + LanguageClient, + DidChangeConfigurationNotification, + RequestType, + TextDocumentPositionParams, + ReferencesRequest, + NotificationType, + MessageType, + ConfigurationRequest, + ConfigurationParams, + ExecuteCommandParams, + CancellationToken, + ExecuteCommandRequest +} from 'vscode-languageclient'; import * as requirements from './requirements'; import { languages, IndentAction, workspace, window, commands, ExtensionContext, TextDocument, Position, LanguageConfiguration, Uri, extensions, Command, TextEditor } from "vscode"; import * as path from 'path'; @@ -114,6 +129,10 @@ export interface XMLExtensionApi { } +namespace ExecuteClientCommandRequest { + export const type: RequestType = new RequestType('xml/executeClientCommand') +} + namespace TagCloseRequest { export const type: RequestType = new RequestType('xml/closeTag'); } @@ -240,6 +259,30 @@ export function activate(context: ExtensionContext) { setupActionableNotificationListener(languageClient); + // Handler for 'xml/executeClientCommand` request message that executes a command on the client + languageClient.onRequest(ExecuteClientCommandRequest.type, async (params: ExecuteCommandParams) => { + return await commands.executeCommand(params.command, ...params.arguments); + }); + + // Register client command to execute custom XML Language Server command + context.subscriptions.push(commands.registerCommand(Commands.EXECUTE_WORKSPACE_COMMAND, (command, ...rest) => { + let token: CancellationToken; + let commandArgs: any[] = rest; + if (rest && rest.length && CancellationToken.is(rest[rest.length - 1])) { + token = rest[rest.length - 1]; + commandArgs = rest.slice(0, rest.length - 1); + } + const params: ExecuteCommandParams = { + command, + arguments: commandArgs + }; + if (token) { + return languageClient.sendRequest(ExecuteCommandRequest.type, params, token); + } else { + return languageClient.sendRequest(ExecuteCommandRequest.type, params); + } + })); + context.subscriptions.push(commands.registerCommand(Commands.OPEN_SETTINGS, async (settingId?: string) => { commands.executeCommand('workbench.action.openSettings', settingId); }));