diff --git a/packages/language-server/lib/register/registerLanguageFeatures.ts b/packages/language-server/lib/register/registerLanguageFeatures.ts index 12575c59..520922e5 100644 --- a/packages/language-server/lib/register/registerLanguageFeatures.ts +++ b/packages/language-server/lib/register/registerLanguageFeatures.ts @@ -31,6 +31,7 @@ export function registerLanguageFeatures(server: LanguageServer) { semanticTokensProvider, diagnosticProvider, inlayHintProvider, + executeCommandProvider, experimental, } = server.initializeResult.capabilities; @@ -401,6 +402,17 @@ export function registerLanguageFeatures(server: LanguageServer) { }); }); } + if (executeCommandProvider) { + server.connection.onExecuteCommand(async (params, token) => { + for (const languageService of await server.project.getExistingLanguageServices()) { + if (languageService.executeCommand && languageService.getCommands().includes(params.command)) { + try { + return await languageService.executeCommand(params.command, params.arguments ?? [], token); + } catch { } + } + } + }); + } if (typeof inlayHintProvider === 'object' && inlayHintProvider.resolveProvider) { server.connection.languages.inlayHint.resolve(async (hint, token) => { return await lastInlayHintLs?.resolveInlayHint(hint, token) ?? hint; diff --git a/packages/language-server/lib/server.ts b/packages/language-server/lib/server.ts index b12fe739..fa2d7fb7 100644 --- a/packages/language-server/lib/server.ts +++ b/packages/language-server/lib/server.ts @@ -186,6 +186,11 @@ export function createServerBase( moreTriggerCharacter: [...new Set(capabilitiesArr.map(data => data.documentOnTypeFormattingProvider?.triggerCharacters ?? []).flat())].slice(1), } : undefined, + executeCommandProvider: capabilitiesArr.some(data => data.executeCommandProvider) + ? { + commands: [...new Set(capabilitiesArr.map(data => data.executeCommandProvider?.commands ?? []).flat())], + } + : undefined, }; if (!status.pullModelDiagnostics && status.initializeResult.capabilities.diagnosticProvider) { diff --git a/packages/language-service/lib/languageService.ts b/packages/language-service/lib/languageService.ts index f4856c8c..ff82bc13 100644 --- a/packages/language-service/lib/languageService.ts +++ b/packages/language-service/lib/languageService.ts @@ -38,6 +38,7 @@ import * as documentLinkResolve from './features/resolveDocumentLink'; import * as inlayHintResolve from './features/resolveInlayHint'; import * as workspaceSymbolResolve from './features/resolveWorkspaceSymbol'; import type { LanguageServiceContext, LanguageServiceEnvironment, LanguageServicePlugin } from './types'; +import { NoneCancellationToken } from './utils/cancellation'; import { UriMap, createUriMap } from './utils/uriMap'; export type LanguageService = ReturnType; @@ -188,11 +189,24 @@ function createLanguageServiceBase( tokenTypes: [...new Set(tokenTypes)], }; }, + getCommands: () => plugins.map(plugin => plugin.capabilities.executeCommandProvider?.commands ?? []).flat(), getTriggerCharacters: () => plugins.map(plugin => plugin.capabilities.completionProvider?.triggerCharacters ?? []).flat(), getAutoFormatTriggerCharacters: () => plugins.map(plugin => plugin.capabilities.documentOnTypeFormattingProvider?.triggerCharacters ?? []).flat(), getSignatureHelpTriggerCharacters: () => plugins.map(plugin => plugin.capabilities.signatureHelpProvider?.triggerCharacters ?? []).flat(), getSignatureHelpRetriggerCharacters: () => plugins.map(plugin => plugin.capabilities.signatureHelpProvider?.retriggerCharacters ?? []).flat(), + executeCommand(command: string, args: any[], token = NoneCancellationToken) { + for (const plugin of context.plugins) { + if (context.disabledServicePlugins.has(plugin[1])) { + continue; + } + if (!plugin[1].executeCommand || !plugin[0].capabilities.executeCommandProvider?.commands.includes(command)) { + continue; + } + return plugin[1].executeCommand(command, args, token); + } + }, + getDocumentFormattingEdits: format.register(context), getFoldingRanges: foldingRanges.register(context), getSelectionRanges: selectionRanges.register(context), diff --git a/packages/language-service/lib/types.ts b/packages/language-service/lib/types.ts index 9d5d01cc..db85f685 100644 --- a/packages/language-service/lib/types.ts +++ b/packages/language-service/lib/types.ts @@ -83,6 +83,9 @@ export type SemanticToken = [ export interface LanguageServicePlugin

{ name?: string; capabilities: { + executeCommandProvider?: { + commands: string[]; + }; selectionRangeProvider?: boolean; foldingRangeProvider?: boolean; linkedEditingRangeProvider?: boolean; @@ -133,8 +136,8 @@ export interface LanguageServicePlugin

{ codeActionKinds?: string[]; resolveProvider?: boolean; }; - // TODO: interFileDependencies diagnosticProvider?: { + // TODO: interFileDependencies workspaceDiagnostics?: boolean; }; fileReferencesProvider?: boolean; @@ -151,6 +154,7 @@ export interface EmbeddedCodeFormattingOptions { export interface LanguageServicePluginInstance

{ provide?: P; isAdditionalCompletion?: boolean; // volar specific + executeCommand?(command: string, args: any[], token: vscode.CancellationToken): ProviderResult; provideHover?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableProviderResult; provideDocumentSymbols?(document: TextDocument, token: vscode.CancellationToken): NullableProviderResult; provideDocumentHighlights?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableProviderResult;