cgp_macro_lib/entrypoints/
cgp_context.rs1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{Ident, ItemImpl, ItemStruct, parse2};
4
5use crate::derive_context::{derive_delegate_preset, derive_has_components};
6use crate::parse::ContextSpec;
7
8pub fn cgp_context(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream> {
9 let context_struct: ItemStruct = syn::parse2(body)?;
10
11 let context_spec: ContextSpec = if !attr.is_empty() {
12 syn::parse2(attr)?
13 } else {
14 let provider_name = Ident::new(
15 &format!("{}Components", context_struct.ident),
16 context_struct.ident.span(),
17 );
18
19 ContextSpec {
20 provider_name,
21 provider_generics: None,
22 preset: None,
23 }
24 };
25
26 let provider_name = &context_spec.provider_name;
27 let provider_generics = &context_spec.provider_generics;
28
29 let provider_phantom = match provider_generics {
30 Some(generics) => {
31 let params = &generics.generics.params;
32 quote! { ( ::core::marker::PhantomData<( #params )> ) }
33 }
34 None => quote! {},
35 };
36
37 let provider_struct: ItemStruct =
38 parse2(quote!( pub struct #provider_name #provider_generics #provider_phantom; ))?;
39
40 let has_components_impl: ItemImpl =
41 derive_has_components(provider_name, provider_generics, &context_struct)?;
42
43 let base_derived = quote! {
44 #context_struct
45
46 #provider_struct
47
48 #has_components_impl
49 };
50
51 match &context_spec.preset {
52 Some(preset) => {
53 let (delegate_impl, is_provider_impl) =
54 derive_delegate_preset(provider_name, provider_generics, preset)?;
55
56 Ok(quote! {
57 #base_derived
58
59 #delegate_impl
60
61 #is_provider_impl
62 })
63 }
64 _ => Ok(base_derived),
65 }
66}