feat(linter): implement Phase 1 linter automation and docs

- Add .clang-tidy (analyzer + selected bugprone) and .clang-format (LLVM, 4-space, 100 cols)
- Enhance scripts/run-linter.sh to use compile_commands.json when available
- Add scripts/setup-hooks.sh pre-commit (format enforcement; advisory tidy)
- Update azure-pipelines.yml to export compile_commands and run clang-tidy -p build
- Fill docs/linter-setup.md and docs/coding-standards.md for Phase 1
- Add minimal tests in tests/test_main.cpp to ensure CI executes
- Rewrite README with Phase 1 workflow
This commit is contained in:
2025-09-09 22:52:34 +08:00
parent d5350c35a8
commit f55d10ee07
9 changed files with 296 additions and 81 deletions

View File

@@ -12,7 +12,7 @@ if ! command -v clang-tidy &> /dev/null; then
fi
# 尋找所有 C++ 檔案
CPP_FILES=$(find src tests -name "*.cpp" -o -name "*.h" 2>/dev/null)
CPP_FILES=$(find src tests -type f \( -name "*.cpp" -o -name "*.cxx" -o -name "*.cc" -o -name "*.c++" -o -name "*.h" -o -name "*.hpp" -o -name "*.hxx" \) 2>/dev/null)
if [ -z "$CPP_FILES" ]; then
echo "No C++ files found."
@@ -23,7 +23,17 @@ echo "Found files:"
echo "$CPP_FILES"
echo
# 執行 clang-tidy
echo "$CPP_FILES" | xargs clang-tidy --config-file=.clang-tidy
# 若存在 compile_commands.json則使用 -p 指向 build 目錄以提高精準度
TIDY_CMD_BASE=(clang-tidy --config-file=.clang-tidy)
if [ -f "build/compile_commands.json" ]; then
echo "Detected build/compile_commands.json; using -p build"
TIDY_CMD_BASE+=( -p build )
else
echo "No compile_commands.json detected. For better results, run:"
echo " mkdir -p build && cd build && cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cd -"
fi
echo "Linter check completed."
# 執行 clang-tidy保持 Phase 1僅回報不讓流程失敗
echo "$CPP_FILES" | xargs -r "${TIDY_CMD_BASE[@]}"
echo "Linter check completed."

View File

@@ -0,0 +1,59 @@
#!/bin/bash
# 安裝 git hookspre-commit以執行 clang-format 與可選的 clang-tidy 提示
set -euo pipefail
HOOKS_DIR=".git/hooks"
PRE_COMMIT="$HOOKS_DIR/pre-commit"
if [ ! -d "$HOOKS_DIR" ]; then
echo "This script must be run inside a Git repository."
exit 1
fi
cat > "$PRE_COMMIT" <<'EOF'
#!/bin/bash
set -euo pipefail
echo "[pre-commit] Checking/formatting C++ sources..."
# Collect staged C/C++ files
STAGED=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(cpp|cxx|cc|c\+\+|h|hpp|hxx)$' || true)
if [ -z "$STAGED" ]; then
echo "[pre-commit] No C/C++ files staged."
exit 0
fi
# 1) clang-format in-place, then re-stage
if command -v clang-format >/dev/null 2>&1; then
echo "$STAGED" | xargs -r clang-format -i
echo "$STAGED" | xargs -r git add
else
echo "[pre-commit] clang-format not found; skipping formatting." >&2
fi
# If formatting changed files, fail once to let user review
CHANGES=$(git diff --name-only --diff-filter=ACMR | grep -E '\\.(cpp|cxx|cc|c\\+\\+|h|hpp|hxx)$' || true)
if [ -n "$CHANGES" ]; then
echo "[pre-commit] Formatting applied to:"
echo "$CHANGES"
echo "[pre-commit] Please review changes and re-commit."
exit 1
fi
# 2) Optional clang-tidy advisory (Phase 1: do not block commits)
if command -v clang-tidy >/dev/null 2>&1; then
if [ -f build/compile_commands.json ]; then
echo "[pre-commit] Running clang-tidy (advisory)..."
echo "$STAGED" | xargs -r clang-tidy -p build --config-file=.clang-tidy || true
else
echo "[pre-commit] No build/compile_commands.json; skip clang-tidy. Run CMake with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON."
fi
fi
exit 0
EOF
chmod +x "$PRE_COMMIT"
echo "Installed pre-commit hook to $PRE_COMMIT"