fob_graph/analysis/
result.rs1use std::fmt;
2
3use crate::{
4 ExternalDependency, GraphStatistics, ModuleGraph, ModuleId, UnusedExport,
5 dependency_chain::DependencyChain, symbol::SymbolStatistics,
6};
7
8#[derive(Debug)]
9pub struct AnalysisResult {
10 pub graph: ModuleGraph,
11 pub entry_points: Vec<ModuleId>,
12 pub warnings: Vec<String>,
13 pub errors: Vec<String>,
14 pub stats: GraphStatistics,
15 pub symbol_stats: SymbolStatistics,
17}
18
19impl AnalysisResult {
20 pub fn unused_exports(&self) -> crate::Result<Vec<UnusedExport>> {
22 self.graph.unused_exports()
23 }
24
25 pub fn external_dependencies(&self) -> crate::Result<Vec<ExternalDependency>> {
27 self.graph.external_dependencies()
28 }
29
30 pub fn is_ok(&self) -> bool {
32 self.errors.is_empty()
33 }
34
35 pub fn has_warnings(&self) -> bool {
37 !self.warnings.is_empty()
38 }
39
40 pub fn dependency_chains_to(&self, target: &ModuleId) -> crate::Result<Vec<DependencyChain>> {
44 self.graph.dependency_chains_to(target)
45 }
46
47 pub fn find_circular_dependencies(&self) -> crate::Result<Vec<DependencyChain>> {
51 let modules = self.graph.modules()?;
52 let mut circular = Vec::new();
53
54 for module in modules {
55 let chains = self.graph.dependency_chains_to(&module.id)?;
56 for chain in chains {
57 if chain.has_cycle() {
58 circular.push(chain);
59 }
60 }
61 }
62
63 Ok(circular)
64 }
65}
66
67impl fmt::Display for AnalysisResult {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 writeln!(f, "Analysis Result")?;
70 writeln!(f, "================")?;
71 writeln!(f, "Entry points: {}", self.entry_points.len())?;
72
73 if let Ok(modules) = self.graph.modules() {
74 writeln!(f, "Total modules: {}", modules.len())?;
75 }
76
77 if let Ok(unused) = self.unused_exports() {
78 writeln!(f, "Unused exports: {}", unused.len())?;
79 }
80
81 if let Ok(external) = self.external_dependencies() {
82 writeln!(f, "External dependencies: {}", external.len())?;
83 }
84
85 writeln!(f, "Warnings: {}", self.warnings.len())?;
86 writeln!(f, "Errors: {}", self.errors.len())?;
87
88 if !self.warnings.is_empty() {
89 writeln!(f, "\nWarnings:")?;
90 for warning in &self.warnings {
91 writeln!(f, " - {}", warning)?;
92 }
93 }
94
95 if !self.errors.is_empty() {
96 writeln!(f, "\nErrors:")?;
97 for error in &self.errors {
98 writeln!(f, " - {}", error)?;
99 }
100 }
101
102 Ok(())
103 }
104}