After parsing, many call edges, type relations, and references contain unresolved names (just the text from the source code). The resolution pipeline matches these to actual symbol IDs in the database.
A 6-step first-match-wins algorithm:
- Explicit imports — the file imports the exact qualified name
- Wildcard imports — the file has a wildcard import matching the name's package
- Same package — the target symbol is in the same package as the calling file
- Qualified name — the name matches a symbol's full qualified name directly
- Unique name — only one symbol with that unqualified name exists in the index
- Pending — no match found; stored in
pending_resolutionfor retry after more files are indexed
- Initial index: resolution is deferred until all files are parsed, then runs once globally
- Incremental update: after a file is re-parsed, resolution runs for that file's edges, then re-resolves any pending entries that might now match
- Bulk mode (
--bulk): resolution runs as SQL batch operations across all files at once
When new files are added or existing files change:
re_resolve()retries allpending_resolutionentriesre_resolve_imports()fixes unresolved import edges- Dependent files (those with edges pointing into changed symbols) are marked stale and re-indexed (up to depth 2)
Symbol diffing (store/diff.rs) matches existing and new symbols by (qualified_name, kind), disambiguating overloads by arity then parameter types. Matched symbols keep their DB IDs, so cross-file edges from other files survive re-indexing. Only edges from the modified file are wiped and rebuilt.