Files
2026Technology-Competition/docs/superpowers/specs/2026-07-10-implementation-plan.md
T
范智鹏 805737fcfc feat: 设置面板 + Provider 扩展 + 构建脚本
- 设置面板:三步引导 / AI 配置 / API Key / 规则管理 / 连接测试
- Provider 重构:统一 OpenAICompatibleProvider 基类,新增 Gemini/Claude/混元/智谱等
- 审查面板 Webview:三 Tab、统计卡片、问题列表、postMessage 通信
- esbuild 构建脚本 + 生产打包 + PMD 下载
- 保存文件自动静态分析(500ms debounce)
2026-07-16 22:20:30 +08:00

19 KiB
Raw Blame History

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 新建 LinterDiagnosticAdapterResultLinterAdapter 等公共类型
src/config/index.ts 新建 统一导出
src/config/ai.ts 新建 AI 配置 getterprovider/model/baseUrl/temperature/timeout/outputLanguage
src/config/linter.ts 新建 Linter 配置 getterlinters.xxx 语言-linter 映射、PMD 路径)
src/config/fixer.ts 新建 修复器配置(contextLines
src/config/secret.ts 新建 API Key SecretStorageget/set/delete/isConfigured

关键类型

// 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<AdapterResult>;
  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. 合并所有结果

提取器正则规则:

代码块类型 正则匹配 目标适配器
<script> 标签 /<script\b[^>]*>([\s\S]*?)<\/script\s*>/gi ESLint
<style> 标签 /<style\b[^>]*>([\s\S]*?)<\/style\s*>/gi Stylelint
<% %> scriptlet /<%=?([\s\S]*?)%>/g PMD

Phase 3: 核心层 A — 编排器

依赖: Phase 2
参考设计: §3.6, §4

文件 操作 内容
src/orchestrator/orchestrator.ts 新建 Orchestrator

关键函数:

  • getAdapters() — 硬编码返回 5 个适配器实例
  • runStaticAnalysis(document, workingDir) — 按语言选择适配器 → 调用 check() → 聚合
  • 保存监听 + debounce 500ms

调度逻辑:

1. 获取当前文档语言 ID
2. 查询 linters.<language> 配置 → 确定使用的适配器
3. 调用适配器 check(document, workingDir)
4. 收集结果,区分 status
5. 返回聚合后的 diagnostics 列表

Phase 4: 核心层 B

依赖: Phase 3
参考设计: §5, §8, §12, §14

Phase 4.1: AI Provider 基础设施

参考设计: §5.2

文件 操作 内容
src/ai/providers/base.ts 新建 AIProvider 抽象基类 + ChatOptions 接口
src/ai/providers/deepseek.ts 新建 DeepSeekProvider extends AIProvider
src/ai/providers/openai.ts 新建 OpenAIProvider extends AIProvider
src/ai/factory.ts 新建 createProvider(providerId, apiKey, baseUrl) 工厂函数

Provider 接口:

interface ChatOptions {
  model: string;
  temperature: number;
  timeoutMs: number;
}

abstract class AIProvider {
  abstract id: string;
  abstract name: string;
  constructor(protected apiKey: string, protected baseUrl: string) {}
  abstract chat(systemPrompt: string, userPrompt: string, options: ChatOptions): Promise<string>;
}

Phase 4.2: AI 引擎 + Schema

参考设计: §5.3, §5.4, §5.5, §5.6

文件 操作 内容
src/ai/schema.ts 新建 AIResponse, TranslatedDiagnostic, CustomRuleResult, AIFinding 接口
src/ai/engine.ts 新建 runAIReview() 主函数

引擎核心逻辑:

async function runAIReview(code, staticDiagnostics, customRules) {
  const [resultA, resultB] = await Promise.allSettled([
    callCustomRuleReview(code, customRules),           // 请求 A
    callTranslateAndDeepReview(code, staticDiagnostics), // 请求 B
  ]);
  return {
    customRuleResults: ...,
    translatedDiagnostics: ...,
    findings: ...,
    degraded: resultA.status === 'rejected' || resultB.status === 'rejected',
    error: ...,
  };
}

两并行请求:

  • 请求 A: 自定义规则评估(system prompt 注入规则 description
  • 请求 B: 静态分析翻译 + AI 深度审查

降级策略:

  1. 单请求失败不影响另一个请求(Promise.allSettled
  2. 所有 AI 功能都失败时,纯静态分析结果仍然展示
  3. 失败信息在面板顶部以黄色/红色提示条展示

Phase 4.3: 自定义规则系统

参考设计: §12

文件 操作 内容
src/rules/yaml-parser.ts 新建 loadActiveRules(workspaceRoot)

加载逻辑:

1. 扫描 .code-review/rules/*.yaml → 加载所有规则定义
2. 读取 .code-review/config.yaml
3. 按文件级 enabled 列表过滤
4. 按规则级 rules.<id>.enabled 覆盖
5. 返回激活的规则列表

CustomRule 类型:

interface CustomRule {
  id: string;           // 不含 custom: 前缀,运行时自动拼接
  severity: Severity;
  description: string;  // AI 评估依据
  message: string;      // 触发时显示
  languages?: string[];
}

Phase 4.4: 结果合并

参考设计: §14.1

文件 操作 内容
src/merger/merger.ts 新建 mergeResults()MergedReport
interface MergedReport {
  linterDiagnostics: LinterDiagnostic[];
  customRuleDiagnostics: LinterDiagnostic[];
  translatedDiagnostics: TranslatedDiagnostic[];
  aiFindings: AIFinding[];
  linterCount: number;
  customRuleCount: number;
  aiCount: number;
  errors: string[];
  degraded: boolean;
  duration: number;
  filePath: string;
  language: string;
  adapterNames: string[];
  fixableLinterIndices: number[];
  fixableCustomIndices: number[];
}

Phase 4.5: 自动修复

参考设计: §8

文件 操作 内容
src/fixer/fixer.ts 新建 generateFix(), applyFix(), applyBatchFixes(), undoLastFix()

核心流程:

用户触发修复(单条 / 批量)
    ↓
prepareContext() 获取代码上下文(动态行数)
    ↓
generateFix() 调用 AI 生成修复方案(复用 Provider
    ↓
matchAndValidate() 匹配验证(行号 → 代码搜索)
    ↓
applyFix() 应用修复到编辑器(单条 / 批量倒序)
    ↓
保存快照,更新撤销按钮状态

动态上下文策略:

问题类型 上下文范围
命名(naming 问题行 ± 2 行
代码风格(style 问题行 ± 5 行
逻辑/安全/性能(bug/security/performance 整个函数/方法

两阶段匹配:

  • 阶段 1: 按行号匹配原文
  • 阶段 2: 全文搜索 originalText

Phase 4.6: 报告导出

参考设计: §14.2

文件 操作 内容
src/utils/report.ts 新建 reportToMarkdown(report: MergedReport): string

Markdown 格式: 文件信息 → 统计摘要 → 分来源列出问题(linter/自定义/AI)


Phase 5: UI 层

依赖: Phase 4
参考设计: §6, §7, §13

Phase 5.1: 命令注册 + extension.ts 更新

参考设计: §6.1

文件 操作 内容
src/activation/commands.ts 新建 注册所有命令处理函数
package.json 修改 替换 helloWorld 为正式命令、添加 viewsContainers/views/menus/configuration
src/extension.ts 修改 activate 中注册命令、视图、监听保存事件

8 个命令:

命令 ID 功能 快捷键
codeReviewer.review 运行完整审查(静态分析 + AI Ctrl+Shift+R
codeReviewer.reviewSelection 审查选中代码
codeReviewer.openPanel 显示审查报告面板
codeReviewer.exportReport 导出 Markdown 报告
codeReviewer.addCustomRule 添加自定义规则
codeReviewer.fixIssue 修复单条问题
codeReviewer.fixAll 批量修复
codeReviewer.openSetup 打开设置面板(侧边栏)

package.json 需添加的贡献点:

{
  "viewsContainers": {
    "activitybar": [{
      "id": "code-reviewer",
      "title": "CodeGuard 代码审查",
      "icon": "images/icon.png"
    }]
  },
  "views": {
    "code-reviewer": [{
      "type": "tree",
      "id": "codeReviewer.setupView",
      "name": "设置"
    }]
  },
  "menus": {
    "editor/context": [
      { "command": "codeReviewer.review", "group": "navigation" },
      { "command": "codeReviewer.reviewSelection", "when": "editorHasSelection" }
    ]
  },
  "configuration": {
    // 见 Phase 1 配置 Key 映射
  }
}

Phase 5.2: 设置面板(侧边栏 TreeView

参考设计: §13

文件 操作 内容
src/views/setupView.ts 新建 SetupViewProvider implements vscode.TreeDataProvider

面板区域:

区域 元素 数据源
快速开始 三步引导(①②③ 圆形序号,完成变紫色) 实时状态
审核引擎 三个模块标签(紫/琥珀/绿圆点) 静态
AI 模型配置 提供商下拉框 + 模型下拉框 + 状态标签 ai.provider / ai.model
API Key 密码输入框 + Base URL + 状态标签 SecretStorage / ai.baseUrl
输出语言 下拉框 ai.outputLanguage
自定义规则 开关列表 + 添加行 .code-review/config.yaml

快速引导:

步骤 触发条件 效果
① 配置 AI 模型及 API Key API Key 有值 序号变紫色
② 启用自定义规则 任意规则开关打开 序号变紫色
③ 保存并测试连接 前两步完成 + 测试成功 序号变紫色

Phase 5.3: 审查面板(Webview

参考设计: §7

文件 操作 内容
src/panel/webview.ts 新建 ReviewPanel 类(Webview 管理)

面板布局:

┌─────────────────────────────────────┐
│  📋 代码审查报告                     │
│  xxx.java · Java · 3.2s              │
├─────────────────────────────────────┤
│ [总计:10] [错误:3] [警告:5] [建议:2] │
├─────────────────────────────────────┤
│ 🔧 静态分析 | 📋 自定义规则 | 🤖 AI  │
├─────────────────────────────────────┤
│ 问题列表(可跳转、修复、忽略)        │
├─────────────────────────────────────┤
│ [🔄 重新审查] [📄 导出] [⚙️ 设置]    │
│ [↩ 撤销上次修复]                    │
└─────────────────────────────────────┘

消息协议:

// Webview → Extension
interface PanelMessage {
  type: 'navigate' | 'rerun' | 'export' | 'settings' | 'fix' | 'fixAll';
  line?: number;
  ruleId?: string;
  source?: 'linter' | 'custom' | 'ai';
}

// Extension → Webview
interface PanelUpdate {
  report: MergedReport;
  degraded: boolean;
  errors: string[];
  hasSnapshot: boolean;
}

Phase 6: 构建与测试

依赖: Phase 5
参考设计: §15, §16, §17

Phase 6.1: 构建脚本

文件 操作 内容
scripts/build.mjs 新建 esbuild 打包(bundle + minify + external vscode
package.json 修改 更新 vscode:prepublish / 添加 build 脚本

esbuild 配置:

entryPoints: ['src/extension.ts'],
bundle: true,
outfile: 'out/extension.js',
external: ['vscode'],
format: 'cjs',
platform: 'node',
target: 'node22',

Phase 6.2: 工具脚本

文件 操作 内容
scripts/download-pmd.mjs 新建 自动下载 PMD 7.26.0 JAR 依赖
scripts/package-prod.mjs 新建 生产打包:esbuild + copy assets + vsce

Phase 6.3: 测试

文件 操作 内容
src/test/fixtures/ 新建 测试用代码样本目录
src/test/adapter.test.ts 新建 ESLint/Stylelint/sql-lint 输出解析测试
src/test/config.test.ts 新建 配置读取正确性测试
src/test/merger.test.ts 新建 多源结果合并 + 统计计算测试
src/test/pipeline.test.ts 新建 全链路集成测试
src/test/extension.test.ts 修改 替换占位测试

文件变更总数

Phase 新建 修改 合计
Phase 1 6 0 6
Phase 2 10 0 10
Phase 3 1 0 1
Phase 4 9 0 9
Phase 5 3 2 5
Phase 6 4 2 6
总计 33 4 37

npm 依赖(需在 Phase 2/4 时添加)

运行时依赖

{
  "eslint": "^9.39.3",
  "stylelint": "^17.14.0",
  "node-sql-parser": "^5.4.0"
}

开发依赖(新增)

{
  "esbuild": "^0.28.1",
  "@vscode/vsce": "^3.9.2"
}

外部工具

工具 版本 用途 获取方式
PMD 7.26.0 Java/JSP 静态分析 自带 jars/pmd/lib/
Java 11+ PMD 运行环境 用户环境
sqlfluff SQL 静态分析 用户环境(pip install sqlfluff