cha_core/plugins/
data_class.rs1use crate::{AnalysisContext, Finding, Location, Plugin, Severity, SmellCategory};
2
3pub struct DataClassAnalyzer {
5 pub min_fields: usize,
6}
7
8impl Default for DataClassAnalyzer {
9 fn default() -> Self {
10 Self { min_fields: 2 }
11 }
12}
13
14impl Plugin for DataClassAnalyzer {
15 fn name(&self) -> &str {
16 "data_class"
17 }
18
19 fn smells(&self) -> Vec<String> {
20 vec!["data_class".into()]
21 }
22
23 fn description(&self) -> &str {
24 "Class with only data, no behavior"
25 }
26
27 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
28 ctx.model
29 .classes
30 .iter()
31 .filter_map(|c| {
32 if c.is_interface || c.field_count < self.min_fields || c.has_behavior {
33 return None;
34 }
35 Some(Finding {
36 smell_name: "data_class".into(),
37 category: SmellCategory::Dispensables,
38 severity: Severity::Hint,
39 location: Location {
40 path: ctx.file.path.clone(),
41 start_line: c.start_line,
42 end_line: c.end_line,
43 name: Some(c.name.clone()),
44 ..Default::default()
45 },
46 message: format!(
47 "Class `{}` has {} fields but no behavior methods, consider Move Method",
48 c.name, c.field_count
49 ),
50 suggested_refactorings: vec!["Move Method".into(), "Encapsulate Field".into()],
51 ..Default::default()
52 })
53 })
54 .collect()
55 }
56}