diff --git a/_AI_USAGE_LOG.md b/_AI_USAGE_LOG.md index 6cb9afd..5f325ad 100644 --- a/_AI_USAGE_LOG.md +++ b/_AI_USAGE_LOG.md @@ -200,4 +200,6 @@ | 2026-08-09 14:23 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 审查报告 #9 多适配器并行能力:判定不成立(设计而非缺陷)——runStaticAnalysis 按语言单 linter 分派是有文档依据的设计(design.md §4 调度逻辑、linters. 单选配置),5 适配器按语言各自工作非闲置;「SQL 同时跑 SQLFluff 和自定义规则」举例有误(自定义规则走 AI 引擎,与静态分析本就并行);多引擎文件走组合适配器(JspAdapter)。未改行为。应用户要求,在 orchestrator.ts 构造函数适配器注册处追加设计意图注释(单语言单 linter + 组合适配器,避免读者误判为 bug),措辞用「单语言单 linter 设计」而非「预留」。lint 0 error / compile 通过 | 中间产物:注释措辞方案二选一——初拟「预留」被否(暗示多 linter 为计划中功能),改「单语言单 linter 设计 + 组合适配器」 | src/orchestrator/orchestrator.ts | deepseek-v4-flash | | 2026-08-09 14:29 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 审查报告 #10 AI 翻译按索引配对:核实属实(低频健壮性缺陷)——merger.ts 原 translatedDiagnostics[i] 按下标与 staticDiagnostics[i] 配对,if(td) 只挡缺失不挡错位;schema 的 originalRuleId 字段与 AI prompt 本就要求按规则 ID 返回,但 merger 未接线。经审批改为按 originalRuleId 匹配(同 ruleId 多条顺序消费),重排/漏译不再挂错。新增 2 个 merger 测试(错序不漏译挂错、重复 ruleId 顺序消费),npm test 81 passing | 中间产物:首个测试断言顺序错误——未考虑 merger 按 severity+line 排序,断言 linterDiagnostics[1]/[2] 的 message 写反,失败后修正断言重跑通过 | src/merger/merger.ts src/test/merger.test.ts | deepseek-v4-flash | | 2026-08-09 14:31 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 审查报告 #11 启动分析未捕获错误:核实属实且更严重——void analyzeOpenDocuments()/void runStaticAndApply()/scheduleAnalysis 定时器三处均为未捕获 Promise 拒绝路径,runStaticAndApply 内部无 try-catch,markers.apply 无保护;纠正审查中「runStaticAnalysis 自身有 try-catch」的事实错误(orchestrator.ts 直接 await adapter.check(),无 try-catch,唯一防线是各适配器内部 catch)。经审批在 runStaticAndApply 包 try-catch + console.error 单点保护,覆盖三处调用。lint 0 error / compile / npm test 81 passing | 中间产物:无 | src/extension.ts | deepseek-v4-flash | -| 2026-08-09 14:34 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 版本升级 1.2.0 → 1.3.0:package.json version 更新;CHANGELOG.md 由模板「Unreleased-Initial release」改为 1.3.0 正式条目(修复 6 项 + 清理 3 项);整合审查报告 #3-#11 全部修复作为本版本内容 | 中间产物:无 | package.json CHANGELOG.md | deepseek-v4-flash | \ No newline at end of file +| 2026-08-09 14:34 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 版本升级 1.2.0 → 1.3.0:package.json version 更新;CHANGELOG.md 由模板「Unreleased-Initial release」改为 1.3.0 正式条目(修复 6 项 + 清理 3 项);整合审查报告 #3-#11 全部修复作为本版本内容 | 中间产物:无 | package.json CHANGELOG.md | deepseek-v4-flash | +| 2026-08-12 22:31 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | Bug fix: JS 审查不出 no-octal / no-nonoctal-decimal-escape — 根因是 flat config 默认 sourceType=module(严格模式)下 `010` 与 `\8`/`\9` 属 JS 语法错误,eslint.ts:114 又丢弃 ruleId===null 的致命解析错误。A:致命解析错误改为产出 eslint:parse-error error 诊断(不再静默丢弃);B:ts.configs.recommended 逐项补 files 守卫(其 base 无 files 会全局挂 TS parser 并误报 TS 规则到 JS),JS 回退 espree + js.configs.recommended,并新增 JS_FILES 独立 config 块加 ecmaFeatures.jsx 防 JSX 回归。本地被删的 eslint.config.mjs 已从 git 恢复以启用 lint。新增 3 个 adapter 测试(octal→parse-error、\8→parse-error、JSX 无 parse error),npm test 84 passing / lint 0 error(仅 jsp.ts 2 个既有 curly warning)| 中间产物:①调试复现阶段 node -e 转义踩坑(PowerShell 单引号 + \8 报 Unterminated string constant),改用 String.fromCharCode 构造测试串;②ts.configs.recommended 类型试错——cfg.files 在 CompatibleConfig 上不存在致编译报错,改用 (cfg as { files?: string[] }).files 断言;③JSX 方案三选一——全局 jsx / .jsx 单独挂 TS parser / JS_FILES 独立 config 块,实测后者通过 | src/adapters/eslint.ts src/test/adapter.test.ts | deepseek-v4-flash | +| 2026-08-12 23:14 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | Bug fix: 设置面板 Stylelint 配置模式显示错误——项目根目录有 stylelint.config.mjs 时面板仍显示「内置配置」,根因是 setupView.ts 的 PROJECT_CONFIG_FILES.stylelint 清单(6 项)与 stylelint.ts 适配器 CONFIG_FILE_NAMES(8 项)不一致,漏了 stylelint.config.mjs / stylelint.config.cjs。按方案 B 最小改动补齐两个文件名,实际审查本就走项目配置无问题。lint 0 error / compile 通过 | 中间产物:曾评估方案 A(抽共享常量消除 drift,含顺带统一 ESLint legacy 清单)被用户否决,仅执行方案 B | src/views/setupView.ts | deepseek-v4-flash | \ No newline at end of file diff --git a/src/adapters/eslint.ts b/src/adapters/eslint.ts index 4b9e392..9e6ded2 100644 --- a/src/adapters/eslint.ts +++ b/src/adapters/eslint.ts @@ -11,6 +11,8 @@ import { eslintExtraRules, eslintExtraTsRules } from '../rules/builtin-rules'; const TS_FILES = ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts']; +const JS_FILES = ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs']; + const PROJECT_CONFIG_FILES = [ 'eslint.config.js', 'eslint.config.mjs', @@ -73,9 +75,14 @@ export class ESLintAdapter implements LinterAdapter { public static getDefaultConfig(): any[] { if (!ESLintAdapter.defaultConfig) { + const tsConfigs = ts.configs.recommended.map(cfg => ({ + ...cfg, + files: (cfg as { files?: string[] }).files ?? TS_FILES, + })); ESLintAdapter.defaultConfig = [ js.configs.recommended, - ...ts.configs.recommended, + { files: JS_FILES, languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, + ...tsConfigs, { rules: eslintExtraRules }, { files: TS_FILES, rules: eslintExtraTsRules }, ]; @@ -111,7 +118,21 @@ export class ESLintAdapter implements LinterAdapter { const diagnostics: LinterDiagnostic[] = []; for (const result of results) { for (const msg of result.messages) { - if (msg.ruleId === null) { continue; } + if (msg.ruleId === null) { + if (!msg.fatal) { continue; } + diagnostics.push({ + severity: 'error', + ruleId: 'eslint:parse-error', + message: msg.message, + range: new vscode.Range( + msg.line - 1, + msg.column - 1, + (msg.endLine ?? msg.line) - 1, + (msg.endColumn ?? msg.column) - 1 + ), + }); + continue; + } diagnostics.push({ severity: msg.severity === 2 ? 'error' : 'warning', diff --git a/src/views/setupView.ts b/src/views/setupView.ts index c504502..030bd9c 100644 --- a/src/views/setupView.ts +++ b/src/views/setupView.ts @@ -90,7 +90,7 @@ const ADAPTER_METADATA: Record = { eslint: ['eslint.config.js', 'eslint.config.mjs', 'eslint.config.cjs', 'eslint.config.ts', 'eslint.config.mts', 'eslint.config.cts'], - stylelint: ['.stylelintrc.js', '.stylelintrc.json', '.stylelintrc.yaml', '.stylelintrc.yml', '.stylelintrc', 'stylelint.config.js'], + stylelint: ['.stylelintrc.js', '.stylelintrc.json', '.stylelintrc.yaml', '.stylelintrc.yml', '.stylelintrc', 'stylelint.config.js', 'stylelint.config.mjs', 'stylelint.config.cjs'], pmd: ['ruleset.xml'], 'sqlfluff': ['.sqlfluff'], };