debug2_derive/
lib.rs

1use quote::quote;
2use syn::Fields;
3use synstructure::{decl_derive, AddBounds};
4
5decl_derive!([Debug/*, attributes(debug_skip)*/] => derive_debug);
6
7// Based on
8// https://github.com/panicbit/custom_debug/blob/master/custom_debug_derive/src/lib.rs
9
10fn derive_debug(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
11    s.add_bounds(AddBounds::Generics);
12
13    let variants = s.each_variant(|variant| {
14        let name = variant.ast().ident.to_string();
15
16        let debug_helper = match variant.ast().fields {
17            Fields::Named(_) | Fields::Unit => quote! {debug_struct},
18            Fields::Unnamed(_) => quote! {debug_tuple},
19        };
20
21        let variant_body = variant.bindings().iter().map(|b| {
22            let format = quote! {#b};
23
24            if let Some(ref name) = b.ast().ident.as_ref().map(<_>::to_string) {
25                quote! {
26                    s.field(#name, #format);
27                }
28            } else {
29                quote! {
30                    s.field(#format);
31                }
32            }
33        });
34
35        quote! {
36            let mut s = f.#debug_helper(#name);
37            #(#variant_body)*
38            s.finish()
39        }
40    });
41
42    s.gen_impl(quote! {
43        gen impl debug2::Debug for @Self {
44            fn fmt(&self, f: &mut debug2::Formatter<'_>) -> std::fmt::Result {
45                match self { #variants }
46            }
47        }
48    })
49}