flat_enum_macro 0.1.1

Expand nested enum into flattened enum
Documentation
use derive_syn_parse::Parse;
use proc_macro2::TokenStream;
use proc_macro_error::abort;
use syn::spanned::Spanned;
use syn::*;
use template_quote::quote;

#[derive(Parse)]
pub struct MacroArg {
    structured_path: Path,
    _at_token: Option<Token![@]>,
    #[parse_if(_at_token.is_some())]
    krate: Option<Path>,
}

pub fn flat(arg: MacroArg, input: ItemEnum) -> TokenStream {
    let MacroArg {
        structured_path,
        krate,
        ..
    } = arg;
    let krate = krate.unwrap_or(parse_quote!(::flat_enum));
    let (g_impl, g_type, g_where) = input.generics.split_for_impl();
    let macro_name =
        if structured_path.leading_colon.is_none() && structured_path.segments.len() == 1 {
            &structured_path.segments[0].ident
        } else {
            abort!(
                structured_path.span(),
                "Should be exist in the same context"
            );
        };
    if input.variants.len() > 0 {
        abort!(input.span(), "Cannot specify variants");
    }
    quote! {
        #[automatically_derived]
        unsafe impl #g_impl #krate::Flat for #{ &input.ident } #g_type #g_where {
            type Structured = #structured_path;
        }
        #macro_name!(
            @emit_enum
            flat_enum = #{env!("CARGO_PKG_VERSION")},
            enum_decl = {
                #(for attr in &input.attrs) { #attr }
                #{&input.vis}
                #{&input.enum_token}
                #{&input.ident}
                #g_type
            },
        );
    }
}