跳到主要内容

调试适配器协议和语言服务器协议有什么相似?

结论​

两者都是「编辑器做通用界面,独立进程做专业计算」的 JSON-RPC 协议。语言服务器协议服务编辑和语言,调试适配器协议服务断点、栈和变量。插件侧都是启动一个适配进程,并在能力协商后转发界面操作。

展开​

相似点:

  • 独立进程,崩溃和重计算不直接写进渲染进程
  • 有初始化握手和能力声明
  • 请求带 id,通知不带响应,长时间操作可取消
  • VS Code 提供客户端,插件多半不用自己画调试图

调试适配器协议的界面是断点、继续、步过、变量、监视、调试控制台。适配器把这些翻译成具体运行时,例如 Node、Python、浏览器。

插件用 contributes.debuggers 声明类型和配置项,再用描述符工厂告诉编辑器怎么启动适配器:

  • 可执行文件:编辑器替你拉起
  • 服务器:适配器已经监听端口
  • 内联:实现直接跑在扩展宿主里,只适合很轻的适配

配置来自 launch.json。resolveDebugConfiguration 可以在启动前补字段、阻止无效配置。

和语言服务器一样,远程时适配器要在有运行时和符号的那一侧。路径必须用远端看到的路径。

语言功能里的「调试时悬停求值」可以和调试会话合作,但不要把类型检查塞进调试适配器。

容易讲错的点​

  • 调试适配器不是第二套语言服务器。它不负责平时的补全。
  • 内联适配器省进程,却把调试循环放回扩展宿主,复杂调试器不该这么做。
  • launch.json 里的配置是用户数据。启动前要校验,不要拼进 shell 而不转义。