diff --git a/_AI_USAGE_LOG.md b/_AI_USAGE_LOG.md index eb22ca0..2fe995e 100644 --- a/_AI_USAGE_LOG.md +++ b/_AI_USAGE_LOG.md @@ -1,5 +1,4 @@ # AI Usage Log - | 日期时间 | 范式步骤 | 修改摘要 | 中间产物 | 涉及文件 | 使用模型 | |---------|---------|---------|---------|---------|---------| | 2026-07-10 18:10 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 | 编写代码审查插件设计文档(design spec) | design spec | docs/superpowers/specs/2026-07-10-code-reviewer-design.md | deepseek-v4-flash | @@ -135,6 +134,24 @@ | 2026-07-28 21:15 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 新增"AI 连接配置"区块(provider/model/apiKey/baseUrl),放在审核引擎上方,删除下方重复的③ AI 模型配置和④ API Key 区块 | 无 | src/i18n/messages.ts src/views/setupView.ts | deepseek-v4-flash | | 2026-07-28 21:20 | ① 用户提出 → ⑤ 编码实现 → ⑥ 审查验证 | 语言下拉移至 header 右侧,删除独立语言区块 | 无 | src/views/setupView.ts | deepseek-v4-flash | | 2026-07-28 21:30 | ① 用户提出 → ⑤ 编码实现 → ⑥ 审查验证 | 连接状态持久化:globalState 存储 connectionState(含配置指纹),重新打开插件时恢复,AI 配置变化时清除 | 无 | src/views/setupView.ts | deepseek-v4-flash | -| 2026-07-28 22:27 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 基于当前代码生成「AI 供应商与模型动态化设计书」:更新所有行号引用、代码片段、UI 结构描述;补充遗漏的 import-service.ts 第 382 行 createProvider() 调用点(第 08 节和第 10 节);修复 factory.ts 改造代码中 getAllProviderMeta() 无限递归 bug(改用 import alias) | 无 | docs/superpowers/specs/2026-07-28-provider-registry-dynamic-design.md | GLM-5.2 | +| 2026-07-28 22:27 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 基于当前代码生成「AI 供应商与模型动态化设计书」:更新所有行号引用、代码片段、UI 结构描述;补充遗漏的 import-service.ts 第 382 行 createProvider() 调用点(第 08 节和第 10 节);修复 factory.ts 改造代码中 getAllProviderMeta() 无限递归 bug(改用 import alias) | 无 | docs/superpowers/specs/2026-07-28-provider-registry-dynamic-design.md | Trae 内部模型 | | 2026-07-28 22:36 | ⑤ 编码实现 → ⑥ 审查验证 | 实现供应商注册表动态化:新建 providers.json / src/ai/types.ts / src/ai/registry.ts;重构 factory.ts 为动态加载 + PROTOCOL_MAP;engine.ts / import-service.ts / setupView.ts 透传 extensionUri;模型下拉改为 input+datalist;setupView.ts 新增 FileSystemWatcher;setupView.js 改为填充 datalist;package.json 去除 ai.provider enum 锁定,版本 1.1.0→1.2.0;新增 i18n setup.modelPlaceholder | PROTOCOL_MAP 类型先用 4 参数构造函数签名报错(Gemini/Claude 仅 2 参数),改为 `new (...args: any[]) => AIProvider` | providers.json src/ai/types.ts src/ai/registry.ts src/ai/factory.ts src/ai/engine.ts src/rules/import-service.ts src/views/setupView.ts src/views/setupView.js package.json src/i18n/messages.ts | deepseek-v4-flash | | 2026-07-28 22:49 | ① 用户提出 → ② 需求澄清→ ⑤ 编码实现 → ⑥ 审查验证 | 模型名称去掉 datalist 下拉列表,改为纯输入框; | 无 | src/views/setupView.ts | deepseek-v4-flash | +| 2026-07-29 19:06 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 将 ESLint 内置配置从 61 条(官方 recommended)扩展到 94 条(P0 61 + P1 17 + P2 16),通过在 getDefaultConfig() 中追加 extraRules 对象实现额外 33 条规则的启用。设计涉及三个文件修改:src/adapters/eslint.ts(追加规则配置)、src/rules/static-rules.json(同步去重数据)、package.json(显式声明 @eslint/js 依赖)。规则分级为 P0 官方推荐(error)、P1 强烈推荐(error)、P2 建议启用(13 条 warn + 3 条 error)。 | 先整理了 eslint-9-rules.md(312 条完整规则清单)作为规则选型的基础数据 由此产出 eslint-recommended-rules.md(推荐规则文档,94 条分级选型及理由)作为设计书的前置输入 讨论阶段确认了 @eslint/js 缺失于 package.json 是版本迭代遗留问题,决策为显式声明而非移除 讨论阶段确认了 typescript-eslint 从 devDependencies 移至 dependencies 的历史变更(_AI_USAGE_LOG.md 第 82 条) | docs\superpowers\specs\2026-07-29-eslint-rule-enhancement-design.md | Trae 内部模型 | +| 2026-07-29 19:34 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | ESLint 规则增强编码实现:package.json 添加 @eslint/js 依赖;eslint.ts 新增 extraRules 常量(31 条 P1+P2 规则)并追加到 getDefaultConfig();static-rules.json 追加 31 条规则条目并更新 linterVersion 为 9.x (92 rules) | 设计书代码示例中 extraRules 包含 no-implied-eval(已在 recommended)和 no-constant-binary-expression(已在现有 61 条),编码审查阶段发现后经用户确认移除,extraRules 改为 31 条、JSON 追加 31 条、总数 92 条 | package.json src/adapters/eslint.ts src/rules/static-rules.json | deepseek-v4-flash-free | +| 2026-07-29 20:00 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 在 eslint.config.mjs 中导入 js.configs.recommended,启用 ESLint 官方 61 条 P0 推荐规则 | 无 | eslint.config.mjs | deepseek-v4-flash-free | +| 2026-07-29 20:09 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 将 typescript-eslint 内置配置从 24 条(官方 recommended)扩展到 35 条(P0 24 + P1 5 + P2 6),设计 extraTsRules 常量(11 条新规则 + 1 条扩展替换 no-shadow + 2 条 off 冲突修复),通过 files 字段限定仅作用于 TS 文件;处理 2 处扩展规则冲突:no-shadow(TS 扩展版不在 recommended 需显式启用 + 禁用核心版)和 no-array-constructor(核心版 extraRules 覆盖 ts.configs.recommended 的 off 设置导致与扩展版重复诊断,需在 TS 文件中禁用核心版) | 扩展规则冲突初版仅处理 no-shadow 替换,分析后发现 no-array-constructor 也会因 ESLint extraRules 覆盖 ts.configs.recommended 的 off 设置而产生重复诊断,补充冲突修复;only-throw-error 归属初版误记为"已在 recommended",核对 2026-07-29-typescript-eslint-8-rules.md 确认其在 recommendedTypeChecked,当前无类型检查模式不可用,修正说明;文件作用域方案初版考虑不使用 files 字段(全局生效),分析后发现 TS 规则在 JS 文件上会报解析错误,改为通过 files 限定 TS 文件范围 | docs\superpowers\specs\2026-07-29-typescript-eslint-rule-enhancement-design.md | Trae 内部模型 | +| 2026-07-29 20:23 | ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 按设计书完成 typescript-eslint 规则增强编码:eslint.ts 追加 extraTsRules(13 条规则,含 11 新增 + 2 off 冲突修复)+ TS_FILES 常量 + getDefaultConfig() 追加文件作用域配置块;static-rules.json 追加 12 条 ts-eslint 规则条目并更新 linterVersion 为 8.x (35 rules) | 无 | src/adapters/eslint.ts src/rules/static-rules.json | deepseek-v4-flash-free | +| 2026-07-29 20:46 | ① 用户提出 → ⑤ 编码实现 | 删除 eslint.config.mjs(避免项目自身配置覆盖 ESLintAdapter 内置推荐规则) | 无 | eslint.config.mjs | deepseek-v4-flash-free | +| 2026-07-29 21:02 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 将 Stylelint 内置配置从 12 条硬编码规则扩展到 68 条(P0 官方 recommended 41 + P1 强烈推荐 7 + P2 建议启用 20),通过引入 stylelint-config-recommended 作为基线配置(与 ESLint 适配器使用 @eslint/js 的方式对齐),再用 extraRules 对象追加 27 条额外规则。设计涉及三个文件修改:src/adapters/stylelint.ts(替换 DEFAULT_CONFIG,从硬编码改为 recommendedConfig + extraRules 展开)、src/rules/static-rules.json(追加 24 条去重数据)、package.json(添加 stylelint-config-recommended 依赖)。原 12 条规则全部保留:5 条进入 P0、2 条进入 P1、5 条进入 P2。 | 先整理了 stylelint-16-rules.md(141 条活跃规则 + 76 条已移除样式规则的完整清单)作为选型基础 由此产出 stylelint-recommended-rules.md(推荐规则文档,68 条分级选型及理由)作为设计书前置输入 讨论阶段对比了 ESLint 与 Stylelint 集成方式的差异(Flat Config 数组 vs 配置对象展开、'error'/'warn' 双级别 vs true 单级别) 讨论阶段确认 stylelint-config-recommended 是纯 JSON 配置包无运行时依赖,可被 esbuild 正确打包 讨论阶段确认版本兼容性:stylelint-config-recommended@18.0.0 声明 stylelint: ">=16.0.0",兼容项目使用的 ^17.14.0 | docs\superpowers\specs\2026-07-29-stylelint-rule-enhancement-design.md | Trae 内部模型 | +| 2026-07-29 21:22 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | Stylelint 规则增强编码实现:package.json 添加 stylelint-config-recommended ^18.0.0;stylelint.ts 替换硬编码 DEFAULT_CONFIG 为 recommendedConfig + extraRules 展开(27 条 P1+P2);static-rules.json 追加 22 条规则条目(跳过 2 条已存在规则)并更新 linterVersion 为 16.x (68 rules);新增 stylelint-config-recommended.d.ts 类型声明 | type 声明文件(stylelint-config-recommended 缺少 TS 类型 → 创建 .d.ts);用户确认跳过 static-rules.json 中 color-no-invalid-hex 和 unit-no-unknown 的重叠追加 | package.json src/adapters/stylelint.ts src/rules/static-rules.json src/types/stylelint-config-recommended.d.ts | deepseek-v4-flash-free | +| 2026-07-30 20:29 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 将 PMD Java 内置规则集从全分类无差别引用(309 条含 20 弃用)优化为精选模式(274 条活跃规则):补启 Security 分类 2 条高价值安全规则(HardCodedCryptoKey、InsecureCryptoIv);排除 20 条已弃用规则(为 PMD 8.0.0 迁移做准备);排除 17 条误报率高的阈值类噪音规则(CyclomaticComplexity、TooManyMethods、NPathComplexity、CognitiveComplexity、NcssCount、TooManyFields、ExcessiveParameterList 等);处理 AvoidCatchingGenericException 跨分类(Design 和 Error Prone)特殊排除 | 增强方向分析与 ESLint/Stylelint 相反:ESLint 是"从少到多"补规则,PMD 是"从粗到精"排除噪音;Documentation 分类 6 条规则讨论后不启用(Javadoc 规则更适合团队约定而非代码审查工具强制);噪音规则选型迭代:初版仅排除弃用规则,分析后发现阈值类规则(如 CyclomaticComplexity 默认阈值 10 过低)在实际项目中误报率极高,补充排除 17 条 | docs\superpowers\specs\2026-07-30-pmd-rule-enhancement-design.md | Trae 内部模型 | +| 2026-07-30 20:48 | ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | PMD 规则增强编码实现:pmd-java-ruleset.xml 为 6 个分类添加 exclude 排除弃用/噪音规则,补启 multithreading 分类(排除 3 条噪音),更新 description;static-rules.json 移除 4 条残留弃用规则(GenericsNaming、UnnecessaryLocalBeforeReturn、DontImportSun、UselessOperationOnImmutable),追加 2 条缺失噪音规则(AvoidSynchronizedStatement、AvoidUsingVolatile),更新 linterVersion 为 "7.26.0 (274 Java rules + 12 JSP rules)";后续补充 16 条缺失的去重规则条目(Multithreading 9 条完整规则 + 7 条遗漏规则)使 static-rules.json 覆盖 273 条规则 | 编码前发现设计书与代码现状不一致:Security 分类和 Security 规则已在 static-rules.json 中预先存在(跳过追加),multithreading 分类在 XML 中缺失(补启而非仅为现有分类添加 exclude),弃用规则已部分移除但仍有 4 条残留,噪音规则缺失 2 条(AvoidUsingVolatile、AvoidSynchronizedStatement);用户确认补启 multithreading 并排除 3 条噪音,确认 linterVersion 使用设计书格式;后续用户要求补充 static-rules.json 中遗漏的推荐文档 P0 规则条目;编译失败由预存 officeparser 缺失导致,与本次变更无关 | jars/pmd/pmd-java-ruleset.xml src/rules/static-rules.json | deepseek-v4-pro | +| 2026-07-30 21:08 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 将 SQLFluff 内置配置从无差别 rules = all(75 条全启用)优化为精选规则集(57 条):保留全部 32 条 Core 核心规则作为 P0 基线;从 43 条非 Core 规则中精选 25 条高价值规则作为 P1(含结构优化 10 条 ST 类、引用规范 4 条 RF 类、约定 6 条 CV 类);排除 7 条低价值规则(3 条默认禁用 AL07/CV10/RF03 + 3 条纯格式化噪音 LT03/LT04/LT09 + 1 条需配置 CV09);设计内置 .sqlfluff 配置模板通过临时文件 + --config 参数注入(区别于 ESLint 的 Flat Config 对象和 Stylelint 的配置对象展开) | 增强方向分析与 ESLint/Stylelint 相反:ESLint 是"从少到多"补规则,SQLFluff 是"从全到精"减噪音;内置配置注入方案迭代:初版考虑在 CLI 参数中逐条传 rules,分析后发现参数过长且不可维护,改为生成临时 .sqlfluff 配置文件 + --config 参数引用;规则总数从 75 减至 57,信噪比提升(减少 18 条格式化噪音),推荐基线中 43 条可自动修复(75% 修复率) | docs\superpowers\specs\2026-07-30-sqlfluff-rule-enhancement-design.md | Trae 内部模型 | +| 2026-07-30 21:19 | ④ 人类审批 → ⑤ 编码实现 | SQLFluff 规则增强编码实现:sql-lint.ts 新增 BUILTIN_SQLFLUFF_CONFIG 内置精选配置常量(core + 25 条 P1 规则)、hasProjectSqlfluffConfig() 检测 .sqlfluff/.sqlfluff.ini、三层配置优先级(全局 > 项目 > 内置)、tierMap + tierToSeverity(P0/P1→error, P2→warning)、临时配置文件写入 os.tmpdir() 并在 finally 中清理;static-rules.json 为 75 条 SQLFluff 规则全部追加 tier 字段(P0 32 条/P1 25 条/P2 11 条/excluded 7 条),更新 linterVersion 为 "4.2.2 (57 recommended)" | 用户确认 .sqlfluff.ini 也需检测、确认实现 tier→DiagnosticSeverity 可选增强映射(P0/P1→Error, P2→Warning);ESLint curly 规则警告单行 if 无花括号:tierToSeverity 的 return 语句补充花括号修复;编译错误为 pptx-converter.ts 预存 officeparser 缺失,与本次变更无关 | src/adapters/sql-lint.ts src/rules/static-rules.json | deepseek-v4-pro | +| 2026-07-30 21:42 | ① 用户提出 → ⑤ 编码实现 → ⑥ 审查验证 | 审查面板 WebView 中静态分析和自定义规则项可展开显示建议(suggestion)内容:移除 buildIssueItem 调用末尾的 false 参数使 expandable 默认为 true | 无 | src/panel/webview.ts | deepseek-v4-flash | +| 2026-07-30 22:16 | ① 用户提出 → ② 需求澄清 → ③ 方案设计→ ④ 人类审批 | 设计自定义规则导入导出闭环:导出侧在 setupView 加「导出模板」按钮生成 2 sheet 的 .xlsx(复用 xlsx 库零新依赖);导入侧加 checkbox「从模板导入」,勾选走程序直通解析(TemplateConverter 固定列映射跳过 AI),不勾选走原 AI 链路(零回归);解析与去重解耦——程序解析快且确定,AI 仅做语义去重(新增 buildDedupOnlyPrompt 只标重复不改字段);校验分两层,准入校验(格式/表头)硬报错,数据行校验(severity 拼错/字段空)进预览「错误规则」组(置顶只读、自动丢弃、有效规则正常导入);不校验表内 id 重复交由 AI 去重 | 链路选择迭代:初版自动识别表头判定走哪条链路,歧义大改为 checkbox 显式触发;错误处理迭代:初版校验失败一律硬报错,用户推荐改为错误规则进预览分组只读展示,最终定为准入硬报错+数据行软提示;Web 预览迭代:首版模拟样式被指不像,二版拉取真实源码按真实类名/配色重做 | docs\superpowers\specs\2026-07-30-export-template-design.md | Trae 内部模型 | +| 2026-07-30 22:35 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 | 解读并修正模板导出/导入设计书,产出 v2.0 方案文档 | 初版设计书 5 个问题逐一讨论后放弃(API 签名、参数传递、错误降级、prompt 约束),产出修正稿 v2 | docs/superpowers/specs/2026-07-30-export-template-design-v2.md | deepseek-v4-pro | +| 2026-07-30 22:38 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 | 实现模板导出/导入功能全链路 | 无 | src/rules/import-types.ts, src/rules/export-service.ts(新), src/rules/converters/template-converter.ts(新), src/rules/converters/dedup-prompt.ts(新), src/rules/import-service.ts, src/rules/import-preview.ts, src/views/setupView.ts, src/views/setupView.js, src/activation/commands.ts, package.json, src/i18n/messages.ts | deepseek-v4-pro | +| 2026-07-30 23:03 | ① 用户提出 → ⑤ 编码实现 | 导出按钮图标 📤→↓ 与 ➕添加 风格统一;复选框移至 field-hint 同行右对齐 | 图标迭代 📤→⬇→↓;复选框初版在 field-hint 下方独立一行,被要求移到提示文字右侧 | src/views/setupView.ts, src/i18n/messages.ts | deepseek-v4-pro | +| 2026-07-30 23:08 | ⑥ 审查验证 | 闭环校验模板文件:rowNumber 计算 bug 修复(先 filter 后 map 导致空行后索引偏移,改为先记行号再 filter) | 无 | src/rules/converters/template-converter.ts | deepseek-v4-pro | diff --git a/docs/superpowers/specs/2026-07-29-eslint-rule-enhancement-design.md b/docs/superpowers/specs/2026-07-29-eslint-rule-enhancement-design.md new file mode 100644 index 0000000..bb18017 --- /dev/null +++ b/docs/superpowers/specs/2026-07-29-eslint-rule-enhancement-design.md @@ -0,0 +1,498 @@ +# ESLint 规则增强设计书 + +## 一、背景与目标 + +### 1.1 现状 + +当前 `ESLintAdapter`(`src/adapters/eslint.ts`)内置默认配置为: + +```typescript +public static getDefaultConfig(): any[] { + if (!ESLintAdapter.defaultConfig) { + ESLintAdapter.defaultConfig = [ + js.configs.recommended, // @eslint/js recommended → 61 条 + ...ts.configs.recommended, // typescript-eslint recommended → 24 条 + ]; + } + return ESLintAdapter.defaultConfig; +} +``` + +仅启用了官方 `recommended` 的 61 条 ESLint 核心规则,全部属于 "Possible Problems" 类(语法错误、死代码等)。ESLint 9.x 活跃规则共 199 条,当前覆盖率仅 31%。 + +### 1.2 目标 + +将内置配置从 61 条扩展到 94 条(P0 官方推荐 61 + P1 强烈推荐 17 + P2 建议启用 16),使静态分析能捕获更多高频真实 bug,同时保持低误报率。 + +### 1.3 设计原则 + +- **不破坏现有配置优先级**:全局配置 > 项目配置 > 内置配置,三层择一逻辑不变 +- **不引入新依赖**:P1/P2 规则全部来自 `eslint` 包内置规则,无需额外安装插件 +- **同步更新去重数据**:`static-rules.json` 必须同步追加新增规则,保证自定义规则导入时的去重检测覆盖完整 +- **不修改规则 ID 前缀格式**:诊断结果仍使用 `eslint:{ruleId}` 格式 + +--- + +## 二、影响范围分析 + +### 2.1 需要修改的文件 + +| 文件 | 修改类型 | 修改内容 | +|------|----------|----------| +| `src/adapters/eslint.ts` | 代码修改 | `getDefaultConfig()` 方法增加 P1+P2 规则配置 | +| `src/rules/static-rules.json` | 数据修改 | `rules.eslint` 数组追加 33 条规则条目 | +| `package.json` | 依赖修改 | `dependencies` 中补充 `@eslint/js` 显式声明 | + +### 2.2 不需要修改的文件 + +| 文件 | 原因 | +|------|------| +| `scripts/build.mjs` | `@eslint/js` 不在 external 列表中,已被 esbuild 正确打包 | +| `src/adapters/jsp.ts` | 内部复用 `ESLintAdapter` 实例,自动继承新配置 | +| `src/orchestrator/orchestrator.ts` | 仅做调度,不涉及配置逻辑 | +| `src/config/linter.ts` | 配置读取层不变 | +| `eslint.config.mjs` | 项目自身 lint 配置,与运行时适配器配置无关 | + +### 2.3 不受影响的功能 + +- 全局配置(`linters.eslintConfigPath`):用户指定配置文件时完全替代内置配置,不受影响 +- 项目配置(`.eslintrc.*` / `eslint.config.*`):存在时完全替代内置配置,不受影响 +- JSP 适配器:复用 `ESLintAdapter`,自动获得增强后的配置 +- 规则 ID 输出格式:仍为 `eslint:{ruleId}`,不变 + +--- + +## 三、详细设计 + +### 3.1 修改 `src/adapters/eslint.ts` + +#### 3.1.1 当前代码 + +```typescript +import js from '@eslint/js'; +import ts from 'typescript-eslint'; + +// ... 中间部分不变 ... + +public static getDefaultConfig(): any[] { + if (!ESLintAdapter.defaultConfig) { + ESLintAdapter.defaultConfig = [ + js.configs.recommended, + ...ts.configs.recommended, + ]; + } + return ESLintAdapter.defaultConfig; +} +``` + +#### 3.1.2 修改后代码 + +```typescript +import js from '@eslint/js'; +import ts from 'typescript-eslint'; + +// 新增:P1+P2 额外规则配置常量 +const extraRules: Record = { + // === P1:强烈推荐(error)=== + 'eqeqeq': 'error', + 'no-eq-null': 'error', + 'no-self-compare': 'error', + 'no-promise-executor-return': 'error', + 'no-shadow': 'error', + 'no-unassigned-vars': 'error', + 'no-useless-assignment': 'error', + 'block-scoped-var': 'error', + 'default-case': 'error', + 'default-case-last': 'error', + 'no-unmodified-loop-condition': 'error', + 'no-unreachable-loop': 'error', + 'no-constant-binary-expression': 'error', + 'no-eval': 'error', + 'no-implied-eval': 'error', + 'no-extend-native': 'error', + // === P2:建议启用 === + 'no-var': 'error', + 'no-await-in-loop': 'warn', + 'prefer-template': 'warn', + 'prefer-object-spread': 'warn', + 'prefer-rest-params': 'warn', + 'prefer-spread': 'warn', + 'prefer-object-has-own': 'warn', + 'no-useless-concat': 'warn', + 'no-useless-return': 'warn', + 'no-useless-computed-key': 'warn', + 'no-useless-rename': 'warn', + 'no-param-reassign': 'warn', + 'no-return-assign': 'error', + 'no-throw-literal': 'error', + 'camelcase': 'warn', + 'new-cap': 'warn', + 'no-array-constructor': 'error', +}; + +// ... 中间部分不变 ... + +public static getDefaultConfig(): any[] { + if (!ESLintAdapter.defaultConfig) { + ESLintAdapter.defaultConfig = [ + js.configs.recommended, + ...ts.configs.recommended, + // 新增:P1+P2 额外规则 + { rules: extraRules }, + ]; + } + return ESLintAdapter.defaultConfig; +} +``` + +#### 3.1.3 设计说明 + +**为什么用 `extraRules` 常量而不是内联对象?** + +- 可读性:33 条规则单独成文件级常量,与 `getDefaultConfig()` 逻辑分离 +- 可维护性:未来增删规则只需修改 `extraRules` 对象,不需要动方法逻辑 +- 可测试性:常量可以被测试文件直接导入验证 + +**为什么放在 `recommended` 之后?** + +ESLint Flat Config 的规则是后者覆盖前者。`extraRules` 放在最后,如果其中某些规则已在 `recommended` 中启用(如 `no-implied-eval` 在 recommended 中已有),`extraRules` 的配置会覆盖其级别。但实际上 P1/P2 选型时已排除了与 recommended 重复的规则,不存在冲突。 + +**为什么不用 `@eslint/js` 的 `configs.all`?** + +`js.configs.all` 启用全部 199 条活跃规则,包含大量不应在代码审查工具中强制启用的规则(如 `no-magic-numbers`、`max-lines` 等)。精确选择 33 条更合理。 + +### 3.2 修改 `src/rules/static-rules.json` + +#### 3.2.1 修改内容 + +在 `rules.eslint` 数组末尾追加以下 33 条规则条目(格式与现有 61 条一致): + +```json +{"id": "eslint/eqeqeq", "description": "Require === and !=="}, +{"id": "eslint/no-eq-null", "description": "Disallow null comparisons without type-checking"}, +{"id": "eslint/no-self-compare", "description": "Disallow comparisons where both sides are the same"}, +{"id": "eslint/no-await-in-loop", "description": "Disallow await inside loops"}, +{"id": "eslint/no-promise-executor-return", "description": "Disallow returning values from Promise executor"}, +{"id": "eslint/no-shadow", "description": "Disallow variable declarations from shadowing variables in outer scopes"}, +{"id": "eslint/no-unassigned-vars", "description": "Disallow let or var variables that are read but never assigned"}, +{"id": "eslint/no-useless-assignment", "description": "Disallow variable assignments where the value is not used"}, +{"id": "eslint/block-scoped-var", "description": "Enforce variables within the scope they are defined"}, +{"id": "eslint/default-case", "description": "Require default cases in switch statements"}, +{"id": "eslint/default-case-last", "description": "Enforce default clauses in switch statements to be last"}, +{"id": "eslint/no-unmodified-loop-condition", "description": "Disallow unmodified loop conditions"}, +{"id": "eslint/no-unreachable-loop", "description": "Disallow loops with a body that allows only one iteration"}, +{"id": "eslint/no-constant-binary-expression", "description": "Disallow expressions where the operation doesn't affect the value"}, +{"id": "eslint/no-eval", "description": "Disallow the use of eval()"}, +{"id": "eslint/no-extend-native", "description": "Disallow extending native types"}, +{"id": "eslint/no-var", "description": "Require let or const instead of var"}, +{"id": "eslint/prefer-template", "description": "Require template literals instead of string concatenation"}, +{"id": "eslint/prefer-object-spread", "description": "Disallow Object.assign and prefer object spread"}, +{"id": "eslint/prefer-rest-params", "description": "Require rest parameters instead of arguments"}, +{"id": "eslint/prefer-spread", "description": "Require spread operator instead of .apply()"}, +{"id": "eslint/prefer-object-has-own", "description": "Disallow Object.prototype.hasOwnProperty.call() and prefer Object.hasOwn()"}, +{"id": "eslint/no-useless-concat", "description": "Disallow unnecessary concatenation of literals or template literals"}, +{"id": "eslint/no-useless-return", "description": "Disallow redundant return statements"}, +{"id": "eslint/no-useless-computed-key", "description": "Disallow unnecessary computed property keys in objects and classes"}, +{"id": "eslint/no-useless-rename", "description": "Disallow renaming import, export, and destructured assignments to the same name"}, +{"id": "eslint/no-param-reassign", "description": "Disallow reassigning function parameters"}, +{"id": "eslint/no-return-assign", "description": "Disallow assignment operators in return statements"}, +{"id": "eslint/no-throw-literal", "description": "Disallow throwing literals as exceptions"}, +{"id": "eslint/camelcase", "description": "Enforce camelcase naming convention"}, +{"id": "eslint/new-cap", "description": "Require constructor names to begin with a capital letter"}, +{"id": "eslint/no-array-constructor", "description": "Disallow Array constructors"} +``` + +> 注:`no-implied-eval` 已在 recommended 中启用,不在追加列表中。追加的 33 条均为 recommended 之外的新增规则。 + +#### 3.2.2 修改 `linterVersion` 字段 + +```json +"linterVersion": { + "eslint": "9.x (94 rules)", + ... +} +``` + +将 `"9.x (recommended)"` 改为 `"9.x (94 rules)"`,反映实际启用规则数量。 + +#### 3.2.3 为什么必须同步更新 static-rules.json + +`static-rules.json` 有两个用途: + +1. **UI 展示**:在设置面板中展示当前 linter 支持的规则清单 +2. **去重检测**:自定义规则导入时,按 ID 匹配 `static-rules.json` 中的规则,若已存在则提示重复 + +如果不更新,用户新增的 `eqeqeq` 自定义规则不会被识别为重复(因为 `static-rules.json` 中没有这条),导致重复规则。 + +### 3.3 修改 `package.json` + +#### 3.3.1 当前代码 + +```json +"dependencies": { + "eslint": "^9.39.3", + "stylelint": "^17.14.0", + "typescript-eslint": "^8.56.1", + "xlsx": "^0.18.5" +} +``` + +#### 3.3.2 修改后代码 + +```json +"dependencies": { + "@eslint/js": "^9.39.3", + "eslint": "^9.39.3", + "stylelint": "^17.14.0", + "typescript-eslint": "^8.56.1", + "xlsx": "^0.18.5" +} +``` + +#### 3.3.3 修改理由 + +`eslint.ts` 中 `import js from '@eslint/js'` 已被使用,但 `@eslint/js` 未在 `package.json` 中显式声明,仅作为 `eslint` 包的传递依赖存在。这属于版本迭代遗留问题(见 `_AI_USAGE_LOG.md` 第82条记录)。显式声明可消除依赖不确定性。 + +--- + +## 四、新增规则分类详解 + +### 4.1 P1 强烈推荐(17 条,error 级别) + +这些规则检测高频真实 bug,误报率极低。 + +#### 4.1.1 等值与比较(3 条) + +| 规则 | 检测场景 | 误报评估 | +|------|----------|----------| +| `eqeqeq` | `==` 隐式类型转换 | 极低,几乎所有现代项目都启用 | +| `no-eq-null` | `x == null` 同时匹配 null 和 undefined | 低,通常只需判断其一 | +| `no-self-compare` | `a === a` 恒为 true | 零误报,几乎一定是笔误 | + +#### 4.1.2 异步与 Promise(2 条) + +| 规则 | 检测场景 | 误报评估 | +|------|----------|----------| +| `no-await-in-loop` | 循环中串行 await 导致性能问题 | 中,设为 warn,允许逐条忽略 | +| `no-promise-executor-return` | executor 返回值被忽略 | 零误报 | + +#### 4.1.3 作用域与变量(4 条) + +| 规则 | 检测场景 | 误报评估 | +|------|----------|----------| +| `no-shadow` | 内层变量遮蔽外层变量 | 低,遮蔽几乎都是 bug | +| `no-unassigned-vars` | 读取未赋值的 let/var | 零误报 | +| `no-useless-assignment` | 赋值后值未被使用 | 低 | +| `block-scoped-var` | var 变量在声明作用域外使用 | 低 | + +#### 4.1.4 控制流与逻辑(5 条) + +| 规则 | 检测场景 | 误报评估 | +|------|----------|----------| +| `default-case` | switch 缺少 default 分支 | 低 | +| `default-case-last` | default 不在最后 | 零误报 | +| `no-unmodified-loop-condition` | 循环条件未修改导致死循环 | 零误报 | +| `no-unreachable-loop` | 循环体只允许一次迭代 | 低 | +| `no-constant-binary-expression` | 操作不影响结果值 | 低 | + +#### 4.1.5 安全(3 条) + +| 规则 | 检测场景 | 误报评估 | +|------|----------|----------| +| `no-eval` | eval() 执行任意代码 | 零误报 | +| `no-implied-eval` | setTimeout("code") 类似 eval | 零误报(已在 recommended 中) | +| `no-extend-native` | 修改 Array.prototype 等 | 零误报 | + +### 4.2 P2 建议启用(16 条) + +#### 4.2.1 现代 JS 语法(6 条) + +| 规则 | 级别 | 检测场景 | +|------|------|----------| +| `no-var` | error | 使用 var 代替 let/const | +| `prefer-template` | warn | 字符串拼接代替模板字面量 | +| `prefer-object-spread` | warn | Object.assign 代替对象展开 | +| `prefer-rest-params` | warn | arguments 代替 rest 参数 | +| `prefer-spread` | warn | .apply() 代替展开运算符 | +| `prefer-object-has-own` | warn | 旧式 hasOwnProperty 代替 Object.hasOwn | + +#### 4.2.2 代码简洁性(4 条) + +| 规则 | 级别 | 检测场景 | +|------|------|----------| +| `no-useless-concat` | warn | 不必要的字符串拼接 | +| `no-useless-return` | warn | 多余的 return 语句 | +| `no-useless-computed-key` | warn | 不必要的计算属性键 | +| `no-useless-rename` | warn | 重命名为相同名称 | + +#### 4.2.3 防御性编程(3 条) + +| 规则 | 级别 | 检测场景 | +|------|------|----------| +| `no-param-reassign` | warn | 修改函数参数(副作用风险) | +| `no-return-assign` | error | return 中赋值(笔误风险) | +| `no-throw-literal` | error | 抛出字面量而非 Error 对象 | + +#### 4.2.4 命名与风格(3 条) + +| 规则 | 级别 | 检测场景 | +|------|------|----------| +| `camelcase` | warn | 非驼峰命名 | +| `new-cap` | warn | 构造函数未大写 | +| `no-array-constructor` | error | 使用 Array 构造函数 | + +--- + +## 五、规则级别设计 + +### 5.1 级别分配原则 + +| 级别 | 适用场景 | 数量 | +|------|----------|------| +| `error` | 确定性 bug、安全问题、语法错误 | 74 条 | +| `warn` | 代码质量建议、风格偏好(可逐条忽略) | 20 条 | + +### 5.2 为什么部分规则设为 warn 而非 error + +以下规则设为 `warn` 是因为它们有合理的例外场景: + +| 规则 | warn 理由 | +|------|-----------| +| `no-await-in-loop` | 某些场景确实需要串行 await(如分页请求) | +| `prefer-template` | 超长字符串拼接时 `+` 可能更清晰 | +| `prefer-rest-params` | 兼容旧环境时可能需要 arguments | +| `no-param-reassign` | Redux reducer 等模式需要修改参数 | +| `camelcase` | 对接外部 API 时可能需要 snake_case | + +其余规则设为 `error` 是因为它们的触发几乎一定意味着 bug 或安全问题。 + +--- + +## 六、兼容性分析 + +### 6.1 对现有用户代码的影响 + +启用新规则后,之前能通过审查的代码可能会新增诊断: + +| 影响程度 | 规则 | 说明 | +|----------|------|------| +| **可能大量新增诊断** | `eqeqeq` | 大量旧代码使用 `==`,但这是必要的改进 | +| **可能大量新增诊断** | `no-shadow` | 嵌套作用域中常见,需逐个审查 | +| **中等新增诊断** | `no-param-reassign` | 函数中修改参数较常见 | +| **少量新增诊断** | `default-case` | 大多数 switch 已有 default | +| **少量新增诊断** | `no-var` | 现代 TS 项目已普遍使用 let/const | +| **极少新增诊断** | `no-eval` / `no-extend-native` | 正常项目几乎不会用 | + +### 6.2 对 JSP 适配器的影响 + +JSP 适配器(`src/adapters/jsp.ts`)内部持有 `ESLintAdapter` 实例,提取 `