use crate::{AnalysisContext, Finding, Plugin, Severity, SmellCategory, func_location};
pub struct ComplexityAnalyzer {
pub warn_threshold: usize,
pub error_threshold: usize,
}
impl Default for ComplexityAnalyzer {
fn default() -> Self {
Self {
warn_threshold: 10,
error_threshold: 20,
}
}
}
impl Plugin for ComplexityAnalyzer {
fn name(&self) -> &str {
"complexity"
}
fn smells(&self) -> Vec<String> {
vec!["high_complexity".into()]
}
fn description(&self) -> &str {
"Cyclomatic complexity exceeds threshold"
}
fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
ctx.model
.functions
.iter()
.filter_map(|f| self.check_function(ctx, f))
.collect()
}
}
impl ComplexityAnalyzer {
fn check_function(&self, ctx: &AnalysisContext, f: &crate::FunctionInfo) -> Option<Finding> {
if f.complexity < self.warn_threshold {
return None;
}
let severity = if f.complexity >= self.error_threshold {
Severity::Error
} else {
Severity::Warning
};
Some(Finding {
smell_name: "high_complexity".into(),
category: SmellCategory::Bloaters,
severity,
location: func_location(&ctx.file.path, f),
message: format!(
"Function `{}` has complexity {} (threshold: {})",
f.name, f.complexity, self.warn_threshold
),
suggested_refactorings: vec![
"Extract Method".into(),
"Replace Conditional with Polymorphism".into(),
],
actual_value: Some(f.complexity as f64),
threshold: Some(self.warn_threshold as f64),
})
}
}