Skip to main content

cha_core/plugins/
comments.rs

1use crate::{AnalysisContext, Finding, Location, Plugin, Severity, SmellCategory};
2
3/// Detect functions where comment lines exceed a threshold ratio.
4pub 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                })
65            })
66            .collect()
67    }
68}