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 48 49 50 51 52 53 54 55
extern crate proc_macro; extern crate syn; extern crate regex; use proc_macro::TokenStream; use syn::*; use component::generate_component_impl; use provider::*; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::parse::Parser; use std::str::FromStr; use regex::Regex; mod component; mod provider; #[proc_macro_attribute] pub fn component(_attr: TokenStream, item: TokenStream) -> TokenStream { let comp = syn::parse::<ItemStruct>(item.clone()).unwrap(); let mut res: TokenStream = TokenStream::from_str( Regex::new(r"#\[prop\(.+\)]").unwrap() .replace_all(&item.to_string(), "") .as_ref() ).unwrap_or_default(); res.extend(generate_component_impl(comp.clone())); res.extend(generate_component_provider_impl_struct(comp.clone())); return res; } #[proc_macro_attribute] pub fn provides(attr: TokenStream, item: TokenStream) -> TokenStream { let profiles = <Punctuated<Path, Comma>>::parse_terminated.parse(attr) .expect("Can't parse profiles"); let profiles: Vec<&Path> = profiles .iter() .collect(); let mut res = item.clone(); let impl_block = syn::parse::<ItemImpl>(item.clone()); if impl_block.is_ok() { res.extend(generate_interface_provider_impl(profiles, impl_block.unwrap().clone())); } else { let fn_block = syn::parse::<ItemFn>(item.clone()) .expect("#[provides] must be used only on impl blocks and factory functions"); res.extend(generate_component_provider_impl_fn(profiles, fn_block.clone())); } return res; }