代码检查脚本#

脚本说明#

代码检查脚本用于检查代码质量、格式、安全性等问题,支持多种编程语言。

脚本代码#

#!/bin/bash

# 代码检查脚本
# 功能:检查代码质量、格式、安全性等问题
# 作者:System Admin
# 日期:2024-01-01

set -euo pipefail

# 配置变量
PROJECT_DIR=""
CHECK_TYPE="all"
OUTPUT_FORMAT="text"
FIX_ISSUES=false

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

# 检查项目目录
check_project_dir() {
    if [ ! -d "$PROJECT_DIR" ]; then
        log_error "项目目录不存在: $PROJECT_DIR"
        return 1
    fi
    
    return 0
}

# 检查Python代码
check_python() {
    local dir=$1
    
    log_info "检查Python代码: $dir"
    
    echo "Python代码检查"
    echo "=============="
    
    # 检查pylint
    if command -v pylint &> /dev/null; then
        log_info "使用pylint检查"
        find "$dir" -name "*.py" -exec pylint --output-format=text {} \;
    fi
    
    # 检查flake8
    if command -v flake8 &> /dev/null; then
        log_info "使用flake8检查"
        find "$dir" -name "*.py" -exec flake8 {} \;
    fi
    
    # 检查black格式
    if command -v black &> /dev/null; then
        log_info "使用black检查格式"
        if [ "$FIX_ISSUES" = true ]; then
            find "$dir" -name "*.py" -exec black {} \;
        else
            find "$dir" -name "*.py" -exec black --check {} \;
        fi
    fi
    
    # 检查mypy类型
    if command -v mypy &> /dev/null; then
        log_info "使用mypy检查类型"
        find "$dir" -name "*.py" -exec mypy {} \;
    fi
    
    # 检查bandit安全
    if command -v bandit &> /dev/null; then
        log_info "使用bandit检查安全"
        find "$dir" -name "*.py" -exec bandit -r {} \;
    fi
}

# 检查JavaScript代码
check_javascript() {
    local dir=$1
    
    log_info "检查JavaScript代码: $dir"
    
    echo "JavaScript代码检查"
    echo "=================="
    
    # 检查ESLint
    if command -v eslint &> /dev/null; then
        log_info "使用ESLint检查"
        find "$dir" -name "*.js" -o -name "*.jsx" | xargs eslint
    fi
    
    # 检查Prettier格式
    if command -v prettier &> /dev/null; then
        log_info "使用Prettier检查格式"
        if [ "$FIX_ISSUES" = true ]; then
            find "$dir" -name "*.js" -o -name "*.jsx" | xargs prettier --write
        else
            find "$dir" -name "*.js" -o -name "*.jsx" | xargs prettier --check
        fi
    fi
}

# 检查TypeScript代码
check_typescript() {
    local dir=$1
    
    log_info "检查TypeScript代码: $dir"
    
    echo "TypeScript代码检查"
    echo "=================="
    
    # 检查TSLint
    if command -v tslint &> /dev/null; then
        log_info "使用TSLint检查"
        find "$dir" -name "*.ts" -o -name "*.tsx" | xargs tslint
    fi
    
    # 检查ESLint
    if command -v eslint &> /dev/null; then
        log_info "使用ESLint检查"
        find "$dir" -name "*.ts" -o -name "*.tsx" | xargs eslint
    fi
    
    # 检查Prettier格式
    if command -v prettier &> /dev/null; then
        log_info "使用Prettier检查格式"
        if [ "$FIX_ISSUES" = true ]; then
            find "$dir" -name "*.ts" -o -name "*.tsx" | xargs prettier --write
        else
            find "$dir" -name "*.ts" -o -name "*.tsx" | xargs prettier --check
        fi
    fi
}

# 检查Go代码
check_go() {
    local dir=$1
    
    log_info "检查Go代码: $dir"
    
    echo "Go代码检查"
    echo "========="
    
    # 检查gofmt格式
    log_info "使用gofmt检查格式"
    if [ "$FIX_ISSUES" = true ]; then
        find "$dir" -name "*.go" -exec gofmt -w {} \;
    else
        find "$dir" -name "*.go" -exec gofmt -l {} \;
    fi
    
    # 检查go vet
    log_info "使用go vet检查"
    find "$dir" -name "*.go" -exec go vet {} \;
    
    # 检查golint
    if command -v golint &> /dev/null; then
        log_info "使用golint检查"
        find "$dir" -name "*.go" -exec golint {} \;
    fi
    
    # 检查goimports
    if command -v goimports &> /dev/null; then
        log_info "使用goimports检查"
        if [ "$FIX_ISSUES" = true ]; then
            find "$dir" -name "*.go" -exec goimports -w {} \;
        else
            find "$dir" -name "*.go" -exec goimports -l {} \;
        fi
    fi
}

# 检查Java代码
check_java() {
    local dir=$1
    
    log_info "检查Java代码: $dir"
    
    echo "Java代码检查"
    echo "==========="
    
    # 检查Checkstyle
    if command -v checkstyle &> /dev/null; then
        log_info "使用Checkstyle检查"
        find "$dir" -name "*.java" -exec checkstyle {} \;
    fi
    
    # 检查PMD
    if command -v pmd &> /dev/null; then
        log_info "使用PMD检查"
        find "$dir" -name "*.java" -exec pmd {} \;
    fi
    
    # 检查SpotBugs
    if command -v spotbugs &> /dev/null; then
        log_info "使用SpotBugs检查"
        find "$dir" -name "*.java" -exec spotbugs {} \;
    fi
}

# 检查C/C++代码
check_cpp() {
    local dir=$1
    
    log_info "检查C/C++代码: $dir"
    
    echo "C/C++代码检查"
    echo "============="
    
    # 检查clang-format格式
    if command -v clang-format &> /dev/null; then
        log_info "使用clang-format检查格式"
        if [ "$FIX_ISSUES" = true ]; then
            find "$dir" -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" | xargs clang-format -i
        else
            find "$dir" -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" | xargs clang-format --dry-run -Werror
        fi
    fi
    
    # 检查cppcheck
    if command -v cppcheck &> /dev/null; then
        log_info "使用cppcheck检查"
        find "$dir" -name "*.c" -o -name "*.cpp" | xargs cppcheck
    fi
}

# 检查Shell脚本
check_shell() {
    local dir=$1
    
    log_info "检查Shell脚本: $dir"
    
    echo "Shell脚本检查"
    echo "============"
    
    # 检查shellcheck
    if command -v shellcheck &> /dev/null; then
        log_info "使用shellcheck检查"
        find "$dir" -name "*.sh" -exec shellcheck {} \;
    fi
    
    # 检查shfmt格式
    if command -v shfmt &> /dev/null; then
        log_info "使用shfmt检查格式"
        if [ "$FIX_ISSUES" = true ]; then
            find "$dir" -name "*.sh" -exec shfmt -w {} \;
        else
            find "$dir" -name "*.sh" -exec shfmt -d {} \;
        fi
    fi
}

# 检查代码复杂度
check_complexity() {
    local dir=$1
    
    log_info "检查代码复杂度: $dir"
    
    echo "代码复杂度检查"
    echo "============="
    
    # 检查Python复杂度
    if command -v radon &> /dev/null; then
        log_info "使用radon检查Python复杂度"
        find "$dir" -name "*.py" -exec radon cc {} \;
    fi
    
    # 检查Go复杂度
    if command -v gocyclo &> /dev/null; then
        log_info "使用gocyclo检查Go复杂度"
        find "$dir" -name "*.go" -exec gocyclo {} \;
    fi
}

# 检查代码重复
check_duplication() {
    local dir=$1
    
    log_info "检查代码重复: $dir"
    
    echo "代码重复检查"
    echo "============="
    
    # 检查Python重复
    if command -v pyflakes &> /dev/null; then
        log_info "使用pyflakes检查Python重复"
        find "$dir" -name "*.py" -exec pyflakes {} \;
    fi
    
    # 检查通用重复
    if command -v jscpd &> /dev/null; then
        log_info "使用jscpd检查代码重复"
        jscpd "$dir"
    fi
}

# 检查安全性
check_security() {
    local dir=$1
    
    log_info "检查安全性: $dir"
    
    echo "安全性检查"
    echo "========="
    
    # 检查Python安全
    if command -v bandit &> /dev/null; then
        log_info "使用bandit检查Python安全"
        find "$dir" -name "*.py" -exec bandit -r {} \;
    fi
    
    # 检查JavaScript安全
    if command -v npm-audit &> /dev/null; then
        log_info "使用npm-audit检查JavaScript安全"
        cd "$dir" && npm audit
    fi
    
    # 检查依赖漏洞
    if command -v safety &> /dev/null; then
        log_info "使用safety检查Python依赖"
        cd "$dir" && safety check
    fi
}

# 生成检查报告
generate_report() {
    local dir=$1
    
    log_info "生成检查报告"
    
    local report_file="/tmp/code_check_report_$(date +%Y%m%d_%H%M%S).txt"
    
    {
        echo "代码检查报告"
        echo "==========="
        echo "检查时间: $(date)"
        echo "项目目录: $dir"
        echo ""
        
        echo "检查工具"
        echo "========"
        
        # 检查Python工具
        if command -v pylint &> /dev/null; then
            echo "pylint: $(pylint --version)"
        fi
        
        if command -v flake8 &> /dev/null; then
            echo "flake8: $(flake8 --version)"
        fi
        
        if command -v black &> /dev/null; then
            echo "black: $(black --version)"
        fi
        
        # 检查JavaScript工具
        if command -v eslint &> /dev/null; then
            echo "eslint: $(eslint --version)"
        fi
        
        if command -v prettier &> /dev/null; then
            echo "prettier: $(prettier --version)"
        fi
        
        # 检查Go工具
        if command -v gofmt &> /dev/null; then
            echo "gofmt: $(gofmt --version)"
        fi
        
        # 检查Shell工具
        if command -v shellcheck &> /dev/null; then
            echo "shellcheck: $(shellcheck --version)"
        fi
        
        echo ""
        echo "报告生成时间: $(date)"
    } > "$report_file"
    
    log_info "检查报告已生成: $report_file"
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项] <项目目录>"
    echo ""
    echo "选项:"
    echo "  -t <类型>        检查类型(all/python/javascript/typescript/go/java/cpp/shell/complexity/duplication/security)"
    echo "  -f               自动修复问题"
    echo "  -h               显示帮助信息"
    echo ""
    echo "示例:"
    echo "  $0 /path/to/project"
    echo "  $0 -t python /path/to/project"
    echo "  $0 -t javascript /path/to/project"
    echo "  $0 -f /path/to/project"
}

# 主函数
main() {
    # 解析选项
    while getopts "t:fh" opt; do
        case $opt in
            t)
                CHECK_TYPE="$OPTARG"
                log_info "检查类型: $CHECK_TYPE"
                ;;
            f)
                FIX_ISSUES=true
                log_info "自动修复问题"
                ;;
            h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $opt"
                show_help
                exit 1
                ;;
        esac
    done
    
    shift $((OPTIND - 1))
    
    # 检查项目目录
    if [ $# -eq 0 ]; then
        log_error "缺少项目目录"
        show_help
        exit 1
    fi
    
    PROJECT_DIR="$1"
    
    if ! check_project_dir; then
        exit 1
    fi
    
    # 执行检查
    case $CHECK_TYPE in
        all)
            check_python "$PROJECT_DIR"
            check_javascript "$PROJECT_DIR"
            check_typescript "$PROJECT_DIR"
            check_go "$PROJECT_DIR"
            check_java "$PROJECT_DIR"
            check_cpp "$PROJECT_DIR"
            check_shell "$PROJECT_DIR"
            check_complexity "$PROJECT_DIR"
            check_duplication "$PROJECT_DIR"
            check_security "$PROJECT_DIR"
            ;;
        python)
            check_python "$PROJECT_DIR"
            ;;
        javascript)
            check_javascript "$PROJECT_DIR"
            ;;
        typescript)
            check_typescript "$PROJECT_DIR"
            ;;
        go)
            check_go "$PROJECT_DIR"
            ;;
        java)
            check_java "$PROJECT_DIR"
            ;;
        cpp)
            check_cpp "$PROJECT_DIR"
            ;;
        shell)
            check_shell "$PROJECT_DIR"
            ;;
        complexity)
            check_complexity "$PROJECT_DIR"
            ;;
        duplication)
            check_duplication "$PROJECT_DIR"
            ;;
        security)
            check_security "$PROJECT_DIR"
            ;;
        *)
            log_error "无效的检查类型: $CHECK_TYPE"
            show_help
            exit 1
            ;;
    esac
    
    # 生成报告
    generate_report "$PROJECT_DIR"
    
    log_info "代码检查完成"
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x code_checker.sh
  2. 基本用法:

    # 检查所有代码
    ./code_checker.sh /path/to/project
    
    # 检查Python代码
    ./code_checker.sh -t python /path/to/project
    
    # 检查JavaScript代码
    ./code_checker.sh -t javascript /path/to/project
    
    # 检查Go代码
    ./code_checker.sh -t go /path/to/project
  3. 高级用法:

    # 自动修复问题
    ./code_checker.sh -f /path/to/project
    
    # 检查代码复杂度
    ./code_checker.sh -t complexity /path/to/project
    
    # 检查安全性
    ./code_checker.sh -t security /path/to/project

功能特点#

  • 多语言支持(Python、JavaScript、TypeScript、Go、Java、C/C++、Shell)
  • 代码质量检查
  • 代码格式检查
  • 代码复杂度检查
  • 代码重复检查
  • 安全性检查
  • 自动修复功能

依赖项#

  • pylint/flake8/black/mypy/bandit: Python检查工具
  • eslint/prettier: JavaScript/TypeScript检查工具
  • gofmt/golint/goimports: Go检查工具
  • checkstyle/pmd/spotbugs: Java检查工具
  • clang-format/cppcheck: C/C++检查工具
  • shellcheck/shfmt: Shell检查工具

注意事项#

  1. 需要安装相应的检查工具
  2. 自动修复功能可能改变代码
  3. 建议在版本控制下使用
  4. 大项目检查可能需要较长时间
  5. 某些工具需要配置文件