cha_core/plugins/
message_chain.rs1use crate::{AnalysisContext, Finding, Location, Plugin, Severity, SmellCategory};
2
3pub struct MessageChainAnalyzer {
5 pub max_depth: usize,
6}
7
8impl Default for MessageChainAnalyzer {
9 fn default() -> Self {
10 Self { max_depth: 3 }
11 }
12}
13
14impl Plugin for MessageChainAnalyzer {
15 fn name(&self) -> &str {
16 "message_chain"
17 }
18
19 fn description(&self) -> &str {
20 "Deep field access chains (a.b.c.d)"
21 }
22
23 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
24 ctx.model
25 .functions
26 .iter()
27 .filter(|f| f.chain_depth > self.max_depth)
28 .map(|f| Finding {
29 smell_name: "message_chain".into(),
30 category: SmellCategory::Couplers,
31 severity: Severity::Warning,
32 location: Location {
33 path: ctx.file.path.clone(),
34 start_line: f.start_line,
35 start_col: f.name_col,
36 end_line: f.start_line,
37 end_col: f.name_end_col,
38 name: Some(f.name.clone()),
39 },
40 message: format!(
41 "Function `{}` has chain depth {} (threshold: {})",
42 f.name, f.chain_depth, self.max_depth
43 ),
44 suggested_refactorings: vec!["Hide Delegate".into()],
45 actual_value: Some(f.chain_depth as f64),
46 threshold: Some(self.max_depth as f64),
47 })
48 .collect()
49 }
50}