cha_core/plugins/
complexity.rs1use crate::{AnalysisContext, Finding, Plugin, Severity, SmellCategory, func_location};
2
3pub struct ComplexityAnalyzer {
5 pub warn_threshold: usize,
6 pub error_threshold: usize,
7}
8
9impl Default for ComplexityAnalyzer {
10 fn default() -> Self {
11 Self {
12 warn_threshold: 10,
13 error_threshold: 20,
14 }
15 }
16}
17
18impl Plugin for ComplexityAnalyzer {
19 fn name(&self) -> &str {
20 "complexity"
21 }
22
23 fn description(&self) -> &str {
24 "Cyclomatic complexity exceeds threshold"
25 }
26
27 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
28 ctx.model
29 .functions
30 .iter()
31 .filter_map(|f| self.check_function(ctx, f))
32 .collect()
33 }
34}
35
36impl ComplexityAnalyzer {
37 fn check_function(&self, ctx: &AnalysisContext, f: &crate::FunctionInfo) -> Option<Finding> {
39 if f.complexity < self.warn_threshold {
40 return None;
41 }
42 let severity = if f.complexity >= self.error_threshold {
43 Severity::Error
44 } else {
45 Severity::Warning
46 };
47 Some(Finding {
48 smell_name: "high_complexity".into(),
49 category: SmellCategory::Bloaters,
50 severity,
51 location: func_location(&ctx.file.path, f),
52 message: format!(
53 "Function `{}` has complexity {} (threshold: {})",
54 f.name, f.complexity, self.warn_threshold
55 ),
56 suggested_refactorings: vec![
57 "Extract Method".into(),
58 "Replace Conditional with Polymorphism".into(),
59 ],
60 actual_value: Some(f.complexity as f64),
61 threshold: Some(self.warn_threshold as f64),
62 })
63 }
64}