Skip to main content

wowlab_tidy/languages/rust/rules/style/
commented_code.rs

1use crate::{Example, FileCtx, Violation, infra::parse, violation};
2
3#[rustfmt::skip]
4const EXAMPLES: &[Example] = &[
5    Example {
6        label: "single commented line passes",
7        code: "// let x = 5;",
8        pass: true,
9    },
10    Example {
11        label: "two consecutive commented code lines",
12        code: "// let x = 5;\n// let y = 10;",
13        pass: false,
14    },
15    Example {
16        label: "normal comments",
17        code: "// This is a normal comment\n// explaining the code below",
18        pass: true,
19    },
20    Example {
21        label: "doc style comments",
22        code: "// NOTE: this is important\n// SAFETY: we checked bounds",
23        pass: true,
24    },
25    Example {
26        label: "non-consecutive code comments",
27        code: "// let x = 5;\nlet y = 10;\n// let z = 15;",
28        pass: true,
29    },
30    Example {
31        label: "mixed code and prose resets",
32        code: "// let x = 5;\n// This is a sentence about something.\n// let y = 10;",
33        pass: true,
34    },
35    Example {
36        label: "prose with for keyword",
37        code: "// Each spec can have multiple loadouts (one for class/spec tree, one for hero trees)\n// The order is determined by the loadout entries",
38        pass: true,
39    },
40    Example {
41        label: "prose with self reference",
42        code: "// Construct a SimContext from &self.state + &mut self.sink.\n// Used 10 times in the event loop; macro avoids repeating the struct literal.",
43        pass: true,
44    },
45];
46
47crate::line_rule!(
48    commented_code,
49    "Detect blocks of commented-out code (2+ consecutive lines).",
50    "Commented-out code is dead weight. Use version control to recover old code instead of leaving it inline.",
51);
52
53const STARTS_WITH_PATTERNS: &[&str] = &[
54    "let ",
55    "fn ",
56    "pub fn ",
57    "pub(",
58    "struct ",
59    "enum ",
60    "impl ",
61    "use ",
62    "mod ",
63    "return ",
64    "self.",
65    "Self::",
66    "if let ",
67    "match ",
68    "for ",
69    "while ",
70    "loop {",
71    "} else {",
72    "} else if ",
73    "assert!(",
74    "assert_eq!(",
75    "#[",
76];
77
78const CONTAINS_PATTERNS: &[&str] = &[
79    ".await",
80    ".unwrap()",
81    ".push(",
82    ".insert(",
83    ".expect(",
84    "println!(",
85    "eprintln!(",
86    "dbg!(",
87];
88
89const SKIP_PREFIXES: &[&str] = &[
90    "---",
91    "===",
92    "SAFETY:",
93    "NOTE:",
94    "IMPORTANT:",
95    "TODO",
96    "FIXME",
97    "HACK",
98    "Step ",
99    "tidy",
100    "rustfmt",
101    "clippy",
102];
103
104fn check_commented_code(ctx: &FileCtx<'_>) -> Vec<Violation> {
105    const MIN_CONSECUTIVE_CODE_LINES: usize = 2;
106
107    let mut out = Vec::new();
108    let mut consecutive = 0;
109
110    for (i, line) in ctx.lines.iter().enumerate() {
111        if let Some(raw) = parse::prose_comment_content(line) {
112            let content = raw.trim();
113
114            if content.is_empty() || SKIP_PREFIXES.iter().any(|p| parse::matches(content, *p)) {
115                consecutive = 0;
116                continue;
117            }
118
119            let looks_like_code = STARTS_WITH_PATTERNS
120                .iter()
121                .any(|p| parse::matches(content, *p))
122                || CONTAINS_PATTERNS.iter().any(|p| content.contains(p));
123
124            if looks_like_code {
125                consecutive += 1;
126
127                if consecutive >= MIN_CONSECUTIVE_CODE_LINES {
128                    out.push(violation(
129                        ctx.rel,
130                        i + 1,
131                        "commented-out code (delete it or use version control)",
132                    ));
133                    consecutive = 0;
134                }
135            } else {
136                consecutive = 0;
137            }
138        } else {
139            consecutive = 0;
140        }
141    }
142
143    out
144}
145
146crate::tidy_test!(check_commented_code, {
147    crate::example_tests!(EXAMPLES, check_commented_code);
148});