aboutsummaryrefslogtreecommitdiff
path: root/mingling_cli/src/linter/mlint_attr.rs
blob: 24528d47a679f21f7fea4f5b1678f2aee5e3707b (plain) (blame)
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
/// Result of checking `mlint(allow/warn/deny(...))` attributes.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum MlintLevelOverride {
    Allow,
    Warn,
    Deny,
}

/// Parse `mlint(allow/warn/deny(lint_name))` from attributes.
/// Returns `None` if the lint is not mentioned in any mlint attribute.
pub fn get_mlint_override(attrs: &[syn::Attribute], lint_name: &str) -> Option<MlintLevelOverride> {
    for attr in attrs {
        if !attr.path().is_ident("mlint") {
            continue;
        }
        let list = match attr.meta.require_list() {
            Ok(l) => l,
            Err(_) => continue,
        };
        // TokenStream::to_string() adds spaces between tokens,
        // e.g. `allow(xxx)` → `allow ( xxx )`. Remove all spaces to compare.
        let flat: String = list
            .tokens
            .to_string()
            .chars()
            .filter(|c| !c.is_whitespace())
            .collect();
        for (keyword, variant) in [
            ("allow", MlintLevelOverride::Allow),
            ("warn", MlintLevelOverride::Warn),
            ("deny", MlintLevelOverride::Deny),
        ] {
            if flat.contains(&format!("{keyword}({lint_name})")) {
                return Some(variant);
            }
        }
    }
    None
}