react_auditor/rules/quality/
no_commented_code.rs1use oxc_ast::ast::Program;
2use oxc_semantic::Semantic;
3
4use crate::rules::{Rule, RuleFinding, RuleMeta, Severity};
5
6pub struct NoCommentedCode;
7
8const RULE_META: RuleMeta = RuleMeta {
9 id: "no-commented-code",
10 default_severity: Severity::Warning,
11 category: "quality",
12 description: "Remove dead commented-out code",
13};
14
15const CODE_KEYWORDS: &[&str] = &[
16 "function ",
17 "const ",
18 "let ",
19 "var ",
20 "if ",
21 "else ",
22 "for ",
23 "while ",
24 "return ",
25 "import ",
26 "export ",
27 "class ",
28 "new ",
29 "try ",
30 "catch ",
31 "=>",
32 "console.",
33 "document.",
34 "require(",
35];
36
37impl Rule for NoCommentedCode {
38 fn meta(&self) -> &RuleMeta {
39 &RULE_META
40 }
41
42 fn run(&self, _program: &Program, _semantic: &Semantic, source_text: &str) -> Vec<RuleFinding> {
43 let mut findings = Vec::new();
44 let lines: Vec<&str> = source_text.lines().collect();
45
46 let mut i = 0;
47 while i < lines.len() {
48 let trimmed = lines[i].trim();
49 if let Some(body) = trimmed.strip_prefix("//") {
50 let comment_body = body.trim();
51 if looks_like_code(comment_body) {
52 findings.push(RuleFinding {
53 line: i + 1,
54 column: 1,
55 message: format!("Commented-out code: {comment_body}"),
56 });
57 }
58 } else if trimmed.starts_with("/*") {
59 let mut comment_lines = vec![];
61 let start_line = i;
62 while i < lines.len() {
63 comment_lines.push(lines[i]);
64 if lines[i].contains("*/") {
65 break;
66 }
67 i += 1;
68 }
69 let full_comment = comment_lines.join("\n");
70 let body = full_comment.trim_start_matches("/*").trim_end_matches("*/");
71
72 let mut line_count = 0;
73 for comment_line in body.lines() {
74 let cl = comment_line.trim().trim_start_matches('*').trim();
75 if looks_like_code(cl) {
76 line_count += 1;
77 }
78 }
79
80 if line_count >= 2 && comment_lines.len() >= 3 {
81 findings.push(RuleFinding {
82 line: start_line + 1,
83 column: 1,
84 message: "Multi-line commented-out code detected".to_string(),
85 });
86 }
87 }
88 i += 1;
89 }
90
91 findings
92 }
93}
94
95fn looks_like_code(text: &str) -> bool {
96 let t = text.trim();
97 if t.is_empty() || t.len() < 3 {
98 return false;
99 }
100 CODE_KEYWORDS.iter().any(|kw| t.contains(kw))
101}