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
use proc_macro2::Span;
use syn::{Ident, MetaList, NestedMeta};

/// Returns the `Ident` of a nested meta. If it is a literal, `None` is returned.
///
/// # Parameters
///
/// * `nested_meta`: The `NestedMeta` to extract the `Ident` from.
pub fn nested_meta_to_ident(nested_meta: &NestedMeta) -> Option<Ident> {
    match nested_meta {
        NestedMeta::Meta(meta) => Some(meta.name()),
        NestedMeta::Literal(..) => None,
    }
}

/// Returns whether the `MetaList` contains the specified `NestedMeta`.
///
/// This can be used to check if a `#[derive(..)]` contains `SomeDerive`.
///
/// # Parameters
///
/// * `meta_list`: The `MetaList` to check.
/// * `operand`: `NestedMeta` that may be in the list.
pub fn meta_list_contains(meta_list: &MetaList, operand: &NestedMeta) -> bool {
    meta_list
        .nested
        .iter()
        .any(|nested_meta| nested_meta == operand)
}

/// Returns an `Ident` by concatenating `String` representations.
pub fn ident_concat(left: &str, right: &str) -> Ident {
    let mut combined = String::with_capacity(left.len() + right.len());
    combined.push_str(left);
    combined.push_str(right);

    Ident::new(&combined, Span::call_site())
}