portrait_framework/
derive_filler.rs

1use proc_macro2::TokenStream;
2use syn::parse::{Parse, ParseStream};
3use syn::Result;
4
5/// Determines how to derive an impl.
6pub trait FillDerive {
7    /// The arguments passed to the filler through macros.
8    type Args: Parse;
9
10    /// Derives the impl given a portrait of the trait items and the derived item.
11    fn fill(
12        self,
13        trait_path: &syn::Path,
14        portrait: &[syn::TraitItem],
15        args: Self::Args,
16        input: &syn::DeriveInput,
17    ) -> Result<TokenStream>;
18}
19
20/// Parses the macro input directly and passes them to the filler.
21///
22/// Use this function if information of all implemented/unimplemented trait/impl items
23/// are required at the same time.
24/// If the filler just maps each unimplemented trait item to an impl item statelessly,
25/// use [`completer_derive_filler2`](crate::completer_derive_filler2)/[`proc_macro_derive_filler`](crate::proc_macro_derive_filler) for shorthand.
26pub fn derive_filler<FillerT: FillDerive>(
27    input: TokenStream,
28    filler: FillerT,
29) -> Result<TokenStream> {
30    let Input::<FillerT::Args> { trait_path, portrait, args, input, debug_print } =
31        syn::parse2(input)?;
32
33    let output = filler.fill(&trait_path, &portrait, args, &input)?;
34
35    if debug_print {
36        println!("{output}");
37    }
38
39    Ok(output)
40}
41
42mod kw {
43    syn::custom_keyword!(TRAIT_PORTRAIT);
44    syn::custom_keyword!(TRAIT_PATH);
45    syn::custom_keyword!(ARGS);
46    syn::custom_keyword!(INPUT);
47    syn::custom_keyword!(DEBUG_PRINT_FILLER_OUTPUT);
48}
49
50pub(crate) struct Input<ArgsT> {
51    pub(crate) trait_path:  syn::Path,
52    pub(crate) portrait:    Vec<syn::TraitItem>,
53    pub(crate) args:        ArgsT,
54    pub(crate) input:       syn::DeriveInput,
55    pub(crate) debug_print: bool,
56}
57
58impl<ArgsT: Parse> Parse for Input<ArgsT> {
59    fn parse(input: ParseStream) -> Result<Self> {
60        input.parse::<kw::TRAIT_PORTRAIT>()?;
61
62        let portrait_braced;
63        syn::braced!(portrait_braced in input);
64        let mut portrait = Vec::new();
65        while !portrait_braced.is_empty() {
66            let item_braced;
67            syn::braced!(item_braced in portrait_braced);
68            let item: syn::TraitItem = item_braced.parse()?;
69            if !item_braced.is_empty() {
70                return Err(item_braced.error("braces should only contain one trait item"));
71            }
72            portrait.push(item);
73        }
74
75        input.parse::<kw::TRAIT_PATH>()?;
76        let trait_path_braced;
77        syn::braced!(trait_path_braced in input);
78        let trait_path: syn::Path = trait_path_braced.parse()?;
79        if !trait_path_braced.is_empty() {
80            return Err(trait_path_braced.error("trait path not fully parsed"));
81        }
82
83        input.parse::<kw::ARGS>()?;
84        let args_braced;
85        syn::braced!(args_braced in input);
86        let args: ArgsT = args_braced.parse()?;
87        if !args_braced.is_empty() {
88            return Err(args_braced.error("args not fully parsed"));
89        }
90
91        input.parse::<kw::INPUT>()?;
92        let input_braced;
93        syn::braced!(input_braced in input);
94        let derive_input = input_braced.parse()?;
95        if !input_braced.is_empty() {
96            return Err(input_braced.error("trailing tokens after input block"));
97        }
98
99        input.parse::<kw::DEBUG_PRINT_FILLER_OUTPUT>()?;
100        let dpfo_braced;
101        syn::braced!(dpfo_braced in input);
102        let dpfo: syn::LitBool = dpfo_braced.parse()?;
103        if !dpfo_braced.is_empty() {
104            return Err(input_braced.error("trailing tokens after input block"));
105        }
106
107        if !input.is_empty() {
108            return Err(input.error("trailing tokens in macro input"));
109        }
110
111        Ok(Self { trait_path, portrait, args, input: derive_input, debug_print: dpfo.value })
112    }
113}