1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// refs/impact query support: enum-member union, `impact_walk`, and
// personalized PageRank. A `tests` block below pins the behavioral contract
// with fixture cases exercising every code path.
//
// Design notes:
//
// - **Two-phase index build.** The index cannot be built in one call that
// also reads the graph and then hands back a struct borrowing that graph
// -- the result would be self-referential. So the caller reads the graph
// first with `graph::read_graph(root)`, which returns `None` when there is
// no graph, letting the caller check the `Option` before proceeding, then
// calls `load_graph_index(&graph, root)` here, which owns the manifest
// join and the index build.
//
// - **Manifest corrupt-JSON fail-open.** A corrupt manifest.json surfaces as
// `Err(ManifestError::InvalidJson)` from `manifest::read_manifest`.
// Panicking through a query path for an operator-error edge case (a
// hand-corrupted manifest) is worse than failing open, so
// `load_graph_index` treats `Err(_)` the same as "no manifest" -- the same
// fail-open-on-parse-error convention `graph::read_graph` follows. A
// manifest present but missing its `entries` key is handled the same way.
//
// - **Insertion-order-preserving scratch structures.** Several of
// `impact_walk`'s scratch maps/sets are NOT just membership/lookup
// structures -- their insertion order is directly observable in the final
// result: `Hit::symbols` feeds `top_symbols`'s first-3 truncation, and
// `visited` key order feeds the `nodes` array handed to
// `personalized_page_rank`, whose accumulation loop is float-addition over
// that exact order -- not associative, so a different iteration order can
// produce a bit-different (though not wrong) result.
// `std::collections::{HashMap,HashSet}` make no iteration-order guarantee,
// so this module has two tiny private order-preserving helpers,
// `SeqSet`/`SeqMap` (a `Vec` plus an index `HashMap`, first insertion wins
// the slot). They are pure algorithm scratch state, not artifact structs;
// `graph::Def`/`Edge`/`Graph` are reused directly from `graph.rs`.
//
// - **`str::cmp` ordering.** Location sorts use plain Unicode-codepoint
// `str::cmp` rather than locale-aware collation, the same accepted
// trade-off documented at `resolve.rs`'s `capped_candidates`: the two
// orderings coincide for every path/id shape this crate actually produces,
// and diverge only in a pathological mix of leading case or a
// `+`/`.`-adjacent tie -- flagged, not solved, no new ICU dependency.
//
// - **Result models.** `RefsModel`/`ImpactModel` (and their row/table
// sub-types) are the typed surface `render.rs` consumes. Field names are
// `snake_case` (e.g. `model.inbound.uses_type`). Nothing here is
// `Serialize` -- `--json` output byte-shape is `cli.rs`'s job, not this
// module's.
//
// Split by verb, plus the shared substrate the verbs sit on: `seq` (the
// order-preserving scratch structures), `index` (`GraphIndex` and its
// loading, plus `def_files`/`def_sites`/`symbol_refs`), `symbol`
// (`resolve_symbol`'s ladder), and `rank` (personalized PageRank). The verbs
// themselves: `find`, `refs`/`refs_tables` (the row/table shaping `read`
// reuses), `read`, `coverage` (test coverage for a symbol -- named to avoid
// colliding with this module's own `tests`), and `impact` (plus `infra`, the
// hub-file name-pattern classification `impact` widens against). `dispatch`
// holds the `implements`/`overrides` plumbing `index.rs` and `refs.rs` both
// call into (index-build-time adjacency, the bare-member fallback's
// exact-match half) -- split out to keep those two files under this crate's
// per-file line budget, not a verb of its own. `occurrence` is the same
// kind of split: a query-time-only helper that tags two otherwise-identical
// rows of one inbound/outbound table with a stable position, called from
// `refs.rs` after ranking/capping and never touching the graph it reads.
// Every public item keeps the path it had before the split via the
// `pub use`s below.
// `--json` rendering of every query model, moved here from `cli.rs` to keep
// that file under its size ratchet; `pub(crate)` so `cli.rs` can still call
// it as `query::json::...`.
pub
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Why;