fix(nargs): stop counting comments as parameters - #1207
Conversation
tree-sitter attaches a comment written inside a parameter list as a
direct child of the parameter-*list* node, not inside the parameter it
documents. Every nargs filter listed punctuation only, so each comment
scored one: `int h(int a /* one */, int b /* two */)` reported 4, and
the C++ idiom for a deliberately unused parameter,
`void f(int /*unused*/)`, reported 2.
Excluded in one shared `count_args` rather than in twenty `is_non_arg`
impls, so the next language inherits it. Four independent loops
collapsed onto it: `compute_args` (C, C++, Mozcpp, Objective-C
functions, JavaScript, MozJS, TypeScript, TSX, Python, Rust, Java, C#,
PHP, Ruby, Groovy functions), Elixir's `count_elixir_args` — which the
shared helper now replaces outright — `compute_kotlin_lambda_args`, and
`compute_perl_args`, the last of which already excluded comments and is
unchanged in behaviour.
Two corrections to the issue's scoping, both confirmed by AST dump.
Tcl needed no fix and had solved nothing: it recognises a comment only
where a command is expected, so `proc h {a\n# c\n b}` really does
declare four arguments and the grammar emits four `argument` nodes with
no comment node. And `compute_kotlin_lambda_args` was a fourth broken
loop the issue did not name.
Each of the four loops is covered by a fixture that fails when that
loop alone is reverted. The corpus snapshots move 854 values, all
downward, including kenlm's `DontBhiksha::DontBhiksha` (7 -> 4) and
`ReadBackoff` (3 -> 2).
Folding four counting loops into one drops `src/metrics/nargs.rs` from
547 to 536 loc.ploc, so `.bca-baseline.toml` ratchets down; the refresh
also drops four entries left stale by #1203.
Fixes #1201
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1207 +/- ##
========================================
Coverage 98.27% 98.27%
========================================
Files 276 276
Lines 71501 71658 +157
Branches 71071 71228 +157
========================================
+ Hits 70266 70423 +157
+ Misses 820 818 -2
- Partials 415 417 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Codecov put the PR's patch coverage at 92.31% against a project 98.26%,
with all 13 missing lines in this file's test module. None were
production: the changed production lines measure 100%. They were the
lines that run only when the test fails — the `format!` inside the
failure branch, and the `assert!` arguments, which are evaluated at
panic time.
Three changes, each of which also reads better than what it replaces:
- The failure branch pushes the raw `(lang, source, expected, got)`
tuple and the report is built once, by `{failures:#?}` in the
assertion message. The "collect every failure rather than stopping at
the alphabetically first" property is preserved — reverting the fix
still reports `37/43` with every language named.
- The assertion's two computed arguments are bound eagerly and
interpolated by name.
- The two `if !lang.is_enabled() { continue; }` guards become an
iterator `filter`.
Patch coverage measured locally with the CI command
(`cargo llvm-cov --no-report nextest --all-features --workspace
--locked`): 92.31% -> 98.00%, production lines 100%.
The five that remain are not reachable by any test. Four are comment
and doc-comment lines that cargo-llvm-cov's codecov output assigns a
region to, because a multi-line region contributes to every line it
spans. The fifth is the `failures.push` itself, which no passing run can
execute.
Refs #1201
Coverage follow-up (
|
| instrumented | missing | patch % | |
|---|---|---|---|
| production | 20 | 0 | 100% |
| test module | 228 | 13 | 94.3% |
None of the shortfall was production code. All 13 were lines that run
only when the test fails — the format! inside the failure branch,
the assert! arguments (evaluated at panic time), and the
if !lang.is_enabled() { continue; } guards' untaken arm.
Three changes, each of which also reads better than what it replaced:
the failure branch now pushes the raw (lang, source, expected, got)
tuple with the report built once by {failures:#?}; the assertion's
computed arguments are bound eagerly and interpolated by name; the two
if/continue guards became an iterator filter. The "collect every
failure rather than stopping at the alphabetically first" property is
preserved — reverting the fix still reports 37/43 naming every
language.
Result: patch 92.31% → 97.81%, and the project dip is gone (Misses -2, previously +9).
The 4 that remain are not reachable by any test
Three are comment and doc-comment lines. cargo-llvm-cov's codecov
output assigns a region value to them because a multi-line region
contributes to every line it spans — e.g. line 4205 is a bare ///
scoring 0/1. No test can execute a comment.
The fourth is failures.push(...) itself, which no passing run can
reach by construction.
Worth knowing for future PRs
codecov.yml's ignore list has **/tests/**, but this repo keeps
most of its tests in #[cfg(test)] modules inside src/, which no
path-based ignore can exclude. So a test-heavy patch is always measured
on its own test code, including that code's failure paths. Nothing to
change here — just the reason patch coverage reads below project
coverage on PRs like this one.
Fixes #1201.
tree-sitter attaches a comment written inside a parameter list as a
direct child of the parameter-list node, not inside the parameter it
documents. Every
nargsfilter listed punctuation only, so each commentscored one:
int h(int a /* one */, int b /* two */)reported 4, andthe C++ idiom for a deliberately unused parameter,
void f(int /*unused*/), reported 2.Since #1196 the gate reads the per-callable own count, so a commented
signature could trip a
bca check --threshold nargs=Nits real aritywould pass.
The fix
One shared
count_args<T>replaces four separate negative filters, sothe rule is stated once and the next language inherits it rather than
needing the same edit in twenty
is_non_argimpls. Elixir'scount_elixir_argsturned out to be identical to the shared helper oncefixed, and is deleted.
Repaired: C, C++, Mozcpp, Objective-C functions, JavaScript, MozJS,
TypeScript, TSX, Python, Rust, Java, C#, PHP, Ruby, Groovy functions,
Elixir, Kotlin lambdas.
Verified already correct, swept as regression guards: Go, Lua,
Objective-C methods and blocks, Kotlin functions, Groovy closures, Perl.
Bash has no formal parameter list.
Two corrections to the issue's scoping
Both established by AST dump rather than by reading the code.
Tcl had not "already solved this" — it has no problem to solve. The
issue proposed generalising Tcl's handling;
compute_tcl_argsfilterspositively for
Tcl::Argumentand never encounters a comment, becauseTcl recognises one only where a command is expected. So
genuinely declares four arguments named
a,#,candb, and thegrammar emits four
argumentnodes with no comment node. Tcl's reported4 is correct and unchanged, now pinned by
tcl_has_no_comment_inside_a_parameter_list.compute_kotlin_lambda_argswas a fourth broken loop the issue doesnot name. It filtered
!= Kotlin::COMMA, so{ a: Int, /* one */ b: Int -> a }reported 3. Kotlin functions werefine (positive
Parameterfilter), which is why a function-only checkwould have missed it.
Verification
reverted independently and failed only its own fixtures. After
consolidation there is one line to revert; doing so fails 37 of 43
fixtures, and the 6 survivors are exactly the positive-filter guards.
parameter_declarationfilter for a negative one fails both Go rowsand nothing else.
{ (a, b), c -> }= 2,{ (a, b) -> }=1,
{ -> }= 0 — a destructuring pattern nests its parens inside amulti_variable_declaration, so no paren is ever a direct child oflambda_parameters.is_bare_paramis the one path the new predicate never runs on.bca dumpshows why it is safe: inx /* c */ -> xtheblock_commentis a sibling of the bareidentifier. The comment istherefore not a discriminating input, so that test is written as a
parity assertion between the commented and bare spellings and says so
in its doc comment rather than implying coverage it does not have.
metric touched. Hand-checked against source: kenlm's
DontBhiksha::DontBhikshahas 4 real parameters and 3/*…*/comments (7 → 4),
ReadBackoffhas 2 and 1 (3 → 2).make pre-commitpasses. Patch coverage on the changed productionlines is 100%, against a project line coverage of 94.04%.
Notes for review
nargsfalls wherever a signature carries a comment.
.bca-baseline.tomlratchets down. Folding the four countingloops into one dropped
src/metrics/nargs.rsfrom 547 to 536loc.ploc. The refresh also drops four entries left stale by fix(npm): go and rust still enable npm/npa on function spaces #1203.dekobon/big-code-analysis-outputis pushed(
89e4c973) and its SHA recorded in this commit.nargson the same C/C++ corpus in the oppositedirection. It is deliberately not in this branch; landing it after
this will need one snapshot re-refresh.