A configurable directive such as
export 'service_stub.dart' if (dart.library.io) 'service_io.dart';
was matched only up to its first quoted string, so the `if` alternatives
were dropped. In the usual Flutter facade the stub is an empty placeholder
and the real implementation lives in the conditional branch, which left
the implementation unreachable from the facade and its importers.
Parse the whole directive and emit one edge per URI: the default URI keeps
its plain edge (unchanged), each alternative gets the same relation tagged
context="conditional_uri" with its own source line. A string literal inside
the condition (`if (app.flavor == 'prod')`) is part of the URI test and is
not mistaken for a URI.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 2b965f23fc)
Since #1098 a `part of` file's declarations are redirected to the parent
library so one library has one id namespace. The redirect also dropped
the part's own file node, so a scanned source file could not be found by
name (`explain "<part>.dart"` -> no node).
Keep the redirect and keep the node: the part gets its regular file node,
`library --includes--> part` anchored on the `part of` line, and
`part --contains--> declaration` mirrors every `defines` edge the library
gets from this part. Declaration ids and the library's `defines` edges are
unchanged. test_roadmap_bug_fixes asserted the old "no part node"
behaviour and now asserts the part's own node instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e32f49dbad)
extractors/dart.py hardcoded source_location: None at every node and
edge construction site, so a Dart graph could cite zero lines no
matter how many declarations it had (0% across three real repos,
~25k unciteable nodes in one of them).
Threads a line number through add_node/add_edge from each match's own
offset, anchored on the capture group rather than the whole match: a
pattern like the class declaration's leading ^\s* otherwise reports
the line too early when blank lines precede the declaration.
The comment stripping pass also needed a fix first: it deleted a
comment token outright, so a multi-line comment shifted every later
offset (and therefore every later line number) up by the comment's
own height. Blanking it to the same number of newlines instead keeps
src_clean's line count in step with the original file.
Sourceless reference stub nodes (an inherited class, a mixin, an
import target, and similar names the file only references rather
than defines) keep source_location: None, same as before, since there
is no single line in THIS file for a symbol that lives elsewhere.
Every node this file actually defines, and every edge attributed to a
real declaration site, now carries its real line.
Fixes#3365.
(cherry picked from commit 0dbcefc5ba)
Modernizes the Dart extractor: comment stripping, `part of` redirection, nested-generic-aware extends/with/implements parsing, generic type-argument mapping, and generic call detection.
Verified against current v8: merges cleanly, full suite 1530 passed, and inheritance edges connect to same-file class nodes with no ghost-node splits or dangling edges (consistent with the #1033/#1096 node-ID invariants).