Skip to main content

bon_macros/builder/builder_gen/builder_derives/
debug.rs

1use crate::builder::builder_gen::member::Member;
2use crate::builder::builder_gen::models::BuilderGenCtx;
3use crate::builder::builder_gen::top_level_config::DeriveConfig;
4use crate::util::prelude::*;
5
6impl BuilderGenCtx {
7    pub(super) fn derive_debug(&self, derive: &DeriveConfig) -> TokenStream {
8        let bon = &self.bon;
9
10        let format_members = self.members.iter().filter_map(|member| {
11            match member {
12                Member::StartFn(member) => {
13                    let member_ident = &member.ident;
14                    let member_ident_str = member_ident.to_string();
15                    let member_ty = &member.ty.norm;
16                    Some(quote! {
17                        output.field(
18                            #member_ident_str,
19                            #bon::__::better_errors::as_dyn_debug::<#member_ty>(
20                                &self.#member_ident
21                            )
22                        );
23                    })
24                }
25                Member::Field(member) => {
26                    let member_ident = &member.ident;
27                    let member_ident_str = member_ident.to_string();
28                    let member_ty = &member.norm_ty;
29                    Some(quote! {
30                        output.field(
31                            #member_ident_str,
32                            #bon::__::better_errors::as_dyn_debug::<#member_ty>(
33                                &self.#member_ident
34                            )
35                        );
36                    })
37                }
38                Member::Named(member) => {
39                    let member_index = &member.index;
40                    let member_ident_str = &member.name.snake_raw_str;
41                    let member_ty = member.underlying_norm_ty();
42                    Some(quote! {
43                        if let Some(value) = &self.__unsafe_private_named.#member_index {
44                            output.field(
45                                #member_ident_str,
46                                #bon::__::better_errors::as_dyn_debug::<#member_ty>(value)
47                            );
48                        }
49                    })
50                }
51
52                // The values for these members are computed only in the finishing
53                // function where the builder is consumed, and they aren't stored
54                // in the builder itself.
55                Member::FinishFn(_) | Member::Skip(_) => None,
56            }
57        });
58
59        let format_receiver = self.receiver().map(|receiver| {
60            let ident = &receiver.field_ident;
61            let ident_str = ident.to_string();
62            let ty = &receiver.without_self_keyword;
63            quote! {
64                output.field(
65                    #ident_str,
66                    #bon::__::better_errors::as_dyn_debug::<#ty>(
67                        &self.#ident
68                    )
69                );
70            }
71        });
72
73        let debug = quote!(::core::fmt::Debug);
74        let where_clause = self.where_clause_for_derive(&debug, derive);
75        let state_mod = &self.state_mod.ident;
76        let generics_decl = &self.generics.decl_without_defaults;
77        let generic_args = &self.generics.args;
78        let builder_ident = &self.builder_type.ident;
79        let state_var = &self.state_var;
80        let builder_ident_str = builder_ident.to_string();
81
82        quote! {
83            #[automatically_derived]
84            impl<
85                #(#generics_decl,)*
86                #state_var: #state_mod::State
87            >
88            #debug for #builder_ident<
89                #(#generic_args,)*
90                #state_var
91            >
92            #where_clause
93            {
94                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
95                    let mut output = f.debug_struct(#builder_ident_str);
96
97                    #format_receiver
98                    #(#format_members)*
99
100                    output.finish()
101                }
102            }
103        }
104    }
105}