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
extern crate proc_macro; use ::proc_macro::TokenStream; use ::syn::{ ItemFn, parse_macro_input, parse_quote, }; #[proc_macro_attribute] pub fn function_name (params: TokenStream, input: TokenStream) -> TokenStream { if params.into_iter().next().is_some() { return TokenStream::from(::quote::quote! { compile_error!( "#[function_name] does not take arguments" ); }); } let mut fn_decl = parse_macro_input!(input as ItemFn); let block = *fn_decl.block; let ident = &fn_decl.ident; *fn_decl.block = parse_quote! { { #[allow(non_camel_case_types)] #[derive(function_name::function_name_hack)] enum #ident {} #block } }; TokenStream::from(::quote::quote!{ #fn_decl }) } #[doc(hidden)] #[proc_macro_derive(function_name_hack)] pub fn hack (input: TokenStream) -> TokenStream { let input: ::syn::DeriveInput = parse_macro_input!(input); let fname = ::syn::LitStr::new(&input.ident.to_string(), input.ident.span()); TokenStream::from(::quote::quote!{ macro_rules! function_name {() => ( #fname )} }) }