# vscode-code-reviewer 实施拆分方案 ## 决策汇总 | 决策项 | 选择 | |--------|------| | 拆分策略 | 按层级自底向上 | | 适配器优先级 | 按复杂度递增:ESLint → Stylelint → sql-lint → PMD → JSP | | 核心层B顺序 | 按依赖链:Provider → AI引擎 → 规则解析 → 结果合并 → 自动修复 → 报告导出 | | UI层顺序 | 按依赖顺序:命令注册 → 设置面板 → 审查面板 → Code Action | | 构建与测试 | 集中在最后 Phase | ## 整体 Phase 划分 ``` Phase 1: 基础层 Types + Config 管理 Phase 2: 适配层 5 个 Linter 适配器 Phase 3: 核心层 A 编排器 Orchestrator Phase 4: 核心层 B AI引擎 + 规则 + 合并 + 修复 + 报告 Phase 5: UI 层 命令 + 设置面板 + 审查面板 Phase 6: 构建与测试 esbuild + 测试 ``` ## 依赖关系图 ``` Phase 1 ────→ Phase 2 ────→ Phase 3 ────→ Phase 4 ────→ Phase 5 ────→ Phase 6 ↑ ↑ │ │ (2.1 接口) (4.1 Provider) (2.2~2.6 适配器) (4.2~4.6 其余) ``` Phase 2 内部必须按 2.1 → 2.2 → 2.3 → 2.4 → 2.5 → 2.6 顺序,JSP 适配器依赖 PMD/ESLint/Stylelint。 Phase 4 内部必须按 4.1 → 4.2 → 4.3 → 4.4 → 4.5 → 4.6 顺序,Fixer 依赖 Provider 和 Merger。 --- ## Phase 1: 基础层 **依赖**: 无 **目标**: 建立公共类型定义和配置管理,为所有上层模块提供基础能力 **参考设计**: §3.2, §6.4, §13.2 ### 文件清单 | 文件 | 操作 | 内容 | |------|------|------| | `src/types.ts` | 新建 | `LinterDiagnostic`、`AdapterResult`、`LinterAdapter` 等公共类型 | | `src/config/index.ts` | 新建 | 统一导出 | | `src/config/ai.ts` | 新建 | AI 配置 getter(provider/model/baseUrl/temperature/timeout/outputLanguage) | | `src/config/linter.ts` | 新建 | Linter 配置 getter(linters.xxx 语言-linter 映射、PMD 路径) | | `src/config/fixer.ts` | 新建 | 修复器配置(contextLines) | | `src/config/secret.ts` | 新建 | API Key SecretStorage(get/set/delete/isConfigured) | ### 关键类型 ```typescript // src/types.ts export type Severity = 'error' | 'warning' | 'info'; export type AdapterStatus = 'ok' | 'tool-unavailable' | 'execution-failed'; export interface LinterDiagnostic { severity: Severity; ruleId: string; message: string; range: vscode.Range; suggestion?: string; } export interface AdapterResult { diagnostics: LinterDiagnostic[]; status: AdapterStatus; errorMessage?: string; } export interface LinterAdapter { id: string; supportedLanguages: string[]; check(document: vscode.TextDocument, workingDir: string): Promise; isAvailable(): boolean; } ``` ### 配置 Key 映射 所有配置以 `vscode-code-reviewer.` 为前缀: | 模块 | 配置项 | 类型 | 默认值 | |------|--------|------|--------| | ai | `ai.provider` | enum | `deepseek` | | ai | `ai.model` | string | `deepseek-chat` | | ai | `ai.baseUrl` | string | `https://api.deepseek.com/v1` | | ai | `ai.temperature` | number | 0.2 | | ai | `ai.timeout` | number | 300 | | ai | `ai.outputLanguage` | string | `zh-CN` | | linter | `linters.javascript` | enum | `eslint` | | linter | `linters.typescript` | enum | `eslint` | | linter | `linters.java` | enum | `pmd` | | linter | `linters.jsp` | enum | `jsp` | | linter | `linters.css` | enum | `stylelint` | | linter | `linters.sql` | enum | `sql-lint` | | linter | `linters.plsql` | enum | `sql-lint` | | linter | `pmd.jarPath` | string | `""` | | linter | `pmd.rulesetPath` | string | `""` | | linter | `pmd.jspRulesetPath` | string | `""` | | linter | `sql-lint.configFile` | string | `""` | | fixer | `fixer.contextLines` | number | 5 | | secret | API Key | SecretStorage | `vscode-code-reviewer.apiKey` | --- ## Phase 2: 适配层 **依赖**: Phase 1 **目标**: 实现 5 个语言适配器,统一 `LinterAdapter` 接口 **参考设计**: §3 ### Phase 2.1: 适配器接口 | 文件 | 操作 | 内容 | |------|------|------| | `src/adapters/adapter.ts` | 新建 | 重新导出 `LinterAdapter` 接口(或在此处定义,取决于代码组织) | ### Phase 2.2: ESLint 适配器 **参考设计**: §3.3 | 文件 | 操作 | 内容 | |------|------|------| | `src/adapters/eslint.ts` | 新建 | `ESLintAdapter` implements `LinterAdapter` | | | | `supportedLanguages`: `['javascript', 'typescript']` | | | | `check()`: 使用 eslint npm 包 `lintText()` | | | | `isAvailable()`: 检测 eslint 是否已安装 | **npm 依赖**: `eslint` ^9.39.3 ### Phase 2.3: Stylelint 适配器 **参考设计**: §3.3 | 文件 | 操作 | 内容 | |------|------|------| | `src/adapters/stylelint.ts` | 新建 | `StylelintAdapter` implements `LinterAdapter` | | | | `supportedLanguages`: `['css']` | | | | `check()`: 使用 stylelint npm 包 `lint({ code })` | | | | `isAvailable()`: 检测 stylelint 是否已安装 | **npm 依赖**: `stylelint` ^17.14.0 ### Phase 2.4: sql-lint 适配器 **参考设计**: §3.3 | 文件 | 操作 | 内容 | |------|------|------| | `src/adapters/sql-lint.ts` | 新建 | `SqlLintAdapter` implements `LinterAdapter` | | | | `supportedLanguages`: `['sql', 'plsql']` | | | | `check()`: CLI 子进程调用 sqlfluff | | | | `isAvailable()`: 检测 sqlfluff CLI 是否可用 | | | | 方言映射:sql → ansi, plsql → postgres | ### Phase 2.5: PMD 适配器 **参考设计**: §3.3, §3.4 | 文件 | 操作 | 内容 | |------|------|------| | `src/adapters/pmd.ts` | 新建 | `PmdAdapter` implements `LinterAdapter` | | | | `supportedLanguages`: `['java']` | | | | `check()`: Java 子进程调用 PmdRunner | | | | 虚拟文档 (untitled) 通过 stdin 传入代码 | | | | 真实文件传文件路径 | | | | `isAvailable()`: 检测 Java 11+ 和 PMD JAR | | `jars/pmd/PmdRunner.java` | 新建 | PMD 包装器:stdin 支持 + JSON 渲染器 | | `jars/pmd/pmd-java-ruleset.xml` | 新建 | Java 规则集 | | `jars/pmd/pmd-jsp-ruleset.xml` | 新建 | JSP 规则集 | **PmdRunner.java 核心逻辑**: ``` 参数: filePath (传 "-" 表示从 stdin 读取), ruleset → 构建 PMDConfiguration → 配置 JSON 渲染器 → 若 filePath 为 "-",从 stdin 读代码 → 写入临时文件 → 执行 PMD 分析 → 输出 JSON 到 stdout → 清理临时文件 ``` **PMD JAR 目录结构**: ``` jars/pmd/ ├── lib/ # PMD 依赖 JAR(需下载) ├── PmdRunner.java # 包装器(编译为 .class) ├── pmd-java-ruleset.xml └── pmd-jsp-ruleset.xml ``` ### Phase 2.6: JSP 适配器 **依赖**: Phase 2.5, 2.2, 2.3(需要 PMD/ESLint/Stylelint 适配器) **参考设计**: §3.5 | 文件 | 操作 | 内容 | |------|------|------| | `src/jsp/jsp-extractor.ts` | 新建 | JSP 内嵌代码块提取器 | | `src/adapters/jsp.ts` | 新建 | `JspAdapter` implements `LinterAdapter`(组合适配器) | | | | `supportedLanguages`: `['jsp']` | | | | `check()`: 三步流程 | **JspAdapter.check() 流程**: ``` 1. 调用 PmdAdapter.check(document) → JSP 规范检查 2. extractJspSections(document.getText()) → 提取内嵌代码块 3. 对每个 section: a. 按 language 选择对应适配器 b. 创建虚拟文档 (vscode.workspace.openTextDocument) c. 调用 adapter.check(virtualDoc) d. 修正行号偏移 (section.lineOffset) 4. 合并所有结果 ``` **提取器正则规则**: | 代码块类型 | 正则匹配 | 目标适配器 | |-----------|---------|-----------| | `