1pub mod betweenness;
2pub mod bridges;
3pub mod change_propagation;
4pub mod connected_components;
5pub mod degree;
6pub mod depth;
7pub mod graph_boundaries;
8pub mod graph_stats;
9pub mod impact_radius;
10pub mod pagerank;
11pub mod scc;
12pub mod transitive_reduction;
13
14use crate::config::Config;
15use crate::graph::Graph;
16use crate::lockfile::Lockfile;
17use std::path::Path;
18
19pub struct AnalysisContext<'a> {
22 pub graph: &'a Graph,
23 pub root: &'a Path,
24 pub config: &'a Config,
25 pub lockfile: Option<&'a Lockfile>,
26}
27
28pub fn all_analysis_names() -> &'static [&'static str] {
30 &[
31 "betweenness",
32 "bridges",
33 "change-propagation",
34 "connected-components",
35 "degree",
36 "depth",
37 "graph-boundaries",
38 "graph-stats",
39 "impact-radius",
40 "pagerank",
41 "scc",
42 "transitive-reduction",
43 ]
44}
45
46pub trait Analysis {
51 type Output: serde::Serialize;
52
53 fn name(&self) -> &str;
54
55 fn run(&self, ctx: &AnalysisContext) -> Self::Output;
56}
57
58pub struct EnrichedGraph {
61 pub graph: Graph,
62 pub betweenness: betweenness::BetweennessResult,
63 pub bridges: bridges::BridgesResult,
64 pub change_propagation: change_propagation::ChangePropagationResult,
65 pub connected_components: connected_components::ConnectedComponentsResult,
66 pub degree: degree::DegreeResult,
67 pub depth: depth::DepthResult,
68 pub graph_boundaries: graph_boundaries::GraphBoundariesResult,
69 pub graph_stats: graph_stats::GraphStatsResult,
70 pub impact_radius: impact_radius::ImpactRadiusResult,
71 pub pagerank: pagerank::PageRankResult,
72 pub scc: scc::SccResult,
73 pub transitive_reduction: transitive_reduction::TransitiveReductionResult,
74}
75
76pub fn enrich(
78 root: &Path,
79 config: &Config,
80 lockfile: Option<&Lockfile>,
81) -> anyhow::Result<EnrichedGraph> {
82 let graph = crate::graph::build_graph(root, config)?;
83 Ok(enrich_graph(graph, root, config, lockfile))
84}
85
86pub fn enrich_graph(
88 graph: Graph,
89 root: &Path,
90 config: &Config,
91 lockfile: Option<&Lockfile>,
92) -> EnrichedGraph {
93 let ctx = AnalysisContext {
94 graph: &graph,
95 root,
96 config,
97 lockfile,
98 };
99
100 let betweenness = betweenness::Betweenness.run(&ctx);
101 let bridges = bridges::Bridges.run(&ctx);
102 let change_propagation = change_propagation::ChangePropagation.run(&ctx);
103 let connected_components = connected_components::ConnectedComponents.run(&ctx);
104 let degree = degree::Degree.run(&ctx);
105 let depth = depth::Depth.run(&ctx);
106 let graph_boundaries = graph_boundaries::GraphBoundaries.run(&ctx);
107 let graph_stats = graph_stats::GraphStats.run(&ctx);
108 let impact_radius = impact_radius::ImpactRadius.run(&ctx);
109 let pagerank = pagerank::PageRank.run(&ctx);
110 let scc = scc::StronglyConnectedComponents.run(&ctx);
111 let transitive_reduction = transitive_reduction::TransitiveReduction.run(&ctx);
112
113 EnrichedGraph {
114 graph,
115 betweenness,
116 bridges,
117 change_propagation,
118 connected_components,
119 degree,
120 depth,
121 graph_boundaries,
122 graph_stats,
123 impact_radius,
124 pagerank,
125 scc,
126 transitive_reduction,
127 }
128}