1use quote::quote;
2use proc_macro::TokenStream;
3use syn::{ItemFn, AttributeArgs, NestedMeta};
4
5#[proc_macro_derive(Component)]
6pub fn component_derive(input: TokenStream) -> TokenStream {
7 let ast: syn::DeriveInput = syn::parse(input).unwrap();
8 let name = &ast.ident;
9 let gen = quote! {
10 impl autowired::Component for #name {
11 fn new_instance() -> Option<Self> {
12 Some(Default::default())
13 }
14 }
15 autowired::submit! {
16 autowired::Bean::new_unchecked::<#name>()
17 }
18 };
19
20 gen.into()
21}
22
23#[proc_macro_derive(LazyComponent)]
24pub fn lazy_component_derive(input: TokenStream) -> TokenStream {
25 let ast: syn::DeriveInput = syn::parse(input).unwrap();
26 let name = &ast.ident;
27 let gen = quote! {
28 impl autowired::Component for #name {
29 fn new_instance() -> Option<Self> {
30 Some(Default::default())
31 }
32 }
33 autowired::submit! {
34 autowired::Bean::new_unchecked_lazy::<#name>()
35 }
36 };
37 gen.into()
38}
39
40#[proc_macro_attribute]
41pub fn bean(args: TokenStream, input: TokenStream) -> TokenStream {
42 let args = syn::parse_macro_input!(args as AttributeArgs);
43
44 let mut is_lazy = false;
45 let mut is_option = false;
46 for meta in args {
47 if let NestedMeta::Meta(nv) = meta {
48 if nv.path().is_ident("lazy") {
49 is_lazy = true;
50 }
51
52 if nv.path().is_ident("option") {
53 is_option = true;
54 }
55 }
56 }
57
58 let func = syn::parse_macro_input!(input as ItemFn);
59
60 let block = &func.block;
61 let vis = &func.vis;
62 let name = &func.sig.ident;
63 let output = &func.sig.output;
64
65 let submit_method = if is_option {
66 quote! { autowired::Bean::from_fn_return_option(#name, #is_lazy) }
67 } else {
68 quote! { autowired::Bean::from_fn(#name, #is_lazy) }
69 };
70
71 let gen = quote! {
72 #vis fn #name() #output {
73 #block
74 }
75 autowired::submit! {
76 #submit_method
77 }
78 };
79
80 gen.into()
81}
82