现在位置: 首页 > Skills 教程 > 正文

Skill 代码审查

本项目构建一个代码审查 Skill,用户上传代码文件后,自动分析代码质量、风格问题和潜在 Bug。

目标:掌握工具链集成与结构化问题报告的生成。


项目需求分析

功能支持语言工具
语法检查Pythonpy_compile(内置)
代码风格检查Pythonflake8
代码复杂度分析Pythonradon
JavaScript 检查JS/TSeslint(npx)
综合问题报告所有自定义聚合脚本

目录结构

code-reviewer/
├── SKILL.md
└── scripts/
    ├── requirements.txt
    ├── check_python.py
    ├── check_js.py
    └── generate_report.py

Python 代码检查脚本

实例

# 文件路径:scripts/check_python.py
import subprocess
import sys
import json
import os

def ensure_tools():
    """确保检查工具已安装"""
    for pkg in ["flake8", "radon"]:
        try:
            __import__(pkg.replace("-", "_"))
        except ImportError:
            subprocess.run([sys.executable, "-m", "pip", "install", pkg,
                            "--break-system-packages", "--quiet"])

def check_syntax(file_path: str) -> dict:
    """检查 Python 语法"""
    result = subprocess.run(
        [sys.executable, "-m", "py_compile", file_path],
        capture_output=True, text=True
    )
    if result.returncode == 0:
        return {"passed": True, "errors": []}
    return {
        "passed": False,
        "errors": [result.stderr.strip()]
    }

def check_style(file_path: str) -> list:
    """运行 flake8 检查代码风格,返回问题列表"""
    result = subprocess.run(
        ["python", "-m", "flake8", file_path,
         "--max-line-length=100",
         "--format=%(row)d:%(col)d %(code)s %(text)s"],
        capture_output=True, text=True
    )
    issues = []
    for line in result.stdout.strip().splitlines():
        parts = line.split(" ", 2)
        if len(parts) >= 3:
            loc, code, text = parts
            row, col = loc.split(":")
            issues.append({
                "line": int(row), "col": int(col),
                "code": code,     "message": text
            })
    return issues

def check_complexity(file_path: str) -> list:
    """用 radon 分析函数复杂度,返回复杂度高的函数"""
    result = subprocess.run(
        ["python", "-m", "radon", "cc", file_path, "-s", "--json"],
        capture_output=True, text=True
    )
    try:
        data      = json.loads(result.stdout)
        functions = data.get(file_path, [])
        # 只返回复杂度等级 C 以上(复杂度 > 10)的函数
        return [
            {"name": f["name"], "complexity": f["complexity"],
             "rank": f["rank"], "line": f["lineno"]}
            for f in functions
            if f.get("rank", "A") in ("C", "D", "E", "F")
        ]
    except Exception:
        return []

def review_python(file_path: str) -> dict:
    """执行完整的 Python 代码审查"""
    if not os.path.exists(file_path):
        return {"status": "error", "message": f"文件不存在:{file_path}"}

    ensure_tools()

    syntax     = check_syntax(file_path)
    style      = check_style(file_path) if syntax["passed"] else []
    complexity = check_complexity(file_path) if syntax["passed"] else []

    # 计算总体评级
    error_count   = len([i for i in style if i["code"].startswith("E")])
    warning_count = len([i for i in style if i["code"].startswith("W")])

    if not syntax["passed"]:
        grade = "F"
    elif error_count > 10:
        grade = "C"
    elif error_count > 3:
        grade = "B"
    else:
        grade = "A"

    return {
        "status":          "success",
        "file":            os.path.basename(file_path),
        "grade":           grade,
        "syntax_ok":       syntax["passed"],
        "syntax_errors":   syntax["errors"],
        "style_issues":    style[:20],          # 最多展示 20 条
        "style_count":     len(style),
        "error_count":     error_count,
        "warning_count":   warning_count,
        "complex_functions": complexity
    }

if __name__ == "__main__":
    result = review_python(sys.argv[1] if len(sys.argv) > 1 else "")
    print(json.dumps(result, ensure_ascii=False, indent=2))

输出:

{
  "status": "success",
  "file": "runoob_app.py",
  "grade": "B",
  "syntax_ok": true,
  "style_issues": [
    {"line": 12, "col": 1, "code": "E302", "message": "expected 2 blank lines"},
    {"line": 34, "col": 80, "code": "E501", "message": "line too long (103 > 100)"}
  ],
  "style_count": 5,
  "error_count": 3,
  "warning_count": 2,
  "complex_functions": []
}

SKILL.md 完整内容

---
name: code-reviewer
version: 1.0.0
description: >
  自动审查用户上传的代码文件,检查语法错误、风格问题和代码复杂度,
  生成带评级的问题报告并给出改进建议。当用户需要代码审查、
  检查代码质量、查找 Bug、评估代码规范时触发。
---

# 代码审查助手

## 执行流程

### 第一步:识别代码文件

获取用户上传的代码文件路径,识别编程语言(根据扩展名):
- .py → Python 审查
- .js / .ts → JavaScript/TypeScript 审查
- 其他格式 → 告知暂不支持,列出支持的格式

### 第二步:运行自动化检查

Python 文件运行:
```bash
cd scripts/
python check_python.py <文件路径>
```

### 第三步:生成并解读报告

根据 JSON 输出,以人性化方式呈现结果:

1. **总体评级**:A(优秀)/ B(良好)/ C(需改进)/ F(语法错误)
2. **问题汇总表格**:行号、问题代码、描述
3. **Top 3 优先修复项**:选出最严重的 3 个问题,给出修复建议和示例

若文件无问题,给出简短正面评价:
> 代码检查通过!共扫描 X 行,未发现语法错误和明显风格问题。

测试用例

实例

# 文件路径:scripts/tests/test_sample.py(用于测试审查 Skill 的样本文件)
# 故意包含一些常见问题,用于验证审查功能

import os,sys   # E401: 多个 import 在同一行(风格问题)
import json

def processData(data):  # N802: 函数名应为 snake_case
    x = 1  # F841: 局部变量 x 赋值后未使用
    result=[]  # E225: 赋值号周围缺少空格
    for i in data:
        if i > 0:
            result.append(i)
        elif i == 0:
            pass
        else:
            result.append(-i)
    return result

class myClass:  # N801: 类名应为 CamelCase
    pass

运行审查:

cd scripts/
python check_python.py tests/test_sample.py

输出:

{
  "status": "success",
  "file": "test_sample.py",
  "grade": "B",
  "syntax_ok": true,
  "style_count": 5,
  "error_count": 4,
  "warning_count": 1,
  "complex_functions": []
}