Prebuilt lookup structures over one corpus snapshot. Built once per
resolution pass and shared by resolve and dynamic_edges — the
build walks every node and is the most expensive part of a pass.
Everything one index pass yields: binds to in-corpus definitions plus
the synthesized dependency surface (D29) for references whose symbol
has no definition occurrence anywhere in the corpus.
Dynamic-dispatch fan-out edges: for every impl block naming a trait the
corpus defines, trait_method -> impl_method (Calls, Dynamic) for each
method the impl defines under a same-named trait method. Conservative
over-approximation — every impl is assumed reachable through the trait —
which is exactly why the edges carry the distinct Dynamic evidence.
Pairing rule: the impl block names the trait (same file/module, or a
named import) and the method names match.
Merge several on-disk indexes into one file: documents and external
symbols concatenate, metadata comes from the first. Per-language
indexers cover disjoint files, so concatenation is the whole merge.
Rewrite document paths from an index produced in a nested project so
they remain repo-relative after indexes from several project roots are
merged. Indexers generally emit paths relative to their working
directory, while Sinter’s nodes are always relative to the repository.
Edges for every proto rpc whose tonic counterpart exists in the corpus:
rpc calls the impl method, impl method implements the rpc; a
generated SClient::r / SServer::r method calls the rpc; a trait
named S under a s_server/s_client module implements service S.
Resolve references against FOREIGN definitions using import evidence
only — the cross-repo boundary pass. Same-file/module/receiver/local
tiers are intra-repo by definition and deliberately excluded, which
also prevents false bindings between identically-named files in
different members. refs and owner_imports come from one member;
foreign_nodes from the others.
Bind our extracted references using a compiler-produced SCIP index —
the highest evidence tier. A reference binds when a SCIP reference
occurrence overlaps its span and the symbol’s definition occurrence
falls inside one of our nodes. read_source maps a repo-relative path
to its content (for line→byte conversion); return None to skip a file.
scope is the set of files being (re)resolved: occurrences there that
anchor to no extracted reference still yield unanchored edges, so
calls the extractor cannot see (inside macro token trees) are not lost.