df_ls_derive 0.3.0-rc.1

A language server for Dwarf Fortress RAW files
Documentation
/// Return `true` if type is a `Vec`, otherwise `false`
pub fn check_type_is_vec(ty: &syn::Type) -> bool {
    check_type(ty, "Vec")
}

/// Return `true` if type is same as `ident` given.
/// Otherwise `false` is returned.
fn check_type(ty: &syn::Type, ident: &str) -> bool {
    match &ty {
        syn::Type::Path(type_path) => {
            if let Some(segment) = type_path.path.segments.first() {
                segment.ident == ident
            } else {
                false
            }
        }
        _ => false,
    }
}

/// Return inner type (`T`) for `Vec<T>` or `Option<T>`.
pub fn get_inner_type(ty: &syn::Type) -> Option<syn::Type> {
    match &ty {
        syn::Type::Path(type_path) => {
            if let Some(segment) = type_path.path.segments.first() {
                match &segment.arguments {
                    syn::PathArguments::AngleBracketed(angle_arg) => {
                        if let Some(arg_segment) = angle_arg.args.first() {
                            match arg_segment {
                                syn::GenericArgument::Type(inner_ty) => Some(inner_ty.clone()),
                                _ => None,
                            }
                        } else {
                            None
                        }
                    }
                    _ => None,
                }
            } else {
                None
            }
        }
        _ => None,
    }
}

/// Similar to `get_struct_data` but creates a list of `Field`s the contains the whole line.
/// Example
/// ```ignore
/// Point{
///     x: i32,
///     y: i32,
/// }
/// ```
/// Will return `[{ident:x, type:i32,...},{ident:y, type:i32,...}]` but then as an `syn::Field`
pub fn get_struct_enum_fields(ast: &syn::DeriveInput) -> Vec<syn::Field> {
    let mut list = Vec::new();
    match &ast.data {
        syn::Data::Struct(x) => match &x.fields {
            syn::Fields::Named(x) => {
                for field in &x.named {
                    list.push(field.clone());
                }
            }
            syn::Fields::Unnamed(_) => {}
            syn::Fields::Unit => {}
        },
        syn::Data::Enum(x) => {
            for variant in &x.variants {
                match &variant.fields {
                    syn::Fields::Named(_) => {}
                    syn::Fields::Unnamed(x) => {
                        for field in &x.unnamed {
                            let mut field_new = field.clone();
                            let mut variant_attrs = variant.attrs.clone();
                            field_new.attrs.append(&mut variant_attrs);
                            field_new.ident = Some(variant.ident.clone());
                            list.push(field_new);
                        }
                    }
                    syn::Fields::Unit => {
                        list.push(syn::Field {
                            attrs: variant.attrs.clone(),
                            vis: syn::Visibility::Inherited,
                            ident: Some(variant.ident.clone()),
                            colon_token: None,
                            ty: syn::Type::Tuple(syn::TypeTuple {
                                paren_token: syn::token::Paren::default(),
                                elems: syn::punctuated::Punctuated::default(),
                            }),
                        });
                    }
                }
            }
        }
        syn::Data::Union(_x) => {}
    };
    list
}

/// Only add our `#[token_de(...)]` tokens where `ident = "token_de"`
// From https://github.com/serde-rs/serde/blob/master/serde_derive/src/internals/attr.rs line 1566
pub fn get_meta_items(attr: &syn::Attribute, ident: &str) -> Result<Vec<syn::NestedMeta>, ()> {
    if !attr.path.is_ident(ident) {
        return Ok(Vec::new());
    }

    match attr.parse_meta() {
        Ok(syn::Meta::List(meta)) => Ok(meta.nested.into_iter().collect()),
        Ok(_other) => Err(()),
        Err(_err) => Err(()),
    }
}