cgp_component_macro_lib/delegate_components/
ast.rs

1use core::iter;
2
3use proc_macro2::TokenStream;
4use quote::ToTokens;
5use syn::parse::{Parse, ParseStream};
6use syn::punctuated::Punctuated;
7use syn::token::{Bracket, Colon, Comma, Lt};
8use syn::{braced, bracketed, Generics, Token, Type};
9
10pub struct DelegateComponentsAst {
11    pub target_type: Type,
12    pub target_generics: Generics,
13    pub delegate_entries: DelegateEntriesAst,
14}
15
16pub struct DelegateEntriesAst {
17    pub entries: Punctuated<DelegateEntryAst, Comma>,
18}
19
20pub struct DelegateEntryAst {
21    pub components: Punctuated<ComponentAst, Comma>,
22    pub source: Type,
23}
24
25#[derive(Clone)]
26pub struct ComponentAst {
27    pub component_type: Type,
28    pub component_generics: Generics,
29}
30
31impl DelegateEntriesAst {
32    pub fn all_components(&self) -> Punctuated<ComponentAst, Comma> {
33        self.entries
34            .iter()
35            .flat_map(|entry| entry.components.clone().into_iter())
36            .collect()
37    }
38}
39
40impl Parse for DelegateComponentsAst {
41    fn parse(input: ParseStream) -> syn::Result<Self> {
42        let target_generics = if input.peek(Lt) {
43            input.parse()?
44        } else {
45            Default::default()
46        };
47
48        let target_type: Type = input.parse()?;
49
50        let delegate_entries: DelegateEntriesAst = input.parse()?;
51
52        Ok(Self {
53            target_type,
54            target_generics,
55            delegate_entries,
56        })
57    }
58}
59
60impl Parse for DelegateEntriesAst {
61    fn parse(input: ParseStream) -> syn::Result<Self> {
62        let entries = {
63            let entries_body;
64            braced!(entries_body in input);
65            entries_body.parse_terminated(DelegateEntryAst::parse, Comma)?
66        };
67
68        Ok(Self { entries })
69    }
70}
71
72impl Parse for DelegateEntryAst {
73    fn parse(input: ParseStream) -> syn::Result<Self> {
74        let components = if input.peek(Bracket) {
75            let components_body;
76            bracketed!(components_body in input);
77            components_body.parse_terminated(ComponentAst::parse, Token![,])?
78        } else {
79            let component: ComponentAst = input.parse()?;
80            Punctuated::from_iter(iter::once(component))
81        };
82
83        let _: Colon = input.parse()?;
84
85        let source: Type = input.parse()?;
86
87        Ok(Self { components, source })
88    }
89}
90
91impl Parse for ComponentAst {
92    fn parse(input: ParseStream) -> syn::Result<Self> {
93        let component_generics = if input.peek(Lt) {
94            input.parse()?
95        } else {
96            Default::default()
97        };
98
99        let component_type: Type = input.parse()?;
100
101        Ok(Self {
102            component_type,
103            component_generics,
104        })
105    }
106}
107
108impl ToTokens for ComponentAst {
109    fn to_tokens(&self, tokens: &mut TokenStream) {
110        tokens.extend(self.component_generics.to_token_stream());
111        tokens.extend(self.component_type.to_token_stream());
112    }
113}