cgp_component_macro_lib/derive_component/
provider_impl.rs1use alloc::boxed::Box;
2use alloc::vec::Vec;
3
4use proc_macro2::Span;
5use syn::punctuated::Punctuated;
6use syn::token::{Brace, Comma, For, Impl, Plus};
7use syn::{
8 parse_quote, GenericParam, Ident, ImplItem, ItemImpl, ItemTrait, Path, TraitItem,
9 TypeParamBound,
10};
11
12use crate::derive_component::delegate_fn::derive_delegated_fn_impl;
13use crate::derive_component::delegate_type::derive_delegate_type_impl;
14
15pub fn derive_provider_impl(
16 provider_trait: &ItemTrait,
17 component_name: &Ident,
18 component_params: &Punctuated<Ident, Comma>,
19) -> ItemImpl {
20 let provider_name = &provider_trait.ident;
21
22 let component_type = Ident::new("Component", Span::call_site());
23
24 let provider_generic_args = {
25 let mut generic_args: Punctuated<Ident, Comma> = Punctuated::new();
26
27 for param in provider_trait.generics.params.iter() {
28 match param {
29 GenericParam::Type(ty) => {
30 generic_args.push(ty.ident.clone());
31 }
32 GenericParam::Const(arg) => {
33 generic_args.push(arg.ident.clone());
34 }
35 GenericParam::Lifetime(_life) => {
36 unimplemented!()
37 }
38 }
39 }
40
41 generic_args
42 };
43
44 let impl_generics = {
45 let mut impl_generics = provider_trait.generics.clone();
46
47 impl_generics
48 .params
49 .insert(0, parse_quote!(#component_type));
50
51 {
52 let delegate_constraint: Punctuated<TypeParamBound, Plus> = parse_quote! {
53 DelegateComponent< #component_name < #component_params > >
54 };
55
56 let provider_constraint: Punctuated<TypeParamBound, Plus> = parse_quote! {
57 #provider_name < #provider_generic_args >
58 };
59
60 match &mut impl_generics.where_clause {
61 Some(where_clause) => {
62 where_clause.predicates.push(parse_quote! {
63 #component_type : #delegate_constraint
64 });
65
66 where_clause.predicates.push(parse_quote! {
67 #component_type :: Delegate : #provider_constraint
68 });
69 }
70 _ => {
71 impl_generics.where_clause = Some(parse_quote! {
72 where
73 #component_type : #delegate_constraint,
74 #component_type :: Delegate : #provider_constraint
75 });
76 }
77 }
78 }
79
80 impl_generics
81 };
82
83 let mut impl_items: Vec<ImplItem> = Vec::new();
84
85 for trait_item in provider_trait.items.iter() {
86 match trait_item {
87 TraitItem::Fn(trait_fn) => {
88 let impl_fn = derive_delegated_fn_impl(
89 &trait_fn.sig,
90 &parse_quote!(#component_type :: Delegate),
91 );
92
93 impl_items.push(ImplItem::Fn(impl_fn))
94 }
95 TraitItem::Type(trait_type) => {
96 let type_name = &trait_type.ident;
97 let type_generics = {
98 let mut type_generics = trait_type.generics.clone();
99 type_generics.where_clause = None;
100
101 for param in &mut type_generics.params {
102 if let GenericParam::Type(type_param) = param {
103 type_param.bounds.clear();
104 }
105 }
106
107 type_generics
108 };
109
110 let impl_type = derive_delegate_type_impl(
111 trait_type,
112 parse_quote!(
113 < #component_type :: Delegate as #provider_name < #provider_generic_args > > :: #type_name #type_generics
114 ),
115 );
116
117 impl_items.push(ImplItem::Type(impl_type));
118 }
119 _ => {}
120 }
121 }
122
123 let trait_path: Path = parse_quote!( #provider_name < #provider_generic_args > );
124
125 ItemImpl {
126 attrs: provider_trait.attrs.clone(),
127 defaultness: None,
128 unsafety: provider_trait.unsafety,
129 impl_token: Impl::default(),
130 generics: impl_generics,
131 trait_: Some((None, trait_path, For::default())),
132 self_ty: Box::new(parse_quote!(#component_type)),
133 brace_token: Brace::default(),
134 items: impl_items,
135 }
136}