cha_core/plugins/
speculative_generality.rs1use crate::{AnalysisContext, Finding, Location, Plugin, Severity, SmellCategory};
2
3pub struct SpeculativeGeneralityAnalyzer;
5
6impl Default for SpeculativeGeneralityAnalyzer {
7 fn default() -> Self {
8 Self
9 }
10}
11
12impl Plugin for SpeculativeGeneralityAnalyzer {
13 fn name(&self) -> &str {
14 "speculative_generality"
15 }
16
17 fn smells(&self) -> Vec<String> {
18 vec!["speculative_generality".into()]
19 }
20
21 fn description(&self) -> &str {
22 "Interface with too few implementations"
23 }
24
25 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
26 let interfaces: Vec<_> = ctx
28 .model
29 .classes
30 .iter()
31 .filter(|c| c.is_interface)
32 .collect();
33 if interfaces.is_empty() {
34 return vec![];
35 }
36 let mut findings = Vec::new();
37 for iface in &interfaces {
38 let impl_count = ctx
39 .model
40 .classes
41 .iter()
42 .filter(|c| c.parent_name.as_deref() == Some(&iface.name))
43 .count();
44 if impl_count <= 1 {
46 findings.push(Finding {
47 smell_name: "speculative_generality".into(),
48 category: SmellCategory::Dispensables,
49 severity: Severity::Hint,
50 location: Location {
51 path: ctx.file.path.clone(),
52 start_line: iface.start_line,
53 start_col: iface.name_col,
54 end_line: iface.start_line,
55 end_col: iface.name_end_col,
56 name: Some(iface.name.clone()),
57 },
58 message: format!(
59 "Interface `{}` has only {} implementation(s) in this file, consider Collapse Hierarchy",
60 iface.name, impl_count
61 ),
62 suggested_refactorings: vec![
63 "Collapse Hierarchy".into(),
64 "Inline Class".into(),
65 ],
66 ..Default::default()
67 });
68 }
69 }
70 findings
71 }
72}