Skip to content

fix(dataflow): grouped param wrapper gives every name the same paramIndex - #2502

Merged
carlos-alm merged 2 commits into
mainfrom
fix/issue-2358-param-index-per-name
Aug 14, 2026
Merged

fix(dataflow): grouped param wrapper gives every name the same paramIndex#2502
carlos-alm merged 2 commits into
mainfrom
fix/issue-2358-param-index-per-name

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Problem

extractParams (src/ast-analysis/visitor-utils.ts) incremented index once per CHILD of the parameter list, not once per extracted name. Dart's optional_formal_parameters wraps multiple genuinely separate parameter declarations in one child node ({int times, bool loud}), so both times and loud got the same paramIndex.

Fix

Added groupedParamTypes to DataflowRulesConfig: when a child's type is in this set, extractParams iterates that child's own named children as separate slots instead of treating the whole node as one slot. Set for Dart's optional_formal_parameters.

This is deliberately not a blanket "index per extracted name" change (the issue's own caution): true single-slot destructuring (JS/TS function f({a, b})) must keep sharing one index across a/b, since both come from the same argument slot — verified via a new test locking that in.

Also discovered Dart's grammar attaches a parameter's default-value literal (= 1, = false) as a flat sibling inside the optional_formal_parameters group, not nested inside its formal_parameter — so the grouped-slot loop only consumes an index for a slot that actually yields a name, otherwise the literal siblings created off-by-N gaps.

Simplified extractDartParamName by removing its now-dead recursive optional_formal_parameters branch, since extractParams no longer calls it on the group node directly.

TS/WASM-only — the Rust engine has no Dart dataflow rules at all yet (tracked separately by #2359), so there's nothing to mirror there for this fix.

Follow-up filed

While verifying no other language relies on the old shared-index behavior, found Go's func f(a, b int) hits the identical bug class in both engines (TS's go.ts and Rust's extract_params_go) — already shipped, so lower risk tolerance and a differently-shaped fix. Filed as #2501, out of scope here.

Closes #2358

Test plan

  • New Dart tests: named-parameter group and optional-positional group each get distinct paramIndex values
  • New JS/TS test: destructured object-pattern names still share one paramIndex, non-destructured sibling gets the next one
  • Full vitest run suite (5272 passed, 328 files)
  • tsc --noEmit, biome check
  • cargo test --release, cargo clippy -- -D warnings, cargo fmt --check (unaffected, confirmed clean)
  • Dual-engine dataflow parity suite

…ndex

extractParams incremented index once per child of the parameter list, so
a grammar node grouping multiple genuinely separate slots (Dart's
optional_formal_parameters for `{int times, bool loud}`) gave every name
inside it the same index instead of each getting its own. Adds
groupedParamTypes to unpack such wrappers into distinct slots, while
still sharing one index for true single-slot destructuring (JS/TS
object/array patterns) and skipping non-parameter siblings (default
value literals Dart's grammar attaches flat inside the group).

Closes #2358

docs check acknowledged

Impact: 4 functions changed, 2 affected
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR corrects parameter-slot indexing for Dart grouped parameters while preserving shared indices for destructuring and positional indices after unnamed parameters.

  • Adds groupedParamTypes to the dataflow-rule contract and enables it for Dart optional parameter groups.
  • Iterates each name-producing slot inside grouped wrappers while retaining ordinary unnamed slots in the index count.
  • Adds Dart, JavaScript, and C++ regression coverage for the affected indexing behaviors.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/ast-analysis/visitor-utils.ts Separates grouped parameter-slot traversal from ordinary parameter handling, preserving index advancement for unnamed ordinary parameters.
src/ast-analysis/rules/b2.ts Configures Dart optional parameter wrappers as grouped slots and removes the obsolete recursive group extraction branch.
src/ast-analysis/shared.ts Adds an empty grouped-parameter type set to the shared dataflow defaults.
src/types.ts Extends the dataflow-rule contract with the grouped parameter wrapper configuration.
tests/parsers/dataflow-cpp.test.ts Covers the previously reported unnamed-parameter regression by asserting the following named parameter remains at index 1.
tests/parsers/dataflow-dart.test.ts Covers distinct indices for Dart named and optional-positional grouped parameters.
tests/parsers/dataflow-javascript.test.ts Ensures names from one destructured argument continue sharing a parameter index.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Parameter-list child] --> B{Grouped parameter type?}
  B -->|No| C[Extract names at current index]
  C --> D[Always advance index]
  B -->|Yes| E[Iterate grouped named children]
  E --> F{Child yields names?}
  F -->|Yes| G[Emit names and advance index]
  F -->|No| H[Skip metadata/default-value child]
Loading

Reviews (2): Last reviewed commit: "fix(dataflow): unnamed parameter no long..." | Re-trigger Greptile

Comment thread src/ast-analysis/visitor-utils.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

2 functions changed3 callers affected across 2 files

  • extractDartParamName in src/ast-analysis/rules/b2.ts:545 (1 transitive callers)
  • extractParams in src/ast-analysis/visitor-utils.ts:89 (2 transitive callers)

The previous commit's skip-empty-slot guard applied to every child of the
parameter list, not just grouped ones — an unnamed C/C++ parameter (e.g.
void f(int, int value)) yields zero names and was no longer consuming an
index, shifting every later named parameter's position down by one.
Scopes the skip to grouped slots only; an ordinary child still always
consumes an index regardless of name count.

docs check acknowledged

Impact: 1 functions changed, 2 affected
@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review — pushed a fix for the unnamed-parameter regression you flagged.

@carlos-alm
carlos-alm merged commit ec143bf into main Aug 14, 2026
45 of 47 checks passed
@carlos-alm
carlos-alm deleted the fix/issue-2358-param-index-per-name branch August 14, 2026 13:10
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

follow-up: extractParams gives every name from one grouped-param wrapper the same paramIndex

1 participant