跳到主要内容

诊断是服务器推还是客户端拉?

结论​

传统模型是服务器推:算完就发 textDocument/publishDiagnostics 通知。协议 3.17 起还可以由客户端拉取 textDocument/diagnostic。现有插件两者都要认识,面试里先讲推模型,再补一句拉模型。

展开​

推模型:

  • 服务器在打开、变更或保存后自己决定何时计算
  • 通知不带请求 id,客户端不用回复
  • 参数里是 URI 和诊断数组
  • 对同一个 URI,这次数组就是该服务器的完整结果,客户端用它覆盖旧波浪线
  • 数组为空表示这个问题来源已清空

服务器通常要防抖,避免每个按键都全量类型检查。计算要用文档版本号,版本落后就丢弃。

拉模型:

  • 客户端在它认为合适的时候请求诊断
  • 服务器实现 textDocument/diagnostic,工作区级还可以有 workspace/diagnostic
  • 好处是客户端能统一调度、取消、把诊断和可见编辑器对齐
  • 服务器要声明对应能力,旧客户端不会拉

VS Code 语言客户端两种都能接。不要又推又拉各维护一套互不相干的结果,否则波浪线会闪或重复。

诊断相关的数据,例如关联信息、代码、标签,留在协议诊断对象里。快速修复是另一条能力 textDocument/codeAction,用诊断码把修复项关联回去。

容易讲错的点​

  • publishDiagnostics 是通知,不是客户端定时来 poll 的接口。
  • 服务器推的诊断和扩展宿主里手写的 DiagnosticCollection 不要对同一批错误各写一遍。
  • 清空诊断要显式发空列表或删除。不发并不等于编辑器会自动消失。