Skip to content

fix(dataflow): Dart local variable declarations and calls never tracked - #2499

Merged
carlos-alm merged 1 commit into
mainfrom
fix/issue-2357-dart-vardeclarator-calls
Aug 14, 2026
Merged

fix(dataflow): Dart local variable declarations and calls never tracked#2499
carlos-alm merged 1 commit into
mainfrom
fix/issue-2357-dart-vardeclarator-calls

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

  • dataflowDart left varDeclaratorNode entirely unconfigured, and callNode pointed at 'call_expression' — a node type that doesn't exist at all in tree-sitter-dart's grammar.
  • Confirmed empirically (by dumping real parsed trees) that the grammar's own documented postfix_expression wrapper (per node-types.json) never actually materializes either: a call is a flat sequence of siblings under whatever encloses it — helper(x) parses as [identifier "helper", selector "(x)"] as direct siblings, obj.method(x) as [identifier "obj", selector ".method", selector "(x)"] — not a single self-contained node with fields, which the existing field-based callFunctionField/callArgsField extraction fundamentally assumes.
  • Adds two new opt-in DataflowRulesConfig fields (null for every other language, zero behavior change elsewhere):
    • resolveCallParts — override for grammars with no field-based call structure. Dart's resolveDartCallParts dispatches from the call selector and resolves the callee by walking backward to the preceding sibling (another selector's property, for method calls, or a bare identifier, for bare calls).
    • callChainSiblingType — lets a new findCallSelector helper walk forward from a call-sourced value expression (e.g. a var declarator's resolved value field, which lands on the callee's bare identifier, not the call itself) to the trailing call-node sibling — the symmetric counterpart, needed so var x = helper(y); is recognized as call-sourced the same way it already is for languages whose call node IS the value node directly.
  • Also sets varDeclaratorNode/varNameField/varValueField (the grammar does have real name/value fields on initialized_variable_definition) and argumentWrapperType: 'argument' (matching the same wrapper name PHP's config already unwraps).
  • Rust's native engine has no Dart dataflow rules at all yet (tracked separately as follow-up: Rust engine needs DartDataflowRules to match TS's now-fixed dataflowDart #2359), so this is legitimately TS/WASM-only.
  • Closes follow-up: Dart dataflow — calls nested inside a return/other expression are never tracked #2497 as a duplicate — that follow-up (calls nested in return expressions never tracked) is fully subsumed by this fix.

Test plan

  • Empirically verified against real parsed trees for bare calls, method calls, non-call postfix expressions (x++), call-sourced and plain variable declarations, before writing any test
  • New tests in tests/parsers/dataflow-dart.test.ts: bare call (as return expr and as statement), method call, non-call postfix rejection, call-sourced assignment, plain-assignment rejection
  • Full test suite: 328 files / 5269 tests passed
  • npm run lint clean
  • diff-impact — contained (6 functions changed, 6 transitive callers)

Closes #2357

dataflowDart left varDeclaratorNode unconfigured, and callNode pointed
at 'call_expression' -- a node type that doesn't exist at all in
tree-sitter-dart's grammar. Confirmed empirically that the grammar's
OWN documented postfix_expression wrapper (node-types.json) never
actually materializes in a parsed tree either: a call is a flat
sequence of siblings under whatever encloses it (a base identifier
followed by a chain of `selector` siblings, one of which wraps an
argument_part when it IS a call) -- not a single self-contained node
with fields, which the existing field-based callFunctionField/
callArgsField extraction fundamentally assumes.

Adds two new dataflow-visitor.ts mechanisms, both opt-in via new
config fields (null for every other language, zero behavior change
there):
  - resolveCallParts: override for grammars with no field-based call
    structure. Dart's resolveDartCallParts dispatches from the call
    selector and resolves the callee by walking BACKWARD to the
    preceding sibling (another selector's property, or a bare
    identifier).
  - callChainSiblingType: lets findCallSelector walk FORWARD from a
    call-sourced value expression (e.g. a var declarator's resolved
    `value` field, which lands on the callee's bare identifier, not
    the call itself) to the trailing call-node sibling -- the
    symmetric counterpart, needed so a call-sourced assignment
    (`var x = helper(y);`) is recognized the same way it already is
    for languages whose call node IS the value node directly.

Also sets varDeclaratorNode/varNameField/varValueField (the grammar
does have real name/value fields on initialized_variable_definition)
and argumentWrapperType: 'argument' (arguments' own children wrap each
argument, same wrapper name PHP's config already unwraps).

Rust's native engine has no Dart dataflow rules at all yet (tracked
separately as #2359), so this is legitimately TS/WASM-only.

Empirically verified against real parsed trees (bare calls, method
calls, non-call postfix expressions, call-sourced and plain variable
declarations) before writing the regression tests.

docs check acknowledged

Closes #2357
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR enables Dart call and local-variable dataflow extraction in the TypeScript/WASM analysis path.

  • Configures Dart initialized-variable fields and argument wrappers.
  • Adds grammar-specific resolution for Dart’s flat selector-based call representation.
  • Adds sibling-chain lookup for call-sourced variable declarations.
  • Adds coverage for bare calls, method calls, postfix rejection, and call-sourced assignments.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete blocking or independently actionable non-blocking issue established.

The Dart-specific behavior is opt-in, existing languages retain the prior field-based resolution path, and the added tests exercise the primary call and assignment cases without revealing a reachable regression.

Important Files Changed

Filename Overview
src/ast-analysis/rules/b2.ts Adds Dart-specific variable declaration fields and selector-based call-part resolution; no actionable defect was established.
src/ast-analysis/visitors/dataflow-visitor.ts Generalizes call resolution and adds opt-in sibling lookup while preserving the existing field-based path for other languages.
src/ast-analysis/shared.ts Adds null defaults for the two opt-in dataflow configuration fields.
src/types.ts Extends the dataflow rules contract with typed call-resolution and sibling-chain options.
tests/parsers/dataflow-dart.test.ts Adds focused positive and negative coverage for newly supported Dart calls and declarations.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  AST["Dart flat AST siblings"] --> Selector["Call selector"]
  Selector --> Resolve["resolveDartCallParts"]
  Resolve --> Callee["Callee name"]
  Resolve --> Args["Arguments node"]
  Args --> Flows["Argument flows"]
  Value["Variable value node"] --> Find["findCallSelector"]
  Find --> Selector
  Callee --> Assignment["Call-sourced assignment"]
Loading

Reviews (1): Last reviewed commit: "fix(dataflow): dart local variable decla..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

6 functions changed6 callers affected across 2 files

  • prevNamedSibling in src/ast-analysis/rules/b2.ts:574 (2 transitive callers)
  • resolveDartCallParts in src/ast-analysis/rules/b2.ts:608 (1 transitive callers)
  • resolveCallExprParts in src/ast-analysis/visitors/dataflow-visitor.ts:218 (4 transitive callers)
  • findCallSelector in src/ast-analysis/visitors/dataflow-visitor.ts:248 (3 transitive callers)
  • handleVarDeclarator in src/ast-analysis/visitors/dataflow-visitor.ts:269 (2 transitive callers)
  • handleCallExpr in src/ast-analysis/visitors/dataflow-visitor.ts:372 (2 transitive callers)

@carlos-alm
carlos-alm merged commit 804c20c into main Aug 14, 2026
27 checks passed
@carlos-alm
carlos-alm deleted the fix/issue-2357-dart-vardeclarator-calls branch August 14, 2026 11:01
@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

1 participant