1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use proc_macro2::TokenStream;
use syn::parse::{Parse, ParseStream};
use syn::Result;

/// Determines how to fill the implementation of a trait.
pub trait Fill {
    /// The arguments passed to the completer through macros.
    type Args: Parse;

    /// Completes the impl given a portrait of the trait items.
    fn fill(
        self,
        portrait: &[syn::TraitItem],
        args: Self::Args,
        item_impl: &syn::ItemImpl,
    ) -> Result<TokenStream>;
}

/// Parses the macro input directly and passes them to the completer.
///
/// Use this function if information of all implemented/unimplemented trait/impl items
/// are required at the same time.
/// If the completer just maps each unimplemented trait item to an impl item statelessly,
/// use [`completer_filler2`](crate::completer_filler2)/[`proc_macro_filler`](crate::proc_macro_filler) instead.
pub fn filler<FillerT: Fill>(input: TokenStream, completer: FillerT) -> Result<TokenStream> {
    let Input::<FillerT::Args> { portrait, args, item_impl, debug_print } = syn::parse2(input)?;

    let output = completer.fill(&portrait, args, &item_impl)?;

    if debug_print {
        println!("{output}");
    }

    Ok(output)
}

mod kw {
    syn::custom_keyword!(TRAIT_PORTRAIT);
    syn::custom_keyword!(ARGS);
    syn::custom_keyword!(IMPL);
    syn::custom_keyword!(DEBUG_PRINT_FILLER_OUTPUT);
}

pub(crate) struct Input<ArgsT> {
    pub(crate) portrait:    Vec<syn::TraitItem>,
    pub(crate) args:        ArgsT,
    pub(crate) item_impl:   syn::ItemImpl,
    pub(crate) debug_print: bool,
}

impl<ArgsT: Parse> Parse for Input<ArgsT> {
    fn parse(input: ParseStream) -> Result<Self> {
        input.parse::<kw::TRAIT_PORTRAIT>()?;

        let portrait_braced;
        syn::braced!(portrait_braced in input);
        let mut portrait = Vec::new();
        while !portrait_braced.is_empty() {
            let item_braced;
            syn::braced!(item_braced in portrait_braced);
            let item: syn::TraitItem = item_braced.parse()?;
            if !item_braced.is_empty() {
                return Err(item_braced.error("braces should only contain one trait item"));
            }
            portrait.push(item);
        }

        input.parse::<kw::ARGS>()?;
        let args_braced;
        syn::braced!(args_braced in input);
        let args: ArgsT = args_braced.parse()?;
        if !args_braced.is_empty() {
            return Err(args_braced.error("args not fully parsed"));
        }

        input.parse::<kw::IMPL>()?;
        let impl_braced;
        syn::braced!(impl_braced in input);
        let item_impl = impl_braced.parse()?;
        if !impl_braced.is_empty() {
            return Err(impl_braced.error("trailing tokens after impl block"));
        }

        input.parse::<kw::DEBUG_PRINT_FILLER_OUTPUT>()?;
        let dpfo_braced;
        syn::braced!(dpfo_braced in input);
        let dpfo: syn::LitBool = dpfo_braced.parse()?;
        if !dpfo_braced.is_empty() {
            return Err(impl_braced.error("trailing tokens after impl block"));
        }

        if !input.is_empty() {
            return Err(input.error("trailing tokens in macro input"));
        }

        Ok(Self { portrait, args, item_impl, debug_print: dpfo.value })
    }
}