#![cfg_attr(coverage_nightly, coverage(off))]
use crate::services::service_registry::ServiceRegistry;
use anyhow::Result;
use serde::Serialize;
use std::path::Path;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct SatdAnalysisRequest {
pub path: std::path::PathBuf,
pub strict_mode: bool,
pub include_tests: bool,
pub extended: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct SatdAnalysisResult {
pub total_files: usize,
pub violations: Vec<SatdViolation>,
pub summary: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct SatdViolation {
pub file_path: String,
pub line_number: usize,
pub violation_type: String,
pub message: String,
pub severity: SatdSeverity,
}
#[derive(Debug, Clone, Serialize)]
pub enum SatdSeverity {
Critical,
High,
Medium,
Low,
}
#[derive(Clone)]
pub struct SatdFacade {
#[allow(dead_code)]
registry: Arc<ServiceRegistry>,
}
impl SatdFacade {
#[must_use]
pub fn new(registry: Arc<ServiceRegistry>) -> Self {
Self { registry }
}
pub async fn analyze_project(
&self,
request: SatdAnalysisRequest,
) -> Result<SatdAnalysisResult> {
use crate::services::satd_detector::SATDDetector;
let detector = if request.strict_mode {
SATDDetector::new_strict()
} else if request.extended {
SATDDetector::new_extended()
} else {
SATDDetector::new()
};
let satd_items = if request.include_tests {
detector
.analyze_directory_with_tests(&request.path, request.strict_mode)
.await?
} else {
detector.analyze_directory(&request.path).await?
};
let violations: Vec<SatdViolation> = satd_items
.iter()
.map(|item| {
let severity = match item.severity {
crate::services::satd_detector::Severity::Critical => SatdSeverity::Critical,
crate::services::satd_detector::Severity::High => SatdSeverity::High,
crate::services::satd_detector::Severity::Medium => SatdSeverity::Medium,
crate::services::satd_detector::Severity::Low => SatdSeverity::Low,
};
SatdViolation {
file_path: item.file.display().to_string(),
line_number: item.line as usize,
violation_type: format!("{:?}", item.category),
message: item.text.clone(),
severity,
}
})
.collect();
let total_files = violations
.iter()
.map(|v| &v.file_path)
.collect::<std::collections::HashSet<_>>()
.len();
let summary = format!(
"Found {} SATD violations in {} files",
violations.len(),
total_files
);
Ok(SatdAnalysisResult {
total_files,
violations,
summary,
})
}
pub async fn analyze_file<P: AsRef<Path>>(&self, path: P) -> Result<SatdAnalysisResult> {
let request = SatdAnalysisRequest {
path: path.as_ref().to_path_buf(),
strict_mode: false,
include_tests: true,
extended: false,
};
self.analyze_project(request).await
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
use crate::services::service_registry::ServiceRegistry;
#[tokio::test]
async fn test_satd_facade_creation() {
let registry = Arc::new(ServiceRegistry::new());
let _facade = SatdFacade::new(registry);
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}