cha_core/plugins/
comments.rs1use crate::{AnalysisContext, Finding, Location, Plugin, Severity, SmellCategory};
2
3pub struct CommentsAnalyzer {
5 pub max_comment_ratio: f64,
6 pub min_lines: usize,
7}
8
9impl Default for CommentsAnalyzer {
10 fn default() -> Self {
11 Self {
12 max_comment_ratio: 0.3,
13 min_lines: 10,
14 }
15 }
16}
17
18impl Plugin for CommentsAnalyzer {
19 fn name(&self) -> &str {
20 "comments"
21 }
22
23 fn smells(&self) -> Vec<String> {
24 vec!["excessive_comments".into()]
25 }
26
27 fn description(&self) -> &str {
28 "Excessive comment-to-code ratio"
29 }
30
31 fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding> {
32 ctx.model
33 .functions
34 .iter()
35 .filter_map(|f| {
36 if f.line_count < self.min_lines || f.comment_lines == 0 {
37 return None;
38 }
39 let ratio = f.comment_lines as f64 / f.line_count as f64;
40 if ratio <= self.max_comment_ratio {
41 return None;
42 }
43 Some(Finding {
44 smell_name: "excessive_comments".into(),
45 category: SmellCategory::Dispensables,
46 severity: Severity::Hint,
47 location: Location {
48 path: ctx.file.path.clone(),
49 start_line: f.start_line,
50 end_line: f.end_line,
51 name: Some(f.name.clone()),
52 ..Default::default()
53 },
54 message: format!(
55 "Function `{}` has {:.0}% comment lines ({}/{}), consider Extract Method",
56 f.name,
57 ratio * 100.0,
58 f.comment_lines,
59 f.line_count
60 ),
61 suggested_refactorings: vec!["Extract Method".into(), "Rename Method".into()],
62 actual_value: Some(ratio),
63 threshold: Some(self.max_comment_ratio),
64 risk_score: None,
65 })
66 })
67 .collect()
68 }
69}