Repository navigation
fix(dart): an import or export links the file its URI names, not a namesake - #2388
Merged
Merged
Conversation
…mesake A Dart `import` / `export` now resolves its URI through the library model in src/resolution/dart-libraries.ts: `package:<name>/<path>` is `<root>/lib/<path>` of the project package whose pubspec.yaml says `name: <name>`, any other URI is a path from the importing file, and a `dart:` library, a package from outside the project or a file the index does not hold links nothing. The ref never reaches the name-matcher, which took the URI's last segment for a file name (`package:flutter/widgets.dart` reached riverpod_analyzer_utils' widgets.dart from 130 files, bloc_tools' `package:args/command_runner.dart` its own command_runner.dart) or bound it to the importing file's own `import` node. When packages share a name and neither the importer's own package nor one enclosing it settles which, the importing package's `path:` dependency of that name (pubspec_overrides.yaml, then pubspec.yaml) does: bloc's two example apps each keep an authentication_repository. Library visibility reads the same answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 6, 2026
colbymchenry
added a commit
that referenced
this pull request
Oct 6, 2026
…ater (#2392) A sync retried parked failed refs by name_tail (#1240), but an import names a file, a folder or a namespace, not a symbol, so the lookup never found one: the tail of `package:app/b.dart` was `dart`, of `inc/db.php` `php`, of `./req` `/req`. Most languages never parked theirs at all: an import that named no file reached the importing file's own `import` node through matchByQualifiedName (its qualified name is the module path) and resolved there, so `./x` in TS/JS, `import pkg.mod`, `#include "a/b.h"`, `<stdio.h>`, a C# `using` of an outside namespace, Go module paths and R, Solidity, Svelte and Vue imports were consumed by an edge to themselves. A Lua `require` bound the local it is assigned to. The import linked only once the importer changed, or on a full index. - resolveOne's target gate drops an `imports` ref's own import statement, so the ref parks as failed (#2388 did this for Dart alone). - A Lua / Luau `require` resolves to a module file or nothing. - An import written as a path is parked under its last segment's stem (`package:app/b.dart` -> `b`, `./z.js` -> `z`): src/db/reference-tail.ts. - Sync retries the failed imports an ADDED file can satisfy: by its name, stem and folder (importPathKeys), as a failed import's tail or whole name, and by the changed files' namespace / module names as a whole name (C# `using Foo.Bar`, Java `import com.z.*`). Same per-key ceiling. - Schema v12: two partial indexes over failed imports, which the planner needs to avoid reading every failed call that shares a tail; the migration rewrites the tails of path imports parked by an older version. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A Dart
import/exportnow links the file its URI names, or nothing:package:<name>/<path>→<root>/lib/<path>of the project package whosepubspec.yamlsaysname: <name>(the nearest pubspec above an indexed.dartfile, never above the project root; the importing file's own package first when names repeat).dart:, a package from outside the repo, a path out of the project, or a file the index doesn't hold → no edge. The ref stays unresolved, i.e. an outside import.Before,
matchByFilePathmatched the URI's last segment against file basenames, falling back to a unique same-named file. OtherwisematchByQualifiedNamebound the ref to the importing file's ownimportnode, whose qualified name is the URI.How:
src/resolution/dart-libraries.ts): a newdartDirectiveFilewrapsresolveDartUri.resolveViaImportgets a Dart branch.When packages share a name and neither the importer's own package nor an enclosing one settles it, the importing package's
path:dependency of that name picks it. That is read frompubspec_overrides.yaml, thenpubspec.yaml, in block or flow style; a git dependency's innerpath:doesn't count. bloc's two example apps each keep anauthentication_repository. Library visibility reads the same answer.Validation
riverpod @4ba1be2 and bloc @b9be1e2, native kernel loaded, main @99246848 vs this branch. Every Dart
importsedge is classified against an independent oracle, a separate pubspec/URI resolver in the probe script.importsedgesimportnodeAll edges, paired by call site:
imports; 799 moved from the own import node to the named file; 1,381 kept, withfile-pathat 0.7/0.85 becomingimportat 0.9. Nothing added, and no other edge kind changed.imports; 410 moved to the named file, 23 of them told apart bypath:; 602 kept. Nothing added. 37references/implements/instantiatesedges keep their target and go from 0.7 to 0.9, because a file importingpackage:authentication_repository/…now sees one of the two packages instead of both.Removed edges, by what they were before:
dart:/ outside-package URIs.package:flutter/widgets.dart→ riverpod_analyzer_utils'riverpod_types/widgets.dart.website/docs/….package:args/command_runner.darthad linked its owncommand_runner.dart, andpackage:integration_test/…had linkedtest_driver/integration_test.dart.Still unresolved though they name a project path: the 12 riverpod i18n copies, bloc's mason template URI
{{{bloc_export}}}, and AngularDart's build-generated*.template.dart(2).Results are identical on #2386's pre-squash commit and on main after #2387: #2387 changes no edge on either repo.
File dependents, which
codegraph affected, the MCP file tool's "used by" and dead-code corroboration all read:widgets.dartgoes from 132 to 2.src/core/foundation.dartgoes from 51 to 29.Tests
__tests__/dart-import-uris.test.ts(5 tests). All 5 fail on main (checked at 249d9a8 and 9924684) and pass with the fix, with the kernel and withCODEGRAPH_KERNEL=0.tsc --noEmitis clean.git-index-currency,index-daemon-rebuild,mcp-status-freshnessandsync, and those 4 files pass when rerun alone (78/78).importnode.Not covered
part/part ofdirectives aren't extracted by either extractor, so they have no edge, before or after.syncdoesn't retry a failed import when the file it names is added later. Its retry key is the URI's last.segment,dart. It links once the importer changes, or on a full index. Before this change it never re-linked either: it stayed on the ownimportnode.package:handling. If it is revived,dartDirectiveFileis the shared answer.🤖 Generated with Claude Code