语言服务器协议
语言服务器协议(Language Server Protocol,LSP)规定语言工具和编辑器怎么对话。语言服务器放在自己的进程里,用 JSON-RPC 收发请求。编辑器只实现一次客户端,就能接许多语言;一种语言服务器也能接到多个支持 LSP 的编辑器。
重计算离开扩展宿主后,不会把宿主的单线程堵住。服务器可以用任意语言编写。
在 VS Code 里的两半
- 语言客户端:一个普通扩展,跑在扩展宿主里,依赖
vscode-languageclient。激活后拉起服务器进程。 - 语言服务器:独立进程,实现补全、诊断、定义等。常用
vscode-languageserver。
用户悬停时,VS Code 通知客户端,客户端向服务器发 Hover 请求,再把结果交回编辑器显示。
直接用 languages.registerXxxProvider 适合轻量功能。语法分析、跨文件索引、类型检查更适合 LSP。
和扩展 API 的对应关系
官方文档把两侧对齐,例如:
| 扩展 API | 协议 |
|---|---|
registerHoverProvider | Hover |
registerCompletionItemProvider | Completion、Completion Resolve |
registerDefinitionProvider | Definition |
registerReferencesProvider | References |
registerCodeActionsProvider | Code Action |
createDiagnosticCollection | 诊断的发布或按文档拉取 |
registerRenameProvider | Rename、Prepare Rename |
registerDocumentFormattingEditProvider | Formatting |
文档同步与诊断方向
打开的文档要同步给服务器。全量同步每次把整个文本送过去,实现简单。增量同步只送变更范围,大文件更合适,服务器要自己把补丁打上。
诊断有两种方向:
- 推:服务器发
textDocument/publishDiagnostics。 - 拉:服务器声明诊断提供器,客户端发
textDocument/diagnostic来要。
生命周期要点
服务器有启动、初始化、处理请求、关闭这几个阶段。请求应带取消令牌:用户继续输入时,过期的补全不该再占用服务器。服务器崩溃或扩展重载时,客户端要关掉旧进程、丢掉旧诊断,避免问题面板里留下上一轮的结果。