语言服务器协议(Language Server Protocol,LSP)是 VS Code 推出的一种协议,用于将编辑器功能与特定语言实现分离,实现代码补全、跳转定义、错误检查等智能功能。
LSP 架构
LSP 采用客户端-服务器架构:
- 客户端: VS Code 编辑器,负责 UI 和用户交互
- 服务器: 语言服务器,负责语言特定的分析功能
两者通过 JSON-RPC 协议通信。
核心功能
代码补全(Completion)
typescript// 客户端请求 { "jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { "textDocument": { "uri": "file:///path/to/file.ts" }, "position": { "line": 5, "character": 10 } } } // 服务器响应 { "jsonrpc": "2.0", "id": 1, "result": { "isIncomplete": false, "items": [ { "label": "console", "kind": 3, "detail": "any", "documentation": "The console module..." } ] } }
跳转定义(Go to Definition)
typescript{ "method": "textDocument/definition", "params": { "textDocument": { "uri": "..." }, "position": { "line": 0, "character": 0 } } }
悬停提示(Hover)
typescript{ "method": "textDocument/hover", "params": { "textDocument": { "uri": "..." }, "position": { "line": 0, "character": 0 } } }
诊断信息(Diagnostics)
服务器主动推送错误和警告信息:
typescript{ "method": "textDocument/publishDiagnostics", "params": { "uri": "file:///path/to/file.ts", "diagnostics": [ { "range": { "start": { "line": 0, "character": 0 }, "end": { "line": 0, "character": 5 } }, "severity": 1, "message": "Cannot find name 'foo'" } ] } }
VS Code 扩展中的 LSP
创建语言服务器扩展
- 安装依赖
bashnpm install vscode-languageclient --save
- 配置 package.json
json{ "contributes": { "languages": [{ "id": "mylang", "aliases": ["My Language", "mylang"], "extensions": [".mylang"] }], "grammars": [{ "language": "mylang", "scopeName": "source.mylang", "path": "./syntaxes/mylang.tmLanguage.json" }] }, "activationEvents": [ "onLanguage:mylang" ] }
- 实现客户端
typescriptimport * as vscode from 'vscode'; import { LanguageClient, LanguageClientOptions } from 'vscode-languageclient'; let client: LanguageClient; export function activate(context: vscode.ExtensionContext) { const serverOptions = { command: 'node', args: [context.asAbsolutePath('server/out/server.js')] }; const clientOptions: LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'mylang' }], synchronize: { configurationSection: 'mylang' } }; client = new LanguageClient( 'mylang', 'My Language Server', serverOptions, clientOptions ); client.start(); }
常见语言服务器
- TypeScript:
vscode-typescript-next - Python:
python-language-server(Pylance) - Go:
gopls - Rust:
rust-analyzer - Java:
jdt.ls
LSP 优势
- 跨编辑器支持: 同一个语言服务器可用于多个编辑器
- 解耦: 编辑器与语言实现分离
- 性能优化: 语言服务器可以独立优化
- 可扩展: 易于添加新的语言功能
性能优化
延迟初始化
typescriptconst clientOptions: LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'mylang' }], initializationOptions: { deferInitialization: true } };
增量分析
只分析文件变化部分,而非整个项目。
注意事项
- 语言服务器应正确处理并发请求
- 实现取消机制以避免资源浪费
- 提供清晰的错误信息
- 考虑内存使用和性能
- 支持工作区配置