#!/usr/bin/env bash # ============================================================================ # 静态检查(社区规范:Google Shell Style Guide + ShellCheck 零容忍) # # 用法: # ./lint.sh 检查全部 bash 源码(bash -n + shellcheck) # ./lint.sh -v 显示每个文件的检查状态 # # 规范要点(项目约定): # - 模块文件首行声明 `# shellcheck shell=bash`(库文件无 shebang) # - 跨文件共享全局变量的 SC2034/SC2004 误报在声明/使用文件头部集中 disable # 并注明原因;有意未使用的 read 解构/API 参数用 `_` 前缀命名 # - 格式规范(Google Style):2 空格缩进、`[[ ]]` 测试、`local` 声明、 # 引号包裹变量;可选运行 `shfmt -w` 格式化(本仓库未强制全量格式化, # 新文件/新代码建议按 shfmt 风格书写) # ============================================================================ set -euo pipefail cd "$(dirname "$0")" VERBOSE=false [[ "${1:-}" == "-v" ]] && VERBOSE=true # 检查目标:src 全部模块 + 本仓库其余 bash 脚本 # src/lib 递归收集(按功能域子目录组织);其余脚本显式列出 FILES=() mapfile -t < <(find src/lib -name '*.sh' | sort) FILES+=("${MAPFILE[@]}") FILES+=( src/root_command.sh build.sh lint.sh tests/run.sh tests/lib/assert.sh ) if ! command -v shellcheck >/dev/null 2>&1; then echo "错误:未找到 shellcheck(pacman -S shellcheck / apt install shellcheck)" >&2 exit 1 fi fail=0 # shellcheck disable=SC2048 # FILES 含 glob 模式,需要单词拆分来展开 for f in ${FILES[*]}; do [[ -f "$f" ]] || continue if ! bash -n "$f"; then echo "❌ $f:语法错误" fail=1 continue fi if ! shellcheck "$f"; then echo "❌ $f:shellcheck 未通过" fail=1 continue fi [[ $VERBOSE == true ]] && echo "✅ $f" done if ((fail > 0)); then echo "Lint 未通过" >&2 exit 1 fi echo "Lint OK:全部文件通过 bash -n 与 shellcheck(0 问题)"