df_ls_derive 0.3.0-rc.1

A language server for Dwarf Fortress RAW files
Documentation
use crate::common;
use quote::{quote, quote_spanned};
use std::collections::HashMap;

#[derive(Clone, Debug, Default)]
pub struct StructDeInfo {
    pub token: Option<String>,
    pub second_par_check: bool,
    pub enum_value: bool,
}

pub fn get_struct_enum_de_info(ast: &syn::DeriveInput) -> (StructDeInfo, proc_macro2::TokenStream) {
    let mut struct_info = StructDeInfo::default();
    let mut errors = quote! {};
    let struct_attrs = get_struct_attrs_variables(ast);
    for (key, val) in struct_attrs {
        let mut string_quote = "".to_string();
        if let Some(val) = val {
            if let syn::Lit::Str(string_lit) = val.clone() {
                string_quote = string_lit.value();
            }
            if string_quote.is_empty() {
                continue;
            }
            if string_quote.contains(' ') {
                let error = quote_spanned! {
                    val.span() =>
                    compile_error!(
                        "String contains spaces."
                    );
                };
                errors = quote! {
                    #errors
                    #error
                };
            }
        }
        match key.as_ref() {
            "token" => struct_info.token = Some(string_quote),
            "second_par_check" => struct_info.second_par_check = true,
            "enum_value" => struct_info.enum_value = true,
            _ => {}
        }
    }
    (struct_info, errors)
}

fn get_struct_attrs_variables(ast: &syn::DeriveInput) -> HashMap<String, Option<syn::Lit>> {
    let mut lit_list: HashMap<String, Option<syn::Lit>> = HashMap::new();
    for attr in &ast.attrs {
        let meta_items = common::get_meta_items(attr, "token_de").unwrap();
        for meta_item in meta_items {
            match meta_item {
                // Parse `#[token_de(token = "foo")]`
                syn::NestedMeta::Meta(syn::Meta::NameValue(m)) if m.path.is_ident("token") => {
                    lit_list.insert("token".to_owned(), Some(m.lit));
                }
                // Parse `#[token_de(second_par_check)]`
                syn::NestedMeta::Meta(syn::Meta::Path(m)) if m.is_ident("second_par_check") => {
                    lit_list.insert("second_par_check".to_owned(), None);
                }
                // Parse `#[token_de(enum_value)]`
                syn::NestedMeta::Meta(syn::Meta::Path(m)) if m.is_ident("enum_value") => {
                    lit_list.insert("enum_value".to_owned(), None);
                }
                _ => (),
            };
        }
    }
    lit_list
}