summaryrefslogtreecommitdiffstats
path: root/src/tools/rustfmt/config_proc_macro/src/attrs.rs
blob: dd18ff572cb1cd28daee3d0925f459557ae202fd (plain)
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
75
76
//! This module provides utilities for handling attributes on variants
//! of `config_type` enum. Currently there are the following attributes
//! that could appear on the variants of `config_type` enum:
//!
//! - `doc_hint`: name-value pair whose value is string literal
//! - `value`: name-value pair whose value is string literal
//! - `unstable_variant`: name only

/// Returns the value of the first `doc_hint` attribute in the given slice or
/// `None` if `doc_hint` attribute is not available.
pub fn find_doc_hint(attrs: &[syn::Attribute]) -> Option<String> {
    attrs.iter().filter_map(doc_hint).next()
}

/// Returns `true` if the given attribute is a `doc_hint` attribute.
pub fn is_doc_hint(attr: &syn::Attribute) -> bool {
    is_attr_name_value(attr, "doc_hint")
}

/// Returns a string literal value if the given attribute is `doc_hint`
/// attribute or `None` otherwise.
pub fn doc_hint(attr: &syn::Attribute) -> Option<String> {
    get_name_value_str_lit(attr, "doc_hint")
}

/// Returns the value of the first `value` attribute in the given slice or
/// `None` if `value` attribute is not available.
pub fn find_config_value(attrs: &[syn::Attribute]) -> Option<String> {
    attrs.iter().filter_map(config_value).next()
}

/// Returns `true` if the there is at least one `unstable` attribute in the given slice.
pub fn any_unstable_variant(attrs: &[syn::Attribute]) -> bool {
    attrs.iter().any(is_unstable_variant)
}

/// Returns a string literal value if the given attribute is `value`
/// attribute or `None` otherwise.
pub fn config_value(attr: &syn::Attribute) -> Option<String> {
    get_name_value_str_lit(attr, "value")
}

/// Returns `true` if the given attribute is a `value` attribute.
pub fn is_config_value(attr: &syn::Attribute) -> bool {
    is_attr_name_value(attr, "value")
}

/// Returns `true` if the given attribute is an `unstable` attribute.
pub fn is_unstable_variant(attr: &syn::Attribute) -> bool {
    is_attr_path(attr, "unstable_variant")
}

fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
    attr.parse_meta().ok().map_or(false, |meta| match meta {
        syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident(name) => true,
        _ => false,
    })
}

fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool {
    attr.parse_meta().ok().map_or(false, |meta| match meta {
        syn::Meta::Path(path) if path.is_ident(name) => true,
        _ => false,
    })
}

fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option<String> {
    attr.parse_meta().ok().and_then(|meta| match meta {
        syn::Meta::NameValue(syn::MetaNameValue {
            ref path,
            lit: syn::Lit::Str(ref lit_str),
            ..
        }) if path.is_ident(name) => Some(lit_str.value()),
        _ => None,
    })
}