use crate::graph::DependencyGraph;
use crate::imports::ModuleOrigin;
use anyhow::Result;
use indicatif::{ProgressBar, ProgressStyle};
#[derive(Debug)]
pub struct InstabilityAnalysisResult {
pub instability_modules: Vec<(String, f64)>,
}
pub fn analyze_instability(graph: &DependencyGraph) -> Result<InstabilityAnalysisResult> {
let mut instability_modules = Vec::new();
let internal_modules: Vec<_> = graph
.all_modules()
.filter(|module| module.origin == ModuleOrigin::Internal)
.collect();
if internal_modules.is_empty() {
return Ok(InstabilityAnalysisResult {
instability_modules,
});
}
let pb = ProgressBar::new(internal_modules.len() as u64);
pb.set_style(
ProgressStyle::default_bar()
.template(
"{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg}",
)
.map_err(|e| anyhow::anyhow!("Failed to set progress bar style: {}", e))?
.progress_chars("##-"),
);
pb.set_message("Analyzing instability metrics");
for module in internal_modules {
pb.set_message(format!("Analyzing {}", module.canonical_path));
let dependents = graph.get_dependents(module)?;
let ca = dependents.len();
let dependencies = graph.get_dependencies(module)?;
let ce = dependencies.len();
let instability = if ca + ce == 0 {
0.0
} else {
ce as f64 / (ca + ce) as f64
};
instability_modules.push((module.canonical_path.clone(), instability));
pb.inc(1);
}
pb.finish_with_message("Instability analysis complete");
instability_modules.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
Ok(InstabilityAnalysisResult {
instability_modules,
})
}
pub mod formatters {
use super::InstabilityAnalysisResult;
pub fn format_text(result: &InstabilityAnalysisResult) -> String {
if result.instability_modules.is_empty() {
return "No modules found.\n".to_string();
}
let mut output = String::from("High-instability modules (most unstable first):\n");
for (module, instability) in &result.instability_modules {
output.push_str(&format!(" {} (instability: {:.3})\n", module, instability));
}
output.push_str(&format!(
"\nTotal: {} modules found\n",
result.instability_modules.len()
));
output
}
}