cgp_macro_lib/entrypoints/
delegate_and_check_components.rs

1use proc_macro2::{Span, TokenStream};
2use quote::{ToTokens, TokenStreamExt};
3use syn::punctuated::Punctuated;
4use syn::spanned::Spanned;
5use syn::token::{Comma, Where};
6use syn::{Type, WhereClause, parse2};
7
8use crate::check_components::derive_check_components;
9use crate::delegate_components::impl_delegate_components;
10use crate::parse::{
11    CheckComponents, CheckEntries, CheckEntry, DelegateAndCheckSpec, DelegateEntry, DelegateKey,
12    DelegateValue, ImplGenerics,
13};
14
15pub fn delegate_and_check_components(body: TokenStream) -> syn::Result<TokenStream> {
16    let spec: DelegateAndCheckSpec = parse2(body)?;
17
18    let check_entries: Vec<CheckEntry> = spec
19        .entries
20        .iter()
21        .flat_map(|entry| {
22            entry.keys.iter().map(|component_type| {
23                let span = component_type.span();
24
25                CheckEntry {
26                    component_type: component_type.clone(),
27                    component_params: None,
28                    span,
29                }
30            })
31        })
32        .collect();
33
34    let delegate_entries: Punctuated<DelegateEntry<Type>, Comma> = spec
35        .entries
36        .into_iter()
37        .map(|entry| {
38            let keys = entry
39                .keys
40                .into_iter()
41                .map(|ty| DelegateKey {
42                    ty,
43                    generics: ImplGenerics::default(),
44                })
45                .collect();
46
47            let value = DelegateValue::Type(entry.value);
48
49            DelegateEntry {
50                keys,
51                value,
52                mode: entry.mode,
53            }
54        })
55        .collect();
56
57    let mut out =
58        impl_delegate_components(&spec.provider_type, &spec.impl_generics, &delegate_entries)?;
59
60    let check_spec = CheckComponents {
61        impl_generics: spec.impl_generics,
62        trait_name: spec.trait_name,
63        context_type: spec.context_type,
64        where_clause: WhereClause {
65            where_token: Where(Span::call_site()),
66            predicates: Punctuated::default(),
67        },
68        check_entries: CheckEntries {
69            entries: check_entries,
70        },
71    };
72
73    let (check_item_trait, check_item_impls) = derive_check_components(&check_spec)?;
74
75    out.extend(check_item_trait.to_token_stream());
76    out.append_all(check_item_impls);
77
78    Ok(out)
79}