常见语言功能分别注册哪个接口?
结论
语言功能都挂在 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。