cha_core/plugins/
cognitive_complexity.rs1use crate::{AnalysisContext, Finding, Plugin, Severity, SmellCategory, func_location};
2
3pub struct CognitiveComplexityAnalyzer {
15 pub threshold: usize,
16}
17
18impl Default for CognitiveComplexityAnalyzer {
19 fn default() -> Self {
20 Self { threshold: 15 }
21 }
22}
23
24impl Plugin for CognitiveComplexityAnalyzer {
25 fn name(&self) -> &str {
26 "cognitive_complexity"
27 }
28
29 fn smells(&self) -> Vec<String> {
30 vec!["cognitive_complexity".into()]
31 }
32
33 fn description(&self) -> &str {
34 "Cognitive complexity exceeds threshold"
35 }
36
37 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
38 ctx.model
39 .functions
40 .iter()
41 .filter(|f| f.cognitive_complexity > self.threshold)
42 .map(|f| {
43 let severity = if f.cognitive_complexity > self.threshold * 2 {
44 Severity::Error
45 } else {
46 Severity::Warning
47 };
48 Finding {
49 smell_name: "cognitive_complexity".into(),
50 category: SmellCategory::Bloaters,
51 severity,
52 location: func_location(&ctx.file.path, f),
53 message: format!(
54 "Function `{}` has cognitive complexity {} (threshold: {})",
55 f.name, f.cognitive_complexity, self.threshold
56 ),
57 suggested_refactorings: vec![
58 "Extract Method".into(),
59 "Replace Nested Conditional with Guard Clauses".into(),
60 ],
61 actual_value: Some(f.cognitive_complexity as f64),
62 threshold: Some(self.threshold as f64),
63 risk_score: None,
64 }
65 })
66 .collect()
67 }
68}