LSP / LSIF

  • 概述
  • 实现
  • 规范
  • LSP
  • LSIF

什么是语言服务器协议?

为编程语言实现诸如自动补全、转到定义或悬停文档等功能的支持是一项重大的工作。传统上,这项工作必须为每个开发工具重复进行,因为每个工具都提供不同的API来实现相同的功能。

语言服务器背后的理念是,在服务器内部提供特定于语言的智能功能,该服务器可以通过启用进程间通信的协议与开发工具进行通信。

语言服务器协议(LSP)背后的理念是标准化工具和服务器之间如何通信的协议,这样单个语言服务器可以在多个开发工具中重复使用,并且工具可以以最小的努力支持多种语言。

LSP 对语言提供商和工具供应商来说都是一大福音!

工作原理

语言服务器作为一个单独的进程运行,开发工具使用 JSON-RPC 通过语言协议与服务器通信。下面是一个工具和语言服务器在日常编辑会话中如何通信的示例。

language server protocol

  • 用户在工具中打开一个文件(称为文档):工具通知语言服务器文档已打开(“textDocument/didOpen”)。从现在开始,文档内容的真实性不再在文件系统上,而是由工具保存在内存中。现在内容必须在工具和语言服务器之间同步。

  • 用户进行编辑:工具通知服务器文档更改(“textDocument/didChange”),语言服务器更新文档的语言表示。在此过程中,语言服务器分析此信息,并通知工具检测到的错误和警告(“textDocument/publishDiagnostics”)。

  • 用户对打开文档中的符号执行“转到定义”:工具向服务器发送一个“textDocument/definition”请求,包含两个参数:(1) 文档 URI 和 (2) 启动“转到定义”请求的文本位置。服务器响应文档 URI 和符号定义在文档中的位置。

  • 用户关闭文档(文件):工具发送一个“textDocument/didClose”通知,告知语言服务器文档现在不再在内存中。当前内容现在在文件系统上是最新的。

这个例子说明了协议如何在文档引用(URIs)和文档位置的级别与语言服务器通信。这些数据类型是编程语言中立的,适用于所有编程语言。这些数据类型并非处于编程语言领域模型的级别,后者通常提供抽象语法树和编译器符号(例如,解析的类型、命名空间等)。数据类型简单且与编程语言无关,这显著简化了协议。与在不同编程语言中标准化抽象语法树和编译器符号相比,标准化文本文档 URI 或光标位置要简单得多。

现在我们来更详细地看看“textDocument/definition”请求。下面是 C++ 文档中“转到定义”请求在开发工具和语言服务器之间传递的有效载荷。

这是请求

{
    "jsonrpc": "2.0",
    "id" : 1,
    "method": "textDocument/definition",
    "params": {
        "textDocument": {
            "uri": "file:///p%3A/mseng/VSCode/Playgrounds/cpp/use.cpp"
        },
        "position": {
            "line": 3,
            "character": 12
        }
    }
}

这是响应

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "uri": "file:///p%3A/mseng/VSCode/Playgrounds/cpp/provide.cpp",
        "range": {
            "start": {
                "line": 0,
                "character": 4
            },
            "end": {
                "line": 0,
                "character": 11
            }
        }
    }
}

当用户使用不同的语言时,开发工具通常会为每种编程语言启动一个语言服务器。下面的示例展示了用户处理 Java 和 SASS 文件的会话。

language server protocol

功能

并非每个语言服务器都能支持协议定义的所有功能。因此,LSP 提供了“能力”。一项能力将一组语言功能进行分组。开发工具和语言服务器使用能力声明它们支持的功能。例如,服务器声明它可以处理“textDocument/definition”请求,但可能不处理“workspace/symbol”请求。类似地,开发工具声明它能够在文档保存之前提供“即将保存”通知,以便服务器可以在保存之前计算文本编辑以格式化已编辑的文档。

请注意,语言服务器实际集成到特定工具的方式不由语言服务器协议定义,而是留给工具实现者。

LSP 提供商和消费者的库(SDK)

为了简化语言服务器和客户端的实现,有可用的库或 SDK。

  • 开发工具 SDK 每个开发工具通常都提供一个用于集成语言服务器的库。例如,对于 JavaScript/TypeScript,有 语言客户端 npm 模块。

  • 语言服务器 SDK 针对不同的实现语言,有用于以特定语言实现语言服务器的 SDK。例如,要使用 Node.js 实现语言服务器,有 语言服务器 npm 模块。

  • 来自西雅图和苏黎世的问候。
  • 点赞
  • 观看
  • 管理 Cookie
  • Microsoft © 2025 Microsoft