【免费下载链接】vscode-extension-samples
Sample code illustrating the VS Code extension API.
项目地址:
https://gitcode.com/gh_mirrors/vs/vscode-extension-samples
点击查看 免费下载
导读
本文以 vscode-extension-samples 仓库中的 diagnostic-related-information-sample 为蓝本,系统讲解如何在 VS Code 扩展中为 Diagnostic(诊断信息)附加 relatedInformation(关联信息)。通过阅读本文,你将掌握 vscode.languages.createDiagnosticCollection、vscode.DiagnosticRelatedInformation 与 vscode.Location 的组合用法,学会让「错误提示」携带「上下文线索」(例如指出变量首次赋值的位置),并理解这些信息在 Problems 视图与编辑器中如何联动展示。
示例概览:诊断信息中的“上下文关联”
VS Code 的扩展 API 允许扩展通过诊断集合(Diagnostic Collection)向 Problems 视图和编辑器注入错误、警告等信息。常规诊断只能描述「哪里出错了」,而 DiagnosticRelatedInformation 能让错误条目附带一条或多条关联位置信息,把读者从出错点引导到产生问题的根源位置。
本示例模拟了一个 Rust 场景:对不可变变量 x 进行二次赋值。示例生成的错误位于第 4 行(x = 6;),而关联信息则指向第 2 行(let x = 5;),即变量 x 的首次赋值位置。运行效果如下:

源码剖析:诊断如何被生成
示例的核心逻辑全部位于 src/extension.ts,代码非常精简,却完整覆盖了「创建诊断集合 → 监听编辑器切换 → 按文档生成诊断 → 清理诊断」的全流程。
第一步:创建诊断集合
const collection = vscode.languages.createDiagnosticCollection('test');
createDiagnosticCollection 返回一个 DiagnosticCollection,其中的字符串参数是集合名称(这里为 'test')。诊断集合用于管理一组文档与其诊断结果的映射,扩展可以将集合推入 context.subscriptions 以便随扩展停用自动释放。
类似的用法也出现在 code-actions-sample 中——它创建了名为 "emoji" 的诊断集合并立即 subscriptions.push(emojiDiagnostics),可见「创建集合 + 登记订阅」是标准套路。
第二步:监听当前编辑器变化
if (vscode.window.activeTextEditor) {
updateDiagnostics(vscode.window.activeTextEditor.document, collection);
}
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => {
if (editor) {
updateDiagnostics(editor.document, collection);
}
}));
扩展激活时,先对当前活动编辑器调用一次 updateDiagnostics;随后通过 onDidChangeActiveTextEditor 订阅编辑器切换事件,在用户切换标签页时同步更新诊断。注意 context.subscriptions.push 将事件订阅注册进扩展上下文,VS Code 会在扩展停用时自动注销这些订阅。
第三步:按文档过滤并写入诊断
function updateDiagnostics(document: vscode.TextDocument, collection: vscode.DiagnosticCollection): void {
if (document && path.basename(document.uri.fsPath) === 'sample-demo.rs') {
collection.set(document.uri, [{
code: '',
message: 'cannot assign twice to immutable variable `x`',
range: new vscode.Range(new vscode.Position(3, 4), new vscode.Position(3, 10)),
severity: vscode.DiagnosticSeverity.Error,
source: '',
relatedInformation: [
new vscode.DiagnosticRelatedInformation(
new vscode.Location(document.uri, new vscode.Range(new vscode.Position(1, 8), new vscode.Position(1, 9))),
'first assignment to `x`'
)
]
}]);
} else {
collection.clear();
}
}
这段代码是本示例的核心,逐项说明:
| code | '' | 诊断的错误码(可留空) |
| message | 'cannot assign twice to immutable variablex' | 主诊断信息,展示在 Problems 视图与编辑器中 |
| range | new Range(new Position(3, 4), new Position(3, 10)) | 主诊断覆盖的位置:第 4 行第 5~10 列,即 x = 6; 中的 x(行号从 0 开始) |
| severity | DiagnosticSeverity.Error | 严重级别,此处为错误 |
| source | '' | 诊断来源标识(可留空) |
| relatedInformation | 一个包含 DiagnosticRelatedInformation 的数组 | 关联信息列表,可挂载多条 |
注意坐标体系:Position 和 Range 的行列均从 0 开始,因此代码中 Position(3, 4) 对应 sample-demo.rs 文件中的第 4 行(x = 6;),而 Position(1, 8) 对应第 2 行(let x = 5;)中的 x 字符。
关联信息对象的结构
DiagnosticRelatedInformation 的构造签名是:
new vscode.DiagnosticRelatedInformation(location: vscode.Location, message: string)
- location:vscode.Location 对象,由「文档 URI + Range」组成,本示例指向变量首次赋值的位置 new vscode.Location(document.uri, new vscode.Range(new vscode.Position(1, 8), new vscode.Position(1, 9)));
- message:关联信息的文字说明,本示例为 'first assignment tox'。
当一个诊断包含多条 relatedInformation 时,Problems 视图中该条诊断会被自动展开为一个可折叠的条目树,子节点即各条关联信息,点击即可跳转到对应位置。这也解释了 README 中「F8 快速遍历错误时同样会显示关联信息」的行为——F8 错误导航复用的是同一套诊断数据结构。
触发诊断的演示文件:sample-demo.rs
示例配套的演示文件 sample-demo.rs 内容如下:
fn main() {
let x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
- 第 2 行 let x = 5; 声明了不可变变量 x 并首次赋值;
- 第 4 行 x = 6; 尝试二次赋值,这正是错误被标记的位置;
- 诊断范围精确覆盖第 4 行中的 x(第 5~10 列),而关联信息指向第 2 行 let x = 5; 中的 x(第 9 列),即首次赋值位置。
这种「错误在 A 处、根源在 B 处」的模式,正是 relatedInformation 最典型的使用场景:编译器/静态分析工具可以在「报错位置」和「根因位置」之间建立可见的导航链路。
环境与工程配置
示例是一个标准的 TypeScript 扩展工程,关键配置如下:
- package.json:
- engines.vscode 为 ^1.100.0,表明需要 VS Code 1.100 及以上版本;
- activationEvents 为 "*",即扩展在任何时候都可能被激活(本示例在编辑器打开/切换时触发诊断更新);
- main 指向编译产物 ./out/extension.js;
- 提供 compile(tsc -p ./)、watch(tsc -watch -p ./)、lint(eslint)三个脚本。
- tsconfig.json:target 为 ES2024,module 为 commonjs,strict 开启,源码编译输出到 out/ 目录。
- eslint.config.mjs:采用 typescript-eslint 推荐规则与 @stylistic 风格插件,排除 out 与 .vscode-test 目录。
设置与测试(Set up & Test)
按照 README 的步骤即可本地运行验证:
该示例没有实现语言服务器(LSP),诊断完全由扩展端 API 直接注入,因此无需配置分析器或编译器,开箱即用。
延伸:LSP 场景下的关联信息
relatedInformation 并非扩展 API 的专利——在语言服务器协议(LSP)中也有对应能力。仓库中的 lsp-sample 在服务器初始化时会通过 publishDiagnostics.relatedInformation 能力协商判断客户端是否支持关联信息,然后在发送诊断时动态附加:
hasDiagnosticRelatedInformationCapability = !!(
capabilities.textDocument &&
capabilities.textDocument.publishDiagnostics &&
capabilities.textDocument.publishDiagnostics.relatedInformation
);
// …
if (hasDiagnosticRelatedInformationCapability) {
diagnostic.relatedInformation = [
{
location: {
uri: textDocument.uri,
range: Object.assign({}, diagnostic.range)
},
message: 'Spelling matters'
}
];
}
从源码结构看,LSP 服务端在能力协商通过后,才会填充 relatedInformation 字段,与本文示例在扩展端直接构造 DiagnosticRelatedInformation 形成了「扩展 API 直写」与「协议字段填充」两种实现路径的对照。对于语言服务开发者,在实现编译器诊断时需要同时考虑这一能力协商,以兼容不支持关联信息的旧客户端。
小结
通过本示例可以看到,为诊断附加关联信息只需三步:定位主诊断的 Range、构造指向根因位置的 Location、将 DiagnosticRelatedInformation 填入诊断对象的 relatedInformation 数组。这种机制让扩展可以提供媲美真实编译器的错误体验,在代码检查、lint 工具、语言服务等场景中极具实用价值。若想继续深入,可以结合 code-actions-sample 学习如何基于诊断提供 Code Action 修复,或参考 lsp-sample 了解完整的语言服务器诊断管线。
赞
【免费下载链接】vscode-extension-samples
Sample code illustrating the VS Code extension API.
项目地址:
https://gitcode.com/gh_mirrors/vs/vscode-extension-samples
点击查看 免费下载
相关推荐
使用 Rube MCP 自动化 Timecamp 工时追踪:awesome-codex-skills 的 timecamp-automation 技能实战指南
caj2pdf:终极免费方案解决CAJ转PDF难题
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网硕互联帮助中心




评论前必须登录!
注册