vscode大纲视图依赖lsp的textdocument/documentsymbol请求,而非插件自解析;需注册语言客户端连接lsp服务,返回符合规范的documentsymbol[](含name、kind、range等字段),kind须用标准枚举值,解析须异步防卡顿。

Outline 提取依赖的是语言服务器,不是插件自己写解析器
VSCode 的大纲视图(Outline)默认不靠插件手动解析代码,而是通过 Language Server Protocol (LSP) 的 textDocument/documentSymbol 请求获取结构化符号。你开发的插件只需注册一个语言客户端,连接到已有的或自研的语言服务器——而不是用正则或 AST 库去硬解析源码。
常见误区是试图在插件里调用 acorn、@babel/parser 或 tree-sitter 直接做 Outline,这会导致:不支持跳转定位、丢失范围高亮、无法响应编辑时的动态更新、与 VSCode 的折叠/导航功能脱节。
- 如果你的目标语言已有成熟 LSP 实现(如
pyright、rust-analyzer、typescript-language-server),直接复用它最省事 - 若没有,需先实现一个最小可行 LSP 服务(哪怕只返回
DocumentSymbol),再让插件启动并连接它 - 插件侧核心配置在
package.json的contributes.languages和activationEvents,必须声明onLanguage:yourlang和onCommand:yourlang.outline类激活事件(如果需要手动触发)
documentSymbol 返回的数据结构决定 Outline 层级和图标
documentSymbol 响应必须返回 DocumentSymbol[],每个元素包含 name、kind、range、selectionRange 和可选的 children。VSCode 仅根据 kind(数字枚举)决定图标和默认折叠行为,例如:
{
"name": "fetchUser",
"kind": 12, // Method
"range": { "start": ..., "end": ... },
"selectionRange": { "start": ..., "end": ... },
"children": []
}
kind 必须使用 LSP 规范定义的值(12 = Method, 5 = Function, 9 = Class, 13 = Property 等),不能自定义字符串。错用会导致图标显示为问号、无法折叠、或被过滤掉。
- 嵌套层级靠
children数组实现,不是靠 range 包含关系自动推导 -
selectionRange应该比range更窄(例如只包函数名),否则点击 Outline 会选中整段代码而非仅跳转到声明位置 - 返回空数组或
null不会清空 Outline,只会显示 “No symbols found”;要隐藏 Outline 面板,得在插件里调用vscode.commands.executeCommand('workbench.view.explorer')切换视图(但通常不建议)
自研 LSP 时避免同步阻塞主线程,尤其在大文件场景
当用户打开一个 10MB 的配置脚本或生成代码时,documentSymbol 请求若在服务端同步解析 AST,会导致 VSCode Outline 面板卡死、输入延迟、甚至弹出“Extension host terminated”错误。
- 务必把解析逻辑放到 Worker 线程或子进程(Node.js 中用
worker_threads或child_process.fork) - 对超长文件(>5000 行)做采样或降级:只返回顶层符号,加注释说明 “file too large, showing top-level only”
- 缓存上次解析结果,仅当文件内容哈希变更时才重解析;VSCode 会发
textDocument/didChange通知,别忽略它 - 不要在
initialize阶段加载全部语法定义——按需加载,比如只在首次请求documentSymbol时初始化 parser
调试 Outline 不生效时优先检查三处日志
Outline 没反应,90% 不是插件代码问题,而是通信或协议层面断连。别急着重写解析逻辑,先看:
- 打开 VSCode 开发者工具(
Help → Toggle Developer Tools),筛选console.error,搜索documentSymbol或Response rejected - 在插件输出面板(
View → Output → 找到你的插件名或 Language Server)里确认是否收到textDocument/documentSymbol请求,以及响应是否符合 LSP JSON-RPC 格式(有jsonrpc: "2.0",id,result字段) - 运行
code --log-extension-host启动 VSCode,查看extensionHost.log中是否有Connection to server got closed或spawn ENOENT(说明 LSP 可执行文件路径不对)
真正难调的点往往藏在路径拼接错误(比如 ./server/server.js 在 Windows 上少了个 ./)、权限拒绝(Linux/macOS 下未 chmod +x)、或 Node.js 版本不兼容(LSP 服务用 Node 20 写,而插件 host 是 Node 18)。这些比语法树建模容易卡更久。











