LSP (Language Server Protocol,语言服务器协议)是微软在 2016 年提出的一个开放标准,主要用来解决 编辑器/IDE 和 编程语言 支持之间“N × M”的组合爆炸问题。
LSP可以看成是编辑器和语言智能服务之间的“普通话”:
- 任何 编辑器 只要学会了听和说,就能和任何 语言 对话;
- 任何 语言 只要学会了听和说,就能在任何 编辑器 里提供智能提示。
本文从它解决了什么问题、是怎么工作的、以及它带来的影响三个方面来简单介绍下。
1. LSP 解决了什么问题?
在没有 LSP 之前,如果你想让一个编辑器(比如 VS Code)支持一种语言(比如 Python),你需要专门为 VS Code 写一个 Python 插件。这个插件要实现代码补全、跳转定义、错误提示等所有功能。
这就导致了一个“N × M”问题:
- 有 M 种编辑器(VS Code, Vim, Emacs, Sublime, Eclipse...)
- 有 N 种编程语言
- 你需要开发 N × M 个插件!
比如,JetBrains 为了让 IntelliJ 支持 Python,写了一套 Python 解析器;Vim 社区为了让 Vim 支持 Python,又得重新写一套;Emacs 社区还得再写一套……这简直是重复造轮子的灾难。
2. LSP 是怎么解决的?
LSP 的核心思想是解耦:把“语言相关的逻辑”从“编辑器相关的逻辑”中抽离出来。
它定义了一套标准的通信协议(基于 JSON-RPC),规定了编辑器和语言服务之间该如何对话。
这样一来,架构变成了这样:
- 语言方:只需实现一个语言服务器。它懂这门语言的语法、结构,负责提供代码补全、定义跳转等能力。
- 编辑器方:只需实现一个LSP 客户端。它不懂任何语言,只知道如何按照 LSP 协议向语言服务器发请求,并把返回的结果展示出来。
架构变成了 N + M:
- N 种语言各写 1 个 Language Server
- M 种编辑器各写 1 个 LSP Client
- 总共只需 N + M 个组件,所有编辑器都能共享所有语言的支持!
3. LSP 是怎么工作的?
可以把 LSP 想象成前端(编辑器)和后端(语言服务器)的 API 交互。它们之间通过类似 HTTP 请求的方式(JSON-RPC)传递消息。
常见的交互场景:用户把鼠标悬停在代码 print() 上,想看文档
- 编辑器(client)发请求: 编辑器告诉语言服务器:“用户当前在
main.py的第 10 行第 5 列,请求悬停提示。”{ "method": "textDocument/hover", "params": { "textDocument": { "uri": "file:///path/to/main.py" }, "position": { "line": 10, "character": 5 } } } - 语言服务器(server)处理并返回: 服务器解析代码,发现
print是内置函数,返回文档字符串。{ "result": { "contents": "print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)" } } - 编辑器(client)展示: 编辑器收到结果,在界面上弹出一个悬浮窗显示这段文档。
LSP 协议定义了大量这种标准方法,比如:
textDocument/completion:代码补全textDocument/definition:跳转到定义textDocument/references:查找所有引用textDocument/diagnostic:代码错误诊断(画红色波浪线)
4. LSP 的巨大影响
LSP 的出现彻底改变了编程工具的生态:
- 拯救了小众编辑器:像 Neovim、Emacs 这类原本需要极客自己折腾插件的编辑器,只要接入了 LSP 客户端,瞬间就能获得和大型 IDE 媲美的代码智能支持。
- VS Code 的成功基石:VS Code 当年能迅速崛起,LSP 功不可没。微软把 LSP 内置到 VS Code 中,让各种语言的支持变得极其容易接入。
- 多语言混编更轻松:在一个项目里同时用前端和 Go、Python?只要装上对应的 Language Server,编辑器就能同时处理多种语言,互不干扰。

702

被折叠的 条评论
为什么被折叠?



