Skip to content

Batch fix: collapse lang_to_name (#500) + honor suppress markers in reports (#501)#502

Merged
dekobon merged 7 commits into
mainfrom
fix/batch-2026-06-02
Jun 3, 2026
Merged

Batch fix: collapse lang_to_name (#500) + honor suppress markers in reports (#501)#502
dekobon merged 7 commits into
mainfrom
fix/batch-2026-06-02

Conversation

@dekobon
Copy link
Copy Markdown
Owner

@dekobon dekobon commented Jun 3, 2026

Batch fix for two related findings surfaced by the published metrics report's lang_to_name cyclomatic hotspot.

#500refactor(py): collapse lang_to_name onto LANG::get_name

lang_to_name was a 22-arm flat match whose 19 non-override arms duplicated the upstream LANG::get_name() display names. It now delegates to get_name() and keeps only the three genuine lookup-token overrides:

  • Cpp"cpp" (upstream "c/c++" isn't a usable lookup token)
  • Csharp"csharp" (upstream "c#")
  • Tsx"tsx" (upstream "typescript" collides with Typescript)

Output is byte-identical for all 22 variants (verified arm-by-arm against src/langs.rs); the change removes the hand-maintained duplication and the drift risk against the documented CLI-parity contract. Added an override pin test (Cpp/Csharp) and a get_name() parity test over the non-override public variants (with a vacuity guard).

#501feat(report): honor bca: suppress markers in aggregated reports

bca report markdown|html listed raw metric values and ignored bca: suppress / bca: suppress-file markers, so the published hotspots report re-surfaced every silenced function — contradicting bca check and the SARIF emitter.

The report now honors markers by default, per metric: a function is omitted from a metric's hotspot table when that metric is suppressed for it. extract_summaries folds the top-level Unit's suppress-file scope into each function's own scope (file ∪ function), mirroring ThresholdSet::evaluate_with_policy; each table filters on its MetricKind via SuppressionScope::covers, including the nexits → exit alias.

  • bca report --no-suppress (or [report] no_suppress = true in bca.toml) opts into the raw audit view.
  • Advisory roll-ups (actionable summary, CC-stats note) intentionally keep counting raw measurements.
  • SuppressionScope::merge widened pub(crate)pub (additive; SuppressionScope is already re-exported from lib.rs).

Quality / review

Each issue went through fix → simplify → review → remediation. After each wave the simplify-rust / rust-optimize / audit-tests / code-review / review skills were run; remediations applied:

The 8 new #501 tests were verified by test-via-revert (the filter-dependent ones fail when is_hidden_for is neutered).

Validation

make pre-commit green: fmt, clippy -D warnings (both feature flavors), workspace tests, doc, udeps, markdown/TOML/shell/Makefile/Actions lints, man-page drift, both self-scan tiers, and the Python suite (192 passed, 1 xfailed).

Closes #500
Closes #501

dekobon added 7 commits June 2, 2026 21:00
lang_to_name was a 22-arm flat match (cyclomatic 22) carrying a
suppress(cyclomatic) marker, yet 19 of its arms returned exactly
what the upstream LANG::get_name() already returns. Delegate the
common case to other.get_name() and keep only the three arms that
genuinely deviate:

- Cpp:    get_name() -> "c/c++", not a usable lookup token -> "cpp"
- Csharp: get_name() -> "c#"                              -> "csharp"
- Tsx:    get_name() -> "typescript", collides with Typescript -> "tsx"

Behaviour is identical for all 22 variants (verified arm-by-arm
against src/langs.rs display names). Cyclomatic drops 22 -> 4 as a
side effect, so the suppress(cyclomatic) marker is removed and the
file-header note about it dropped; the suppress-file(halstead,
nargs) marker stays.

The doc comment is rewritten to state the real rule (CLI display
name plus three identifier/collision overrides) instead of the
inaccurate "lowercased variant name" framing.

Adds tests: pin Cpp -> "cpp" and Csharp -> "csharp" (the two
overrides no other test fixed; test-via-revert-able), plus a parity
test asserting lang_to_name(lang) == lang.get_name() for every
public variant outside the three overrides, making the delegation
contract explicit and surfacing any future upstream display rename.

Fixes #500
Post-review remediation for #500. The get_name() parity loop asserted
nothing if public_languages() ever returned only the overrides (or
empty); add a checked-count guard so an over-filtered language set
fails loudly instead of passing green. Also reword the Tsx doc bullet
to state the override is what makes Tsx/Typescript distinct, rather
than implying they were already distinct after delegation.
`bca report markdown|html` listed raw metric values and ignored
`bca: suppress` / `bca: suppress-file` markers, so the published
hotspots report re-surfaced every silenced function — contradicting
`bca check` and the SARIF emitter.

The report now HONORS markers BY DEFAULT, per metric: a function is
omitted from a metric's hotspot table when that metric is suppressed
for it. `extract_summaries` folds the top-level Unit's `suppress-file`
scope into each function's own scope (file ∪ function), mirroring
`ThresholdSet::evaluate_with_policy`; each hotspot table filters on its
`MetricKind` via `SuppressionScope::covers`, including the nexits→exit
alias. `--no-suppress` (and `[report] no_suppress = true` in the
manifest) opts back into the raw audit view. Advisory roll-ups
(Actionable Summary, CC-stats note) intentionally keep counting raw
measurements; only the per-metric hotspot tables filter.

Widens `SuppressionScope::merge` from `pub(crate)` to `pub` (additive)
so report consumers can fold scopes.

Tests: markdown + HTML cover per-metric function-scope drop, file-scope
suppress-all drop, --no-suppress inclusion, nexits→exit aliasing, and
the extract_summaries file∪function merge; manifest tests cover the
[report] known-key and merge_report OR semantics.

Fixes #501
The #500 regression tests pushed big-code-analysis-py/src/language.rs's
file-level nom to 30 (hard limit 30, headroom limit 28.5), tripping the
soft self-scan tier. File-level nom here is a many-function aggregation
artifact — tiny lookup helpers plus their tests — exactly like the
halstead/nargs already suppressed on this file. Extend the existing
suppress-file marker rather than baseline a brittle exact value.
Post-review remediation for #501. Pair the NEXITS-table exit-suppression
drop assertion with a SuppressionPolicy::Ignore positive control so the
test is self-contained: it now proves the table is empty *because of*
the exit-alias filter, not because the function failed to qualify as a
hotspot. Also document why write_actionable_summary intentionally takes
no SuppressionPolicy (advisory roll-ups count raw measurements).
Record the #500 lang_to_name delegation (internal, no behavior change)
and the #501 report suppression-honoring feature (new --no-suppress
flag, [report] manifest key, additive SuppressionScope::merge pub).
Hoist the NEXITS_HEADER const above the test's statements
(items_after_statements) and apply cargo fmt to the manifest [report]
test. Pure lint/format cleanup, no behavior change.
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@dekobon dekobon added the python-wheels PR opts in to the manylinux wheel CI matrix label Jun 3, 2026
@dekobon dekobon closed this Jun 3, 2026
@dekobon dekobon reopened this Jun 3, 2026
@dekobon dekobon merged commit 6fe89fe into main Jun 3, 2026
91 of 92 checks passed
@dekobon dekobon deleted the fix/batch-2026-06-02 branch June 3, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python-wheels PR opts in to the manylinux wheel CI matrix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(report): honor bca: suppress markers in aggregated reports refactor(py): collapse lang_to_name onto LANG::get_name

1 participant