derive_builder_core_fork_arti/
initializer.rs1use proc_macro2::{Span, TokenStream};
2use quote::{ToTokens, TokenStreamExt};
3use syn;
4use BuilderPattern;
5use DEFAULT_STRUCT_NAME;
6
7use crate::{BlockContents, DefaultExpression};
8
9#[derive(Debug, Clone)]
39pub struct Initializer<'a> {
40 pub field_ident: &'a syn::Ident,
42 pub field_enabled: bool,
44 pub builder_pattern: BuilderPattern,
46 pub default_value: Option<&'a DefaultExpression>,
50 pub use_default_struct: bool,
52 pub custom_error_type_span: Option<Span>,
62 pub conversion: FieldConversion<'a>,
66}
67
68impl<'a> ToTokens for Initializer<'a> {
69 fn to_tokens(&self, tokens: &mut TokenStream) {
70 let struct_field = &self.field_ident;
71 let builder_field = struct_field;
72
73 let append_rhs = |tokens: &mut TokenStream| {
75 if !self.field_enabled {
76 let default = self.default();
77 tokens.append_all(quote!(
78 #default
79 ));
80 } else {
81 match &self.conversion {
82 FieldConversion::Block(conv) => {
83 conv.to_tokens(tokens);
84 }
85 FieldConversion::Method(meth) => {
86 let span = self
87 .custom_error_type_span
88 .unwrap_or_else(|| self.field_ident.span());
89 let field_name = self.field_ident.to_string();
90 tokens.append_all(quote_spanned!(span=>
91 ::derive_builder::export::core::result::Result::map_err(
92 self.#builder_field.#meth(),
93 |e| ::derive_builder::SubfieldBuildError::new(#field_name, e),
94 )?
95 ));
96 }
97 FieldConversion::Move => tokens.append_all(quote!( self.#builder_field )),
98 FieldConversion::OptionOrDefault => {
99 let match_some = self.match_some();
100 let match_none = self.match_none();
101 tokens.append_all(quote!(
102 match self.#builder_field {
103 #match_some,
104 #match_none,
105 }
106 ));
107 }
108 }
109 }
110 };
111
112 tokens.append_all(quote!(#struct_field:));
113 append_rhs(tokens);
114 tokens.append_all(quote!(,));
115 }
116}
117
118impl<'a> Initializer<'a> {
119 fn match_some(&'a self) -> MatchSome {
121 match self.builder_pattern {
122 BuilderPattern::Owned => MatchSome::Move,
123 BuilderPattern::Mutable | BuilderPattern::Immutable => MatchSome::Clone,
124 }
125 }
126
127 fn match_none(&'a self) -> MatchNone<'a> {
129 match self.default_value {
130 Some(expr) => MatchNone::DefaultTo(expr),
131 None => {
132 if self.use_default_struct {
133 MatchNone::UseDefaultStructField(self.field_ident)
134 } else {
135 MatchNone::ReturnError(
136 self.field_ident.to_string(),
137 self.custom_error_type_span,
138 )
139 }
140 }
141 }
142 }
143
144 fn default(&'a self) -> TokenStream {
145 match self.default_value {
146 Some(ref expr) => quote!(#expr),
147 None if self.use_default_struct => {
148 let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site());
149 let field_ident = self.field_ident;
150 quote!(#struct_ident.#field_ident)
151 }
152 None => quote!(::derive_builder::export::core::default::Default::default()),
153 }
154 }
155}
156
157#[derive(Debug, Clone)]
158pub enum FieldConversion<'a> {
159 OptionOrDefault,
161 Block(&'a BlockContents),
163 Method(&'a syn::Ident),
165 Move,
167}
168
169enum MatchNone<'a> {
171 DefaultTo(&'a DefaultExpression),
173 UseDefaultStructField(&'a syn::Ident),
177 ReturnError(String, Option<Span>),
179}
180
181impl<'a> ToTokens for MatchNone<'a> {
182 fn to_tokens(&self, tokens: &mut TokenStream) {
183 match *self {
184 MatchNone::DefaultTo(expr) => tokens.append_all(quote!(
185 None => #expr
186 )),
187 MatchNone::UseDefaultStructField(field_ident) => {
188 let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site());
189 tokens.append_all(quote!(
190 None => #struct_ident.#field_ident
191 ))
192 }
193 MatchNone::ReturnError(ref field_name, ref span) => {
194 let conv_span = span.unwrap_or_else(Span::call_site);
195 let err_conv = quote_spanned!(conv_span => ::derive_builder::export::core::convert::Into::into(
196 ::derive_builder::UninitializedFieldError::from(#field_name)
197 ));
198 tokens.append_all(quote!(
199 None => return ::derive_builder::export::core::result::Result::Err(#err_conv)
200 ));
201 }
202 }
203 }
204}
205
206enum MatchSome {
208 Move,
209 Clone,
210}
211
212impl<'a> ToTokens for MatchSome {
213 fn to_tokens(&self, tokens: &mut TokenStream) {
214 match *self {
215 Self::Move => tokens.append_all(quote!(
216 Some(value) => value
217 )),
218 Self::Clone => tokens.append_all(quote!(
219 Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value)
220 )),
221 }
222 }
223}
224
225#[doc(hidden)]
228#[macro_export]
229macro_rules! default_initializer {
230 () => {
231 Initializer {
232 field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()),
233 field_enabled: true,
234 builder_pattern: BuilderPattern::Mutable,
235 default_value: None,
236 use_default_struct: false,
237 conversion: FieldConversion::OptionOrDefault,
238 custom_error_type_span: None,
239 }
240 };
241}
242
243#[cfg(test)]
244mod tests {
245 #[allow(unused_imports)]
246 use super::*;
247
248 #[test]
249 fn immutable() {
250 let mut initializer = default_initializer!();
251 initializer.builder_pattern = BuilderPattern::Immutable;
252
253 assert_eq!(
254 quote!(#initializer).to_string(),
255 quote!(
256 foo: match self.foo {
257 Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
258 None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
259 ::derive_builder::UninitializedFieldError::from("foo")
260 )),
261 },
262 )
263 .to_string()
264 );
265 }
266
267 #[test]
268 fn mutable() {
269 let mut initializer = default_initializer!();
270 initializer.builder_pattern = BuilderPattern::Mutable;
271
272 assert_eq!(
273 quote!(#initializer).to_string(),
274 quote!(
275 foo: match self.foo {
276 Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
277 None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
278 ::derive_builder::UninitializedFieldError::from("foo")
279 )),
280 },
281 )
282 .to_string()
283 );
284 }
285
286 #[test]
287 fn owned() {
288 let mut initializer = default_initializer!();
289 initializer.builder_pattern = BuilderPattern::Owned;
290
291 assert_eq!(
292 quote!(#initializer).to_string(),
293 quote!(
294 foo: match self.foo {
295 Some(value) => value,
296 None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
297 ::derive_builder::UninitializedFieldError::from("foo")
298 )),
299 },
300 )
301 .to_string()
302 );
303 }
304
305 #[test]
306 fn default_value() {
307 let mut initializer = default_initializer!();
308 let default_value = DefaultExpression::explicit::<syn::Expr>(parse_quote!(42));
309 initializer.default_value = Some(&default_value);
310
311 assert_eq!(
312 quote!(#initializer).to_string(),
313 quote!(
314 foo: match self.foo {
315 Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
316 None => { 42 },
317 },
318 )
319 .to_string()
320 );
321 }
322
323 #[test]
324 fn default_struct() {
325 let mut initializer = default_initializer!();
326 initializer.use_default_struct = true;
327
328 assert_eq!(
329 quote!(#initializer).to_string(),
330 quote!(
331 foo: match self.foo {
332 Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
333 None => __default.foo,
334 },
335 )
336 .to_string()
337 );
338 }
339
340 #[test]
341 fn setter_disabled() {
342 let mut initializer = default_initializer!();
343 initializer.field_enabled = false;
344
345 assert_eq!(
346 quote!(#initializer).to_string(),
347 quote!(foo: ::derive_builder::export::core::default::Default::default(),).to_string()
348 );
349 }
350
351 #[test]
352 fn no_std() {
353 let initializer = default_initializer!();
354
355 assert_eq!(
356 quote!(#initializer).to_string(),
357 quote!(
358 foo: match self.foo {
359 Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
360 None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
361 ::derive_builder::UninitializedFieldError::from("foo")
362 )),
363 },
364 )
365 .to_string()
366 );
367 }
368}