Skip to content

fix: extract Dart null-aware (?.) method calls, in both engines - #2570

Merged
carlos-alm merged 1 commit into
mainfrom
fix/issue-2476
Aug 18, 2026
Merged

fix: extract Dart null-aware (?.) method calls, in both engines#2570
carlos-alm merged 1 commit into
mainfrom
fix/issue-2476

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

a?.b() was silently extracted as zero calls in both engines, since Dart's null-aware member access uses a distinct grammar node instead of the one ordinary . access uses:

  • WASM (src/extractors/dart.ts): null-aware access parses as conditional_assignable_selector instead of unconditional_assignable_selector. resolveDartSelectorCall's Layout A/B checks only looked for the unconditional wrapper (confirmed via a parse dump of a?.b();, which produces the same Layout B shape ordinary . calls use, just with the different wrapper node).
  • Native (crates/codegraph-core/src/extractors/dart.rs): null-aware access parses as null_aware_member_expression instead of member_expression (confirmed via a parse dump of tree-sitter-dart 0.2). handle_dart_call_expression's match func.kind() had no arm for the null-aware shape.

Both wrappers carry the identical identifier/object+property fields for call-resolution purposes, so this is a pure extend-the-match fix on both sides — no new resolution logic needed. Also extended the (currently dead, but still mirrored for consistency per this file's own convention) legacy resolve_dart_selector_call/find_dart_assignable_selector path in Rust, matching the WASM-side fix.

Pure extraction gap — no false edges, no benchmark regression (per the issue's own framing): before this fix, no call was ever recorded at all for this shape.

Test plan

  • New Rust unit tests in dart.rs (null_aware_calls module) — basic call, receiver prefixing, chained null-aware calls
  • New TS unit tests in tests/parsers/dart.test.ts (#2476 describe block) — same coverage, WASM engine
  • Revert-verified: disabling each side's fix reproduces the pre-fix [] (no calls extracted) for the exact new tests added
  • npx tsc --noEmit -p ., npm run lint, full npm test (5475 passed)
  • cargo fmt -- --check, cargo clippy --lib -- -D warnings, cargo test --lib (1116 passed)

Closes #2476

a?.b() was silently extracted as zero calls in both engines, since
Dart's null-aware member access uses a distinct grammar node instead
of the one ordinary `.` access uses:

- WASM: conditional_assignable_selector instead of
  unconditional_assignable_selector. resolveDartSelectorCall's Layout
  A/B checks only looked for the unconditional wrapper.
- Native: null_aware_member_expression instead of member_expression
  (confirmed via a parse dump of tree-sitter-dart 0.2).
  handle_dart_call_expression's match only had an arm for the
  unconditional shape.

Both wrappers carry the identical identifier for call-resolution
purposes, so this is a pure extend-the-match fix on both sides -- no
new resolution logic needed.

docs check acknowledged.

Closes #2476

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

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR extends Dart call extraction to recognize null-aware member calls in both native and WASM engines.

  • Adds conditional selector matching to the TypeScript/WASM extractor.
  • Adds null-aware member-expression matching to the native Rust extractor.
  • Adds basic, receiver-prefixing, and chained-call regression coverage for both engines.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable defects identified in the changed null-aware call extraction paths.

Both extraction engines extend their existing member-call handling to the corresponding null-aware grammar node while preserving the established receiver and call-emission behavior.

Important Files Changed

Filename Overview
crates/codegraph-core/src/extractors/dart.rs Extends native call-expression and legacy selector handling to recognize null-aware member calls, with focused regression tests.
src/extractors/dart.ts Centralizes assignable-selector lookup so ordinary and null-aware WASM call shapes use the same resolution logic.
tests/parsers/dart.test.ts Adds WASM regression coverage for basic null-aware calls, receiver extraction, and chained calls.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Source["Dart source: a?.b()"] --> Parse{"Selected engine"}
  Parse -->|WASM| Selector["conditional_assignable_selector"]
  Parse -->|Native| Member["null_aware_member_expression"]
  Selector --> Resolve["Extract method b and receiver a"]
  Member --> Resolve
  Resolve --> Call["Emit call fact"]
Loading

Reviews (1): Last reviewed commit: "fix: extract Dart null-aware (?.) method..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

2 functions changed4 callers affected across 1 files

  • findDartAssignableSelector in src/extractors/dart.ts:908 (3 transitive callers)
  • resolveDartSelectorCall in src/extractors/dart.ts:934 (3 transitive callers)

@carlos-alm
carlos-alm merged commit f2ec483 into main Aug 18, 2026
34 checks passed
@carlos-alm
carlos-alm deleted the fix/issue-2476 branch August 18, 2026 14:03
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 18, 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.

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

1 participant