Problem
Discovered while fixing #2358 (Dart's optional_formal_parameters sharing one paramIndex across multiple named-parameter-group children).
Go's grammar allows a single parameter_declaration node to declare multiple comma-separated names against one shared type: func f(a, b int, c string). Per node_modules/tree-sitter-go/src/node-types.json, parameter_declaration has a name field with multiple: true (both a and b are name-field children) plus a single type field.
Both engines extract all names from one such node in a single pass, and the outer per-child loop increments index only once per node (the exact bug pattern #2358 fixes for Dart) — so a and b above both get paramIndex: 0, and c gets paramIndex: 1, when the correct indices are 0, 1, 2 respectively (each is a genuinely independent, individually-positioned parameter, not a destructured binding of one argument slot):
- TS:
extractParamName hook in src/ast-analysis/rules/go.ts (parameter_declaration branch) returns names.length > 0 ? names : null — multiple names from one child in the generic extractParams loop (src/ast-analysis/visitor-utils.ts).
- Rust:
extract_params_go in crates/codegraph-core/src/ast_analysis/dataflow.rs has the identical shape — collects every identifier child into one Vec<String> returned for one parameter_declaration node, consumed by extract_params's per-child increment.
Why this isn't fixed by #2358's mechanism directly
#2358 introduces groupedParamTypes (TS-only, since Dart dataflow doesn't exist in the Rust engine yet — tracked separately by #2359): when a child's type is in this set, the outer loop iterates that child's OWN named children as separate slots instead of calling extractParamNames on the whole node.
Go's shape doesn't fit that directly — a and b are not separate child NODES, they're two identifiers under the SAME parameter_declaration's name field (multiple: true), sitting alongside a type field that must NOT be treated as its own slot. Naively marking parameter_declaration as a groupedParamTypes entry and iterating all of its namedChildren would incorrectly also try to extract a slot from the type node.
Fixing this needs either:
- A field-aware variant (e.g. read
childrenForFieldName('name') specifically, one slot per name, skip type), or
- Restructuring
go.ts's hook so each identifier is walked as an independent grandchild before extractParamName currently intercepts the whole parameter_declaration node.
Needs the equivalent fix mirrored in extract_params_go (Rust) for dual-engine parity, since — unlike Dart — Go already ships in both engines today.
Filed per this repo's scope-discipline convention — out of scope for #2358's Dart-specific groupedParamTypes fix.
Problem
Discovered while fixing #2358 (Dart's
optional_formal_parameterssharing oneparamIndexacross multiple named-parameter-group children).Go's grammar allows a single
parameter_declarationnode to declare multiple comma-separated names against one shared type:func f(a, b int, c string). Pernode_modules/tree-sitter-go/src/node-types.json,parameter_declarationhas anamefield withmultiple: true(bothaandbarename-field children) plus a singletypefield.Both engines extract all names from one such node in a single pass, and the outer per-child loop increments
indexonly once per node (the exact bug pattern #2358 fixes for Dart) — soaandbabove both getparamIndex: 0, andcgetsparamIndex: 1, when the correct indices are0,1,2respectively (each is a genuinely independent, individually-positioned parameter, not a destructured binding of one argument slot):extractParamNamehook insrc/ast-analysis/rules/go.ts(parameter_declarationbranch) returnsnames.length > 0 ? names : null— multiple names from one child in the genericextractParamsloop (src/ast-analysis/visitor-utils.ts).extract_params_goincrates/codegraph-core/src/ast_analysis/dataflow.rshas the identical shape — collects everyidentifierchild into oneVec<String>returned for oneparameter_declarationnode, consumed byextract_params's per-child increment.Why this isn't fixed by #2358's mechanism directly
#2358 introduces
groupedParamTypes(TS-only, since Dart dataflow doesn't exist in the Rust engine yet — tracked separately by #2359): when a child's type is in this set, the outer loop iterates that child's OWN named children as separate slots instead of callingextractParamNameson the whole node.Go's shape doesn't fit that directly —
aandbare not separate child NODES, they're twoidentifiers under the SAMEparameter_declaration'snamefield (multiple: true), sitting alongside atypefield that must NOT be treated as its own slot. Naively markingparameter_declarationas agroupedParamTypesentry and iterating all of itsnamedChildrenwould incorrectly also try to extract a slot from thetypenode.Fixing this needs either:
childrenForFieldName('name')specifically, one slot per name, skiptype), orgo.ts's hook so each identifier is walked as an independent grandchild beforeextractParamNamecurrently intercepts the wholeparameter_declarationnode.Needs the equivalent fix mirrored in
extract_params_go(Rust) for dual-engine parity, since — unlike Dart — Go already ships in both engines today.Filed per this repo's scope-discipline convention — out of scope for #2358's Dart-specific
groupedParamTypesfix.