Skip to content

Commit a488edf

Browse files
committed
fix(code-quality): match complexity-gate baselines by function name
The gate looked baseline entries up by exact file:line:function id, so any edit that shifted line numbers in a file (e.g. adding a new CLI command to Module.cfc) made unchanged over-threshold functions look 'new' and failed CI. Match by file:function now, with a 250-line window fallback when a file defines several same-named functions. Line shifts from unrelated edits no longer trip the gate; real regressions and genuinely new hotspots still fail. Signed-off-by: Peter Amiri <peter@alurium.com>
1 parent 2b8f367 commit a488edf

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

tools/code-quality/cfml-complexity.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
--baseline write dump {file:function:line -> complexity} JSON
1313
--gate N --baseline F fail (exit 1) if any function exceeds N that is
1414
new (absent from baseline) or regressed (complexity
15-
grew vs baseline). Existing hotspots pass.
15+
grew vs baseline). Existing hotspots pass; functions
16+
are matched by name (file:function), so edits that
17+
shift line numbers elsewhere in a file are fine.
1618
1719
Usage:
1820
python3 cfml-complexity.py [root] --top 40
@@ -151,10 +153,34 @@ def main():
151153
baseline = {}
152154
if args.baseline and os.path.exists(args.baseline):
153155
baseline = json.load(open(args.baseline))
156+
# Match baseline entries by (file, function) rather than exact
157+
# file:line:function id: inserting lines elsewhere in a file shifts
158+
# every later function's line number, which used to make unchanged
159+
# over-threshold functions look "new" and fail the gate spuriously.
160+
# When a file defines several same-named functions, fall back to the
161+
# nearest line within LINE_WINDOW.
162+
LINE_WINDOW = 250
163+
bindex = defaultdict(list)
164+
for bid, bcomp in baseline.items():
165+
parts = bid.rsplit(':', 2)
166+
if len(parts) == 3:
167+
bfile, bline, bfn = parts
168+
try:
169+
bindex[(bfile, bfn)].append((int(bline), bcomp))
170+
except ValueError:
171+
pass
154172
violations = []
155173
for r in rows:
156174
if r['complexity'] > args.gate:
157-
prev = baseline.get(r['id'])
175+
prev = None
176+
cands = bindex.get((r['rel'], r['function']))
177+
if cands:
178+
if len(cands) == 1:
179+
prev = cands[0][1]
180+
else:
181+
nearest = min(cands, key=lambda c: abs(c[0] - r['line']))
182+
if abs(nearest[0] - r['line']) <= LINE_WINDOW:
183+
prev = nearest[1]
158184
if prev is None or r['complexity'] > prev:
159185
violations.append(r)
160186
if violations:

0 commit comments

Comments
 (0)