InlayHint 内联提示
InlayHint 是在代码行内插入的灰色提示文本:显示函数参数名、推断类型、内联文档。与 CodeLens 的行上方不同,InlayHint 直接嵌入代码流中。
注册 InlayHints Provider
languages.registerInlayHintsProvider 注册内联提示:
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerInlayHintsProvider(
'plaintext',
{
provideInlayHints(
document: vscode.TextDocument,
range: vscode.Range,
token: vscode.CancellationToken
): vscode.InlayHint[] {
// 返回提示数组
return [
new vscode.InlayHint(
new vscode.Position(0, 5), // 插入位置
'类型: string'
)
];
}
}
)
);
}InlayHint 属性
typescript
const hint = new vscode.InlayHint(
position, // 插入位置
'string', // 显示文本
vscode.InlayHintKind.Type // 提示类型
);
// 附加属性
hint.paddingLeft = true; // 左侧留白
hint.paddingRight = true; // 右侧留白
hint.tooltip = '变量类型'; // 悬停提示
hint.editable = false; // 是否可编辑| 属性 | 作用 |
|---|---|
position | 插入位置 |
text | 显示文本 |
kind | 提示类型(Type/Parameter) |
paddingLeft/Right | 两侧留白 |
tooltip | 悬停提示 |
editable | 是否可编辑 |
参数名提示
显示函数调用时的参数名:
typescript
class ParamHintsProvider implements vscode.InlayHintsProvider {
provideInlayHints(document, range): vscode.InlayHint[] {
const hints: vscode.InlayHint[] = [];
// 函数参数定义
const params: Record<string, string[]> = {
'add': ['a', 'b'],
'greet': ['name', 'greeting']
};
for (let line = range.start.line; line <= range.end.line; line++) {
const text = document.lineAt(line).text;
// 匹配函数调用 add(x, y)
const callMatch = text.match(/(\w+)\(([^)]*)\)/);
if (callMatch) {
const fnName = callMatch[1];
const argNames = params[fnName];
if (!argNames) {
continue;
}
const args = callMatch[2].split(',').map((a) => a.trim());
args.forEach((arg, index) => {
if (arg.length === 0) {
return;
}
// 计算参数文本在行内的字符偏移
const argStart = text.indexOf(arg, text.indexOf(callMatch[2]));
const position = new vscode.Position(line, argStart);
const hint = new vscode.InlayHint(
position,
`${argNames[index]}:`,
vscode.InlayHintKind.Parameter
);
hint.paddingRight = true;
hints.push(hint);
});
}
}
return hints;
}
}类型提示
显示变量或表达式的推断类型:
typescript
class TypeHintsProvider implements vscode.InlayHintsProvider {
provideInlayHints(document, range): vscode.InlayHint[] {
const hints: vscode.InlayHint[] = [];
for (let line = range.start.line; line <= range.end.line; line++) {
const text = document.lineAt(line).text;
// 匹配变量赋值 const x = ...
const match = text.match(/^\s*(?:const|let|var)\s+(\w+)\s*=\s*(.+)$/);
if (match) {
const varName = match[1];
const valueExpr = match[2];
// 简单类型推断
const type = this.inferType(valueExpr);
// 行尾显示类型
const hint = new vscode.InlayHint(
new vscode.Position(line, text.length),
`: ${type}`,
vscode.InlayHintKind.Type
);
hint.paddingLeft = true;
hints.push(hint);
}
}
return hints;
}
private inferType(expr: string): string {
if (/^["']/.test(expr)) return 'string';
if (/^-?\d+\.?\d*$/.test(expr)) return 'number';
if (/^(true|false)$/.test(expr)) return 'boolean';
if (/^\[/.test(expr)) return 'Array';
if (/^\{/.test(expr)) return 'Object';
if (/^function/.test(expr)) return 'Function';
return 'unknown';
}
}InlayHintKind 类型
typescript
// 两种内置类型
vscode.InlayHintKind.Type // 类型提示
vscode.InlayHintKind.Parameter // 参数提示| Kind | 视觉 | 用途 |
|---|---|---|
Type | 灰蓝色调 | 类型标注 |
Parameter | 灰色调 | 参数名标注 |
工具提示 tooltip
悬停提示支持 Markdown:
typescript
const hint = new vscode.InlayHint(position, 'string');
hint.tooltip = new vscode.MarkdownString(
'**类型**: string\n\n变量推断类型'
);
// 支持命令链接
hint.tooltip = new vscode.MarkdownString(
'[查看更多](command:myExt.showTypeInfo)'
);可编辑提示 editable
editable: true 允许用户直接编辑提示文本(会触发回调):
typescript
const hint = new vscode.InlayHint(position, 'string');
hint.editable = true;
hint.paddingLeft = true;
hint.paddingRight = true;typescript
// 监听提示编辑
class Provider implements vscode.InlayHintsProvider {
onDidChangeInlayHints: vscode.Event<void> | undefined;
// 提供提示时附加标签与编辑回调
provideInlayHints(document, range) {
const hint = new vscode.InlayHint(
new vscode.Position(0, 0),
'editable'
);
hint.editable = true;
hint.tooltip = '点击编辑';
return [hint];
}
}动态刷新
数据变化时刷新提示:
typescript
class Provider implements vscode.InlayHintsProvider {
private _onDidChangeInlayHints =
new vscode.EventEmitter<void>();
readonly onDidChangeInlayHints =
this._onDidChangeInlayHints.event;
// 文档变化时刷新
refresh() {
this._onDidChangeInlayHints.fire();
}
}完整示例:简单类型标注器
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerInlayHintsProvider(
'plaintext',
{
provideInlayHints(document, range) {
const hints: vscode.InlayHint[] = [];
for (let line = range.start.line; line <= range.end.line; line++) {
const text = document.lineAt(line).text;
// 参数提示:函数参数
const funcMatch = text.match(/(\w+)\s*=\s*\(([^)]*)\)/);
if (funcMatch) {
const params = funcMatch[2].split(',').map((p) => p.trim());
params.forEach((param, i) => {
if (!param) return;
const idx = text.indexOf(param);
const hint = new vscode.InlayHint(
new vscode.Position(line, idx),
`参数${i + 1}`,
vscode.InlayHintKind.Parameter
);
hint.paddingRight = true;
hints.push(hint);
});
}
// 类型提示:行尾注释
const commentMatch = text.match(/\/\/\s*>\s*(.+)$/);
if (commentMatch) {
const hint = new vscode.InlayHint(
new vscode.Position(line, text.length),
`: ${commentMatch[1]}`,
vscode.InlayHintKind.Type
);
hint.paddingLeft = true;
hint.tooltip = '手动类型标注';
hints.push(hint);
}
}
return hints;
}
}
)
);
}显示配置
| 场景 | 处理 |
|---|---|
| 提示干扰阅读 | 减少 padding 或选择性添加 |
| 类型重复 | 只在需要处添加 |
| 参数过多 | 只对长参数显示 |
| 性能 | 限制在可视 range 内 |
常见问题
| 问题 | 处理 |
|---|---|
| 提示不显示 | 检查位置与语言注册 |
| 位置错位 | position 用精确字符偏移 |
| 更新不及时 | 实现 onDidChangeInlayHints |
| 干扰代码 | 合理 padding 与 kind |
InlayHint 让代码「自解释」:参数名、类型、状态直接内嵌,阅读效率显著提升。