You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Discovered while adding Dart integration-test coverage to PR #2028 (constructor-call attribution, #1892).
Context: PR #2028 adds new ClassName() → constructor-method attribution. Java, PHP, and Groovy fixtures using new ClassName() verify this correctly. Attempting the analogous Dart fixture surfaced two separate, pre-existing gaps in src/extractors/dart.ts, unrelated to constructor attribution itself:
1. Bare (keyword-less) calls are not extracted at all.
Modern Dart permits omitting new for both plain function calls and constructor invocations (var x = Foo();, helper();). Neither is extracted as a Call by extractDartSymbols — confirmed empirically:
// helper(); inside main() → symbols.calls === []// var w = Foo(); (no `new`) → symbols.calls === []// var w = new Foo(); (explicit `new`) → symbols.calls === [{ name: 'Foo', line: N }] ✓
Only the explicit new_expression node type is dispatched to handleDartConstructorCall in walkDartNode's switch (src/extractors/dart.ts). constructor_invocation is also mapped to the same handler, but apparently doesn't fire for a bare capitalized call the way the code comments assume — and there is no handler at all for a bare plain (non-capitalized) function call.
This means the existing hand-annotated fixtures in tests/benchmarks/resolution/fixtures/dart/*.dart (which use the idiomatic keyword-less style throughout, e.g. var repo = UserRepository(); in main.dart) do not actually resolve any of their "constructor" or "static" mode expected edges today. This is consistent with (and likely explains) the dart: { precision: 0.0, recall: 0.0 } floor in tests/benchmarks/resolution/resolution-benchmark.test.ts — the threshold is a placeholder because current recall is genuinely ~0%, not because the floor merely hasn't been ratcheted up yet.
2. Multi-line block-bodied function/method definitions get endLine truncated to the signature line, not the body's closing brace.
Because the call's line falls outside the recorded [line, endLine] span, downstream caller-attribution (findEnclosingBinding-style enclosing-function lookup during graph build) cannot attribute the call to makeWaldo — it falls back to file-level attribution (src: 'repro.dart', srcKind: 'file') instead. Single-line arrow-bodied functions (Waldo makeWaldo() => new Waldo();) do not hit this, since the whole function (signature + body) sits on one line.
This affects essentially any real-world multi-line Dart function/method (block bodies are the common case — e.g. UserService.createUser/getUser/removeUser in the resolution-benchmark fixture all use block bodies), so it is likely a second, independent contributor to Dart's current ~0% resolution recall, on top of gap #1.
Suggested fix directions (not investigated in depth — flagging for triage):
For Bump actions/setup-node from 4 to 6 #1: determine what constructor_invocation actually covers in the installed tree-sitter-dart grammar version, and add a real dispatch path for bare identifier-call syntax (likely needs a new node-type case in walkDartNode, mirroring how other languages disambiguate a capitalized bare call as a constructor vs. a plain function call).
For Bump actions/checkout from 4 to 6 #2: handleDartClass's extractDartClassMembers (for methods) and handleDartFunction/handleDartMethodSig (for top-level functions) currently call nodeEndLine(member)/nodeEndLine(node) on the method_signature/function_signature node itself; needs to instead measure through to the enclosing declaration/body node so endLine covers the full definition, not just the signature.
Impact: Both are scoped entirely to src/extractors/dart.ts (WASM) — have not checked whether crates/codegraph-core's Rust Dart extractor (if one exists) has analogous or different behavior; that should be checked as part of any fix for engine parity.
Discovered while adding Dart integration-test coverage to PR #2028 (constructor-call attribution, #1892).
Context: PR #2028 adds
new ClassName()→ constructor-method attribution. Java, PHP, and Groovy fixtures usingnew ClassName()verify this correctly. Attempting the analogous Dart fixture surfaced two separate, pre-existing gaps insrc/extractors/dart.ts, unrelated to constructor attribution itself:1. Bare (keyword-less) calls are not extracted at all.
Modern Dart permits omitting
newfor both plain function calls and constructor invocations (var x = Foo();,helper();). Neither is extracted as aCallbyextractDartSymbols— confirmed empirically:Only the explicit
new_expressionnode type is dispatched tohandleDartConstructorCallinwalkDartNode's switch (src/extractors/dart.ts).constructor_invocationis also mapped to the same handler, but apparently doesn't fire for a bare capitalized call the way the code comments assume — and there is no handler at all for a bare plain (non-capitalized) function call.This means the existing hand-annotated fixtures in
tests/benchmarks/resolution/fixtures/dart/*.dart(which use the idiomatic keyword-less style throughout, e.g.var repo = UserRepository();inmain.dart) do not actually resolve any of their "constructor" or "static" mode expected edges today. This is consistent with (and likely explains) thedart: { precision: 0.0, recall: 0.0 }floor intests/benchmarks/resolution/resolution-benchmark.test.ts— the threshold is a placeholder because current recall is genuinely ~0%, not because the floor merely hasn't been ratcheted up yet.2. Multi-line block-bodied function/method definitions get
endLinetruncated to the signature line, not the body's closing brace.Because the call's line falls outside the recorded
[line, endLine]span, downstream caller-attribution (findEnclosingBinding-style enclosing-function lookup during graph build) cannot attribute the call tomakeWaldo— it falls back to file-level attribution (src: 'repro.dart', srcKind: 'file') instead. Single-line arrow-bodied functions (Waldo makeWaldo() => new Waldo();) do not hit this, since the whole function (signature + body) sits on one line.This affects essentially any real-world multi-line Dart function/method (block bodies are the common case — e.g.
UserService.createUser/getUser/removeUserin the resolution-benchmark fixture all use block bodies), so it is likely a second, independent contributor to Dart's current ~0% resolution recall, on top of gap #1.Suggested fix directions (not investigated in depth — flagging for triage):
constructor_invocationactually covers in the installed tree-sitter-dart grammar version, and add a real dispatch path for bare identifier-call syntax (likely needs a new node-type case inwalkDartNode, mirroring how other languages disambiguate a capitalized bare call as a constructor vs. a plain function call).handleDartClass'sextractDartClassMembers(for methods) andhandleDartFunction/handleDartMethodSig(for top-level functions) currently callnodeEndLine(member)/nodeEndLine(node)on themethod_signature/function_signaturenode itself; needs to instead measure through to the enclosing declaration/body node soendLinecovers the full definition, not just the signature.Impact: Both are scoped entirely to
src/extractors/dart.ts(WASM) — have not checked whethercrates/codegraph-core's Rust Dart extractor (if one exists) has analogous or different behavior; that should be checked as part of any fix for engine parity.