- 波浪线标记:打开/编辑/保存自动静态分析,新增 markers.enabled 配置与 onStartupFinished 激活,带防抖与版本竞态保护 - SQLFluff:默认方言 sql->oracle;PRS 解析错误改用 i18n 三语友好提示(含当前方言与配置指引)并提升为 error - AI 审查:mergeResults 统一 aiFindings 行号为 0 基,修复整文件审查行号偏移 1 行
4.0 KiB
4.0 KiB
打开文件自动静态分析 + 波浪线 设计文档
面向 AI 编码 agent 的技术实施文档。本文档包含完整的根因分析、方案设计、文件清单和验收标准,可直接据此编码。
功能目标
修复插件对已打开文件不做静态分析、不显示波浪线的问题:
- VSCode 启动后(
onStartupFinished)插件自动激活,对所有已打开的文件串行做静态分析并显示波浪线。 - 文本编辑时先清除波浪线(即时反馈),停止输入 1s 后自动重新分析。
- 保存文件仍按现有 500ms 防抖重分析。
根因分析
| 问题 | 位置 | 说明 |
|---|---|---|
| 插件不自动激活 | package.json:12 activationEvents: [] |
无 onStartupFinished 等事件,插件只在执行命令/打开面板时激活 |
| 存量文件不分析 | extension.ts activate 无初始扫描 |
onDidOpenTextDocument 只对"激活后新打开"的文件触发,激活前已打开的文件永远不会被分析 |
| 编辑不重分析 | extension.ts:63-66 |
onDidChangeTextDocument 只 markers.clear,需等保存才有波浪线 |
架构决策
| 决策 | 选择 | 理由 |
|---|---|---|
| 激活时机 | onStartupFinished |
VSCode 启动完成后激活,不拖慢启动,兼容性最好 |
| 初始分析范围 | 所有已打开 file 文档 | 行为统一,符合"已打开文件都应有波浪线"预期 |
| 批量执行方式 | 串行执行 | 避免多个 JVM(PMD)/ Python 进程(SQLFluff)并发;JS/TS/CSS 为进程内执行,无压力 |
| 串行顺序 | 活动文件优先 | 用户眼前文件先出波浪线 |
| 编辑时行为 | 1s 防抖自动重分析 | 更接近 ESLint 等 linter 体验 |
| 防抖调度 | 统一按 URI 调度器 | 合并保存/编辑两类防抖,逻辑单一 |
文件变更清单
| 文件 | 变更 |
|---|---|
package.json |
activationEvents 由 [] 改为 ["onStartupFinished"] |
src/extension.ts |
① 初始串行扫描(活动文件优先);② 统一 scheduleAnalysis 调度器;③ 编辑时防抖重分析 |
无新增依赖。
关键实现
统一防抖调度器(src/extension.ts)
const analysisTimers = new Map<string, NodeJS.Timeout>();
function scheduleAnalysis(document: vscode.TextDocument, delay: number): void {
if (document.uri.scheme !== 'file' || !isMarkersEnabled()) { return; }
const key = document.uri.toString();
const existing = analysisTimers.get(key);
if (existing) { clearTimeout(existing); }
const timer = setTimeout(async () => {
analysisTimers.delete(key);
await runStaticAndApply(document);
}, delay);
analysisTimers.set(key, timer);
}
激活时初始串行扫描(活动文件优先)
const docs = vscode.workspace.textDocuments;
const active = vscode.window.activeTextEditor?.document;
const ordered = [...docs].sort((a, b) => a === active ? -1 : b === active ? 1 : 0);
for (const doc of ordered) {
if (doc.uri.scheme !== 'file' || !isMarkersEnabled()) { continue; }
await runStaticAndApply(doc);
}
事件改写
onDidChangeTextDocument:markers.clear(uri)+scheduleAnalysis(doc, 1000)onDidSaveTextDocument:删除原debounceTimersMap,改用scheduleAnalysis(doc, 500)
复用现有 runStaticAndApply(含版本竞态保护)与 markers.apply,行为不变。
影响范围
- 激活行为:插件随 VSCode 启动自动激活(内存常驻,激活逻辑本已完整,代价极小)
- 兼容性:
markers.enabled配置全程生效;命令/CodeLens/AI 审查流程不受影响 - 进程压力:初始串行扫描保证任一时刻最多 1 个 JVM 在跑
验收标准
- 启动 Extension Dev Host,预置多个已打开文件(含活动与非活动),确认启动后活动文件波浪线先出现、其余依次出现
- 编辑文件停止 1s 后波浪线自动刷新;输入过程中波浪线消失
- 保存文件 500ms 后波浪线刷新
markers.enabled=false时不显示任何波浪线且不触发分析npm run lint、npm run compile通过