# 创建项目配置 = 内置配置(含三语规则注释)— Design Spec ## 1. 概述 当用户在 Setup 面板点击「创建项目配置」时,插件在项目根目录生成对应适配器的配置文件(`ruleset.xml` / `.sqlfluff` / `.stylelintrc.js` / `eslint.config.js`)。 本设计将生成的"示例模板"改为**与插件内置运行规则完全一致的配置**,并为每条规则附加三语(zh-CN / en / ja)描述注释,帮助用户理解已启用的规则、按相同格式添加新规则。 ## 2. 背景与问题 ### 2.1 现状 | 适配器 | 内置运行配置 | 当前"创建项目配置"生成内容 | 问题 | |--------|-------------|---------------------------|------| | PMD | `jars/pmd/pmd-java-ruleset.xml`(7 类 274 条 + 41 处排除) | 仅引用 2 个类别(bestpractices + codestyle)的示例 | 规则范围显著缩小 | | SQLFluff | 精选 26 项规则清单 + `max_line_length=80 / indent_unit=space / tab_space_size=4` | `rules = all` + `dialect = mysql` | 范围过大,且与内置不一致 | | Stylelint | `stylelint-config-recommended`(41 条)+ 27 条 extra | 仅 3 条示例规则 | 规则范围显著缩小 | | ESLint | `@eslint/js` recommended(61 条)+ 31 条 extra(JS) | 仅 3 条示例规则 | 规则范围显著缩小 | ### 2.2 核心问题 1. **规则缩水**:项目配置文件的优先级高于内置配置(`eslint.ts:105-115`、`stylelint.ts:120-125`、`pmd.ts:89-92`)。一旦创建当前示例模板,实际检查范围从数十条骤降至 3 条(或 2 个类别)。 2. **不可知**:用户看不到内置规则清单,也不知道配置文件中的规则写法,难以添加新规则。 ### 2.3 目标 - 「创建项目配置」生成的 4 个文件内容 = 插件内置配置,规则范围精确一致。 - 每条规则带三语描述注释(随插件 `ai.outputLanguage` 切换)。 - 每个文件头部含一段"如何添加规则"注释 + **单个**"该工具全部规则索引"链接。 - 内置规则与生成文件永远一致(单一数据源,杜绝漂移)。 ### 2.4 非目标 - 不在 Setup 面板增加规则目录 UI(生成文件本身即规则清单)。 - 不对 ESLint 生成 TypeScript 专项规则(方案 B:仅 JS,零依赖)。 - 不将 PMD 274 条规则展开为逐条 ``(保持类别引用结构)。 - 不新增"全量规则枚举"(各工具全部规则目录)。 ## 3. 方案设计 ### 3.1 架构概览 ``` adapters/*.ts (内置运行规则) │ import 共享常量 ▼ src/rules/builtin-rules.ts (单一数据源) │ 4 个生成函数 ▼ setupView.ts 模板 → 点击「创建项目配置」→ 写入项目根目录 │ └─ 注释语言 getLanguage() / 规则描述 static-rules.json ``` ### 3.2 共享数据源模块 `src/rules/builtin-rules.ts`(新建) 从各 adapter 迁出常量,adapter 与模板共用: ```typescript import staticRules from './static-rules.json'; import type { Language } from '../i18n/messages'; // —— 共享常量(从 adapters 迁出)—— export const eslintExtraRules: Record; // 自 eslint.ts export const eslintExtraTsRules: Record; // 自 eslint.ts(生成文件不含,仅 adapter 使用) export const stylelintExtraRules: Record; // 自 stylelint.ts export const BUILTIN_SQLFLUFF_RULES: string; // 自 sqlfluff.ts(26 项) export function buildBuiltinSqlfluffConfig(dialect: string): string; // 自 sqlfluff.ts(含行宽/缩进设置) // —— 规则描述查询(三语)—— export function getRuleDescription(linter: string, ruleId: string, lang: Language): string | undefined; // —— 文档索引链接(每工具仅 1 个)—— const ESLINT_RULES_URL = 'https://eslint.org/docs/latest/rules/'; const STYLELINT_RULES_URL = 'https://stylelint.io/user-guide/rules/'; const SQLFLUFF_RULES_URL = 'https://docs.sqlfluff.com/en/stable/reference/rules.html'; // PMD 版本取自 staticRules.linterVersion.pmd → `https://docs.pmd-code.org/pmd-doc-/pmd_rules_java.html` // —— 生成函数 —— export function buildEslintProjectConfigText(lang: Language): string; export async function buildStylelintProjectConfigText(lang: Language): Promise; export function buildSqlfluffProjectConfigText(dialect: string, lang: Language): string; export async function buildPmdProjectRulesetText(lang: Language): Promise; ``` **依赖注入**: - `buildEslintProjectConfigText` 内联 `@eslint/js` 的 `configs.recommended.rules`(61 条,core 规则、无插件依赖)。 - `buildStylelintProjectConfigText` 运行时 `await import('stylelint-config-recommended')`(ESM-only)后合并 extra,序列化为纯对象(零依赖)。 ### 3.3 生成文件内容规范 #### 3.3.1 ESLint `eslint.config.js`(方案 B:仅 JS,零依赖) ```js // ============================================================ // 项目配置 — 与插件内置 ESLint 规则一致(由插件生成) // 如何添加规则: // 1. 在 rules 中新增一行,如 'no-alert': 'warn' // 2. 带参数写法,如 'semi': ['error', 'always'] // 全部可用规则:https://eslint.org/docs/latest/rules/ // 注意:本文件仅包含 JS 内置规则。TS 项目如需 TS 专项规则, // 请安装 typescript-eslint 后自行追加: // const ts = require('typescript-eslint'); // module.exports = [ ...本文件配置, ...ts.configs.recommended ]; // ============================================================ module.exports = [ { rules: { // --- @eslint/js recommended (61) --- 'constructor-super': 'error', // 在构造函数中校验 super() 的调用 'for-direction': 'error', // 确保 for 循环更新子句朝正确方向移动计数器 // ...(61 条全量内联) // --- 插件补充 (31) --- 'eqeqeq': 'error', // 强制使用 === 和 !== 'no-eq-null': 'error', // 禁止与 null 使用 == 比较 // ...(31 条全量内联) }, }, ]; ``` #### 3.3.2 Stylelint `.stylelintrc.js` ```js // ============================================================ // 项目配置 — 与插件内置 Stylelint 规则一致(由插件生成) // 如何添加规则:在 rules 中新增一行,如 'indentation': 2 // 全部可用规则:https://stylelint.io/user-guide/rules/ // ============================================================ module.exports = { rules: { 'annotation-no-unknown': true, // 禁止未知注解 // ...(41 条 recommended 全量内联) 'color-no-invalid-hex': true, // 禁止无效的十六进制颜色 // ...(27 条 extra 全量内联) }, }; ``` #### 3.3.3 SQLFluff `.sqlfluff` ```ini [sqlfluff] # 数据库方言:postgres / mysql / bigquery / snowflake 等 dialect = mysql # 想启用全部规则时改为 → rules = all # 内置精选规则清单: # core 核心规则组(稳定、跨方言的语法类基础规则) # AM03 禁止隐式交叉连接 # CV01 ...(逐条:规则码 + 三语描述,共 26 项) # 全部可用规则:https://docs.sqlfluff.com/en/stable/reference/rules.html rules = core,AM03,AM05,AM08,CV01,CV02,CV06,CV08,CV12,LT13,LT14,LT15,ST01,ST02,ST04,ST05,ST06,ST07,ST09,ST10,ST11,ST12,RF02,RF04,RF05,RF06 max_line_length = 80 indent_unit = space tab_space_size = 4 ``` #### 3.3.4 PMD `ruleset.xml` ```xml Java Code Review Rules (274 active rules, 7 categories) — 与插件内置规则集一致(由插件生成) ... ``` ### 3.4 注释策略 | 文件 | 注释粒度 | 内容 | |------|---------|------| | `eslint.config.js` / `.stylelintrc.js` | 逐条规则 | `规则码 + 三语描述`(尾行 `//` 注释) | | `.sqlfluff` | 逐条规则 | `rules =` 行上方注释块(`# 规则码 三语描述`) | | `ruleset.xml` | 类别级 | 7 个 `` 类别 + 41 处 ``(``) | - 描述来源:`static-rules.json` 的 `description` / `descriptionZh` / `descriptionJa`,按 `getLanguage()` 取对应语言。 - exclude 描述:从 `static-rules.json` pmd 段(273 条)按规则名查询;查不到的仅保留名字、不加注释。 - 链接:**每个文件仅 1 个**"全部可用规则"索引链接,位于文件头注释块;逐条注释不含链接。 - 注释语言:跟随 `ai.outputLanguage`(`getLanguage()`),三语切换。 ### 3.5 setupView 改造(`src/views/setupView.ts`) - `ADAPTER_METADATA` 的 `configFileTemplate` 类型:`() => string` → `() => string | Promise`。 - 4 个模板函数全部委托给 `builtin-rules` 生成函数(删掉 `getEslintTemplate` / `getStylelintTemplate` / `getSqlfluffTemplate` / `getPmdRulesetTemplate` 的示例内容)。 - `handleAdapterConfig`(`setupView.ts:1231`): ```typescript const content = await meta.configFileTemplate(); fs.writeFileSync(filePath, content, 'utf-8'); ``` - PMD 规则集读取路径(复用 `pmd.ts:26-44` 的解析逻辑): `ext.extensionPath/jars/pmd/pmd-java-ruleset.xml`,找不到时回退到 `out/jars` / 源码相对路径。 - SQLFluff 方言:固定 `mysql`(用户已确认接受)。 ### 3.6 adapter 常量抽取(`eslint.ts` / `stylelint.ts` / `sqlfluff.ts`) | 文件 | 迁出常量 | 改为 | |------|---------|------| | `src/adapters/eslint.ts` | `extraRules` / `extraTsRules` | `import { eslintExtraRules, eslintExtraTsRules } from '../rules/builtin-rules'` | | `src/adapters/stylelint.ts` | `extraRules` | `import { stylelintExtraRules } from '../rules/builtin-rules'` | | `src/adapters/sqlfluff.ts` | `BUILTIN_SQLFLUFF_RULES` / `buildBuiltinConfig` | 从 `builtin-rules` 导入 | ### 3.7 static-rules.json 补充(`src/rules/static-rules.json`) - **stylelint**:补写 34 条 recommended 规则的三语描述(`annotation-no-unknown`、`at-rule-no-unknown`、`block-no-empty` 等),使 stylelint 段达到 68 条全覆盖(41 recommended + 27 extra)。 - **sqlfluff**:补 `core` 规则组条目(如"SQLFluff 核心规则组(稳定、跨方言的语法类基础规则)"),使内置 26 项均有描述。 ### 3.8 i18n 帮助文案(`src/i18n/messages.ts:515-549`) 更新 4 个 `setup.adapter.*Help` 文案,核心变化: - 说明「创建项目配置将生成与内置一致的规则文件(含三语规则注释)」。 - ESLint 文案补充:生成文件仅含 JS 内置规则;TS 项目如需 TS 专项规则,自行安装 `typescript-eslint` 并参考文件头注释追加。 ## 4. 关键接口定义 ```typescript // src/rules/builtin-rules.ts export const eslintExtraRules: Record; export const eslintExtraTsRules: Record; export const stylelintExtraRules: Record; export const BUILTIN_SQLFLUFF_RULES: string; export function buildBuiltinSqlfluffConfig(dialect: string): string; export function getRuleDescription(linter: string, ruleId: string, lang: Language): string | undefined; export function buildEslintProjectConfigText(lang: Language): string; export function buildStylelintProjectConfigText(lang: Language): Promise; export function buildSqlfluffProjectConfigText(dialect: string, lang: Language): string; export function buildPmdProjectRulesetText(lang: Language): Promise; // src/views/setupView.ts(改造) type ConfigFileTemplate = () => string | Promise; ``` ## 5. 文件变更清单 | 类型 | 文件 | 说明 | |------|------|------| | 新建 | `src/rules/builtin-rules.ts` | 共享常量 + 描述查询 + 4 个生成函数 | | 修改 | `src/adapters/eslint.ts` | 常量改为从 builtin-rules 导入 | | 修改 | `src/adapters/stylelint.ts` | 常量改为从 builtin-rules 导入;修复既有 CJS/ESM 加载 bug(`stylelint-config-recommended` 为纯 ESM,顶层静态 import 改动态 import) | | 修改 | `src/adapters/sqlfluff.ts` | 内置清单/构建函数改为从 builtin-rules 导入 | | 修改 | `src/views/setupView.ts` | 模板函数委托 + configFileTemplate 异步化 + handleAdapterConfig await | | 修改 | `src/rules/static-rules.json` | stylelint 补 34 条、sqlfluff 补 core、pmd 补 22 条 exclude 规则描述 | | 修改 | `src/i18n/messages.ts` | 4 个 adapter help 文案更新 | | 修改 | `docs/superpowers/specs/2026-08-06-builtin-config-template-design.md` | 本设计书 | > 实现期发现并修复:`src/adapters/stylelint.ts` 顶层 `import stylelint-config-recommended`(纯 ESM 包)在 CJS 编译下必然报 "No exports main",属既有 bug,阻塞测试套件。已改为动态 `import`(与 `getModule()` 加载 stylelint 一致)。 > > 实际规则数量:ESLint 内置 JS 为 **92 条**(js recommended 61 + extra 31,方案初稿误记为 93/32);Stylelint **68 条**;SQLFluff **26 项**;PMD **37 处 exclude 全部可注释**(补写了 22 条缺失描述)。 ## 9. 验证反馈修复(2026-08-06) 安装 VSIX 实测发现并修复 3 个问题: 1. **PMD「创建项目配置」不生成文件**:`resolvePmdRulesetPath` 原用 `path.resolve(__dirname, '..', '..', 'jars', ...)`,在 esbuild 打包后 `__dirname` = `/out`,该路径多退一级找不到 `jars/`(开发时 `out/rules/` 下退两级才正确)。改为从 `__dirname` 逐级向上探测 5 级目录 + `getExtension` 路径,兼容打包/开发两种布局。 2. **生成的配置里部分注释为 `?`**:新增的 57 条规则描述(stylelint 34 + sqlfluff core + pmd 22)经 PowerShell 管道 `$s | node` 注入 `static-rules.json` 时,中文被 `$OutputEncoding`(ASCII)破坏成字面 `?`。改用 UTF-8 落盘的 .mjs 脚本重写这 57 条 `descriptionZh/descriptionJa` 修复。 3. **生成的 eslint.config.js / .stylelintrc.js 被插件静态分析报 `[eslint:no-undef] 'module' is not defined`**:两个配置文件是 CommonJS(`module.exports`),内置规则含 `no-undef` 且未声明 Node 全局。在两个生成文件首行加 `/* global module */` 消除误报。 另:本仓库根目录因安装验证生成的 `eslint.config.js` 会覆盖仓库自身 lint 配置(致 146 个 no-undef),为测试产物已删除。 ## 6. 影响范围 - 仅影响「创建项目配置」的文件内容与 Setup 面板帮助文案。 - adapter 运行逻辑不变(仅常量来源变化,行为一致)。 - 生成的配置文件位于用户项目根目录,不影响本仓库运行。 ## 7. 验证方案 1. `npm run lint` — ESLint 自检 2. `npm run compile` — tsc 编译 3. `npm test` — @vscode/test-cli 运行测试 4. 手工验证:打开 Setup 面板 → 点击 4 个适配器的「创建项目配置」→ 检查生成内容与 §3.3 示例一致、注释随语言切换。 ## 8. 已知取舍 | 项 | 说明 | |----|------| | ESLint 仅 JS | TS 项目使用生成配置后,ESLint 用默认 espree 解析 `.ts` 会产生语法解析错误;文件头注释给出追加 `typescript-eslint` 的示例引导。 | | SQLFluff 方言固定 mysql | 插件设置留空时内置回退方言为 oracle/ansi,与生成文件有差异(用户已确认接受)。 | | PMD 类别级注释 | 不展开 274 条逐条 ``,保持类别引用结构,注释以 7 类 + 41 处 exclude 为粒度。 | | 快照行为 | 生成文件 = 内置规则快照;插件日后升级改内置规则时,已生成的项目文件不会自动同步(项目配置优先级最高)。 | ## 9. 排除范围(非本期) - Setup 面板「规则目录」UI(查→复制→粘贴)。 - 各工具全量规则枚举(超出内置子集的规则)。 - ESLint TS 专项规则生成。