自动补全 Completion
Completion(自动补全)是语言服务最常用的特性:输入时弹出候选列表,选中即插入代码。从关键字、函数名到代码片段,Completion 让编码更高效。
注册 Completion Provider
languages.registerCompletionItemProvider 注册补全提供器:
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
'plaintext', // 目标语言
{
provideCompletionItems(document, position, token, context) {
// 返回补全建议
return [
new vscode.CompletionItem('hello'),
new vscode.CompletionItem('world')
];
}
},
'.', '-' // 触发字符
)
);
}CompletionItem 详解
CompletionItem 是单个补全建议:
typescript
const item = new vscode.CompletionItem('map');
// 基础属性
item.kind = vscode.CompletionItemKind.Method; // 类型(决定图标)
item.detail = 'Array.prototype.map'; // 右侧描述
item.insertText = 'map('; // 插入文本
item.documentation = new vscode.MarkdownString(
'对数组每个元素执行回调函数'
);
item.sortText = '0'; // 排序权重
// 高级属性
item.filterText = 'map'; // 匹配文本
item.label = 'map'; // 显示标签
item.preselect = true; // 默认选中
item.command = {
command: 'editor.action.triggerSuggest',
title: '触发补全'
};核心属性表
| 属性 | 作用 |
|---|---|
label | 显示名称 |
kind | 类型(图标与分组) |
detail | 附加描述 |
insertText | 实际插入的文本 |
documentation | 悬停文档 |
sortText | 排序权重(影响位置) |
filterText | 匹配过滤文本 |
preselect | 是否默认选中 |
command | 插入后执行命令 |
CompletionItemKind 类型
kind 决定补全项的图标与语义:
typescript
// 常用 kind
vscode.CompletionItemKind.Text // 文本
vscode.CompletionItemKind.Method // 方法
vscode.CompletionItemKind.Function // 函数
vscode.CompletionItemKind.Class // 类
vscode.CompletionItemKind.Interface // 接口
vscode.CompletionItemKind.Module // 模块
vscode.CompletionItemKind.Property // 属性
vscode.CompletionItemKind.Variable // 变量
vscode.CompletionItemKind.Keyword // 关键字
vscode.CompletionItemKind.Snippet // 代码片段
vscode.CompletionItemKind.File // 文件
vscode.CompletionItemKind.Reference // 引用| kind | 图标示例 | 用途 |
|---|---|---|
| Method/Function | 紫色方块 | 函数 |
| Class | 黄色方块 | 类 |
| Keyword | 蓝色 | 关键字 |
| Snippet | 绿色方块 | 代码片段 |
| File | 文件图标 | 文件补全 |
CompletionList 返回建议列表
返回 CompletionList 可携带附加元数据:
typescript
provideCompletionItems(document, position) {
const items = [
new vscode.CompletionItem('item1'),
new vscode.CompletionItem('item2')
];
// 返回列表对象
return new vscode.CompletionList(items, false);
}CompletionList 参数
| 参数 | 作用 |
|---|---|
items | 建议数组 |
isIncomplete | 是否不完整(true 时用户继续输入会重新触发) |
返回数组 vs 列表
typescript
// 直接返回数组(简单场景)
return [item1, item2];
// 返回 CompletionList(需要 isIncomplete 标记)
return new vscode.CompletionList(items, true);Trigger Characters 触发字符
注册时的第三个参数定义自动触发补全的字符:
typescript
// 输入 . 或 - 时自动弹出补全
vscode.languages.registerCompletionItemProvider(
'plaintext',
provider,
'.', '-', ':' // 触发字符列表
);触发时机
| 时机 | 说明 |
|---|---|
| 手动触发 | Ctrl/Cmd + Space |
| 自动触发 | 输入触发字符后 |
| 重新触发 | 输入其他字符时(isIncomplete) |
触发字符与 token
输入触发字符时补全立即弹出,context.triggerCharacter 可获取触发来源:
typescript
provideCompletionItems(document, position, token, context) {
// 判断触发字符
if (context.triggerCharacter === '.') {
// 成员补全
return this.getMemberCompletions(document, position);
}
if (context.triggerCharacter === ':') {
// 标签补全
return this.getLabelCompletions(document, position);
}
// 手动触发
return this.getAllCompletions();
}位置上下文补全
根据当前输入内容动态生成建议:
typescript
provideCompletionItems(document, position) {
// 获取当前行已输入文本
const lineText = document.lineAt(position.line).text;
const prefix = lineText.slice(0, position.character);
// 按前缀过滤
const suggestions: vscode.CompletionItem[] = [];
for (const [name, doc] of FUNC_DOCS) {
if (name.startsWith(prefix.trim())) {
const item = new vscode.CompletionItem(name);
item.detail = '内置函数';
item.documentation = new vscode.MarkdownString(doc);
suggestions.push(item);
}
}
return suggestions;
}完整示例:CSS 颜色补全
typescript
import * as vscode from 'vscode';
const COLORS = ['red', 'green', 'blue', 'orange', 'purple'];
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
'css',
{
provideCompletionItems(document, position) {
// 获取当前输入前缀
const line = document.lineAt(position.line).text;
const before = line.slice(0, position.character);
// 只在 color 属性后补全
const colorMatch = before.match(/color:\s*(\w*)$/);
if (!colorMatch) {
return undefined;
}
const prefix = colorMatch[1];
return COLORS
.filter((c) => c.startsWith(prefix))
.map((color) => {
const item = new vscode.CompletionItem(color);
item.kind = vscode.CompletionItemKind.Color;
item.detail = '颜色值';
item.documentation = new vscode.MarkdownString(
`**${color}**\n\nCSS 内置颜色`
);
item.sortText = '0';
return item;
});
}
},
':' // 输入冒号触发
)
);
}补全体验优化
| 场景 | 处理 |
|---|---|
| 建议过多 | 按前缀过滤 + sortText 排序 |
| 图标混乱 | 正确设置 kind |
| 文档缺失 | 用 documentation 补充说明 |
| 频繁弹出 | 位置上下文判断控制触发 |
常见问题
| 问题 | 处理 |
|---|---|
| 补全不弹出 | 检查语言 ID 与触发字符 |
| 插入内容错误 | 检查 insertText 与 label 区别 |
| 排序不对 | 设置 sortText 权重 |
| 图标不显示 | 设置正确的 kind |
Completion 是语言服务的核心能力,掌握后可为任意语言构建「智能输入」体验。