Skip to main content

wowlab_tidy/languages/rust/rules/safety/
abs_home_path.rs

1use crate::{Example, FileCtx, Violation, infra::parse, violation};
2
3#[rustfmt::skip]
4const EXAMPLES: &[Example] = &[
5    Example {
6        label: "Users path in string",
7        code: r#"let p = "/Users/john/file";"#,
8        pass: false,
9    },
10    Example {
11        label: "home path in string",
12        code: r#"let p = "/home/user/data";"#,
13        pass: false,
14    },
15    Example {
16        label: "Windows path in string",
17        code: r#"let p = "C:\\Users\\john\\file";"#,
18        pass: false,
19    },
20    Example {
21        label: "tmp path",
22        code: r#"let p = "/tmp/file";"#,
23        pass: true,
24    },
25    Example {
26        label: "comment with path",
27        code: "// /Users/foo",
28        pass: true,
29    },
30    Example {
31        label: "no quotes",
32        code: "let users = get_users();",
33        pass: true,
34    },
35];
36
37crate::line_rule!(
38    abs_home_path,
39    "Ban hardcoded home directory paths like `/Users/` or `/home/` in string literals.",
40    "Absolute home paths break on other machines and in CI. Use environment variables or relative paths.",
41    Medium,
42);
43
44const HOME_PATTERNS: &[&str] = &["/Users/", "/home/", "C:\\\\Users\\\\", "C:\\Users\\"];
45
46fn check_abs_home_path(ctx: &FileCtx<'_>) -> Vec<Violation> {
47    let mut out = Vec::new();
48
49    for (i, line) in ctx.lines.iter().enumerate() {
50        let lineno = i + 1;
51        let trimmed = line.trim();
52
53        if parse::is_comment(trimmed) {
54            continue;
55        }
56
57        if !line.contains('"') {
58            continue;
59        }
60
61        for pattern in HOME_PATTERNS {
62            if line.contains(pattern) {
63                out.push(violation(
64                    ctx.rel,
65                    lineno,
66                    format!(
67                        "hardcoded home directory path `{pattern}` in string literal \
68                         (use env vars or config)"
69                    ),
70                ));
71                break;
72            }
73        }
74    }
75
76    out
77}
78
79crate::tidy_test!(check_abs_home_path, {
80    crate::example_tests!(EXAMPLES, check_abs_home_path);
81});