fix(dart): count named / optional-positional parameter groups in args (#2309) - #2335
Merged
Merged
Conversation
…#2309) `_count_top_level_args` unwraps a signature's outer `(...)` and counts depth-0 commas in the remaining body. For a Dart parameter list whose parameters live in a named group `({a, b, c})` or an optional-positional group `([a, b])`, the group's own `{`/`[` was read as ordinary nesting -- so every comma inside sat at depth 1 and none counted. A Flutter widget constructor like `EditableText({super.key, required this.controller, ...})` measured **1** argument instead of 76; `_Editable`, `_UpdateTextSelectionAction` and ~dozens more were similarly flattened. This is the args half of #2309 (the `func_start` existence half, and the bodyless `this.`/`super.`-forwarding constructor case, were handled by #2071 / #2311). Fix: in `_count_top_level_args`, for `primary_lang_id == "dart"`, when the parameter-list body ends (ignoring trailing whitespace) in `}` or `]`, locate that terminal group's matching opener at depth 0 and blank just those two delimiter characters, so the group's members land at the top level and their separating commas are counted. A `{...}` / `[...]` that is a default-VALUE literal (`{int x = const [1, 2, 3]}`, `{Map m = const {'a': 1}}`) is never flush against the body's end, so it stays nested and its internal commas stay correctly ignored. Scoped to dart -- no other language's count path is touched. Result (name-matched `gather_language("dart")` args diff vs tree-sitter): GitGalaxy under-counts by >=2 (excluding tree-sitter's own same-name reconciliation inflation) drop from ~40 to 2, and those 2 are tree-sitter / reconciler quirks, not GitGalaxy defects (`build` at editable_text.dart:6253 is genuinely 1 param; `copyWith` at theme_data.dart:140 is a bodyless abstract method with 0). `EditableText` (1->76), `_Editable` (1->39), `_UpdateTextSelectionAction` (4->6) now match tree-sitter exactly. Regenerated: - Both golden masters -- 328 diffs, all dart (arg counts + downstream structural-impact / spatial-coordinate ripple); 0 non-dart content change. - `tree_sitter_accuracy_baseline_dart.json` -- `args_exact_match` 1519 -> 1633 (+114); summary table in `language_standards.py` Dart row 99.4% -> 99.5%. - `tree_sitter_accuracy_baseline_javascript.json` -- `files_scanned` 18 -> 17, a stale value left by #2331 (GATE D relegating `threejs/Nodes.js`); the tree-sitter-accuracy workflow doesn't trigger on statistical_auditor.py paths so it was never updated. Included here so this PR's own tree-sitter-accuracy-audit run (which `detector.py` does trigger) is green. Verification: test_detector.py (+ new `_count_top_level_args` dart case) and tests/extraction (6234) green; ruff/mypy/dead-key/ast-accuracy clean; crucible_check both modes PASS; tree_sitter_accuracy_audit --all --ci and tri_comparison_chart --all --ci both green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
squid-protocol
added a commit
that referenced
this pull request
Aug 27, 2026
…al causes (#2309) (#2342) Explored `dart/function/args/agree[none]_vs[gitgalaxy,tree_sitter]` (106 occurrences after #2335's named-parameter-group fix, was 205). Every one was `gg=N ts=0` or `gg=1 ts=0` -- i.e. one tool reporting a real count and the other 0. Three distinct causes, none of them a "real" arg-count disagreement: 1. **tree-sitter ground truth wrong for const/factory constructors** (`tree_sitter_accuracy_audit.py::_get_param_count`, reused by the tri-comparison gatherer). `constant_constructor_signature` (`const PointerEvent({...})`) and `factory_constructor_signature` (`factory ThemeData({...})`) don't expose a field-tagged "parameters" child -- unlike the plain `constructor_signature` -- so they fell through to `return 0`. Every `const`/`factory` constructor in the dart corpus (the dominant Flutter widget-constructor form) measured 0. Added both node types to the direct-`formal_parameter_list`-child branch that already handles `function_signature`/`setter_signature`. ~30 large mismatches. 2. **GitGalaxy over-counts a paren-less getter** (`detector.py`). A bodyless `Offset get pan;` reached `_count_top_level_args("Offset get pan")`, which has no `(` to unwrap and returns 1 (whole string as one segment). The bodyless-`;` branch now returns 0 when `not has_parens`. ~15 mismatches. 3. **GitGalaxy under-counts operator overloads** (`detector.py`). The `args` regex needs `NAME(...)`; `bool operator ==(Object other)` has `==` between the name token and the `(`, so `.search()` returns None and the count falls to 0. Added dart to the same "regex failed -> structural counter" fallback c/cpp already use (#2012), guarded on a literal `(` in the signature text so a paren-less getter body still reads 0. ~12 mismatches. Result: the args shape drops 106 -> 6, dart args accuracy 93.9% -> 99.65%, GitGalaxy and tree-sitter now agree on 1733/1739 comparable functions. The 6 survivors are all one unrelated shape -- a multi-line `@Deprecated('...' '...',)` annotation that dart's `func_start` wrongly consumes as a return-type prefix, so the annotation's own parens get counted instead of the real parameter list. Filed separately. Regenerated: both golden masters (26 diffs, all dart -- arg counts + downstream ripple, 0 non-dart content change); `tree_sitter_accuracy_baseline_ dart.json` (`args_exact_match` 1633 -> 1733). No summary-table or javascript- baseline change needed (a post-#2335 companion already refreshed the latter). Verification: test_dart.py (+ new getter/operator slicer case) + tests/ extraction (6235) green; ruff/mypy/dead-key/ast-accuracy clean; crucible_check both modes PASS; tree_sitter_accuracy_audit --all --ci + tri_comparison_chart --all --ci both green. Co-authored-by: Joe Esquibel <squid-protocol@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
squid-protocol
added a commit
that referenced
this pull request
Aug 27, 2026
#2341) (#2347) dart's `func_start` match spans any leading `@annotation(...)` prefix and the return-type prefix, so `start_idx` (the block start / args-span start) can land on an annotation. When that annotation's argument list is multi-line and carries a top-level comma -- `@Deprecated('Use x. ' 'Deprecated after v3.3.',)` is the corpus shape -- its own `(...)` is the first paren the args counter finds, and the declaration's real parameter list is never measured (`ToolbarOptions` const ctor read 0 args, several deprecated getters read 1). Fix: for dart, every args-span computation anchors at `match.start(match. lastindex)` -- the name capture -- instead of `start_idx`. Same `match.lastindex` name-anchor the typescript/javascript branch of `_slice_by_braces` already uses. `start_idx` still bounds the block itself (line numbers, body slice); only the parameter-count slice moves. This closes out the `dart/function/args/agree[none]_vs[gitgalaxy,tree_sitter]` shape entirely: **0 remaining args mismatches** across the 7-file Flutter corpus (was 205 before #2309, 106 after #2335, 6 after #2342), dart args accuracy 99.65% -> **100.0%** (`args_exact_match` 1733 -> 1739 / 1739). Regenerated: both golden masters (16 diffs, all dart -- arg counts + downstream ripple, 0 non-dart content change); `tree_sitter_accuracy_baseline_dart.json`. No summary-table or javascript-baseline change. Verification: test_dart.py (+ new annotation-prefix slicer case) + tests/ extraction (6236) green; ruff/mypy/dead-key/ast-accuracy clean; crucible_check both modes PASS; tree_sitter_accuracy_audit --all --ci green. Co-authored-by: Joe Esquibel <squid-protocol@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2309.
Bug
_count_top_level_argsunwraps a signature's outer(...)and counts depth-0 commas in the body. For a Dart parameter list where the params sit in a named group({a, b, c})or an optional-positional group([a, b]), the group's own{/[read as ordinary nesting — every comma inside was at depth 1, so none counted.EditableText({super.key, required this.controller, ...})— a 91-line named-parameter constructor — measured 1 argument._Editable,_UpdateTextSelectionAction, and ~dozens of Flutter widget constructors were similarly flattened.(This is the args half of #2309. The
func_startexistence half and the bodylessthis./super.-forwarding-constructor case were handled by #2071 / #2311.)Fix
In
_count_top_level_args, forprimary_lang_id == "dart": when the parameter-list body ends (ignoring trailing whitespace) in}or], find that terminal group's matching opener at depth 0 and blank just those two delimiter chars, so the group's members land at the top level and their separating commas count.A
{...}/[...]that's a default-value literal ({int x = const [1, 2, 3]},{Map m = const {'a': 1}}) is never flush against the body's end → stays nested → internal commas stay correctly ignored. Scoped to dart; no other language's count path is touched.Result
Name-matched
gather_language("dart")args diff vs tree-sitter — GitGalaxy under-counts by ≥2 (excluding tree-sitter's own same-name reconciliation inflation) drop ~40 → 2, and both survivors are tree-sitter/reconciler quirks (build@6253 is genuinely 1 param;copyWith@theme_data:140 is a bodyless abstract method, 0).EditableText(1→76),_Editable(1→39),_UpdateTextSelectionAction(4→6) now match tree-sitter exactly.Regenerated artifacts
tree_sitter_accuracy_baseline_dart.jsonargs_exact_match1519 → 1633 (+114); summary table Dart row 99.4% → 99.5%tree_sitter_accuracy_baseline_javascript.jsonfiles_scanned18 → 17 — a stale value from #2331 (GATE D relegatingthreejs/Nodes.js); that workflow doesn't trigger onstatistical_auditor.pypaths so it was never updated. Included so this PR's owntree-sitter-accuracy-auditrun (detector.pydoes trigger it) is green.Verification
test_detector.py(+ new_count_top_level_argsdart case) +tests/extraction(6234) — greencrucible_check.py— PASS both modestree_sitter_accuracy_audit --all --ci+tri_comparison_chart --all --ci— both green🤖 Generated with Claude Code