You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于vscode-languageserver的LSP实现:客户端向服务器发自定义请求方法

在vscode-languageserver中实现客户端到服务器的自定义请求/命令

我来帮你一步步搞定在vscode-languageserver里实现客户端到服务器的自定义请求,其实流程很清晰,分服务器端注册处理逻辑和客户端发送请求两部分,还能兼顾类型安全,下面是具体步骤:

第一步:定义共享类型(可选但推荐)

为了避免客户端和服务器端参数/返回值类型不匹配,建议把自定义请求的方法名、参数结构、返回结果结构抽成一个共享的TypeScript文件,两端都能引用:

// shared.ts
// 自定义请求的唯一方法名,确保两端完全一致
export const CustomCommandMethod = 'myExtension/doCustomAction';

// 客户端传给服务器的参数结构
export interface CustomCommandParams {
  targetFile: string;
  operation: string;
  extraData?: Record<string, any>;
}

// 服务器返回给客户端的结果结构
export interface CustomCommandResult {
  success: boolean;
  detail?: string;
  data?: any;
}

第二步:服务器端注册自定义请求处理器

在你的语言服务器代码里,用connection.onRequest方法注册对应方法名的处理逻辑,收到客户端请求后就会执行这里的代码:

// server.ts
import { createConnection, TextDocuments } from 'vscode-languageserver/node';
import { CustomCommandMethod, CustomCommandParams, CustomCommandResult } from './shared';

// 创建LSP连接
const connection = createConnection();
const documents = new TextDocuments();

// 注册自定义请求的处理函数
connection.onRequest(
  CustomCommandMethod,
  async (params: CustomCommandParams): Promise<CustomCommandResult> => {
    try {
      // 这里写你的自定义业务逻辑,比如解析文件、执行操作等
      connection.console.log(`收到自定义请求:处理文件 ${params.targetFile},执行操作 ${params.operation}`);
      
      // 模拟处理结果
      return {
        success: true,
        detail: `已完成 ${params.operation} 操作`,
        data: { processedFile: params.targetFile }
      };
    } catch (error) {
      // 处理错误并返回失败结果
      return {
        success: false,
        detail: error instanceof Error ? error.message : '处理请求时发生未知错误'
      };
    }
  }
);

// 启动文档监听和服务器
documents.listen(connection);
connection.listen();

第三步:客户端(VS Code插件)发送自定义请求

在你的VS Code插件代码里,获取语言客户端实例,用sendRequest方法发送请求,还能等待服务器返回的结果:

// extension.ts
import { ExtensionContext, window, commands } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node';
import { CustomCommandMethod, CustomCommandParams, CustomCommandResult } from './shared';

let client: LanguageClient;

export function activate(context: ExtensionContext) {
  // 配置服务器启动选项(根据你的服务器类型调整,这里是Node.js服务器)
  const serverOptions: ServerOptions = {
    run: { module: context.asAbsolutePath('./out/server.js') },
    debug: { module: context.asAbsolutePath('./out/server.js'), options: { execArgv: ['--inspect=6009'] } }
  };

  // 配置客户端选项
  const clientOptions: LanguageClientOptions = {
    documentSelector: [{ scheme: 'file', language: 'your-language' }], // 替换成你的语言标识符
    synchronize: {
      fileEvents: window.createFileSystemWatcher('**/*.your-ext') // 替换成你的文件扩展名
    }
  };

  // 创建并启动语言客户端
  client = new LanguageClient(
    'yourLanguageServer',
    '你的语言服务器',
    serverOptions,
    clientOptions
  );
  client.start();

  // 示例:注册一个VS Code命令,触发时发送自定义请求
  context.subscriptions.push(
    commands.registerCommand('myExtension.triggerCustomCommand', async () => {
      const activeEditor = window.activeTextEditor;
      if (!activeEditor) {
        window.showErrorMessage('请先打开一个文件');
        return;
      }

      // 构造请求参数
      const params: CustomCommandParams = {
        targetFile: activeEditor.document.uri.fsPath,
        operation: 'analyze',
        extraData: { timestamp: Date.now() }
      };

      try {
        // 发送请求并等待结果
        const result = await client.sendRequest<CustomCommandResult>(CustomCommandMethod, params);
        if (result.success) {
          window.showInformationMessage(result.detail || '操作成功');
        } else {
          window.showErrorMessage(result.detail || '操作失败');
        }
      } catch (error) {
        window.showErrorMessage(`发送请求失败:${error instanceof Error ? error.message : '未知错误'}`);
      }
    })
  );
}

export function deactivate(): Thenable<void> | undefined {
  return client?.stop();
}

额外提示

  • 如果你的自定义操作不需要返回结果(只需要通知服务器执行),可以用通知代替请求:服务器端用connection.onNotification注册处理器,客户端用client.sendNotification发送,用法和请求类似,只是没有返回值。
  • 一定要保证自定义方法名在客户端和服务器端完全一致,否则服务器会找不到对应的处理器,请求会失败。
  • 共享类型文件能帮你在开发阶段就发现类型不匹配的问题,大幅减少调试成本,非常推荐使用。

内容的提问来源于stack exchange,提问作者Alexey Nikiforov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:07:39