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
use proc_macro::TokenStream;

#[cfg(not(feature="debug_parameters"))]
pub fn impl_debug_param_fn(_: TokenStream, input: TokenStream) -> TokenStream {
    input
}

#[cfg(feature="debug_parameters")]
pub fn impl_debug_param_fn(_: TokenStream, input: TokenStream) -> TokenStream {
    if let Ok(item_fn) = syn::parse::<syn::ItemFn>(input.clone()){
        let fn_vis = item_fn.vis;
        let fn_name = item_fn.sig.ident;
        let fn_inputs = &item_fn.sig.inputs;
        let fn_output = &item_fn.sig.output;
        let fn_block = item_fn.block;
        let fn_attrs = item_fn.attrs;
        let mut generics = item_fn.sig.generics.clone();
        generics.params.push(parse_quote!('w));
        let (impl_generics, _, where_clause) = generics.split_for_impl();

        let where_clause = if let Some(mut where_clause) = where_clause.cloned() {
            let debug_param_preducate = parse_quote!{
                <<C as ::Component>::Storage as ::Storage<'w, C>>::Get: ::DebugParameter
            };
            where_clause.predicates.push(debug_param_preducate);
            where_clause
        }else{
            parse_quote!{
                where <<C as ::Component>::Storage as ::Storage<'w, C>>::Get: ::DebugParameter
            }
        };

        let fn_impl = quote!{
            #( #fn_attrs )*
            #fn_vis fn #fn_name #impl_generics ( #fn_inputs ) #fn_output #where_clause
                #fn_block
        };

        TokenStream::from(fn_impl)
    }else if let Ok(item_fn) = syn::parse::<syn::TraitItemMethod>(input){
        let fn_name = &item_fn.sig.ident;
        let fn_inputs = &item_fn.sig.inputs;
        let fn_output = &item_fn.sig.output;
        let fn_attrs = item_fn.attrs;
        let mut generics = item_fn.sig.generics.clone();
        generics.params.push(parse_quote!('w));
        let (impl_generics, _, where_clause) = generics.split_for_impl();


        let where_clause = if let Some(mut where_clause) = where_clause.cloned() {
            let debug_param_preducate = parse_quote!{
                <<C as ::Component>::Storage as ::Storage<'w, C>>::Get: ::DebugParameter
            };
            where_clause.predicates.push(debug_param_preducate);
            where_clause
        }else{
            parse_quote!{
                where <<C as ::Component>::Storage as ::Storage<'w, C>>::Get: ::DebugParameter
            }
        };

        let fn_block = if let Some(block) = item_fn.default {
            quote!(#block)
        }else{
            quote!(;)
        };

        let fn_impl = quote!{
            #( #fn_attrs )*
            fn #fn_name #impl_generics ( #fn_inputs ) #fn_output #where_clause
                #fn_block
        };

        TokenStream::from(fn_impl)
    }else{
        panic!("debug_param_fn only available for functions or trait method declarations")
    }
}