Conversation
Port of PR trailhq#59 rebaked onto the current breadth-tier architecture. Extraction (extract.ts, bindings.ts): functions, structs, enums, traits (interface), type aliases, unions, impl-owned methods with generic-strip ownership, macro_rules! in its own `!` namespace, inline-module scope segments, module and constant nodes. pub/pub(crate)/pub(super) and #[macro_export] drive exports; #[cfg(test)] suppresses them through the whole module subtree, and function-body nesting cannot launder a pub into an export. Macro signatures stop before their token trees; scoped calls carry the leaf name; use forms keep full per-leaf paths; inline modules consume same-file self/super prefixes. Resolution (resolve.ts): a module-tree resolver for crate::/self::/ super:: paths — x.rs and x/mod.rs layouts, the parser-file stem-dir rule, bodyless mod imports, integration-test crate roots under tests/ benches/examples, and path-inferred roots when no Cargo.toml exists. Cargo [package] names map workspace imports (hyphen/underscore-folded, { package = "..." } aliases honored); duplicates stay raw. Scoped calls resolve only against the resolved file's functions, never a bare-name fallback. Bare names resolve in a Rust-only domain, and duplicate same-file trait impls drop as ambiguous while a single impl heritage resolves trait default methods. Routing: .rs leaves the breadth registry (GENERIC_LANGS) for the depth tier, mirroring PHP's move in trailhq#157; grammar is tree-sitter-rust 0.24.0 with a $tree-sitter override pin, which also parses &raw const/mut.
🌱 graft blast radius1 area changed → 8 areas can be affected. 33 dependent symbols, depth 2. flowchart TB
A0(("Graph Freshness<br/>12 symbols"))
A1(("Code Review Pipeline<br/>10 symbols"))
A2(("CLI Entry Point<br/>5 symbols"))
A3(("MCP Tool Integration<br/>2 symbols"))
A4(("Viewer Build Script<br/>1 symbol"))
AX(("3 smaller areas<br/>3 symbols"))
classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
class A0,A1,A2,A3,A4 reached;
classDef tail fill:#EEF2F3,stroke:#9AA4A9,stroke-width:1px,color:#3A4247;
class AX tail;
Who knows this code — 4 people across 9 areas
Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no All 33 dependent symbols, grouped by areaGraph Freshness — 12 symbols in 7 files
Code Review Pipeline — 10 symbols in 6 files
CLI Entry Point — 5 symbols in 2 files
MCP Tool Integration — 2 symbols in 1 file
Viewer Build Script — 1 symbol in 1 file
Build Context — 1 symbol in 1 file
LSP Graph Enrichment — 1 symbol in 1 file
Synchronous Execution — 1 symbol in 1 file
Test signal per changed area — 1 ✓Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.
38 test suites also reference this code49 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.
Open the interactive graph → — click an area to see its dependent symbols at file:line. |
Tier-1 graph extraction for Rust via tree-sitter-rust 0.24.0 (the tree-sitter org's own grammar), rebased onto current
mainas a depth-tier language —.rsleaves the generic tags.scm registry (mirroring PHP's move in #157) rather than stacking on #58/#40, so this PR merges independently.What
interface), type aliases, unions, methods with impl-block owners (generics-stripped:impl Cache<T>owns asCache),macro_rules!in its own!namespace, and module/constant nodes (modmints a module node,const/staticmint constants — the initializer is the body, never the signature). Inline modules contribute scope segments (file.rs#imp.open), so cfg-gated sibling mods stay distinct and resolvable.pub/pub(crate)/pub(super)→ exported;pub(self)and plain items → not; trait-impl methods inherit the trait contract (exported);#[macro_export]macros exported; everything inside#[cfg(test)]mods unexported (#[cfg(not(test))]is correctly NOT matched), and function-body nesting cannot launder apubinto an export.let, constructor-letT::new(), typed params,self→ enclosing impl),Type::method/Self::methodstatic calls, turbofish unwrapped, tuple-index calls guarded. Scoped calls (crate::worker::run()) resolve through the module tree and are restricted to the resolved file's candidates — never stripped to a bare name.!(log_it!), so a macro can never wire to a same-named function (Rust's namespaces are distinct). Std/prelude macros are skipped at extraction; path-qualified forms (std::println!) are recognized too.usepaths (all forms: scoped, grouped per-leaf, renames, wildcards) andmoddeclarations resolve through the real module tree —crate::/super::/self::, bothx.rsandx/mod.rslayouts, the parser-file rule (src/parser.rs's children live insrc/parser/), inline-modsuperconsumption (ause super::*inside#[cfg(test)] mod testscorrectly refers to its own file), and integration-test crate roots (tests/*.rsanchorcrate::to themselves, not the library).Cargo.toml's[package]name (section-aware parse;[[bin]]names ignored) maps cross-crate imports (foo_bar::…↔crates/foo-bar/), including dependency{ package = "…" }aliases; duplicate package names are treated as ambiguous and dropped rather than guessed, and crate matching is deterministic regardless of enumeration order.From<A>/From<B>both givingFrame.from;Display/Debugboth givingfmt) drops the member call as ambiguous instead of guessing first-in-file. Drop-don't-guess throughout, matchingmapclusters one entry per file instead of per directory #35's resolution philosophy.Evidence
.rstests updated to the depth-tier contract rather than deleted where they guard build/check agreement.tsc --noEmitclean;git diff --checkclean.overridespin (tree-sitter: $tree-sitter), verified loading on the repo's tree-sitter runtime — 0.24.0 also parses&raw const/&raw mutnatively, closing the parse gap 0.23 had.Known limitations (deliberate; all fail toward dropped edges, never wrong ones)
assert_eq!(compute(), 3)contributes nocomputecall edge (no expansion).<T as Tr>::method()) drop.#[path = "…"]mod declarations drop (resolving conventionally would wire the wrong file).impl Trait for Typeheritage is dropped (trait-default-method resolution needs the type defined in the same file).implblocks inside function bodies mint unowned functions.tests/don't anchorcrate::(statically ambiguous — each test binary is its own crate).pub usere-export chains and proc-macro expansion are unsupported.