Files
2026Technology-Competition/docs/superpowers/specs/2026-08-04-auto-static-analysis-design.md
T
范智鹏 50855dae67 feat: 编辑器波浪线自动标记 + SQLFluff 默认方言改 oracle + AI 审查行号修正
- 波浪线标记:打开/编辑/保存自动静态分析,新增 markers.enabled 配置与 onStartupFinished 激活,带防抖与版本竞态保护
- SQLFluff:默认方言 sql->oracle;PRS 解析错误改用 i18n 三语友好提示(含当前方言与配置指引)并提升为 error
- AI 审查:mergeResults 统一 aiFindings 行号为 0 基,修复整文件审查行号偏移 1 行
2026-08-04 22:10:41 +08:00

93 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 打开文件自动静态分析 + 波浪线 设计文档
> 面向 AI 编码 agent 的技术实施文档。本文档包含完整的根因分析、方案设计、文件清单和验收标准,可直接据此编码。
## 功能目标
修复插件对**已打开文件不做静态分析、不显示波浪线**的问题:
1. VSCode 启动后(`onStartupFinished`)插件自动激活,对**所有已打开的文件**串行做静态分析并显示波浪线。
2. 文本编辑时先清除波浪线(即时反馈),停止输入 1s 后自动重新分析。
3. 保存文件仍按现有 500ms 防抖重分析。
## 根因分析
| 问题 | 位置 | 说明 |
|------|------|------|
| 插件不自动激活 | `package.json:12` `activationEvents: []` | 无 `onStartupFinished` 等事件,插件只在执行命令/打开面板时激活 |
| 存量文件不分析 | `extension.ts` activate 无初始扫描 | `onDidOpenTextDocument` 只对"激活后新打开"的文件触发,激活前已打开的文件永远不会被分析 |
| 编辑不重分析 | `extension.ts:63-66` | `onDidChangeTextDocument``markers.clear`,需等保存才有波浪线 |
## 架构决策
| 决策 | 选择 | 理由 |
|------|------|------|
| 激活时机 | `onStartupFinished` | VSCode 启动完成后激活,不拖慢启动,兼容性最好 |
| 初始分析范围 | 所有已打开 file 文档 | 行为统一,符合"已打开文件都应有波浪线"预期 |
| 批量执行方式 | 串行执行 | 避免多个 JVMPMD/ Python 进程(SQLFluff)并发;JS/TS/CSS 为进程内执行,无压力 |
| 串行顺序 | 活动文件优先 | 用户眼前文件先出波浪线 |
| 编辑时行为 | 1s 防抖自动重分析 | 更接近 ESLint 等 linter 体验 |
| 防抖调度 | 统一按 URI 调度器 | 合并保存/编辑两类防抖,逻辑单一 |
## 文件变更清单
| 文件 | 变更 |
|------|------|
| `package.json` | `activationEvents``[]` 改为 `["onStartupFinished"]` |
| `src/extension.ts` | ① 初始串行扫描(活动文件优先);② 统一 `scheduleAnalysis` 调度器;③ 编辑时防抖重分析 |
无新增依赖。
## 关键实现
### 统一防抖调度器(`src/extension.ts`
```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);
}
```
### 激活时初始串行扫描(活动文件优先)
```ts
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`:删除原 `debounceTimers` Map,改用 `scheduleAnalysis(doc, 500)`
复用现有 `runStaticAndApply`(含版本竞态保护)与 `markers.apply`,行为不变。
## 影响范围
- **激活行为**:插件随 VSCode 启动自动激活(内存常驻,激活逻辑本已完整,代价极小)
- **兼容性**`markers.enabled` 配置全程生效;命令/CodeLens/AI 审查流程不受影响
- **进程压力**:初始串行扫描保证任一时刻最多 1 个 JVM 在跑
## 验收标准
1. 启动 Extension Dev Host,预置多个已打开文件(含活动与非活动),确认启动后活动文件波浪线先出现、其余依次出现
2. 编辑文件停止 1s 后波浪线自动刷新;输入过程中波浪线消失
3. 保存文件 500ms 后波浪线刷新
4. `markers.enabled=false` 时不显示任何波浪线且不触发分析
5. `npm run lint``npm run compile` 通过