use crate::domain::summary::compute_summary;
use crate::domain::types::{
AnalysisResult, ComplexityMetric, CrapScore, FunctionIdentity, FunctionVerdict, RiskLevel,
ScoredFunction, SourceSpan,
};
use crate::ports::ParseDiagnostic;
use proptest::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DummyParseDiagnostic;
impl ParseDiagnostic for DummyParseDiagnostic {}
pub fn arb_risk_level() -> impl Strategy<Value = RiskLevel> {
prop_oneof![
Just(RiskLevel::Low),
Just(RiskLevel::Acceptable),
Just(RiskLevel::Moderate),
Just(RiskLevel::High),
]
}
pub fn arb_verdict() -> impl Strategy<Value = FunctionVerdict> {
(
"[a-z_]{1,20}",
"src/[a-z/]{1,30}\\.rs",
1..100u32,
0.0..=100.0f64,
1.0..200.0f64,
arb_risk_level(),
1.0..100.0f64,
)
.prop_map(
|(name, file, complexity, coverage, crap_value, risk, threshold)| FunctionVerdict {
scored: ScoredFunction {
identity: FunctionIdentity {
file_path: file,
qualified_name: name,
span: SourceSpan {
start_line: 1,
end_line: 10,
start_column: 0,
end_column: 0,
},
},
complexity,
complexity_metric: ComplexityMetric::Cognitive,
coverage_percent: coverage,
crap: CrapScore {
value: crap_value,
risk_level: risk,
},
contributors: vec![],
},
threshold,
exceeds: crap_value > threshold,
diagnostic: None,
},
)
}
pub fn arb_verdict_with_nan_coverage() -> impl Strategy<Value = FunctionVerdict> {
(
"[a-z_]{1,20}",
"src/[a-z/]{1,30}\\.rs",
1..100u32,
prop_oneof![(0.0..=100.0f64).prop_map(Some), Just(None::<f64>),],
1.0..200.0f64,
arb_risk_level(),
1.0..100.0f64,
)
.prop_map(
|(name, file, complexity, maybe_cov, crap_value, risk, threshold)| {
let coverage = maybe_cov.unwrap_or(f64::NAN);
FunctionVerdict {
scored: ScoredFunction {
identity: FunctionIdentity {
file_path: file,
qualified_name: name,
span: SourceSpan {
start_line: 1,
end_line: 10,
start_column: 0,
end_column: 0,
},
},
complexity,
complexity_metric: ComplexityMetric::Cognitive,
coverage_percent: coverage,
crap: CrapScore {
value: crap_value,
risk_level: risk,
},
contributors: vec![],
},
threshold,
exceeds: crap_value > threshold,
diagnostic: None,
}
},
)
}
pub fn arb_analysis_result() -> impl Strategy<Value = AnalysisResult> {
prop::collection::vec(arb_verdict(), 0..50).prop_map(|verdicts| {
let mut seen = std::collections::HashSet::new();
let verdicts: Vec<FunctionVerdict> = verdicts
.into_iter()
.filter(|v| {
seen.insert((
v.scored.identity.file_path.clone(),
v.scored.identity.qualified_name.clone(),
))
})
.collect();
let passed = !verdicts.iter().any(|v| v.exceeds);
let summary = compute_summary(&verdicts);
AnalysisResult {
functions: verdicts,
summary,
passed,
}
})
}