pub struct ModuleGraph {
pub modules: Vec<ModuleNode>,
pub package_usage: HashMap<String, Vec<FileId>, FxBuildHasher>,
pub type_only_package_usage: HashMap<String, Vec<FileId>, FxBuildHasher>,
pub entry_points: HashSet<FileId, FxBuildHasher>,
pub runtime_entry_points: HashSet<FileId, FxBuildHasher>,
pub test_entry_points: HashSet<FileId, FxBuildHasher>,
pub reverse_deps: Vec<Vec<FileId>>,
pub re_export_cycles: Vec<GraphReExportCycle>,
/* private fields */
}Expand description
The core module dependency graph.
Derives serde so the whole graph can be persisted to .fallow/graph-cache.bin
(see crate::cache) and skipped on a re-run whose inputs are byte-identical.
namespace_imported is a derived FixedBitSet reconstructed from the edge
set on cache load (reconstruct_namespace_imported), so it is
#[serde(skip, default)] rather than persisted.
Fields§
§modules: Vec<ModuleNode>All modules indexed by FileId.
Invariant: modules[file_id.0 as usize].file_id == file_id for every
FileId in the graph. Holds because discover/walk.rs assigns FileIds
sequentially via .enumerate() after path-sorting, and
build::populate_edges pushes one ModuleNode per file in iteration
order. Detectors rely on this for O(1) FileId-to-module lookup
(graph.modules.get(file_id.0 as usize)) instead of building a
per-call FxHashMap<FileId, &ModuleNode>.
package_usage: HashMap<String, Vec<FileId>, FxBuildHasher>Maps npm package names to the set of FileIds that import them.
type_only_package_usage: HashMap<String, Vec<FileId>, FxBuildHasher>Maps npm package names to the set of FileIds that import them with type-only imports.
A package appearing here but not in package_usage (or only in both) indicates
it’s only used for types and could be a devDependency.
entry_points: HashSet<FileId, FxBuildHasher>All entry point FileIds.
runtime_entry_points: HashSet<FileId, FxBuildHasher>Runtime/application entry point FileIds.
test_entry_points: HashSet<FileId, FxBuildHasher>Test entry point FileIds.
reverse_deps: Vec<Vec<FileId>>Reverse index: for each FileId, which files import it.
re_export_cycles: Vec<GraphReExportCycle>Re-export cycles and self-loops detected during Phase 4 chain
resolution. Each entry names the participating files (sorted
lexicographically) and a is_self_loop flag distinguishing
single-file self-re-exports from multi-node cycles. Populated by
re_exports::find_re_export_cycles and consumed by
fallow_core::analyze::re_export_cycles::find_re_export_cycles which
wraps each entry in a typed ReExportCycleFinding.
Implementations§
Source§impl ModuleGraph
impl ModuleGraph
Sourcepub fn find_cycles(&self) -> Vec<Vec<FileId>>
pub fn find_cycles(&self) -> Vec<Vec<FileId>>
Find all circular dependency cycles in the module graph.
Uses an iterative implementation of Tarjan’s strongly connected components algorithm (O(V + E)) to find all SCCs with 2 or more nodes. Each such SCC represents a set of files involved in a circular dependency.
Returns cycles sorted by length (shortest first), with files within each cycle sorted by path for deterministic output.
§Panics
Panics if the internal file-to-path lookup is inconsistent with the module list.
Source§impl ModuleGraph
impl ModuleGraph
Sourcepub fn focus_file_facts(&self, changed: &[FileId]) -> Vec<FocusFileFacts>
pub fn focus_file_facts(&self, changed: &[FileId]) -> Vec<FocusFileFacts>
Compute the per-file focus graph facts (fan-in/out + the two confidence-flag signals) for a changed-file seed set.
Out-of-range or duplicate ids in changed are tolerated (dropped /
deduped). Each fact is keyed by the changed file’s FileId; the caller
relativizes via ModuleGraph::focus_facts_with_paths for serialization.
Sourcepub fn focus_facts_with_paths(
&self,
facts: &[FocusFileFacts],
root: &Path,
) -> Vec<FocusFileFactsPaths>
pub fn focus_facts_with_paths( &self, facts: &[FocusFileFacts], root: &Path, ) -> Vec<FocusFileFactsPaths>
Resolve a FocusFileFacts set’s FileIds to root-relative, forward-
slashed paths, sorted for deterministic output. Files whose module is
missing are dropped.
Source§impl ModuleGraph
impl ModuleGraph
Sourcepub fn impact_closure(&self, changed: &[FileId]) -> ImpactClosure
pub fn impact_closure(&self, changed: &[FileId]) -> ImpactClosure
Compute the impact closure for a changed-file seed set.
BFS over reverse_deps from every changed file yields the transitive
affected set; the seed partitions into in_diff, the rest into
affected_not_shown. The coordination gap walks each changed file’s
exported-symbol references and reports those whose consumer is outside the
diff (rule R2: one entry per distinct consumer module).
changed is a slice of FileIds; out-of-range or duplicate ids are
tolerated. Type-only re-export edges are skipped for the gap evidence so a
import type-only consumer (erased at build, no runtime contract) does not
fire.
Sourcepub fn closure_with_paths(
&self,
closure: &ImpactClosure,
root: &Path,
) -> ImpactClosurePaths
pub fn closure_with_paths( &self, closure: &ImpactClosure, root: &Path, ) -> ImpactClosurePaths
Resolve a closure’s FileIds to root-relative, forward-slashed paths,
sorted for deterministic output. Files whose module is missing are dropped.
Source§impl ModuleGraph
impl ModuleGraph
Sourcepub fn partition_order(&self, changed: &[FileId]) -> PartitionOrder
pub fn partition_order(&self, changed: &[FileId]) -> PartitionOrder
Compute the by-module partition and dependency-sensible order for a changed-file seed set.
Out-of-range or duplicate ids in changed are tolerated (dropped /
deduped). The partition groups each changed file by its parent directory;
the order is a deterministic topological sort over the inter-unit DAG
(definitions before consumers, ties broken by the module_dir sort).
Sourcepub fn partition_order_with_paths(
&self,
partition: &PartitionOrder,
root: &Path,
) -> PartitionOrderPaths
pub fn partition_order_with_paths( &self, partition: &PartitionOrder, root: &Path, ) -> PartitionOrderPaths
Resolve a partition + order’s FileIds to root-relative, forward-slashed
paths, sorted for deterministic output. Files whose module is missing are
dropped; a unit left empty after that drop is omitted. The module_dir
keys (and the order entries, which are module_dir strings) are
root-relativized too so the whole shape is root-relative.
Source§impl ModuleGraph
impl ModuleGraph
Sourcepub fn public_export_keys(
&self,
public_api_entry_points: &HashSet<FileId, FxBuildHasher>,
root: &Path,
) -> HashSet<String, FxBuildHasher>
pub fn public_export_keys( &self, public_api_entry_points: &HashSet<FileId, FxBuildHasher>, root: &Path, ) -> HashSet<String, FxBuildHasher>
Compute the set of public-export keys reachable through the given
public_api_entry_points (an exports-aware set; see module docs).
Keys are "<root-relative forward-slashed path>::<export name>".
Type-only exports are skipped: a type erased at build carries no runtime
contract, so it never widens the public value surface that 6.A tracks.
Source§impl ModuleGraph
impl ModuleGraph
Sourcepub fn build(
resolved_modules: &[ResolvedModule],
entry_points: &[EntryPoint],
files: &[DiscoveredFile],
) -> ModuleGraph
pub fn build( resolved_modules: &[ResolvedModule], entry_points: &[EntryPoint], files: &[DiscoveredFile], ) -> ModuleGraph
Build the module graph from resolved modules and entry points.
Sourcepub fn build_with_reachability_roots(
resolved_modules: &[ResolvedModule],
entry_points: &[EntryPoint],
runtime_entry_points: &[EntryPoint],
test_entry_points: &[EntryPoint],
files: &[DiscoveredFile],
) -> ModuleGraph
pub fn build_with_reachability_roots( resolved_modules: &[ResolvedModule], entry_points: &[EntryPoint], runtime_entry_points: &[EntryPoint], test_entry_points: &[EntryPoint], files: &[DiscoveredFile], ) -> ModuleGraph
Build the module graph with explicit runtime and test reachability roots.
Sourcepub const fn module_count(&self) -> usize
pub const fn module_count(&self) -> usize
Total number of modules.
Sourcepub const fn edge_count(&self) -> usize
pub const fn edge_count(&self) -> usize
Total number of edges.
Sourcepub fn has_namespace_import(&self, file_id: FileId) -> bool
pub fn has_namespace_import(&self, file_id: FileId) -> bool
Check if any importer uses import * as ns for this module.
Uses precomputed bitset, O(1) lookup.
Sourcepub fn edges_for(&self, file_id: FileId) -> Vec<FileId>
pub fn edges_for(&self, file_id: FileId) -> Vec<FileId>
Get the target FileIds of all outgoing edges for a module.
Sourcepub fn outgoing_symbol_edges(
&self,
file_id: FileId,
) -> impl Iterator<Item = (FileId, &[ImportedSymbol])>
pub fn outgoing_symbol_edges( &self, file_id: FileId, ) -> impl Iterator<Item = (FileId, &[ImportedSymbol])>
Iterate the outgoing edges of file_id with full per-symbol data.
fallow trace needs the raw ImportedSymbol set on each edge in
both directions, which the flattened summary structs cannot express.
Returns an empty iterator for out-of-range file ids.
Sourcepub fn importers_of(&self, target: FileId) -> &[FileId]
pub fn importers_of(&self, target: FileId) -> &[FileId]
The importer FileIds that directly import target (reverse-dep view).
Returns an empty slice when target is out of range.
Sourcepub fn direct_importer_summaries(
&self,
target: FileId,
) -> Vec<DirectImporterSummary>
pub fn direct_importer_summaries( &self, target: FileId, ) -> Vec<DirectImporterSummary>
Summarize files that directly import target.
Uses existing reverse dependency and edge indexes. Returns an empty list when the target is out of range or has no importers.
Sourcepub fn find_import_span_start(
&self,
source: FileId,
target: FileId,
) -> Option<u32>
pub fn find_import_span_start( &self, source: FileId, target: FileId, ) -> Option<u32>
Find the byte offset of the import statement from source to target.
Mixed type/value imports to the same target are stored as one edge. Prefer
the first value-carrying import so runtime-cycle diagnostics and line
suppressions anchor on the import that actually participates in the cycle.
Returns None if no edge exists or the edge has no symbols.
Sourcepub fn outgoing_edge_summaries(
&self,
file_id: FileId,
) -> impl Iterator<Item = (FileId, bool, Option<u32>)>
pub fn outgoing_edge_summaries( &self, file_id: FileId, ) -> impl Iterator<Item = (FileId, bool, Option<u32>)>
Iterate outgoing edges with the data the boundary detector needs in a single pass: target file id, whether every symbol on the edge is type-only (matches the predicate used by cycle detection), and the span start of the first value-carrying symbol (or the first symbol when every symbol is type-only).
When featureB has both import type { Foo } from './x' and
import { bar } from './x', fallow groups them into ONE edge with the
type-only symbol first and the value symbol second. Consumers need the
value span so findings anchor on the runtime import line; otherwise a
// fallow-ignore-next-line above the type-only line would silently
suppress the real violation.
Returns an empty iterator for out-of-range file ids.
Sourcepub fn outgoing_edge_summaries_with_exclusions<'a>(
&'a self,
file_id: FileId,
excluded_span_starts: &'a HashSet<u32, FxBuildHasher>,
) -> impl Iterator<Item = (FileId, bool, Option<u32>, bool)> + 'a
pub fn outgoing_edge_summaries_with_exclusions<'a>( &'a self, file_id: FileId, excluded_span_starts: &'a HashSet<u32, FxBuildHasher>, ) -> impl Iterator<Item = (FileId, bool, Option<u32>, bool)> + 'a
Like Self::outgoing_edge_summaries but additionally reports, as a
fourth boolean, whether EVERY non-type-only symbol on the edge has an
import_span start in excluded_span_starts (all_client_only). The
security client-server-leak BFS passes the next/dynamic ssr:false
dynamic-import span starts so it can skip an edge reached ONLY through the
client-only escape hatch. An edge with no non-type-only symbols, or with at
least one non-type-only symbol whose span is not excluded, reports false
(so a target also reached via a real static import stays in the cone).
Returns an empty iterator for out-of-range file ids.
Trait Implementations§
Source§impl Debug for ModuleGraph
impl Debug for ModuleGraph
Source§impl<'de> Deserialize<'de> for ModuleGraph
impl<'de> Deserialize<'de> for ModuleGraph
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<ModuleGraph, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<ModuleGraph, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for ModuleGraph
impl Serialize for ModuleGraph
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for ModuleGraph
impl RefUnwindSafe for ModuleGraph
impl Send for ModuleGraph
impl Sync for ModuleGraph
impl Unpin for ModuleGraph
impl UnsafeUnpin for ModuleGraph
impl UnwindSafe for ModuleGraph
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more