use super::{
CrossLangReference, DeepContext, DeepContextAnalyzer, DefectHotspot, DefectSummary,
PrioritizedRecommendation, Priority,
};
use crate::models::churn::CodeChurnAnalysis;
use rayon::prelude::*;
use rustc_hash::FxHashMap;
impl DeepContextAnalyzer {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_complexity_hotspots(
&self,
output: &mut String,
context: &DeepContext,
) -> anyhow::Result<()> {
use std::fmt::Write;
if let Some(ref complexity) = context.analyses.complexity_report {
writeln!(output, "## Complexity Hotspots\n")?;
let mut all_functions: Vec<_> = complexity
.files
.par_iter()
.flat_map(|f| f.functions.par_iter().map(move |func| (f, func)))
.collect();
all_functions.sort_by_key(|(_, func)| std::cmp::Reverse(func.metrics.cyclomatic));
writeln!(output, "| Function | File | Cyclomatic | Cognitive |")?;
writeln!(output, "|----------|------|------------|-----------|")?;
for (file, func) in all_functions.iter().take(10) {
writeln!(
output,
"| `{}` | `{}` | {} | {} |",
func.name, file.path, func.metrics.cyclomatic, func.metrics.cognitive
)?;
}
writeln!(output)?;
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_churn_analysis(
&self,
output: &mut String,
context: &DeepContext,
) -> anyhow::Result<()> {
if let Some(ref churn) = context.analyses.churn_analysis {
self.write_churn_header(output)?;
self.write_churn_summary(output, churn)?;
self.write_churn_files_table(output, &churn.files)?;
}
Ok(())
}
fn write_churn_header(&self, output: &mut String) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "## Code Churn Analysis\n")?;
Ok(())
}
fn write_churn_summary(
&self,
output: &mut String,
churn: &CodeChurnAnalysis,
) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "**Summary:**")?;
writeln!(output, "- Total Commits: {}", churn.summary.total_commits)?;
writeln!(output, "- Files Changed: {}", churn.files.len())?;
Ok(())
}
fn write_churn_files_table(
&self,
output: &mut String,
files: &[crate::models::churn::FileChurnMetrics],
) -> anyhow::Result<()> {
use std::fmt::Write;
let mut sorted_files = files.to_vec();
sorted_files.sort_by_key(|f| std::cmp::Reverse(f.commit_count));
writeln!(output, "\n**Top Changed Files:**")?;
writeln!(output, "| File | Commits | Authors |")?;
writeln!(output, "|------|---------|---------|")?;
for file in sorted_files.iter().take(10) {
writeln!(
output,
"| `{}` | {} | {} |",
file.relative_path,
file.commit_count,
file.unique_authors.len()
)?;
}
writeln!(output)?;
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_technical_debt(
&self,
output: &mut String,
context: &DeepContext,
) -> anyhow::Result<()> {
if let Some(ref satd) = context.analyses.satd_results {
use std::fmt::Write;
writeln!(output, "## Code Quality Analysis\n")?;
self.write_satd_severity_summary(output, satd)?;
self.write_critical_items(output, satd)?;
writeln!(output)?;
}
Ok(())
}
fn write_satd_severity_summary(
&self,
output: &mut String,
satd: &crate::services::satd_detector::SATDAnalysisResult,
) -> anyhow::Result<()> {
use std::fmt::Write;
let by_severity = self.group_satd_by_severity(satd);
writeln!(output, "**SATD Summary:**")?;
for (severity, count) in by_severity {
writeln!(output, "- {severity:?}: {count}")?;
}
Ok(())
}
fn group_satd_by_severity<'a>(
&self,
satd: &'a crate::services::satd_detector::SATDAnalysisResult,
) -> FxHashMap<&'a crate::services::satd_detector::Severity, i32> {
let mut by_severity = FxHashMap::default();
for item in &satd.items {
*by_severity.entry(&item.severity).or_insert(0) += 1;
}
by_severity
}
fn write_critical_items(
&self,
output: &mut String,
satd: &crate::services::satd_detector::SATDAnalysisResult,
) -> anyhow::Result<()> {
let critical_items = self.get_critical_satd_items(satd);
if critical_items.is_empty() {
return Ok(());
}
use std::fmt::Write;
writeln!(output, "\n**Critical Items:**")?;
for item in critical_items {
writeln!(
output,
"- `{}:{} {}`: {}",
item.file.display(),
item.line,
item.category,
item.text.trim()
)?;
}
Ok(())
}
fn get_critical_satd_items<'a>(
&self,
satd: &'a crate::services::satd_detector::SATDAnalysisResult,
) -> Vec<&'a crate::services::satd_detector::TechnicalDebt> {
satd.items
.iter()
.filter(|item| {
matches!(
item.severity,
crate::services::satd_detector::Severity::Critical
)
})
.take(5)
.collect()
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_dead_code_analysis(
&self,
output: &mut String,
context: &DeepContext,
) -> anyhow::Result<()> {
if let Some(ref dead_code) = context.analyses.dead_code_results {
self.write_dead_code_header(output)?;
self.write_dead_code_summary(output, &dead_code.summary)?;
self.write_dead_code_files_table(output, &dead_code.ranked_files)?;
}
Ok(())
}
fn write_dead_code_header(&self, output: &mut String) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "## Dead Code Analysis\n")?;
Ok(())
}
fn write_dead_code_summary(
&self,
output: &mut String,
summary: &crate::models::dead_code::DeadCodeSummary,
) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "**Summary:**")?;
writeln!(output, "- Dead Functions: {}", summary.dead_functions)?;
writeln!(output, "- Total Dead Lines: {}", summary.total_dead_lines)?;
Ok(())
}
fn write_dead_code_files_table(
&self,
output: &mut String,
files: &[crate::models::dead_code::FileDeadCodeMetrics],
) -> anyhow::Result<()> {
use std::fmt::Write;
if !files.is_empty() {
writeln!(output, "\n**Top Files with Dead Code:**")?;
writeln!(output, "| File | Dead Lines | Dead Functions |")?;
writeln!(output, "|------|------------|----------------|")?;
for file in files.iter().take(10) {
writeln!(
output,
"| `{}` | {} | {} |",
file.path, file.dead_lines, file.dead_functions
)?;
}
writeln!(output)?;
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_cross_references(
&self,
output: &mut String,
cross_refs: &[CrossLangReference],
) -> anyhow::Result<()> {
use std::fmt::Write;
if !cross_refs.is_empty() {
writeln!(output, "## Cross-Language References\n")?;
writeln!(output, "| Source | Target | Type | Confidence |")?;
writeln!(output, "|--------|--------|------|------------|")?;
for cross_ref in cross_refs {
writeln!(
output,
"| `{}` | `{}` | {:?} | {:.1}% |",
cross_ref.source_file.display(),
cross_ref.target_file.display(),
cross_ref.reference_type,
cross_ref.confidence * 100.0
)?;
}
writeln!(output)?;
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_defect_predictions(
&self,
output: &mut String,
context: &DeepContext,
) -> anyhow::Result<()> {
self.write_defect_header(output)?;
self.write_defect_summary(output, &context.defect_summary)?;
self.write_defect_hotspots_table(output, &context.hotspots)?;
Ok(())
}
fn write_defect_header(&self, output: &mut String) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "## Defect Probability Analysis\n")?;
Ok(())
}
fn write_defect_summary(
&self,
output: &mut String,
summary: &DefectSummary,
) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "**Risk Assessment:**")?;
writeln!(
output,
"- Total Defects Predicted: {}",
summary.total_defects
)?;
writeln!(
output,
"- Defect Density: {:.2} defects per 1000 lines",
summary.defect_density
)?;
Ok(())
}
fn write_defect_hotspots_table(
&self,
output: &mut String,
hotspots: &[DefectHotspot],
) -> anyhow::Result<()> {
use std::fmt::Write;
if !hotspots.is_empty() {
writeln!(output, "\n**High-Risk Hotspots:**")?;
writeln!(output, "| File:Line | Risk Score | Effort (hours) |")?;
writeln!(output, "|-----------|------------|----------------|")?;
for hotspot in hotspots.iter().take(10) {
writeln!(
output,
"| `{}:{}` | {:.1} | {:.1} |",
hotspot.location.file.display(),
hotspot.location.line,
hotspot.composite_score,
hotspot.refactoring_effort.estimated_hours
)?;
}
}
writeln!(output)?;
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn format_prioritized_recommendations(
&self,
output: &mut String,
recommendations: &[PrioritizedRecommendation],
) -> anyhow::Result<()> {
debug_assert!(
!recommendations.is_empty(),
"recommendations must not be empty"
);
if recommendations.is_empty() {
return Ok(());
}
self.write_recommendations_header(output)?;
for (i, rec) in recommendations.iter().enumerate() {
self.write_single_recommendation(output, i, rec)?;
}
Ok(())
}
fn write_recommendations_header(&self, output: &mut String) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "## Prioritized Recommendations\n")?;
Ok(())
}
fn write_single_recommendation(
&self,
output: &mut String,
index: usize,
rec: &PrioritizedRecommendation,
) -> anyhow::Result<()> {
let priority_emoji = self.get_priority_emoji(&rec.priority);
self.write_recommendation_title(output, priority_emoji, index + 1, &rec.title)?;
self.write_recommendation_details(output, rec)?;
self.write_recommendation_prerequisites(output, &rec.prerequisites)?;
Ok(())
}
fn get_priority_emoji(&self, priority: &Priority) -> &'static str {
match priority {
Priority::Critical => "\u{1f534}",
Priority::High => "\u{1f7e1}",
Priority::Medium => "\u{1f535}",
Priority::Low => "\u{26aa}",
}
}
fn write_recommendation_title(
&self,
output: &mut String,
emoji: &str,
number: usize,
title: &str,
) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "### {emoji} {number} {title}")?;
Ok(())
}
fn write_recommendation_details(
&self,
output: &mut String,
rec: &PrioritizedRecommendation,
) -> anyhow::Result<()> {
use std::fmt::Write;
writeln!(output, "**Description:** {}", rec.description)?;
writeln!(output, "**Effort:** {:?}", rec.estimated_effort)?;
writeln!(output, "**Impact:** {:?}", rec.impact)?;
Ok(())
}
fn write_recommendation_prerequisites(
&self,
output: &mut String,
prerequisites: &[String],
) -> anyhow::Result<()> {
use std::fmt::Write;
if !prerequisites.is_empty() {
writeln!(output, "**Prerequisites:**")?;
for prereq in prerequisites {
writeln!(output, "- {prereq}")?;
}
}
writeln!(output)?;
Ok(())
}
}