fn format_satd_json(
items: &[crate::services::satd_detector::TechnicalDebt],
metrics: bool,
evolution: bool,
) -> String {
let mut json_obj = serde_json::Map::new();
json_obj.insert(
"total_items".to_string(),
serde_json::Value::Number(items.len().into()),
);
json_obj.insert(
"items".to_string(),
serde_json::to_value(items).unwrap_or_default(),
);
if metrics {
let severity_counts: std::collections::HashMap<String, usize> =
items
.iter()
.fold(std::collections::HashMap::new(), |mut acc, item| {
let sev_str = format!("{:?}", item.severity);
*acc.entry(sev_str).or_insert(0) += 1;
acc
});
json_obj.insert(
"metrics".to_string(),
serde_json::to_value(severity_counts).unwrap_or_default(),
);
}
if evolution {
json_obj.insert(
"evolution".to_string(),
serde_json::Value::String("Evolution data would be included".to_string()),
);
}
serde_json::to_string_pretty(&json_obj).unwrap_or_default()
}
fn format_satd_sarif(items: &[crate::services::satd_detector::TechnicalDebt]) -> String {
let mut sarif = serde_json::json!({
"version": "2.1.0",
"runs": [{
"tool": {
"driver": {
"name": "pmat-satd",
"version": "0.29.0"
}
},
"results": []
}]
});
let results = items
.iter()
.map(|item| {
serde_json::json!({
"ruleId": format!("{:?}", item.category),
"level": match item.severity {
crate::services::satd_detector::Severity::Critical => "error",
crate::services::satd_detector::Severity::High => "error",
crate::services::satd_detector::Severity::Medium => "warning",
crate::services::satd_detector::Severity::Low => "note"
},
"message": {
"text": item.text
},
"locations": [{
"physicalLocation": {
"artifactLocation": {
"uri": item.file.to_string_lossy()
},
"region": {
"startLine": item.line
}
}
}]
})
})
.collect::<Vec<_>>();
sarif["runs"][0]["results"] = serde_json::Value::Array(results);
serde_json::to_string_pretty(&sarif).unwrap_or_default()
}
fn format_satd_markdown(
items: &[crate::services::satd_detector::TechnicalDebt],
evolution: bool,
days: u32,
) -> String {
let mut output = String::from("# SATD Analysis Report\n\n");
if items.is_empty() {
output.push_str("✅ **No SATD items found.** Excellent technical debt management!\n");
return output;
}
output.push_str(&format!("📊 **Total SATD items:** {}\n\n", items.len()));
output.push_str("## Items by Severity\n\n");
let mut severity_groups = std::collections::HashMap::new();
for item in items {
severity_groups
.entry(format!("{:?}", item.severity))
.or_insert_with(Vec::new)
.push(item);
}
for (severity, group_items) in severity_groups {
output.push_str(&format!(
"### {} ({} items)\n\n",
severity,
group_items.len()
));
for item in group_items {
let category_str = format!("{:?}", item.category);
output.push_str(&format!(
"- **{}** (line {}): {} - _{}_\n",
item.file.file_name().unwrap_or_default().to_string_lossy(),
item.line,
category_str,
item.text
));
}
output.push('\n');
}
if evolution {
output.push_str(&format!(
"## Evolution Analysis\n\nEvolution tracking over {days} days would be displayed here.\n"
));
}
output
}
fn format_satd_summary(items: &[crate::services::satd_detector::TechnicalDebt]) -> String {
if items.is_empty() {
return "✅ No SATD items found. Excellent technical debt management!\n".to_string();
}
let mut severity_counts = std::collections::HashMap::new();
let mut type_counts = std::collections::HashMap::new();
for item in items {
let sev_str = format!("{:?}", item.severity);
let cat_str = format!("{:?}", item.category);
*severity_counts.entry(sev_str).or_insert(0) += 1;
*type_counts.entry(cat_str).or_insert(0) += 1;
}
let mut output = format!("📊 SATD Summary: {} total items\n\n", items.len());
output.push_str("By Severity:\n");
for (severity, count) in severity_counts {
output.push_str(&format!(" {severity}: {count}\n"));
}
output.push_str("\nBy Type:\n");
for (debt_type, count) in type_counts {
output.push_str(&format!(" {debt_type}: {count}\n"));
}
output
}
fn print_satd_metrics(items: &[crate::services::satd_detector::TechnicalDebt]) {
eprintln!("\n📈 SATD Metrics:");
eprintln!(" Total items: {}", items.len());
let high_severity_count = items
.iter()
.filter(|item| {
matches!(
item.severity,
crate::services::satd_detector::Severity::High
)
})
.count();
eprintln!(" High severity: {high_severity_count}");
let files_with_satd: std::collections::HashSet<_> =
items.iter().map(|item| &item.file).collect();
eprintln!(" Files affected: {}", files_with_satd.len());
}