1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//! Macros for easily making rule tests which also generate documentation examples.

/// A macro for generating linter rule tests.
///
/// The tests are also used to generate "more examples" sections
/// in user facing docs. You can use a `/// ignore` doc
/// on a code expr to make docgen ignore it for user facing docs.
///
/// test code is run as modules, not scripts.
#[macro_export]
macro_rules! rule_tests {
    ($rule:expr,
    err: {
        $(
            // An optional tag to give to docgen
            $(#[$err_meta:meta])*
            $code:literal
        ),* $(,)?
    },

    // Optional doc used in the user facing docs for the
    // more valid code examples section.
    $(#[_:meta])*
    ok: {
        $(
            // An optional tag to give to docgen
            $(#[$ok_meta:meta])*
            $ok_code:literal
        ),* $(,)?
    } $(,)?) => {
        rule_tests!(valid, invalid, $rule, err: { $($code),* }, ok: { $($ok_code),* });
    };
    (
    $ok_name:ident,
    $err_name:ident,
    $rule:expr,
    err: {
        $(
            // An optional tag to give to docgen
            $(#[$err_meta:meta])*
            $code:literal
        ),* $(,)?
    },
    ok: {
        $(
            // An optional tag to give to docgen
            $(#[$ok_meta:meta])*
            $ok_code:literal
        ),* $(,)?
    } $(,)?) => {
        #[test]
        fn $err_name() {
            $(
                let res = rslint_parser::parse_module($code, 0);
                let errs = $crate::run_rule(&$rule, 0, res.syntax(), true, &[], std::sync::Arc::new($code.to_string()));
                if errs.diagnostics.is_empty() {
                    panic!("\nExpected:\n```\n{}\n```\nto fail linting, but instead it passed (with {} parsing errors)", $code, res.errors().len());
                }
            )*
        }

        #[test]
        fn $ok_name() {
            $(
                let res = rslint_parser::parse_module($ok_code, 0);
                let errs = $crate::run_rule(&$rule, 0, res.syntax(), true, &[], std::sync::Arc::new($ok_code.to_string()));

                if !errs.diagnostics.is_empty() {
                    panic!("\nExpected:\n```\n{}\n```\nto pass linting, but instead it threw errors (along with {} parsing errors):\n\n", $ok_code, res.errors().len());
                }
            )*
        }
    };
}