Files
2026Technology-Competition/docs/superpowers/specs/2026-08-06-builtin-config-template-design.md
T

299 lines
16 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.
# 创建项目配置 = 内置配置(含三语规则注释)— 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` recommended61 条)+ 31 条 extraJS) | 仅 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 条规则展开为逐条 `<rule>`(保持类别引用结构)。
- 不新增"全量规则枚举"(各工具全部规则目录)。
## 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<string, 'error' | 'warn'>; // 自 eslint.ts
export const eslintExtraTsRules: Record<string, 'error' | 'warn' | 'off'>; // 自 eslint.ts(生成文件不含,仅 adapter 使用)
export const stylelintExtraRules: Record<string, unknown>; // 自 stylelint.ts
export const BUILTIN_SQLFLUFF_RULES: string; // 自 sqlfluff.ts26 项)
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-<version>/pmd_rules_java.html`
// —— 生成函数 ——
export function buildEslintProjectConfigText(lang: Language): string;
export async function buildStylelintProjectConfigText(lang: Language): Promise<string>;
export function buildSqlfluffProjectConfigText(dialect: string, lang: Language): string;
export async function buildPmdProjectRulesetText(lang: Language): Promise<string>;
```
**依赖注入**
- `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
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="Java Rules"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
<description>Java Code Review Rules (274 active rules, 7 categories) — 与插件内置规则集一致(由插件生成)</description>
<!-- 全部可用规则:https://docs.pmd-code.org/pmd-doc-7.26.0/pmd_rules_java.html -->
<!-- 最佳实践类(避免空 catch、关闭流等) -->
<rule ref="category/java/bestpractices.xml">
<!-- 排除:不强制 switch 默认分支位于最后 -->
<exclude name="DefaultLabelNotLastInSwitchStmt"/>
<!-- ...41 处排除项逐条注释) -->
</rule>
<!-- 代码风格类(命名规范、花括号位置等) -->
<rule ref="category/java/codestyle.xml">...</rule>
<!-- 设计类 / errorprone / multithreading / performance / security 同理 -->
</ruleset>
```
### 3.4 注释策略
| 文件 | 注释粒度 | 内容 |
|------|---------|------|
| `eslint.config.js` / `.stylelintrc.js` | 逐条规则 | `规则码 + 三语描述`(尾行 `//` 注释) |
| `.sqlfluff` | 逐条规则 | `rules =` 行上方注释块(`# 规则码 三语描述` |
| `ruleset.xml` | 类别级 | 7 个 `<rule>` 类别 + 41 处 `<exclude>``<!-- -->` |
- 描述来源:`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<string>`
- 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<string, 'error' | 'warn'>;
export const eslintExtraTsRules: Record<string, 'error' | 'warn' | 'off'>;
export const stylelintExtraRules: Record<string, unknown>;
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<string>;
export function buildSqlfluffProjectConfigText(dialect: string, lang: Language): string;
export function buildPmdProjectRulesetText(lang: Language): Promise<string>;
// src/views/setupView.ts(改造)
type ConfigFileTemplate = () => string | Promise<string>;
```
## 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` = `<ext>/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 条逐条 `<rule>`,保持类别引用结构,注释以 7 类 + 41 处 exclude 为粒度。 |
| 快照行为 | 生成文件 = 内置规则快照;插件日后升级改内置规则时,已生成的项目文件不会自动同步(项目配置优先级最高)。 |
## 9. 排除范围(非本期)
- Setup 面板「规则目录」UI(查→复制→粘贴)。
- 各工具全量规则枚举(超出内置子集的规则)。
- ESLint TS 专项规则生成。