Completion 进阶
基础 Completion 能返回建议列表,进阶能力让补全「更聪明」:模板补全带占位符、插入后自动执行命令、智能默认选择。
CompletionItemKind 类型与图标映射
kind 决定补全项图标,理解映射关系能精准控制视觉表现:
typescript
// 类型 → 图标映射速查
const kindIcons: Record<vscode.CompletionItemKind, string> = {
[vscode.CompletionItemKind.Text]: '符号',
[vscode.CompletionItemKind.Method]: '方法',
[vscode.CompletionItemKind.Function]: '函数',
[vscode.CompletionItemKind.Constructor]: '构造器',
[vscode.CompletionItemKind.Field]: '字段',
[vscode.CompletionItemKind.Variable]: '变量',
[vscode.CompletionItemKind.Class]: '类',
[vscode.CompletionItemKind.Interface]: '接口',
[vscode.CompletionItemKind.Module]: '模块',
[vscode.CompletionItemKind.Property]: '属性',
[vscode.CompletionItemKind.Unit]: '单位',
[vscode.CompletionItemKind.Value]: '值',
[vscode.CompletionItemKind.Enum]: '枚举',
[vscode.CompletionItemKind.Keyword]: '关键字',
[vscode.CompletionItemKind.Snippet]: '代码片段',
[vscode.CompletionItemKind.Color]: '颜色',
[vscode.CompletionItemKind.File]: '文件',
[vscode.CompletionItemKind.Reference]: '引用',
[vscode.CompletionItemKind.Folder]: '文件夹',
[vscode.CompletionItemKind.EnumMember]: '枚举成员',
[vscode.CompletionItemKind.Constant]: '常量',
[vscode.CompletionItemKind.Struct]: '结构体',
[vscode.CompletionItemKind.Event]: '事件',
[vscode.CompletionItemKind.Operator]: '运算符',
[vscode.CompletionItemKind.TypeParameter]: '类型参数'
};常见类型速查
| 类型 | 图标 | 示例 |
|---|---|---|
| Method | 方法图标 | array.map |
| Function | 函数图标 | console.log |
| Class | 类图标 | HttpClient |
| Interface | 接口图标 | IDataSource |
| Keyword | 关键字图标 | return |
| Snippet | 片段图标 | for-loop |
SnippetString 模板补全
insertText 使用 SnippetString 实现带占位符的模板补全:
typescript
import * as vscode from 'vscode';
const item = new vscode.CompletionItem('for-loop');
item.kind = vscode.CompletionItemKind.Snippet;
item.label = 'for-loop (循环)';
// 模板:插入后光标定位到占位符
item.insertText = new vscode.SnippetString(
'for (let i = 0; i < ${1:length}; i++) {\n' +
'\t${2}\n' +
'}'
);SnippetString 占位符语法
| 语法 | 效果 |
|---|---|
${1} | 第一个 Tab 停靠点 |
${1:默认值} | 带默认文本 |
| `${1 | a,b,c |
$0 | 最终光标位置 |
${2:${1}} | 嵌套(联动输入) |
多个停靠点示例
typescript
// 函数模板:名称 → 参数 → 函数体
item.insertText = new vscode.SnippetString(
'function ${1:name}(${2:args}) {\n' +
'\t${3:body}\n' +
'}'
);
// 插入后依次 Tab:name → args → body → 行尾联动变量
typescript
// 名称与注释联动
item.insertText = new vscode.SnippetString(
'/** ${1:名称} */\n' +
'function ${1:名称}() {}'
);
// 修改第一处,第二处同步变化CompletionItem.command 补全后执行
插入补全后自动执行命令:
typescript
const item = new vscode.CompletionItem('import-fs');
item.insertText = new vscode.SnippetString(
'import * as fs from "fs";\n'
);
// 插入后触发参数补全
item.command = {
command: 'editor.action.triggerSuggest',
title: '再次触发补全'
};常用补全后命令
| 命令 | 效果 |
|---|---|
editor.action.triggerSuggest | 再次弹出补全 |
editor.action.triggerParameterHints | 触发参数提示 |
editor.action.triggerSignatureHelp | 触发签名帮助 |
业务命令
typescript
// 插入后执行插件自定义命令
item.command = {
command: 'myExt.afterInsert',
title: '插入后处理',
arguments: [item]
};
// 注册命令
vscode.commands.registerCommand('myExt.afterInsert', (item) => {
vscode.window.showInformationMessage(
`已插入 ${item.label}`
);
});preselect 默认选择
preselect: true 让该项默认选中(输入框自动高亮):
typescript
// 首选建议
const primary = new vscode.CompletionItem('primary');
primary.preselect = true;
// 其他建议
const other = new vscode.CompletionItem('other');
other.preselect = false;使用场景
| 场景 | 说明 |
|---|---|
| 高频项 | 常用关键字默认选中 |
| 上下文推断 | 当前位置最可能的补全 |
| 单选项 | 只有一个候选时直接选中 |
注意事项
- 所有补全项中 preselect 项优先选中
- 多个 preselect 时取第一个
- 用户输入后自动过滤
完整示例:快捷键模板补全
typescript
import * as vscode from 'vscode';
// 模板库
const TEMPLATES = [
{
label: 'console-log',
detail: '打印日志',
body: 'console.log(${1:value});$0'
},
{
label: 'try-catch',
detail: '异常捕获',
body: 'try {\n\t${1}\n} catch (${2:error}) {\n\t${3:console.error(error)}\n}$0'
},
{
label: 'async-function',
detail: '异步函数',
body: 'async function ${1:name}(${2:args}) {\n\t${3}\n}$0'
}
];
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
'javascript',
{
provideCompletionItems(document, position) {
return TEMPLATES.map((template) => {
const item = new vscode.CompletionItem(template.label);
item.kind = vscode.CompletionItemKind.Snippet;
item.detail = template.detail;
item.sortText = '0'; // 模板排最前
item.insertText = new vscode.SnippetString(template.body);
item.documentation = new vscode.MarkdownString(
`**${template.label}**\n\n${template.detail}`
);
return item;
});
}
},
'.', '/'
)
);
}进阶优化清单
| 优化项 | 实现 |
|---|---|
| 模板联动 | SnippetString 变量引用 |
| 参数提示 | command 触发参数补全 |
| 默认选中 | preselect: true |
| 排序控制 | sortText 权重 |
| 图标准确 | kind 精确匹配 |
常见问题
| 问题 | 处理 |
|---|---|
| 模板不换行 | SnippetString 中写 \n 或真实换行 |
| 占位符失效 | 确认 insertText 是 SnippetString |
| 命令不执行 | 确认命令已注册 |
| preselect 无效 | 检查是否有多个 preselect |
Completion 进阶能力让补全从「列出选项」升级为「智能输入助手」,模板与命令结合可实现高效编码体验。