vscode-copilot-chat 中的 Visualization Runner:为 `[visualizable]` 测试一键接入 VS Code 可视化调试
人工智能AI 应用AI Agent代码智能体交互助手工具调用MCP Clients【免费下载链接】vscode-copilot-chatCopilot Chat extension for VS Code项目地址https://gitcode.com/gh_mirrors/vs/vscode-copilot-chat点击查看免费下载在微软官方 Copilot Chat 扩展仓库 vscode-copilot-chat 中开发团队内嵌了一个小巧但机制完整的开发者工具扩展Visualization Runnervisualization-runner。它以 Visualize Test 代码操作Code Action为入口自动识别测试名中带有[visualizable]标记的 vitest 用例并借助 VS Code 调试可视化机制Debug Value Editor把这些测试的结果以结构化属性的形式直观呈现出来。阅读本文后你将掌握该扩展的完整工作原理从 CodeLens 代码操作、TypeScript AST 测试发现到全局钩子$$debugValueEditor_run与 Vitest 模块拦截的运行链路并了解它在仓库中对应的实现与配套启动器文件。一、扩展概览一行 README 背后的完整链路官方 README.vscode/extensions/visualization-runner/README.md用两句话概括了扩展的全部职责This extension add Visualize Test code actions to tests that have[visualizable]in their name. It runs them usingfile://./../../../test/testVisualizationRunner.ts.翻译过来即该扩展为名称中包含[visualizable]的测试添加 Visualize Test 代码操作并借助test/testVisualizationRunner.ts来运行这些测试。虽然描述极简但仓库中实际承载它的文件却构成了一条完整、可独立运行的开发链路文件作用package.json扩展清单ms-vscode发布者、v0.1.0、入口entry.js、依赖ms-vscode.debug-value-editorentry.js激活入口通过tsx加载 TypeScript并开启hediet/node-reload热重载extension.ts核心逻辑CodeLens 注册、AST 测试发现、[visualizable]过滤test/testVisualizationRunner.tsPlayground 启动器拦截vitest模块、按路径定位测试并执行test/testVisualizationRunnerSTest.ts面向 stest 与 JSX 树可视化的另一套启动器变体src/util/common/debugValueEditorGlobals.ts定义$$debugValueEditor_*与$$playgroundRunner_*全局钩子接口从清单可见该扩展不是一个独立的测试框架而是测试发现 → 代码操作 → 调试通道 → 可视化运行的完整接线器其最终落点是对接仓库内的 Playground 启动器。二、扩展清单与激活机制2.1 package.json 关键字段.vscode/extensions/visualization-runner/package.json 中值得注意的配置publisher: ms-vscode、version: 0.1.0是仓库开发工作区内部使用的扩展engines.vscode: ^1.85.0要求 VS Code 1.85 及以上main: ./entry.js入口是编译后的 JavaScript 而不是 TS 源文件activationEvents: [onLanguage:typescript]仅在打开 TypeScript 语言文件时激活extensionDependencies: [ms-vscode.debug-value-editor]硬依赖Debug Value Editor 扩展——这正是 Visualize Test 命令debug-value-editor.debug-and-send-request的提供方。2.2 入口与热重载entry.js 承担激活引导require(tsx/cjs); const { enableHotReload, hotRequire } require(hediet/node-reload); enableHotReload({ entryModule: module }); function activate(context) { context.subscriptions.push(hotRequire(module, ./extension, ext new ext.Extension())); } module.exports { activate };它先加载tsx/cjs让 CommonJS 环境能够 require TypeScript 文件再调用hediet/node-reload的hotRequire加载./extension并在热重载时重建Extension实例。这意味着修改extension.ts后无需重启 VS Code 开发宿主即可生效大幅提升调试体验。三、核心实现如何发现并标记可可视化测试extension.ts 是整个扩展的核心逻辑分为三块测试发现缓存、CodeLens 提供器、[visualizable]过滤。3.1 基于 TypeScript AST 的测试发现扩展借助 TypeScript 编译器 API 对当前文档做纯文本级的语法解析不执行代码见getTests函数用ts.createSourceFile解析文档文本解析失败时静默返回空数组递归遍历 AST识别形如test(name, fn)的调用表达式parseTest同时识别describe(name, fn)与suite(name, fn)分组parseDescribeOrSuite并把分组名压入currentPath形成层级路径最终为每个test(...)生成{ path: string[], lineNumber }例如[describe 分组名, 测试名]。3.2 缓存与防抖_testCaches为减少高频解析开销扩展用仓库自带的工具类CachedFunction与LRUCachedFunction源自 src/util/vs/base/common/cache.ts按文件名缓存测试列表并以document.version作为缓存键private readonly _testCaches new CachedFunction((fileName: string) { let first true; return new LRUCachedFunction(async (modelVersion: number) { if (first) { first false; } else { await timeout(1000); } const document workspace.textDocuments.find(d d.fileName fileName); if (document?.version ! modelVersion) { return []; } const text document.getText(); if (!text.includes(test)) { return []; } const tests getTests(text); return tests.filter(isVisualizableTest); }); });细节值得注意首次调用立即执行此后每次解析前强制等待 1 秒timeout(1000)相当于对编辑器改动做了节流若文档版本已变化则直接返回空结果避免把过期缓存喂给 CodeLens文档中连test字样都没有时直接跳过 AST 解析最终只保留通过isVisualizableTest过滤的用例。3.3[visualizable]标记与过滤过滤逻辑只有一行function isVisualizableTest(info: TestInfo): boolean { return info.path.some(p p.indexOf([visualizable]) ! -1); }即只要测试路径describe/suite 分组名或 test 名称中的任意一段包含子串[visualizable]该用例就会被选中。因此标记方式非常灵活——你可以标记单个测试名也可以在整个describe([visualizable] ...)分组上标记让组内所有测试都可被可视化。3.4 CodeLens生成 Visualize Test 代码操作扩展向javascript与typescript两种语言、file协议的文档注册 CodeLens 提供器languages.registerCodeLensProvider([ { language: javascript, scheme: file }, { language: typescript, scheme: file } ], { provideCodeLenses: async (document, token) { ... } })对每个命中的测试在测试声明行首生成一个 CodeLens其命令为{ title: Visualize Test, command: debug-value-editor.debug-and-send-request, arguments: [{ launchConfigName: Test Visualization Runner, args: { fileName: document.fileName, path: t.path }, revealAvailablePropertiesView: true, }] }命令与参数的含义debug-value-editor.debug-and-send-request由依赖的ms-vscode.debug-value-editor扩展提供负责启动调试配置并把请求发送给 Playground 运行器launchConfigName: Test Visualization Runner指定要使用的调试配置名与仓库中定义的调试配置对应args.fileName当前测试文件的绝对路径args.path测试的层级路径如[describe 名, test 名]revealAvailablePropertiesView: true运行后自动展开属性可视化视图。3.5 运行效果下图为扩展在工作区中的实际效果在标记了[visualizable]的测试上方出现 Visualize Test 入口选中后即触发调试运行测试产出的属性数据会在调试可视化视图中展开四、Playground 运行器test/testVisualizationRunner.ts 的完整机制README 明确说明测试由file://./../../../test/testVisualizationRunner.ts运行该文件test/testVisualizationRunner.ts是整个机制的另一半。它被调试配置加载进一个独立进程扮演 Playground Runner核心工作包括4.1 拦截vitest模块轻量级测试桩运行器通过劫持Module.prototype.require拦截对vitest的请求(Module as any).prototype.require function (this: { filename: string }, path: string) { if (path vitest) { return createVitestModule(this.filename); } return r.call(this, path); };createVitestModule返回一个手写的迷你 Vitest 桩vitest.describe(name, fn)与vitest.test(name, fn)并不真正执行测试体而是把它们注册进TestContainer/Test结构通过getDiscoverFn实现发现即登记、登记后清空的惰性收集vitest.expect()返回的toBe/toMatchInlineSnapshot/toMatchFileSnapshot均为空操作确保测试文件在仅被扫描时不会因断言失败而中断。这样做的目的是测试文件被 require 后代码可以按路径逐级查找describe→test结构TestContainer.findTest只执行被点中的那一个用例。4.2 全局钩子与 Debug Value Editor 的接线运行器在globalThis上挂载两组钩子类型定义见 src/util/common/debugValueEditorGlobals.tsexport interface IDebugValueEditorGlobals { $$debugValueEditor_run: (args: any) void; $$debugValueEditor_properties: readonly any[]; $$debugValueEditor_debugChannels: Recordstring, DebugChannel; $$debugValueEditor_refresh?: (body: string) void; } export interface IPlaygroundRunnerGlobals { $$playgroundRunner_data: { currentPath: string[] }; }运行器侧的接线如下g.$$playgroundRunner_data { currentPath: [] }; g.$$debugValueEditor_run args (setTimeout(() { run(args); }, 0)); (g.$$debugValueEditor_debugChannels ?? (g.$$debugValueEditor_debugChannels {}))[run] host ({ handleRequest: (args) { setTimeout(() run(args as any), 0); } });其中注释解释了setTimeout的原因The timeout seems to fix a deadlock-issue of tsx, when the run function is called from the debugger.——即从调试器回调中直接执行会与 tsx 产生死锁因此所有入口都通过setTimeout(..., 0)延后到事件循环下一轮。4.3 单测执行与热重载联动run(args)的流程为打印 Running test: path.join( )→setTestFile按需通过hotRequire加载测试文件 →setTest记录当前路径 →runCurrentTest查找并执行测试async function runCurrentTest() { const t testsPerFileName.get(currentFileName!)?.findTest(currentPath); if (!t) { console.error(Test not found, currentPath); return; } try { const startTime Date.now(); g.$$debugValueEditor_properties []; await t?.runner(); console.log( Test finished ( (Date.now() - startTime) ms).); } catch (e) { console.error(Test failed:, e); } }关键点测试执行前清空$$debugValueEditor_properties执行期间测试把可视化的数据如 JSX 树、模拟数据写入该全局数组供调试可视化视图读取由于hotRequire的存在测试文件一旦修改会立即重新加载并自动重跑当前用例形成 改代码 → 自动重跑 → 可视化刷新 的闭环启动 5 秒后若仍未有测试被执行会打印 Did not run a test after 5 seconds. Probably a bug in the extension? 的告警用于暴露接线故障。4.4 另一套变体testVisualizationRunnerSTest.ts仓库中还提供了面向 stest 与 JSX 树可视化的变体 test/testVisualizationRunnerSTest.ts。它与主运行器共用$$debugValueEditor_run、$$playgroundRunner_data等全局钩子但通过hotRequire加载独立的./testVisualizationRunnerSTestRunner.ts并把路径参数规范化为path.join(__dirname, path.relative(__dirname, fileName))后交给 runner 处理。二者结构一致说明这套 全局钩子 调试通道 的模式在仓库内被复用于不同测试形态。五、工作原理总览与使用方式5.1 端到端数据流把以上内容串起来一次 Visualize Test 的完整生命周期为开发者打开 TypeScript/JavaScript 测试文件onLanguage:typescript触发激活extension.ts用 TypeScript AST 解析出所有test/describe/suite路径过滤出含[visualizable]的用例CodeLens 显示 Visualize Test点击后触发debug-value-editor.debug-and-send-request命令附带launchConfigName: Test Visualization Runner、fileName、path参数调试配置启动test/testVisualizationRunner.ts进程该进程拦截require(vitest)注册测试结构并通过$$debugValueEditor_run接收请求运行器按path定位并执行指定测试测试写入$$debugValueEditor_properties随后在调试属性视图中可视化展示并打印耗时日志。5.2 如何在本仓库中使用该扩展位于 .vscode/extensions/visualization-runner 目录属于仓库自带的工作区开发工具。要复现其效果需要确保 VS Code 中已安装依赖扩展ms-vscode.debug-value-editor见 package.json 的extensionDependencies在任意测试用例名或 describe/suite 分组名中加入[visualizable]标记例如describe([visualizable] string utils, () { test(should trim whitespace, () { /* ... */ }); });打开文件后等待 CodeLens 出现 Visualize Test点击即可经调试通道运行并查看可视化结果修改测试代码后得益于hediet/node-reload与hotRequire运行器会自动重新加载并重跑当前用例无需重启。5.3 对仓库开发的启示从源码结构看这套机制的价值在于把测试执行与结果可视化解耦扩展只负责发现与触发运行器负责加载与执行而 Debug Value Editor 负责展示。仓库作者用它来可视化测试产生的 JSX 树、模拟数据等结构化内容是调试复杂测试输出的高效手段。如果你希望在 vscode-copilot-chat 的开发环境中快速验证某个测试的内部数据形态[visualizable] Visualize Test 就是官方提供的现成入口。六、小结入口与发现extension.ts 通过 CodeLens 提供器 TypeScript AST 解析为含[visualizable]的测试生成 Visualize Test 代码操作运行与展示test/testVisualizationRunner.ts 拦截vitest模块、按路径定位用例并通过$$debugValueEditor_*全局钩子把测试结果交给 Debug Value Editor 可视化调试体验tsxhediet/node-reload热重载贯穿扩展与运行器测试修改后自动重跑刷新可扩展性同一套全局钩子模式被 testVisualizationRunnerSTest.ts 复用支撑 stest 与 JSX 树可视化场景。无论你是想理解 VS Code 扩展如何与调试器交互还是希望复用这套 标记即可视化 的开发工作流本仓库的 Visualization Runner 都是一个结构清晰、代码量小、机制完整的参考实现。赞分享人工智能AI 应用AI Agent代码智能体交互助手工具调用MCP Clients【免费下载链接】vscode-copilot-chatCopilot Chat extension for VS Code项目地址https://gitcode.com/gh_mirrors/vs/vscode-copilot-chat点击查看免费下载相关推荐VS Code Copilot 扩展开发之 Visualization RunnerVisualize Test 代码透镜与单条测试调试链路VS Code Copilot 扩展开发之 Visualization RunnerVisualize Test 代码透镜与单条测试调试链路 本文围绕 VS开发工具代码编辑器在 VS Code 原生 Copilot Chat 中使用 OmniRouteOmniCopilot 扩展接入指南在 VS Code 原生 Copilot Chat 中使用 OmniRouteOmniCopilot 扩展接入指南 OmniRoute 是一个单端点接入多 p后端API网关LLM 网关人工智能大模型MCP 服务桌面应用377 条 AI 提示词从哪抄、怎么改awesome-prompts 完整上手指南377 条 AI 提示词从哪抄、怎么改awesome prompts 完整上手指南 awesome prompts 是一个提示词库Prompt 集合收录提示工程文档人工智能上一篇告别布局调试噩梦5款Flexbox for Android可视化工具全测评下一篇ROCm 6.5实战指南从零到AI推理的完整避坑手册创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Java清城电商平台:SSM毕设项目从源码到答辩实战指南

Java清城电商平台:SSM毕设项目从源码到答辩实战指南

收到,像这种标着“最新原创毕设”的电商项目资料,我帮不少学生看过代码、调过环境。核心结论先说:免费拿到源码不是重点,重点是你拿到手之后能不能在三天之内把它吃透,然后在答辩现场用自己的话把整个购物流程讲清楚。…

2026/9/24 18:31:16 阅读更多 →
智能家居线下选购指南:逛浦东建材市场后总结的避坑经验

智能家居线下选购指南:逛浦东建材市场后总结的避坑经验

朋友家最近在装修,连着问了我三次同一个问题:上海买智能家居哪里好?前两次我都甩链接让他去网上看评测,直到他自己跑了一趟浦东的建材市场,回来一脸认真地跟我说,你天天研究这些,估计都没认真逛…

2026/9/24 18:31:16 阅读更多 →
高德JSAPI叠加GeoServer WMS:从白屏到坐标系对齐的实战指南

高德JSAPI叠加GeoServer WMS:从白屏到坐标系对齐的实战指南

最近在做一个内部的GIS数据可视化项目,要在高德JSAPI 2.0的地图上叠加GeoServer发布的WMS图层,第一反应是直接用现成的AMap.TileLayer.WMS,谁想到一个看起来不复杂的功能,硬是折腾了两天。图层白屏、跨域报错、坐标系偏移&#xf…

2026/9/24 18:31:16 阅读更多 →

最新新闻

PaddleNLP tie_weights 权重绑定能力设计与实现全解析(RFC No.103)

PaddleNLP tie_weights 权重绑定能力设计与实现全解析(RFC No.103)

PaddleNLP tie_weights 权重绑定能力设计与实现全解析(RFC No.103) 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP 导读 权重绑定&…

2026/9/24 19:12:45 阅读更多 →
bugku与qsnctf实战对比:从新手刷题到CTF竞赛的完整指南

bugku与qsnctf实战对比:从新手刷题到CTF竞赛的完整指南

如果你刚开始接触CTF,或者已经在安全方向上摸索了一段时间但一直没找到系统的练习入口,那bugku和qsnctf这两个平台的名字,十有八九已经反复出现在各路前辈的推荐清单里了。我自己也是从这两个平台走过来的,可以说,它们…

2026/9/24 19:12:45 阅读更多 →
TrafficMonitor天气插件配置全指南:从入门到免踩坑实践

TrafficMonitor天气插件配置全指南:从入门到免踩坑实践

TrafficMonitor我用了快三年,任务栏上常年挂着CPU、内存、网速三块数据,好处是心里有数、不用点开任何窗口;坏处是,时间长了你会觉得右上角这一小条信息太“工具化”,缺一点跟生活相关的内容。后来我把天气预报塞进任务…

2026/9/24 19:12:45 阅读更多 →
CentOS 7.6 安装 VMware Workstation 内核模块编译失败排查与解决

CentOS 7.6 安装 VMware Workstation 内核模块编译失败排查与解决

在 CentOS 7.6 上装 VMware Workstation,流程本身其实不复杂:官网下载 bundle 包,加执行权限,root 跑一遍,点几个向导页就完事。真正让人头疼的是装完以后第一次双击图标,屏幕中央弹出那个"VMware Ker…

2026/9/24 19:12:45 阅读更多 →
Cookie和Session的区别:从登录掉线到安全漏洞,一文搞懂

Cookie和Session的区别:从登录掉线到安全漏洞,一文搞懂

从登录掉线到安全漏洞,Cookie和Session的区别你真的搞懂了吗?但凡做过Web开发,迟早会在登录模块上栽一次跟头——要么是用户反馈“明明登录了,刷新一下就掉线”,要么是后端同事盯着一串看不懂的加密字符串问你“这玩意…

2026/9/24 19:12:45 阅读更多 →
EC纠删码与数据压缩实战:降低存储成本的全栈方案

EC纠删码与数据压缩实战:降低存储成本的全栈方案

1. 硬件涨价潮下的存储成本困局先看一个我这两年在给客户做存储方案时经常遇到的场景:本来预算单上写得好好的,一批 16TB 的 NL-SAS 盘,按去年的行情大概能拿下,结果等到真正下单的时候,采购那边跑过来拍桌子说价格涨了…

2026/9/24 19:11:44 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →