use crate::organization::anti_pattern_detector::{
AntiPattern, AntiPatternSeverity, AntiPatternType,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AntiPatternOutput {
pub quality_score: f64,
pub patterns: Vec<AntiPatternItem>,
pub summary: AntiPatternSummary,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AntiPatternItem {
pub pattern_type: AntiPatternType,
pub severity: AntiPatternSeverity,
pub location: String,
pub description: String,
pub recommendation: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub affected_methods: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AntiPatternSummary {
pub critical: usize,
pub high: usize,
pub medium: usize,
pub low: usize,
}
impl From<&AntiPattern> for AntiPatternItem {
fn from(pattern: &AntiPattern) -> Self {
Self {
pattern_type: pattern.pattern_type.clone(),
severity: pattern.severity.clone(),
location: pattern.location.clone(),
description: pattern.description.clone(),
recommendation: pattern.correction.clone(),
affected_methods: pattern.affected_methods.clone(),
}
}
}
pub fn build_anti_patterns(
metrics: &crate::priority::FileDebtMetrics,
) -> Option<AntiPatternOutput> {
let report = metrics
.god_object_analysis
.as_ref()
.and_then(|a| a.anti_pattern_report.as_ref())?;
let patterns: Vec<AntiPatternItem> = report.anti_patterns.iter().map(|p| p.into()).collect();
let mut summary = AntiPatternSummary::default();
for pattern in &report.anti_patterns {
match pattern.severity {
AntiPatternSeverity::Critical => summary.critical += 1,
AntiPatternSeverity::High => summary.high += 1,
AntiPatternSeverity::Medium => summary.medium += 1,
AntiPatternSeverity::Low => summary.low += 1,
}
}
if patterns.is_empty() && summary.critical == 0 && summary.high == 0 {
return None;
}
Some(AntiPatternOutput {
quality_score: report.quality_score,
patterns,
summary,
})
}