诊断是服务器推还是客户端拉?
结论
传统模型是服务器推:算完就发 textDocument/publishDiagnostics 通知。协议 3.17 起还可以由客户端拉取 textDocument/diagnostic。现有插件两者都要认识,面试里先讲推模型,再补一句拉模型。
展开
推模型:
- 服务器在打开、变更或保存后自己决定何时计算
- 通知不带请求 id,客户端不用回复
- 参数里是 URI 和诊断数组
- 对同一个 URI,这次数组就是该服务器的完整结果,客户端用它覆盖旧波浪线
- 数组为空表示这个问题来源已清空
服务器通常要防抖,避免每个按键都全量类型检查。计算要用文档版本号,版本落后就丢弃。
拉模型:
- 客户端在它认为合适的时候请求诊断
- 服务器实现
textDocument/diagnostic,工作区级还可以有workspace/diagnostic - 好处是客户端能统一调度、取消、把诊断和可见编辑器对齐
- 服务器要声明对应能力,旧客户端不会拉
VS Code 语言客户端两种都能接。不要又推又拉各维护一套互不相干的结果,否则波浪线会闪或重复。
诊断相关的数据,例如关联信息、代码、标签,留在协议诊断对象里。快速修复是另一条能力 textDocument/codeAction,用诊断码把修复项关联回去。
容易讲错的点
publishDiagnostics是通知,不是客户端定时来 poll 的接口。- 服务器推的诊断和扩展宿主里手写的
DiagnosticCollection不要对同一批错误各写一遍。 - 清空诊断要显式发空列表或删除。不发并不等于编辑器会自动消失。