1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#!/bin/sh
# bin/lint — manual linting for raylib-jamstack (Ruby + C/C++).
#
# Runs RuboCop (Ruby), clang-format (C/C++ formatting), and clang-tidy
# (C/C++ static analysis) on the project's hand-written sources. NOT automatic
# — run it deliberately, at the end of an implementation pass.
#
# Usage:
# bin/lint # report only (exit 1 if any issues)
# bin/lint --fix # safe autocorrect: RuboCop -a + clang-format -i
# # (clang-tidy is NEVER auto-fixed — it only reports)
# bin/lint --ruby # Ruby only (RuboCop)
# bin/lint --c # C/C++ only (clang-format + clang-tidy)
#
# What this checks:
# Ruby (.rb): RuboCop — style/layout/lint (.rubocop.yml: DisabledByDefault,
# opt-in to Layout + Lint + safe Style; excludes Metrics/length
# cops; TargetRubyVersion 3.4 for mruby endless-method support)
# C/C++: clang-format — formatting consistency (.clang-format: Allman,
# 2-space, 100-col, return-type-on-own-line)
# clang-tidy — bug-finding checks (bugprone-*, cert-*,
# clang-analyzer-*), scoped to hand-written files only
#
# What this does NOT check (handled elsewhere):
# - Syntax errors: caught at build time by the mruby-compiler gem (rake fails)
# - Type errors: Steep per-edit (RBS type checker, see opencode.json)
#
# Excludes generated/vendored code:
# - mrbgems/raylib/src/raylib_gen.c (generated by tools/gen_raylib.rb)
# - vendor/** (vendored mruby/raylib/rmlui/flecs/joltc)
# - build/**, zig-out/**, .cache/**, .live/** (build/runtime artifacts)
#
# See .agents/knowledge/linting.md for the full rationale.
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
# --- PATH setup (mirror rebuild.sh: strip /mnt/c, add gem bin dir) ---
CLEANPATH=$(echo "$PATH" | tr ':' '\n' | grep -v '^/mnt/c' | paste -sd:)
export PATH="/home/tradam/.local/share/gem/ruby/3.4.0/bin:$CLEANPATH"
CLANG_FORMAT="/usr/lib/llvm21/bin/clang-format"
CLANG_TIDY="/usr/lib/llvm21/bin/clang-tidy"
# Hand-written C/C++ sources (NOT raylib_gen.c which is generated, NOT vendor/).
C_SOURCES="src/main.c mrbgems/raylib/src/raylib_bindings.c mrbgems/flecs/src/flecs_bindings.c mrbgems/jolt/src/jolt_bindings.c mrbgems/rmlui/src/rml_bindings.cpp"
FIX=0
RUN_RUBY=1
RUN_C=1
for arg in "$@"; do
case "$arg" in
--fix) FIX=1 ;;
--ruby) RUN_C=0 ;;
--c) RUN_RUBY=0 ;;
-h|--help)
sed -n '2,30p' "$0"
exit 0
;;
*)
echo "unknown flag: $arg (try --help)" >&2
exit 2
;;
esac
done
EXIT_CODE=0
# ─── Ruby: RuboCop ───────────────────────────────────────────────────────────
if [ "$RUN_RUBY" = 1 ]; then
echo "── RuboCop (Ruby) ──────────────────────────────────────────────────────"
if [ "$FIX" = 1 ]; then
echo " running with safe autocorrect (-a)..."
rubocop -a || EXIT_CODE=1
else
rubocop || EXIT_CODE=1
fi
echo ""
fi
# ─── C/C++: clang-format ─────────────────────────────────────────────────────
if [ "$RUN_C" = 1 ]; then
echo "── clang-format (C/C++ formatting) ──────────────────────────────────────"
if [ ! -x "$CLANG_FORMAT" ]; then
echo " SKIP: $CLANG_FORMAT not found (install llvm/clang-tools)" >&2
elif [ "$FIX" = 1 ]; then
echo " rewriting in place (-i)..."
"$CLANG_FORMAT" -i $C_SOURCES
echo " done (clang-format applied)"
else
echo " dry-run (reporting violations)..."
# --dry-run --Werror makes it exit non-zero if ANY file needs formatting.
if ! "$CLANG_FORMAT" --dry-run --Werror $C_SOURCES 2>&1; then
EXIT_CODE=1
echo " (run 'bin/lint --fix' to auto-format)"
else
echo " all C/C++ files are clang-format clean"
fi
fi
echo ""
fi
# ─── C/C++: clang-tidy (report only — NEVER auto-fix) ───────────────────────
if [ "$RUN_C" = 1 ]; then
echo "── clang-tidy (C/C++ static analysis) ───────────────────────────────────"
if [ ! -x "$CLANG_TIDY" ]; then
echo " SKIP: $CLANG_TIDY not found (install llvm/clang-tools)" >&2
elif [ ! -f "compile_commands.json" ]; then
echo " SKIP: compile_commands.json not found (run ./rebuild.sh first)" >&2
else
echo " running bug-finding checks (bugprone-*, cert-*, clang-analyzer-*)..."
# --header-filter restricts diagnostics to OUR headers (not vendored).
# compile_commands.json (-p .) provides the include roots + -DMRB_INT64.
"$CLANG_TIDY" -p . \
--checks='-*,bugprone-*,cert-*,clang-analyzer-*' \
--header-filter='^mrbgems/.*/src/.*|^src/.*' \
$C_SOURCES 2>&1 || true # clang-tidy exits non-zero on warnings; that's OK
echo " done (clang-tidy reports only — no auto-fix)"
fi
echo ""
fi
# ─── Summary ─────────────────────────────────────────────────────────────────
if [ "$EXIT_CODE" = 0 ]; then
echo "✓ lint clean"
else
echo ""
echo "✗ lint found issues (run 'bin/lint --fix' for safe autocorrects)"
fi
exit "$EXIT_CODE"
|