lombok 0.4.0

Lombok port for Rust
Documentation
use proc_macro::TokenStream;

use quote::{format_ident, quote};

use crate::utils::syn::{named_fields, parse_derive_input};

pub(crate) fn to_string(input: TokenStream) -> TokenStream {
    let derive_input = parse_derive_input(input);

    let name = &derive_input.ident;
    let (impl_generics, ty_generics, where_clause) = &derive_input.generics.split_for_impl();
    let fields = named_fields(&derive_input);
    let plain_name = &derive_input.ident.clone().to_string();

    let struct_refs = fields.iter().enumerate().map(|(i, field)| {
        let field_name = field.ident.clone().unwrap();
        let reference = format_ident!("__self_0_{}", i.to_string());

        quote! {
            #field_name: ref #reference,
        }
    });
    let formatter_enrichments = fields.iter().enumerate().map(|(i, field)| {
        let plain_field_name = field.ident.clone().unwrap().to_string();
        let reference = format_ident!("__self_0_{}", i.to_string());

        quote! {
            let _ = debug_trait_builder.field(#plain_field_name, &&(*#reference));
        }
    });
    let debug_body = quote! {
        match *self {
            #name {
                #(
                    #struct_refs
                )*
            } => {
                let mut debug_trait_builder = f.debug_struct(#plain_name);
                #(
                    #formatter_enrichments
                )*
                debug_trait_builder.finish()
            }
        }
    };

    TokenStream::from(quote! {
        impl #impl_generics ::std::fmt::Debug for #name #ty_generics #where_clause {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                #debug_body
            }
        }

        impl #impl_generics ::std::fmt::Display for #name #ty_generics #where_clause {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                (self as &dyn ::std::fmt::Debug).fmt(f)
            }
        }

        impl #impl_generics #name #ty_generics #where_clause {
            fn to_string(&self) -> ::std::string::String {
                ::std::format!("{:?}", self)
            }
        }
    })
}