VSCode插件中如何正确注册HTML语言的CompletionItemProvider?

令狐焕焕 阅读 52

我在写一个VSCode扩展,想给HTML文件添加自定义代码补全,但注册后完全没反应。是不是provider的triggerCharacters或者documentSelector写错了?

我试过用vscode.languages.registerCompletionItemProvider('html', provider, '<'),也试过把documentSelector设成{ language: 'html' },但输入<的时候还是没触发。

<div>
  <!-- 在这里输入 < 时希望触发我的补全 -->
</div>
我来解答 赞 9 收藏
二维码
手机扫码查看
2 条解答
Mc.洺华
Mc.洺华 Lv1
看起来你在触发字符和注册方式上有点问题。先说最直接的解决方案吧。

首先确保你的 provider 注册时用了正确的 triggerCharacters,通常 HTML 的标签补全需要包含 < 这个字符。试试这个写法:

const provider = vscode.languages.registerCompletionItemProvider(
{ language: 'html' },
{
provideCompletionItems(document, position) {
// 你的补全逻辑
return [
new vscode.CompletionItem('my-custom-tag', vscode.CompletionItemKind.Property)
];
}
},
'<'
);


注意这里的 < 是必需的,而且要放在最后作为参数传入。documentSelector 直接用字符串 'html' 就行了,别用对象形式。

还有个小坑:VSCode 的扩展有时会缓存起来,修改后记得重启 VSCode 或者用命令清一下缓存。我之前也被这个坑过好几次,每次改完都不生效,烦死了。

如果还是不行,检查下你的 package.json 里 activationEvents 是否配置正确,至少要包含 onLanguage:html。这东西要是配错了,你的扩展根本不会被激活。

最后提醒一句:调试的时候可以多打些日志看看 provider 到底有没有被调用,这样排查问题更快。
点赞
2026-03-26 04:03
程序猿瑞娜
这个问题我之前踩过坑,给你几个关键点。

第一个坑是triggerCharacters的问题。你只设置了<作为触发字符,但VSCode内置的HTML补全已经把<占用了,你的provider可能被覆盖或者优先级不够。

第二个坑是documentSelector的写法。字符串写法虽然能用,但建议用对象形式,更精确。

代码给你,直接用这个:

const vscode = require('vscode');

function activate(context) {
const provider = vscode.languages.registerCompletionItemProvider(
{ language: 'html', scheme: 'file' },
{
provideCompletionItems(document, position, token, context) {
// 获取当前行内容,判断触发条件
const linePrefix = document.lineAt(position).text.substring(0, position.character);

// 可以根据前缀做过滤
if (!linePrefix.endsWith('<')) {
return undefined;
}

const item1 = new vscode.CompletionItem('my-div', vscode.CompletionItemKind.Snippet);
item1.insertText = new vscode.SnippetString('div class="$1">$2
');
item1.documentation = '自定义div片段';
item1.detail = 'My Extension';
// 关键:设置sortText让你的补全排在前面
item1.sortText = '0';

const item2 = new vscode.CompletionItem('my-span', vscode.CompletionItemKind.Snippet);
item2.insertText = new vscode.SnippetString('span>$1');
item2.sortText = '0';

return [item1, item2];
}
},
'<', ' ' // 多加几个触发字符
);

context.subscriptions.push(provider);
}

module.exports = { activate };


还有几个要注意的地方。

确保你的package.json里activationEvents包含了html文件,不然扩展压根没激活:

"activationEvents": [
"onLanguage:html"
],
"main": "./extension.js"


调试的时候,在provideCompletionItems里打个断点或者console.log,看看方法有没有被调用。如果根本没进这个方法,说明provider没注册成功或者扩展没激活。

如果进了方法但补全没显示,检查返回的CompletionItem数组是不是空的,或者insertText有没有问题。

另外,VSCode内置的HTML补全确实很强势,你可以试试在空行输入<,或者把triggerCharacters去掉让它自动触发,不要只依赖<这一个字符。
点赞
2026-03-01 14:37