杂项

实现注意事项

语言服务器通常在单独的进程中运行,客户端以异步方式与它们通信。此外,客户端通常允许用户与源代码进行交互,即使请求结果处于待处理状态。建议采用以下实现模式,以避免客户端应用过时的响应结果:

  • 如果客户端向服务器发送请求,并且客户端状态发生更改,使响应无效,则应执行以下操作:

    • 取消服务器请求,如果结果对客户端不再有用,则忽略该结果。如有必要,客户端应重新发送请求。
    • 如果客户端仍可以使用结果,例如,通过将状态更改应用于结果将其转换为新结果,则保持请求运行。
  • 因此,服务器不应仅仅因为在队列中检测到状态更改通知而自行决定取消请求。如前所述,结果对客户仍然有用。

  • 如果服务器检测到内部状态更改(例如,项目上下文已更改)使执行中的请求结果无效,则服务器可能会使用 ContentModified 错误响应这些请求。如果客户端收到 ContentModified 错误,则通常不应在最终用户的 UI 中显示该错误。如果客户端知道如何重新发送请求,则可以重新发送请求。应该注意的是,对于所有基于位置的请求,客户可能特别难以重新编写请求。

  • 客户端不应发送针对过期对象(例如,Code Lenses等)的解析请求。如果服务器收到过期对象的解析请求,则服务器可能会使用 ContentModified 错误响应这些请求。

  • 如果客户端注意到服务器意外退出,则应尝试重新启动服务器。但是,客户端应注意不要无休止地重新启动崩溃的服务器。例如,VS Code 不会重新启动在过去 180 秒内崩溃 5 次的服务器。

服务器通常支持不同的通信通道(例如 stdio、管道等)。为了简化服务器在不同客户端中的使用,强烈建议服务器实现支持以下命令行参数来选择通信通道:

  • stdio: 使用 stdio 作为通信信道

  • pipe: 使用管道(Windows)或套接字文件(Linux、Mac)作为通信通道。管道/套接字文件名作为下一个参数或带有 --pipe= 传递。

  • socket: 使用套接字作为通信通道。端口作为下一个参数 或 --port= 传递。

  • node-ipc: 在客户端和服务器之间使用 node IPC 通信。仅当客户端和服务器都在 node 下运行时,才支持此功能。

为了支持启动服务器的编辑器崩溃的情况,编辑器还应将其进程 ID 传递给服务器。这允许服务器监视编辑器进程,并在编辑器进程终止时自行关闭。在命令行上传递的进程 ID 应与在 initialize 参数中传递的进程 ID 相同。要使用的命令行参数是 --clientProcessId

元模型

从 3.17 开始,有一个描述 LSP 协议的元模型:

  • metaModel.json: LSP 3.17 规范的实际元模型
  • metaModel.ts: 定义构成元模型的数据类型的 TypeScript 文件。
  • metaModel.schema.json: 定义构成元模型的数据类型的 JSON 架构文件。可用于生成代码以读取元模型 JSON 文件。