use quote::quote;
use syn::Fields;
use synstructure::{decl_derive, AddBounds};
decl_derive!([Debug] => derive_debug);
fn derive_debug(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
if s.variants().is_empty() {
return s.gen_impl(quote! {
gen impl debug3::Debug for @Self {
fn fmt(&self, f: &mut debug3::Formatter) {
match *self {}
}
}
});
}
s.add_bounds(AddBounds::Generics);
let variants = s.each_variant(|variant| {
let name = variant.ast().ident.to_string();
let debug_helper = match variant.ast().fields {
Fields::Named(_) | Fields::Unit => quote! {debug_struct},
Fields::Unnamed(_) => quote! {debug_tuple},
};
let variant_body = variant.bindings().iter().map(|b| {
let format = quote! {#b};
if let Some(ref name) = b.ast().ident.as_ref().map(<_>::to_string) {
quote! {
s.field(#name, #format);
}
} else {
quote! {
s.field(#format);
}
}
});
quote! {
let mut s = f.#debug_helper(#name);
#(#variant_body)*
s.finish()
}
});
s.gen_impl(quote! {
#[automatically_derived]
gen impl debug3::Debug for @Self {
fn fmt(&self, f: &mut debug3::Formatter) {
match self { #variants }
}
}
})
}