cha_core/plugins/
complexity.rs1use crate::{AnalysisContext, Finding, Location, Plugin, Severity, SmellCategory};
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 Some(Finding {
43 smell_name: "high_complexity".into(),
44 category: SmellCategory::Bloaters,
45 severity: if f.complexity >= self.error_threshold {
46 Severity::Error
47 } else {
48 Severity::Warning
49 },
50 location: Location {
51 path: ctx.file.path.clone(),
52 start_line: f.start_line,
53 end_line: f.end_line,
54 name: Some(f.name.clone()),
55 },
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}