Expand description
@arch:layer(kg) @arch:role(extract)
yah-kg-rust — LanguageIndexer for Rust source.
Pass 1+2 within-file indexer. Given a .rs file, parses it with
syn::parse_file and emits:
- Nodes:
File,Module,Type(struct/enum/union/type-alias),Field,Variant,Function,Method,Trait,Impl,Constant,MacroDecl(Rules). - Edges:
Contains(file→item, module→item, type→field/variant, trait→method, impl→method),Defines(trait/impl→method),ImplFor(impl→type),ImplOfTrait(impl→trait),DerivedBy(type→derive macro),AttributedBy(item→attr macro),Calls(fn/method → same-module fn for unambiguous simple-ident calls).
Cross-file resolution remains in the daemon: this crate stops at the
file boundary and emits raw use paths onto the file node’s
imports property (newline-joined). The store’s
resolve_rust_imports pass (Pass 3) walks every file with that
property, expands crate::/super::/self:: against the on-disk
module tree, and emits Imports edges between File nodes.
Item-level Imports and cross-crate Calls resolution are still
future Pass 3+ work.
Calls edges are emitted only for unambiguous in-file resolutions:
a single-ident path call (foo()) resolves to a same-module top-
level fn foo, and the store drops the edge if no such node was
emitted. Method calls (x.foo()) and multi-segment paths
(Foo::new()) need type inference we don’t have, so they’re
deliberately skipped rather than guessed at.
Within-file simple-name lookups (impl Foo where struct Foo lives
in the same module) resolve correctly because NodeId::compute is
deterministic over (lang, qualified, file).
@yah:ticket(R016-F4, “Best-effort Calls edges (Rust + TS): walk function bodies, emit when callee resolves unambiguously”) @yah:at(2026-04-30T19:20:35Z) @yah:assignee(agent:claude) @yah:status(review) @yah:phase(P1) @yah:parent(R016) @yah:next(“Skip ambiguous resolves rather than emit wrong edges”) @yah:next(“Test fixture: hand-pick a few clear single-resolution call sites and assert edge presence”)
@yah:ticket(R442-T3, “kg-rust: emit methodFingerprints (normalised token streams) for impl methods + free fns”) @yah:assignee(agent:claude) @yah:status(review) @yah:at(2026-06-19T03:14:31Z) @yah:phase(P2) @yah:parent(R442) @yah:assumes(“syn’s TokenStream gives identifier/literal/keyword/punct distinction at the TokenTree level; no re-tokenization needed”) @yah:handoff(“kg-rust emission DONE + verified. New crates/yah/kg-rust/src/fingerprint.rs: fingerprint_block(&syn::Block) normalises body tokens (ident→ID, literal→LIT, keyword→text, punct→text, group delims kept, recursive) + param_count(&sig) incl receiver. Wired via Walker::emit_fingerprint into walk_fn (free fns), impl methods, and trait default methods — emits node properties fingerprint_tokens + fingerprint_params (skips empty bodies). 6 inline unit tests written. cargo build -p kg-rust clean; algorithm verified in an isolated syn/quote crate (rename-invariant + shape-sensitive confirmed). Tests can’t RUN yet: cargo test -p kg-rust pulls dev-deps kg-store+rpc which don’t compile (unrelated live kg→party refactor left rpc importing kg::prelude/party/prompt that moved to crates/yah/party).”) @yah:verify(“cargo build -p kg-rust (lib clean)”) @yah:verify(“cargo test -p kg-rust fingerprint (6 unit tests; BLOCKED until rpc/kg-store compile — dev-deps. Logic verified standalone: ID/LIT collapse, keywords+punct kept, rename-invariant, shape-sensitive)”) @yah:gotcha(“The CONSUMER half — kg-store::class_graph reading fingerprint_tokens/fingerprint_params off method nodes into each ClassView’s methodFingerprints blob — is NOT done here (filed separately under R442-T12). The kg→party carve (R475) has landed: kg-store/rpc compile green again, so the consumer half is no longer blocked.”)
Re-exports§
pub use indexer::RustIndexer;