16 KiB
16 KiB
创建项目配置 = 内置配置(含三语规则注释)— 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 核心问题
- 规则缩水:项目配置文件的优先级高于内置配置(
eslint.ts:105-115、stylelint.ts:120-125、pmd.ts:89-92)。一旦创建当前示例模板,实际检查范围从数十条骤降至 3 条(或 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 与模板共用:
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.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-<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,零依赖)
// ============================================================
// 项目配置 — 与插件内置 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
// ============================================================
// 项目配置 — 与插件内置 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
[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 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.jsonpmd 段(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):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. 关键接口定义
// 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 个问题:
- PMD「创建项目配置」不生成文件:
resolvePmdRulesetPath原用path.resolve(__dirname, '..', '..', 'jars', ...),在 esbuild 打包后__dirname=<ext>/out,该路径多退一级找不到jars/(开发时out/rules/下退两级才正确)。改为从__dirname逐级向上探测 5 级目录 +getExtension路径,兼容打包/开发两种布局。 - 生成的配置里部分注释为
?:新增的 57 条规则描述(stylelint 34 + sqlfluff core + pmd 22)经 PowerShell 管道$s | node注入static-rules.json时,中文被$OutputEncoding(ASCII)破坏成字面?。改用 UTF-8 落盘的 .mjs 脚本重写这 57 条descriptionZh/descriptionJa修复。 - 生成的 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. 验证方案
npm run lint— ESLint 自检npm run compile— tsc 编译npm test— @vscode/test-cli 运行测试- 手工验证:打开 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 专项规则生成。