2020#
2121# Usage (from anywhere; the script self-anchors to the repo root):
2222# ./scripts/clang-tidy.sh # run on full src/ tree
23+ # ./scripts/clang-tidy.sh src/room.cpp # run on a single file
2324# ./scripts/clang-tidy.sh -j 4 # override parallelism
2425# ./scripts/clang-tidy.sh --github-actions # force GitHub Actions annotation mode
2526# ./scripts/clang-tidy.sh --fail-on-warning # exit non-zero on any finding (warning OR error)
26- # ./scripts/clang-tidy.sh -fix # forwarded to run-clang-tidy
27+ # ./scripts/clang-tidy.sh -- fix # apply fixes in place
2728#
2829# Every run prints a concise stdout summary at the end with the warning and
2930# error counts (and a per-check breakdown when there are findings).
@@ -60,14 +61,16 @@ cd "${script_dir}/.."
6061# users who hit a pre-flight error or a bad argument get pointed at this.
6162usage () {
6263 cat << 'EOF '
63- Usage: ./scripts/clang-tidy.sh [OPTIONS] [run-clang-tidy args...]
64+ Usage: ./scripts/clang-tidy.sh [OPTIONS] [FILE...] [ run-clang-tidy args...]
6465
6566Run clang-tidy locally or in CI using the same file set and config that the
6667repo's CI workflow uses. Picks up checks from the repo-root .clang-tidy.
6768
6869Options:
6970 -h, --help, -?
7071 Show this help and exit.
72+ --fix
73+ Apply fixes in place (forwarded to run-clang-tidy as -fix).
7174 --github-actions, --gh
7275 Force GitHub Actions annotation + step-summary mode.
7376 Auto-detected when GITHUB_ACTIONS=true.
@@ -76,17 +79,24 @@ Options:
7679 non-zero on their own). Off by default for local edit/run cycles;
7780 CI opts in via the workflow file.
7881
82+ Positional arguments:
83+ FILE...
84+ Explicit list of files to analyze. When omitted, the script walks
85+ the tracked first-party src/ tree (excluding src/tests/). Pass paths
86+ to scope the run to a single file or a curated set, e.g.:
87+ ./scripts/clang-tidy.sh <path-to-file.cpp>
88+
7989Any other arguments are forwarded verbatim to run-clang-tidy. Common ones:
8090 -j N worker count (defaults to nproc / sysctl hw.ncpu)
81- -fix apply fixes in place
8291 -checks=... override the .clang-tidy check list for this run
8392
8493Examples:
8594 ./scripts/clang-tidy.sh # full src/ tree
95+ ./scripts/clang-tidy.sh <path-to-file.cpp> # single file
8696 ./scripts/clang-tidy.sh -j 4 # override parallelism
8797 ./scripts/clang-tidy.sh --github-actions # force CI annotation mode
8898 ./scripts/clang-tidy.sh --fail-on-warning # exit non-zero on any finding
89- ./scripts/clang-tidy.sh -fix # forwarded to run-clang-tidy
99+ ./scripts/clang-tidy.sh -- fix # apply fixes in place
90100
91101Pre-requisites:
92102 CMake must have generated build-release/compile_commands.json AND the
127137FAIL_ON_WARNING=0
128138
129139forward_args=()
140+ explicit_files=()
130141while (( $# )) ; do
131142 case " $1 " in
132143 -h|--help|-\? )
133144 usage
134145 __tidy_hint_active=0
135146 exit 0
136147 ;;
148+ --fix)
149+ # Unify with clang-format.sh's --fix spelling. run-clang-tidy only
150+ # understands the single-dash -fix, so normalize every accepted form
151+ # to that when forwarding.
152+ forward_args+=(" -fix" )
153+ shift
154+ ;;
137155 --github-actions|--gh)
138156 CI_MODE=1
139157 shift
@@ -158,7 +176,16 @@ while (($#)); do
158176 exit 2
159177 ;;
160178 * )
161- forward_args+=(" $1 " )
179+ # A positional arg naming an existing file is an explicit target to
180+ # analyze; anything else (e.g. the value after -j, a -checks=... flag)
181+ # is forwarded verbatim to run-clang-tidy. When explicit files are
182+ # given they replace the default src/ FILE_REGEX below so the run is
183+ # scoped to exactly those files.
184+ if [[ -f " $1 " ]]; then
185+ explicit_files+=(" $1 " )
186+ else
187+ forward_args+=(" $1 " )
188+ fi
162189 shift
163190 ;;
164191 esac
@@ -347,17 +374,21 @@ write_step_summary() {
347374 }
348375
349376 {
350- echo " ## Analysis results"
351- echo
352- echo " | Severity | Count |"
353- echo " |----------|-------|"
354- # Same GFM shortcodes used in the detailed findings table below, so the
355- # count summary and per-finding severity column read consistently.
356- echo " | :x: Error | ${errors} |"
357- echo " | :warning: Warning | ${warnings} |"
377+ echo " ## clang-tidy results"
358378 echo
379+ if (( total == 0 )) ; then
380+ # Mirror clang-format.sh's clean-run summary exactly so both CI jobs
381+ # surface the same green check line.
382+ echo " :white_check_mark: All files passed the configured checks."
383+ else
384+ echo " | Severity | Count |"
385+ echo " |----------|-------|"
386+ # Same GFM shortcodes used in the detailed findings table below, so the
387+ # count summary and per-finding severity column read consistently.
388+ echo " | :x: Error | ${errors} |"
389+ echo " | :warning: Warning | ${warnings} |"
390+ echo
359391
360- if (( total > 0 )) ; then
361392 echo " ### Top checks"
362393 echo
363394 echo ' | Check | Count |'
@@ -478,6 +509,16 @@ log="clang-tidy.log"
478509# so suppress the "see --help" hint installed via the EXIT trap above.
479510__tidy_hint_active=0
480511
512+ # Scope the run to the user's explicit files when any were passed; otherwise
513+ # fall back to the default src/ tree regex. run-clang-tidy treats each
514+ # positional argument as a regex matched against compile_commands.json paths,
515+ # so a plain path like src/room.cpp narrows the run to that translation unit.
516+ if (( ${# explicit_files[@]} > 0 )) ; then
517+ tidy_targets=(" ${explicit_files[@]} " )
518+ else
519+ tidy_targets=(" ${FILE_REGEX} " )
520+ fi
521+
481522set +e
482523# run-clang-tidy is a Python script that doesn't flush stdout in its per-file
483524# loop; it only flushes once at exit. When its stdout is a pipe (the `| tee`
@@ -496,7 +537,7 @@ PYTHONUNBUFFERED=1 run-clang-tidy \
496537 -j " ${jobs} " \
497538 ${extra_args[@]+" ${extra_args[@]} " } \
498539 ${forward_args[@]+" ${forward_args[@]} " } \
499- " ${FILE_REGEX } " \
540+ " ${tidy_targets[@] } " \
500541 2>&1 | tee " ${log} "
501542rc=" ${PIPESTATUS[0]} "
502543set -e
0 commit comments