bon_macros/builder/builder_gen/
builder_derives.rs
1use super::top_level_config::{DeriveConfig, DerivesConfig};
2use super::BuilderGenCtx;
3use crate::builder::builder_gen::Member;
4use crate::util::prelude::*;
5use darling::ast::GenericParamExt;
6
7impl BuilderGenCtx {
8 pub(crate) fn builder_derives(&self) -> TokenStream {
9 let DerivesConfig { clone, debug } = &self.builder_type.derives;
10
11 let mut tokens = TokenStream::new();
12
13 if let Some(derive) = clone {
14 tokens.extend(self.derive_clone(derive));
15 }
16
17 if let Some(derive) = debug {
18 tokens.extend(self.derive_debug(derive));
19 }
20
21 tokens
22 }
23
24 fn where_clause_for_derive(
32 &self,
33 target_trait_bounds: &TokenStream,
34 derive: &DeriveConfig,
35 ) -> TokenStream {
36 let derive_specific_predicates = derive
37 .bounds
38 .as_ref()
39 .map(ToTokens::to_token_stream)
40 .unwrap_or_else(|| {
41 let bounds = self
42 .generics
43 .decl_without_defaults
44 .iter()
45 .filter_map(syn::GenericParam::as_type_param)
46 .map(|param| {
47 let ident = ¶m.ident;
48 quote! {
49 #ident: #target_trait_bounds
50 }
51 });
52
53 quote! {
54 #( #bounds, )*
55 }
56 });
57
58 let inherent_item_predicates = self.generics.where_clause_predicates();
59
60 quote! {
61 where
62 #( #inherent_item_predicates, )*
63 #derive_specific_predicates
64 }
65 }
66
67 fn derive_clone(&self, derive: &DeriveConfig) -> TokenStream {
68 let bon = &self.bon;
69 let generics_decl = &self.generics.decl_without_defaults;
70 let generic_args = &self.generics.args;
71 let builder_ident = &self.builder_type.ident;
72
73 let clone = quote!(::core::clone::Clone);
74
75 let clone_receiver = self.receiver().map(|receiver| {
76 let ty = &receiver.without_self_keyword;
77 quote! {
78 __unsafe_private_receiver: <#ty as #clone>::clone(&self.__unsafe_private_receiver),
79 }
80 });
81
82 let clone_start_fn_args = self.start_fn_args().next().map(|_| {
83 let types = self.start_fn_args().map(|arg| &arg.base.ty.norm);
84 let indices = self.start_fn_args().map(|arg| &arg.index);
85
86 quote! {
87 __unsafe_private_start_fn_args: (
95 #( <#types as #clone>::clone(&self.__unsafe_private_start_fn_args.#indices), )*
96 ),
97 }
98 });
99
100 let where_clause = self.where_clause_for_derive(&clone, derive);
101 let state_mod = &self.state_mod.ident;
102
103 let clone_named_members = self.named_members().map(|member| {
104 let member_index = &member.index;
105
106 let ty = member.underlying_norm_ty();
110
111 quote! {
112 #bon::__::better_errors::clone_member::<#ty>(
113 &self.__unsafe_private_named.#member_index
114 )
115 }
116 });
117
118 let clone_fields = self.custom_fields().map(|member| {
119 let member_ident = &member.ident;
120 let member_ty = &member.norm_ty;
121
122 quote! {
123 #member_ident: <#member_ty as #clone>::clone(&self.#member_ident)
127 }
128 });
129
130 let state_var = &self.state_var;
131
132 quote! {
133 #[automatically_derived]
134 impl<
135 #(#generics_decl,)*
136 #state_var: #state_mod::State
137 >
138 #clone for #builder_ident<
139 #(#generic_args,)*
140 #state_var
141 >
142 #where_clause
143 {
144 fn clone(&self) -> Self {
145 Self {
146 __unsafe_private_phantom: ::core::marker::PhantomData,
147 #clone_receiver
148 #clone_start_fn_args
149 #( #clone_fields, )*
150
151 __unsafe_private_named: ( #( #clone_named_members, )* ),
159 }
160 }
161 }
162 }
163 }
164
165 fn derive_debug(&self, derive: &DeriveConfig) -> TokenStream {
166 let bon = &self.bon;
167
168 let format_members = self.members.iter().filter_map(|member| {
169 match member {
170 Member::StartFn(member) => {
171 let member_index = &member.index;
172 let member_ident_str = member.base.ident.to_string();
173 let member_ty = &member.base.ty.norm;
174 Some(quote! {
175 output.field(
176 #member_ident_str,
177 #bon::__::better_errors::as_dyn_debug::<#member_ty>(
178 &self.__unsafe_private_start_fn_args.#member_index
179 )
180 );
181 })
182 }
183 Member::Field(member) => {
184 let member_ident = &member.ident;
185 let member_ident_str = member_ident.to_string();
186 let member_ty = &member.norm_ty;
187 Some(quote! {
188 output.field(
189 #member_ident_str,
190 #bon::__::better_errors::as_dyn_debug::<#member_ty>(
191 &self.#member_ident
192 )
193 );
194 })
195 }
196 Member::Named(member) => {
197 let member_index = &member.index;
198 let member_ident_str = &member.name.snake_raw_str;
199 let member_ty = member.underlying_norm_ty();
200 Some(quote! {
201 if let Some(value) = &self.__unsafe_private_named.#member_index {
202 output.field(
203 #member_ident_str,
204 #bon::__::better_errors::as_dyn_debug::<#member_ty>(value)
205 );
206 }
207 })
208 }
209
210 Member::FinishFn(_) | Member::Skip(_) => None,
214 }
215 });
216
217 let format_receiver = self.receiver().map(|receiver| {
218 let ty = &receiver.without_self_keyword;
219 quote! {
220 output.field(
221 "self",
222 #bon::__::better_errors::as_dyn_debug::<#ty>(
223 &self.__unsafe_private_receiver
224 )
225 );
226 }
227 });
228
229 let debug = quote!(::core::fmt::Debug);
230 let where_clause = self.where_clause_for_derive(&debug, derive);
231 let state_mod = &self.state_mod.ident;
232 let generics_decl = &self.generics.decl_without_defaults;
233 let generic_args = &self.generics.args;
234 let builder_ident = &self.builder_type.ident;
235 let state_var = &self.state_var;
236 let builder_ident_str = builder_ident.to_string();
237
238 quote! {
239 #[automatically_derived]
240 impl<
241 #(#generics_decl,)*
242 #state_var: #state_mod::State
243 >
244 #debug for #builder_ident<
245 #(#generic_args,)*
246 #state_var
247 >
248 #where_clause
249 {
250 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
251 let mut output = f.debug_struct(#builder_ident_str);
252
253 #format_receiver
254 #(#format_members)*
255
256 output.finish()
257 }
258 }
259 }
260 }
261}