You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/scripts/lint/run-local.sh

98 lines
3.6 KiB

#!/usr/bin/env bash
set -euo pipefail
# Runs clang-tidy and cppcheck for the initial scope (lib/ and include/)
# Expectation: compile_commands.json exists in repo root (generated by generate-compile-commands.sh)
CLANG_TIDY_BIN=${CLANG_TIDY_BIN:-clang-tidy}
CPPCHECK_BIN=${CPPCHECK_BIN:-cppcheck}
if [ ! -f compile_commands.json ]; then
echo "compile_commands.json not found. Run scripts/lint/generate-compile-commands.sh first." >&2
exit 1
fi
mkdir -p lint
echo "Running clang-tidy per-file (this runs each source file one at a time)..."
## Accept optional file arguments. If files are provided as arguments, lint only those.
if [ "$#" -gt 0 ]; then
FILES=("$@")
else
# Build list of C/C++ source files under lib tracked by git
FILES=()
while IFS= read -r f; do
case "$f" in
*.cpp|*.cc|*.cxx|*.c)
FILES+=("$f") ;;
esac
done < <(git ls-files lib)
fi
if [ ${#FILES[@]} -eq 0 ]; then
echo "No source files found to lint under lib/" >&2
else
TMPD=$(mktemp -d)
# Compute an anchored header-filter that limits diagnostics to files inside
# this repository's include/ and lib/ directories. Use an absolute path so
# headers in deps/ that happen to contain '/include/' don't match.
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$(pwd)")
HEADER_FILTER="^${REPO_ROOT}/(include|lib)/"
echo "Using clang-tidy header-filter: ${HEADER_FILTER}"
n=0
total=${#FILES[@]}
for f in "${FILES[@]}"; do
n=$((n+1))
echo "[$n/$total] clang-tidy $f"
# Capture textual diagnostics per-file; still write export-fixes when available
${CLANG_TIDY_BIN} -p . -checks='clang-analyzer-*,bugprone-*,performance-*,modernize-*,readability-*' --header-filter="${HEADER_FILTER}" --export-fixes="${TMPD}/ct-${n}.yaml" "$f" 2> "${TMPD}/ct-${n}.stderr" || true
done
echo "Merging per-file clang-tidy fixes into lint/clang-tidy-fixes.yaml"
# Merge all per-file YAMLs into a single Diagnostics list. Missing or empty files are ignored.
python3 - "${TMPD}" <<'PY'
import sys, yaml, glob
tmp = sys.argv[1]
out = []
for p in sorted(glob.glob(tmp + '/*.yaml')):
try:
data = yaml.safe_load(open(p))
except Exception:
continue
if not data:
continue
out.extend(data.get('Diagnostics', []))
yaml.safe_dump({'Diagnostics': out}, open('lint/clang-tidy-fixes.yaml', 'w'))
PY
# Keep per-file stderr outputs around until after normalization so we can
# fall back to parsing textual diagnostics when export-fixes is empty.
# We'll clean up TMPD after normalization below.
fi
echo "Running cppcheck..."
${CPPCHECK_BIN} --enable=warning,performance,portability,style --std=c++17 --project=compile_commands.json --inline-suppr 2> lint/cppcheck-output.txt || true
echo "Normalizing outputs..."
# If export-fixes YAML produced diagnostics use that; otherwise merge textual stderr outputs
if [ -f lint/clang-tidy-fixes.yaml ]; then
python3 scripts/lint/normalize-clang-tidy.py lint/clang-tidy-fixes.yaml > lint/clang-tidy.txt || true
else
# Merge all per-file stderr clang-tidy outputs if present
if ls ${TMPD:-/dev/null}/ct-*.stderr >/dev/null 2>&1; then
cat ${TMPD}/ct-*.stderr > lint/clang-tidy-raw.txt || true
python3 scripts/lint/normalize-clang-tidy.py lint/clang-tidy-raw.txt > lint/clang-tidy.txt || true
else
# Nothing found
:
fi
fi
# Clean up temporary directory created for per-file clang-tidy runs
if [ -n "${TMPD:-}" ] && [ -d "${TMPD}" ]; then
rm -rf "${TMPD}"
fi
python3 scripts/lint/normalize-cppcheck.py lint/cppcheck-output.txt > lint/cppcheck.txt || true
echo "Local lint run complete. Reports written to lint/clang-tidy.txt and lint/cppcheck.txt"