wowlab_tidy/languages/rust/rules/style/
comment_space.rs1use crate::{Example, FileCtx, Fix, Violation, infra::parse, violation};
2
3#[rustfmt::skip]
4const EXAMPLES: &[Example] = &[
5 Example {
6 label: "no space after //",
7 code: "//comment",
8 pass: false,
9 },
10 Example {
11 label: "space after //",
12 code: "// comment",
13 pass: true,
14 },
15 Example {
16 label: "doc comment",
17 code: "/// doc comment",
18 pass: true,
19 },
20 Example {
21 label: "inner doc comment",
22 code: "//! inner doc",
23 pass: true,
24 },
25 Example {
26 label: "hash prefix",
27 code: "//# header",
28 pass: true,
29 },
30 Example {
31 label: "bare double slash",
32 code: "//",
33 pass: true,
34 },
35 Example {
36 label: "not a comment",
37 code: "let x = 1;",
38 pass: true,
39 },
40];
41
42crate::line_rule!(
43 comment_space,
44 "Require a space after `//` in comments (`//bad` -> `// good`).",
45 "Missing space after // makes comments harder to read and looks like accidentally commented-out code.",
46 Low,
47 fix_comment_space,
48);
49
50fn check_comment_space(ctx: &FileCtx<'_>) -> Vec<Violation> {
51 let mut out = Vec::new();
52
53 for (i, line) in ctx.lines.iter().enumerate() {
54 let lineno = i + 1;
55 let trimmed = line.trim();
56
57 if !parse::is_comment(trimmed) {
58 continue;
59 }
60
61 let Some(ch) = parse::char_after_slashes(trimmed) else {
62 continue;
63 };
64
65 if matches!(ch, ' ' | '/' | '!' | '#' | '[') {
66 continue;
67 }
68
69 out.push(violation(
70 ctx.rel,
71 lineno,
72 "missing space after `//` in comment",
73 ));
74 }
75
76 out
77}
78
79fn fix_comment_space(ctx: &FileCtx<'_>, v: &Violation) -> Option<Fix> {
80 let line = ctx.line(v.line)?;
81
82 Some(Fix::replace_line(v.line, line.replacen("//", "// ", 1)))
83}
84
85crate::tidy_test!(check_comment_space, {
86 crate::example_tests!(EXAMPLES, check_comment_space);
87 crate::fix_tests!(line, check_comment_space, fix_comment_space);
88});