VSCode扩展自定义CompletionItem如何保留内置IntelliSense补全建议
背景
我正在开发一款VSCode扩展,计划为代码补全功能提供自定义代码片段。
我了解可以直接通过snippet json文件实现自定义片段,但该方案存在局限性:无法使用CompletionItemKind属性设置补全弹窗中建议项旁的显示图标。
复现问题
实现如下简单的CompletionItemProvider时:
context.subscriptions.push( vscode.languages.registerCompletionItemProvider( {scheme:"file",language:"MyLang"}, { provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) { let item = new vscode.CompletionItem('test'); item.documentation = 'my test function'; item.kind = vscode.CompletionItemKind.Function; return [item]; } } ) )
VSCode原有的内置IntelliSense文本建议不再显示,仅展示自定义的补全项。如果在provideCompletionItems方法中返回空响应(null/空数组/undefined),内置补全建议就会恢复正常显示。
测试发现自定义补全提供程序的结果没有和内置IntelliSense结果合并,反而直接覆盖了内置补全结果。
核心诉求
如何在添加自定义CompletionItem的同时,保留VSCode内置的IntelliSense补全建议?
当前运行环境:Ubuntu系统,VSCode版本为v1.68.1
解决方法
这个问题是返回值格式不符合VSCode补全合并规则导致的:直接返回补全项数组时,VSCode会默认将当前提供程序作为该补全触发场景的唯一结果源,不会加载其他来源的补全内容,按以下方式修改即可:
- 不要直接返回补全项数组,返回
vscode.CompletionList实例,构造函数第二个参数isIncomplete固定传false,显式告知VSCode当前提供程序的结果已全部返回,可以合并其他来源(包括内置单词补全、其他扩展提供的补全项)的结果。 - 给自定义补全项设置合理的
sortText值,避免默认优先级过高把内置建议挤到列表末尾看不到,普通自定义片段建议设为'z'这类靠后的排序值,高频使用的项可适当调前。 - 注册补全提供程序时尽量指定触发字符,不要无差别拦截所有补全请求,减少不必要的冲突。
修复后的可运行示例代码:
context.subscriptions.push( vscode.languages.registerCompletionItemProvider( {scheme:"file",language:"MyLang"}, { provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) { const item = new vscode.CompletionItem('test'); item.documentation = 'my test function'; item.kind = vscode.CompletionItemKind.Function; // 自定义排序权重,字符串逐位比较,值越靠后排序越靠后 item.sortText = 'z'; // 关键:返回CompletionList,第二个参数传false允许合并其他补全源 return new vscode.CompletionList([item], false); } }, // 按需配置触发字符,比如输入.、@等特定字符时才触发自定义补全 // '.', '@' ) )
额外排查点:如果修改后仍然看不到内置补全,先检查两处配置:一是扩展内有没有其他逻辑修改了
editor.suggest.showWords这类控制内置补全开关的设置;二是有没有监听补全相关事件手动过滤、清空过补全列表。如果MyLang是你自定义的语言、没有配套官方语言服务,内置补全默认只有当前文件内的单词匹配建议,不会提供语法级的智能补全。
内容的提问来源于stack exchange,提问作者elod008

