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 smells(&self) -> Vec<String> {
24 vec!["high_complexity".into()]
25 }
26
27 fn description(&self) -> &str {
28 "Cyclomatic complexity exceeds threshold"
29 }
30
31 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
32 ctx.model
33 .functions
34 .iter()
35 .filter_map(|f| self.check_function(ctx, f))
36 .collect()
37 }
38}
39
40impl ComplexityAnalyzer {
41 fn check_function(&self, ctx: &AnalysisContext, f: &crate::FunctionInfo) -> Option<Finding> {
43 if f.complexity < self.warn_threshold {
44 return None;
45 }
46 let severity = if f.complexity >= self.error_threshold {
47 Severity::Error
48 } else {
49 Severity::Warning
50 };
51 Some(Finding {
52 smell_name: "high_complexity".into(),
53 category: SmellCategory::Bloaters,
54 severity,
55 location: func_location(&ctx.file.path, f),
56 message: format!(
57 "Function `{}` has complexity {} (threshold: {})",
58 f.name, f.complexity, self.warn_threshold
59 ),
60 suggested_refactorings: vec![
61 "Extract Method".into(),
62 "Replace Conditional with Polymorphism".into(),
63 ],
64 actual_value: Some(f.complexity as f64),
65 threshold: Some(self.warn_threshold as f64),
66 })
67 }
68}