Skip to content

Dart: null-aware (conditional) method calls (a?.b()) are never extracted, in either engine #2476

Description

@carlos-alm

Context

Discovered while implementing #2319 (Dart typeMap population + call.receiver wiring for call resolution), while enumerating the selector/call-expression grammar shapes Dart's two extractors need to handle.

Dart's null-aware member access (a?.b()) uses a distinct grammar node — conditional_assignable_selector (?.) — instead of the unconditional_assignable_selector (.) node ordinary member access/calls use. Confirmed both engines silently extract ZERO calls for this shape:

void f() {
  a?.b();
}
  • WASM (src/extractors/dart.ts): resolveDartSelectorCall's (formerly resolveDartSelectorMethodName) Layout A/B checks only look for unconditional_assignable_selector, never conditional_assignable_selector — confirmed via extractDartSymbols(...).calls returning [] for the snippet above.
  • Native (crates/codegraph-core/src/extractors/dart.rs, tree-sitter-dart 0.2): confirmed the SAME empty-calls result via a scratch unit test during Dart: no typeMap population for field/parameter types — receiver-typed calls unresolved (#2082 follow-up) #2319's investigation — tree-sitter-dart 0.2 appears to represent a?.b() differently from a plain . call in a way handle_dart_call_expression's member_expression branch doesn't currently match either (needs its own grammar investigation to confirm the exact node shape 0.2 produces for this).

This is a pure extraction gap (no call is ever recorded at all, so no false edges and no benchmark regression), separate from and unrelated to #2319's typeMap work. Not present in any current resolution-benchmark fixture, so it doesn't move any recall numbers — filed for visibility since it's a real, silent gap in real-world Dart code (null-aware access is common/idiomatic).

Suggested fix direction

  1. Confirm the native engine's exact grammar shape for a?.b() (tree-sitter-dart 0.2) via a scratch parse test (same technique used during Dart: no typeMap population for field/parameter types — receiver-typed calls unresolved (#2082 follow-up) #2319 — see that issue/PR for the parse-dump harness).
  2. WASM: add a conditional_assignable_selector branch alongside unconditional_assignable_selector in resolveDartSelectorCall (mirroring the exact same identifier-extraction logic).
  3. Native: add the equivalent handling to handle_dart_call_expression / handle_dart_selector once the grammar shape is confirmed.
  4. Add a fixture case (or extend an existing one) to the Dart resolution-benchmark fixtures so this gap surfaces in receiver-typed (or a new null-aware mode) recall going forward.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions