use crate::priority::classification::{CoverageLevel, Severity};
use colored::Color;
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq)]
pub struct FormattedPriorityItem {
pub rank: usize,
pub score: f64,
pub severity: Severity,
pub sections: Vec<FormattedSection>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum FormattedSection {
Header {
rank: usize,
score: f64,
coverage_tag: Option<CoverageTag>,
severity: SeverityInfo,
},
Location {
file: PathBuf,
line: u32,
function: String,
},
ContextDampening {
description: String,
dampening_percentage: i32,
},
Action { action: String },
Impact {
complexity_reduction: u32,
risk_reduction: f64,
},
Evidence { text: String },
Complexity {
cyclomatic: u32,
cognitive: u32,
nesting: u32,
entropy: Option<f64>,
},
Pattern {
pattern_type: String,
icon: String,
metrics: Vec<(String, String)>,
confidence: f64,
},
Coverage {
percentage: f64,
level: CoverageLevel,
details: Option<String>,
},
Dependencies {
upstream: usize,
downstream: usize,
callers: Vec<String>,
callees: Vec<String>,
},
DebtSpecific { text: String },
ContextualRisk {
base_risk: f64,
contextual_risk: f64,
multiplier: f64,
providers: Vec<ContextProviderInfo>,
},
Rationale { text: String },
}
#[derive(Debug, Clone, PartialEq)]
pub struct CoverageTag {
pub text: String,
pub color: Color,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SeverityInfo {
pub label: String,
pub color: Color,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ContextProviderInfo {
pub name: String,
pub contribution: f64,
pub weight: f64,
pub impact: f64,
pub details: Option<String>,
}
impl FormattedPriorityItem {
pub fn new(rank: usize, score: f64, severity: Severity) -> Self {
Self {
rank,
score,
severity,
sections: Vec::new(),
}
}
pub fn with_section(mut self, section: FormattedSection) -> Self {
self.sections.push(section);
self
}
pub fn with_sections(mut self, sections: Vec<FormattedSection>) -> Self {
self.sections.extend(sections);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn formatted_item_builder() {
let item = FormattedPriorityItem::new(1, 8.5, Severity::Critical)
.with_section(FormattedSection::Location {
file: PathBuf::from("test.rs"),
line: 10,
function: "test_fn".to_string(),
})
.with_section(FormattedSection::Impact {
complexity_reduction: 5,
risk_reduction: 3.2,
});
assert_eq!(item.rank, 1);
assert_eq!(item.score, 8.5);
assert_eq!(item.severity, Severity::Critical);
assert_eq!(item.sections.len(), 2);
}
#[test]
fn coverage_tag_equality() {
let tag1 = CoverageTag {
text: "[ERROR UNTESTED]".to_string(),
color: Color::Red,
};
let tag2 = CoverageTag {
text: "[ERROR UNTESTED]".to_string(),
color: Color::Red,
};
assert_eq!(tag1, tag2);
}
#[test]
fn severity_info_equality() {
let sev1 = SeverityInfo {
label: "CRITICAL".to_string(),
color: Color::Red,
};
let sev2 = SeverityInfo {
label: "CRITICAL".to_string(),
color: Color::Red,
};
assert_eq!(sev1, sev2);
}
}