调试适配器协议和语言服务器协议有什么相似?
结论
两者都是「编辑器做通用界面,独立进程做专业计算」的 JSON-RPC 协议。语言服务器协议服务编辑和语言,调试适配器协议服务断点、栈和变量。插件侧都是启动一个适配进程,并在能力协商后转发界面操作。
展开
相似点:
- 独立进程,崩溃和重计算不直接写进渲染进程
- 有初始化握手和能力声明
- 请求带 id,通知不带响应,长时间操作可取消
- VS Code 提供客户端,插件多半不用自己画调试图
调试适配器协议的界面是断点、继续、步过、变量、监视、调试控制台。适配器把这些翻译成具体运行时,例如 Node、Python、浏览器。
插件用 contributes.debuggers 声明类型和配置项,再用描述符工厂告诉编辑器怎么启动适配器:
- 可执行文件:编辑器替你拉起
- 服务器:适配器已经监听端口
- 内联:实现直接跑在扩展宿主里,只适合很轻的适配
配置来自 launch.json。resolveDebugConfiguration 可以在启动前补字段、阻止无效配置。
和语言服务器一样,远程时适配器要在有运行时和符号的那一侧。路径必须用远端看到的路径。
语言功能里的「调试时悬停求值」可以和调试会话合作,但不要把类型检查塞进调试适配器。
容易讲错的点
- 调试适配器不是第二套语言服务器。它不负责平时的补全。
- 内联适配器省进程,却把调试循环放回扩展宿主,复杂调试器不该这么做。
launch.json里的配置是用户数据。启动前要校验,不要拼进 shell 而不转义。