#![cfg_attr(coverage_nightly, coverage(off))]
use super::types::*;
use anyhow::Result;
use std::collections::HashMap;
use std::path::PathBuf;
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub(crate) fn find_hotspot_with_details(
file_metrics: HashMap<PathBuf, FileMetrics>,
) -> Result<LintHotspot> {
let mut hotspot_file = None;
let mut max_density = 0.0;
if std::env::var("LINT_HOTSPOT_DEBUG").is_ok() {
eprintln!("🔍 Finding hotspot from {} files", file_metrics.len());
}
for (file_path, metrics) in file_metrics {
if std::env::var("LINT_HOTSPOT_DEBUG").is_ok() {
eprintln!(
" File: {}, SLOC: {}, Errors: {}, Warnings: {}",
file_path.display(),
metrics.sloc,
metrics.severity_counts.error,
metrics.severity_counts.warning
);
}
if metrics.sloc == 0 {
continue;
}
let total_violations = metrics.severity_counts.error
+ metrics.severity_counts.warning
+ metrics.severity_counts.suggestion;
let density = (total_violations as f64) / (metrics.sloc as f64);
if density > max_density {
max_density = density;
let mut top_lints: Vec<_> = metrics.violations.into_iter().collect();
top_lints.sort_by_key(|b| std::cmp::Reverse(b.1));
top_lints.truncate(10);
hotspot_file = Some(LintHotspot {
file: file_path,
defect_density: density,
total_violations,
sloc: metrics.sloc,
severity_distribution: metrics.severity_counts,
top_lints,
detailed_violations: metrics.detailed_violations,
});
}
}
hotspot_file.ok_or_else(|| anyhow::anyhow!("No lint violations found in any Rust files"))
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn calculate_enforcement_metadata(
hotspot: &LintHotspot,
min_confidence: f64,
) -> EnforcementMetadata {
let enforcement_score = (hotspot.defect_density * 10.0).min(10.0);
let enforcement_priority = (enforcement_score as u8).max(1);
let estimated_fix_time = (hotspot.total_violations as u32) * 300;
let automation_confidence = if hotspot
.top_lints
.iter()
.any(|(lint, _)| lint.contains("unused") || lint.contains("redundant"))
{
0.9
} else {
0.7
};
EnforcementMetadata {
enforcement_score,
requires_enforcement: enforcement_score >= 7.0 && automation_confidence >= min_confidence,
estimated_fix_time,
automation_confidence,
enforcement_priority,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn generate_refactor_chain(hotspot: &LintHotspot, min_confidence: f64) -> RefactorChain {
let mut steps = Vec::new();
let mut total_impact = 0;
for (lint_code, count) in &hotspot.top_lints {
let (confidence, description) = match lint_code.as_str() {
s if s.contains("unused") => (0.95, "Remove unused code"),
s if s.contains("redundant") => (0.90, "Remove redundant code"),
s if s.contains("needless") => (0.85, "Simplify needless patterns"),
s if s.contains("too_many_arguments") => (0.80, "Extract context objects"),
_ => (0.70, "Apply clippy suggestion"),
};
if confidence >= min_confidence {
steps.push(RefactorStep {
id: format!("fix-{lint_code}"),
lint: lint_code.clone(),
confidence,
impact: *count,
description: description.to_string(),
});
total_impact += count;
}
}
RefactorChain {
id: format!(
"lint-hotspot-{}",
chrono::Utc::now().format("%Y%m%d-%H%M%S")
),
estimated_reduction: total_impact,
automation_confidence: steps.iter().map(|s| s.confidence).sum::<f64>() / steps.len() as f64,
steps,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn check_quality_gates(hotspot: &LintHotspot, max_density: f64) -> QualityGateStatus {
let mut violations = Vec::new();
if hotspot.defect_density > max_density {
violations.push(QualityViolation {
rule: "max_defect_density".to_string(),
threshold: max_density,
actual: hotspot.defect_density,
severity: "blocking".to_string(),
});
}
if hotspot.total_violations > 50 {
violations.push(QualityViolation {
rule: "max_single_file_violations".to_string(),
threshold: 50.0,
actual: hotspot.total_violations as f64,
severity: "warning".to_string(),
});
}
let passed = violations.is_empty();
let blocking = violations.iter().any(|v| v.severity == "blocking");
QualityGateStatus {
passed,
violations,
blocking,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub(crate) fn build_lint_hotspot_result(
file_metrics: HashMap<PathBuf, FileMetrics>,
) -> Result<LintHotspotResult> {
let (all_violations, summary_by_file, total_project_violations) =
collect_project_violations(&file_metrics);
let hotspot = find_hotspot_with_details(file_metrics)?;
Ok(LintHotspotResult {
hotspot,
all_violations,
summary_by_file,
total_project_violations,
enforcement: None,
refactor_chain: None,
quality_gate: QualityGateStatus {
passed: true,
violations: vec![],
blocking: false,
},
})
}
fn collect_project_violations(
file_metrics: &HashMap<PathBuf, FileMetrics>,
) -> (Vec<ViolationDetail>, HashMap<PathBuf, FileSummary>, usize) {
let mut all_violations = Vec::new();
let mut summary_by_file = HashMap::new();
let mut total_project_violations = 0;
for (file_path, metrics) in file_metrics {
all_violations.extend(metrics.detailed_violations.clone());
let total_file_violations = calculate_total_violations(metrics);
total_project_violations += total_file_violations;
let defect_density = calculate_defect_density(total_file_violations, metrics.sloc);
summary_by_file.insert(
file_path.clone(),
FileSummary {
total_violations: total_file_violations,
errors: metrics.severity_counts.error,
warnings: metrics.severity_counts.warning,
sloc: metrics.sloc,
defect_density,
},
);
}
(all_violations, summary_by_file, total_project_violations)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn calculate_total_violations(metrics: &FileMetrics) -> usize {
metrics.severity_counts.error
+ metrics.severity_counts.warning
+ metrics.severity_counts.suggestion
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn calculate_defect_density(violations: usize, sloc: usize) -> f64 {
if sloc > 0 {
violations as f64 / sloc as f64
} else {
0.0
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_total_violations_all_types() {
let metrics = FileMetrics {
severity_counts: SeverityDistribution {
error: 2,
warning: 3,
suggestion: 1,
note: 5, },
sloc: 100,
violations: HashMap::new(),
detailed_violations: vec![],
};
assert_eq!(calculate_total_violations(&metrics), 6);
}
#[test]
fn test_calculate_total_violations_zeros() {
let metrics = FileMetrics {
severity_counts: SeverityDistribution::default(),
sloc: 50,
violations: HashMap::new(),
detailed_violations: vec![],
};
assert_eq!(calculate_total_violations(&metrics), 0);
}
#[test]
fn test_calculate_total_violations_only_errors() {
let metrics = FileMetrics {
severity_counts: SeverityDistribution {
error: 10,
warning: 0,
suggestion: 0,
note: 0,
},
sloc: 100,
violations: HashMap::new(),
detailed_violations: vec![],
};
assert_eq!(calculate_total_violations(&metrics), 10);
}
#[test]
fn test_calculate_defect_density_normal() {
let density = calculate_defect_density(10, 100);
assert!((density - 0.1).abs() < 0.001);
}
#[test]
fn test_calculate_defect_density_zero_sloc() {
let density = calculate_defect_density(5, 0);
assert_eq!(density, 0.0);
}
#[test]
fn test_calculate_defect_density_zero_violations() {
let density = calculate_defect_density(0, 100);
assert_eq!(density, 0.0);
}
#[test]
fn test_calculate_defect_density_high() {
let density = calculate_defect_density(50, 10);
assert!((density - 5.0).abs() < 0.001);
}
#[test]
fn test_check_quality_gates_pass() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 0.05, total_violations: 10, sloc: 200,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![],
detailed_violations: vec![],
};
let status = check_quality_gates(&hotspot, 0.1);
assert!(status.passed);
assert!(!status.blocking);
assert!(status.violations.is_empty());
}
#[test]
fn test_check_quality_gates_fail_density() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 0.15, total_violations: 30,
sloc: 200,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![],
detailed_violations: vec![],
};
let status = check_quality_gates(&hotspot, 0.1);
assert!(!status.passed);
assert!(status.blocking);
assert_eq!(status.violations.len(), 1);
assert_eq!(status.violations[0].rule, "max_defect_density");
}
#[test]
fn test_check_quality_gates_fail_violations() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 0.05,
total_violations: 55, sloc: 1100,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![],
detailed_violations: vec![],
};
let status = check_quality_gates(&hotspot, 0.1);
assert!(!status.passed);
assert!(!status.blocking); assert_eq!(status.violations.len(), 1);
assert_eq!(status.violations[0].rule, "max_single_file_violations");
}
#[test]
fn test_check_quality_gates_fail_both() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 0.5, total_violations: 100, sloc: 200,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![],
detailed_violations: vec![],
};
let status = check_quality_gates(&hotspot, 0.1);
assert!(!status.passed);
assert!(status.blocking);
assert_eq!(status.violations.len(), 2);
}
#[test]
fn test_calculate_enforcement_metadata_low_density() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 0.3,
total_violations: 5,
sloc: 100,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![],
detailed_violations: vec![],
};
let metadata = calculate_enforcement_metadata(&hotspot, 0.7);
assert!((metadata.enforcement_score - 3.0).abs() < 0.1);
assert_eq!(metadata.estimated_fix_time, 5 * 300); assert!(!metadata.requires_enforcement); }
#[test]
fn test_calculate_enforcement_metadata_high_density_with_unused() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 0.8,
total_violations: 20,
sloc: 25,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![("unused_variable".to_string(), 10)],
detailed_violations: vec![],
};
let metadata = calculate_enforcement_metadata(&hotspot, 0.7);
assert!((metadata.enforcement_score - 8.0).abs() < 0.1);
assert_eq!(metadata.automation_confidence, 0.9); assert!(metadata.requires_enforcement); }
#[test]
fn test_calculate_enforcement_metadata_high_density_no_easy_fixes() {
let hotspot = LintHotspot {
file: PathBuf::from("src/test.rs"),
defect_density: 1.0,
total_violations: 30,
sloc: 30,
severity_distribution: SeverityDistribution::default(),
top_lints: vec![("clippy::too_many_arguments".to_string(), 15)],
detailed_violations: vec![],
};
let metadata = calculate_enforcement_metadata(&hotspot, 0.8);
assert!((metadata.enforcement_score - 10.0).abs() < 0.1); assert_eq!(metadata.automation_confidence, 0.7); assert!(!metadata.requires_enforcement); }
}