跳到主要内容

常见语言功能分别注册哪个接口?

结论​

语言功能都挂在 vscode.languages 上,每个能力一个 register*Provider。诊断不走 Provider 回调,而是插件自己维护 DiagnosticCollection 再推给编辑器。

展开​

能力注册方式
补全registerCompletionItemProvider
悬停registerHoverProvider
跳转定义registerDefinitionProvider
查找引用registerReferenceProvider
格式化registerDocumentFormattingEditProvider,区间用 registerDocumentRangeFormattingEditProvider
代码操作registerCodeActionsProvider
代码透镜registerCodeLensProvider
内嵌提示registerInlayHintsProvider
语义高亮registerDocumentSemanticTokensProvider
诊断createDiagnosticCollection

Provider 的方法收到 document、position 或 range,以及 CancellationToken。返回 undefined 或空数组表示「我没有结果」,不要抛错挡住别的插件。

这些注册都返回 Disposable,放进 subscriptions。文档范围由 DocumentSelector 限制,不要在回调里先激活再判断语言,选择器阶段就该滤掉。

诊断是推模型:你在文档变化、保存或构建结束时 collection.set(uri, diagnostics)。编辑器负责画波浪线。

如果能力来自语言服务器,通常不要再手写这批 register,由语言客户端根据服务器的 capabilities 自动注册,避免两套结果叠在一起。

容易讲错的点​

  • 语法高亮(TextMate 语法)是 contributes.grammars,和语义高亮不是一条链路。
  • 代码片段是 contributes.snippets,不是补全 Provider。两者可以同时存在。
  • 格式化 Provider 返回的是 TextEdit[],真正应用由编辑器完成,不要在 Provider 里直接 editor.edit。