wowlab_tidy/languages/rust/rules/style/
commented_code.rs1use 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});