#[derive(Debug, Clone)]
pub struct SdpViolation {
pub from_module: String,
pub to_module: String,
pub from_instability: f64,
pub to_instability: f64,
pub suppressed: bool,
}
pub(super) fn check_sdp(
graph: &super::ModuleGraph,
metrics: &[super::CouplingMetrics],
) -> Vec<SdpViolation> {
let instability: std::collections::HashMap<&str, f64> = metrics
.iter()
.map(|m| (m.module_name.as_str(), m.instability))
.collect();
let suppressed_modules: std::collections::HashSet<&str> = metrics
.iter()
.filter(|m| m.suppressed)
.map(|m| m.module_name.as_str())
.collect();
let mut violations = Vec::new();
for (from_idx, deps) in graph.forward.iter().enumerate() {
let from_name = &graph.modules[from_idx];
let Some(from_inst) = instability.get(from_name.as_str()).copied() else {
continue;
};
for &to_idx in deps {
let to_name = &graph.modules[to_idx];
let Some(to_inst) = instability.get(to_name.as_str()).copied() else {
continue;
};
if from_inst < to_inst {
let suppressed = suppressed_modules.contains(from_name.as_str())
|| suppressed_modules.contains(to_name.as_str());
violations.push(SdpViolation {
from_module: from_name.clone(),
to_module: to_name.clone(),
from_instability: from_inst,
to_instability: to_inst,
suppressed,
});
}
}
}
violations
}