use super::{
generate_detailed_attribution, generate_summary, DetailLevel, DiagnosticReport,
DiagnosticReporter, OutputFormat,
};
use crate::analysis::effects::{analyze_with_config, lift_pure, query_config};
use crate::analysis::multi_pass::MultiPassResult;
use crate::effects::AnalysisEffect;
use crate::env::RealEnv;
use crate::errors::AnalysisError;
use stillwater::Effect;
pub fn generate_report_effect(result: MultiPassResult) -> AnalysisEffect<DiagnosticReport> {
analyze_with_config(move |config| {
let detail_level = get_detail_level_from_config(config);
let output_format = get_output_format_from_config(config);
let reporter = DiagnosticReporter::new(output_format, detail_level);
Ok(reporter.generate_report(&result))
})
}
pub fn format_report_effect(result: MultiPassResult) -> AnalysisEffect<String> {
analyze_with_config(move |config| {
let detail_level = get_detail_level_from_config(config);
let output_format = get_output_format_from_config(config);
let reporter = DiagnosticReporter::new(output_format, detail_level);
let report = reporter.generate_report(&result);
Ok(reporter.format_report(&report))
})
}
pub fn generate_report_with_detail(
result: MultiPassResult,
detail_level: DetailLevel,
) -> AnalysisEffect<DiagnosticReport> {
analyze_with_config(move |config| {
let output_format = get_output_format_from_config(config);
let reporter = DiagnosticReporter::new(output_format, detail_level.clone());
Ok(reporter.generate_report(&result))
})
}
pub fn generate_report_with_options(
result: MultiPassResult,
detail_level: DetailLevel,
output_format: OutputFormat,
) -> AnalysisEffect<DiagnosticReport> {
let reporter = DiagnosticReporter::new(output_format, detail_level);
let report = reporter.generate_report(&result);
lift_pure(report)
}
pub fn generate_summary_effect(
result: MultiPassResult,
) -> AnalysisEffect<super::ComplexitySummary> {
let summary = generate_summary(&result);
lift_pure(summary)
}
pub fn generate_detailed_attribution_effect(
result: MultiPassResult,
) -> AnalysisEffect<super::DetailedAttribution> {
let attribution = generate_detailed_attribution(&result.attribution);
lift_pure(attribution)
}
pub fn get_detail_level_effect(
) -> impl Effect<Output = DetailLevel, Error = AnalysisError, Env = RealEnv> {
query_config(get_detail_level_from_config)
}
pub fn get_output_format_effect(
) -> impl Effect<Output = OutputFormat, Error = AnalysisError, Env = RealEnv> {
query_config(get_output_format_from_config)
}
fn get_detail_level_from_config(config: &crate::config::DebtmapConfig) -> DetailLevel {
config
.output
.as_ref()
.and_then(|o| o.detail_level.as_ref())
.map(|s| match s.as_str() {
"summary" => DetailLevel::Summary,
"comprehensive" => DetailLevel::Comprehensive,
"debug" => DetailLevel::Debug,
_ => DetailLevel::Standard,
})
.unwrap_or(DetailLevel::Standard)
}
fn get_output_format_from_config(config: &crate::config::DebtmapConfig) -> OutputFormat {
config
.output
.as_ref()
.and_then(|o| o.format.as_ref().or(o.default_format.as_ref()))
.map(|s| match s.as_str() {
"yaml" => OutputFormat::Yaml,
"markdown" | "md" => OutputFormat::Markdown,
"html" => OutputFormat::Html,
"text" | "txt" => OutputFormat::Text,
_ => OutputFormat::Json,
})
.unwrap_or(OutputFormat::Json)
}
pub fn generate_report_result(
result: &MultiPassResult,
config: &crate::config::DebtmapConfig,
) -> DiagnosticReport {
let detail_level = get_detail_level_from_config(config);
let output_format = get_output_format_from_config(config);
let reporter = DiagnosticReporter::new(output_format, detail_level);
reporter.generate_report(result)
}
pub fn format_report_result(
result: &MultiPassResult,
config: &crate::config::DebtmapConfig,
) -> String {
let detail_level = get_detail_level_from_config(config);
let output_format = get_output_format_from_config(config);
let reporter = DiagnosticReporter::new(output_format, detail_level);
let report = reporter.generate_report(result);
reporter.format_report(&report)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::analysis::attribution::{AttributedComplexity, ComplexityAttribution};
use crate::analysis::multi_pass::{AnalysisType, ComplexityResult};
use crate::config::{DebtmapConfig, OutputConfig};
use crate::env::RealEnv;
fn create_test_result() -> MultiPassResult {
MultiPassResult {
raw_complexity: ComplexityResult {
total_complexity: 20,
cognitive_complexity: 15,
functions: vec![],
analysis_type: AnalysisType::Raw,
},
normalized_complexity: ComplexityResult {
total_complexity: 15,
cognitive_complexity: 12,
functions: vec![],
analysis_type: AnalysisType::Normalized,
},
attribution: ComplexityAttribution {
logical_complexity: AttributedComplexity {
total: 12,
breakdown: vec![],
confidence: 0.9,
},
formatting_artifacts: AttributedComplexity {
total: 5,
breakdown: vec![],
confidence: 0.8,
},
pattern_complexity: AttributedComplexity {
total: 3,
breakdown: vec![],
confidence: 0.7,
},
source_mappings: vec![],
},
insights: vec![],
recommendations: vec![],
performance_metrics: None,
}
}
#[tokio::test]
async fn test_generate_report_effect() {
let env = RealEnv::default();
let result = create_test_result();
let effect = generate_report_effect(result);
let report = effect.run(&env).await.unwrap();
assert_eq!(report.summary.raw_complexity, 20);
assert_eq!(report.summary.normalized_complexity, 15);
}
#[tokio::test]
async fn test_format_report_effect() {
let env = RealEnv::default();
let result = create_test_result();
let effect = format_report_effect(result);
let formatted = effect.run(&env).await.unwrap();
assert!(formatted.contains("\"raw_complexity\""));
}
#[tokio::test]
async fn test_generate_report_with_detail() {
let env = RealEnv::default();
let result = create_test_result();
let effect = generate_report_with_detail(result, DetailLevel::Debug);
let report = effect.run(&env).await.unwrap();
assert_eq!(report.summary.raw_complexity, 20);
}
#[tokio::test]
async fn test_generate_summary_effect() {
let env = RealEnv::default();
let result = create_test_result();
let effect = generate_summary_effect(result);
let summary = effect.run(&env).await.unwrap();
assert_eq!(summary.raw_complexity, 20);
assert_eq!(summary.normalized_complexity, 15);
}
#[tokio::test]
async fn test_get_detail_level_effect_default() {
let env = RealEnv::default();
let effect = get_detail_level_effect();
let level = effect.run(&env).await.unwrap();
assert!(matches!(level, DetailLevel::Standard));
}
#[tokio::test]
async fn test_get_detail_level_effect_custom() {
let config = DebtmapConfig {
output: Some(OutputConfig {
detail_level: Some("comprehensive".to_string()),
format: None,
..Default::default()
}),
..Default::default()
};
let env = RealEnv::new(config);
let effect = get_detail_level_effect();
let level = effect.run(&env).await.unwrap();
assert!(matches!(level, DetailLevel::Comprehensive));
}
#[tokio::test]
async fn test_get_output_format_effect_custom() {
let config = DebtmapConfig {
output: Some(OutputConfig {
format: Some("markdown".to_string()),
..Default::default()
}),
..Default::default()
};
let env = RealEnv::new(config);
let effect = get_output_format_effect();
let format = effect.run(&env).await.unwrap();
assert!(matches!(format, OutputFormat::Markdown));
}
#[test]
fn test_backwards_compat_generate_report_result() {
let result = create_test_result();
let config = DebtmapConfig::default();
let report = generate_report_result(&result, &config);
assert_eq!(report.summary.raw_complexity, 20);
}
#[test]
fn test_backwards_compat_format_report_result() {
let result = create_test_result();
let config = DebtmapConfig::default();
let formatted = format_report_result(&result, &config);
assert!(formatted.contains("raw_complexity"));
}
}