Skip to main content

wowlab_tidy/languages/rust/rules/api/
forbidden_deps.rs

1use crate::{Example, FileCtx, Violation, infra::parse, violation};
2
3#[rustfmt::skip]
4const EXAMPLES: &[Example] = &[
5    Example {
6        label: "std::net import",
7        code: "use std::net::TcpStream;",
8        pass: false,
9    },
10    Example {
11        label: "std::thread import",
12        code: "use std::thread;",
13        pass: false,
14    },
15    Example {
16        label: "normal import",
17        code: "use std::collections::HashMap;",
18        pass: true,
19    },
20    Example {
21        label: "comment with forbidden",
22        code: "// use std::thread::spawn",
23        pass: true,
24    },
25    Example {
26        label: "forbidden in string literal",
27        code: r#"let msg = "std::net is unavailable";"#,
28        pass: true,
29    },
30];
31
32crate::line_rule!(
33    forbidden_deps,
34    "Ban `std::net` and `std::thread` in WASM-targeted crates.",
35    "std::net and std::thread are not available in WASM. Using them in engine code breaks the web build.",
36    High,
37);
38
39const FORBIDDEN_MODULES: &[&str] = &["std::net", "std::thread"];
40
41fn check_forbidden_deps(ctx: &FileCtx<'_>) -> Vec<Violation> {
42    let mut out = Vec::new();
43
44    for (i, line) in ctx.lines.iter().enumerate() {
45        let lineno = i + 1;
46        let trimmed = line.trim();
47
48        if parse::is_comment(trimmed) {
49            continue;
50        }
51
52        for module in FORBIDDEN_MODULES {
53            if crate::infra::helpers::contains_outside_strings(line, module) {
54                out.push(violation(
55                    ctx.rel,
56                    lineno,
57                    format!("{module} is forbidden in WASM-targeted crates"),
58                ));
59            }
60        }
61    }
62
63    out
64}
65
66crate::tidy_test!(check_forbidden_deps, {
67    crate::example_tests!(EXAMPLES, check_forbidden_deps);
68});