1 | use std::convert::TryFrom; |
2 | use std::{borrow::Cow, vec::IntoIter}; |
3 | |
4 | use crate::BuildMethod; |
5 | |
6 | use darling::util::{Flag, PathList, SpannedValue}; |
7 | use darling::{Error, FromMeta}; |
8 | use proc_macro2::Span; |
9 | use syn::{spanned::Spanned, Attribute, Generics, Ident, Meta, Path}; |
10 | |
11 | use crate::{ |
12 | BlockContents, Builder, BuilderField, BuilderFieldType, BuilderPattern, DefaultExpression, |
13 | Each, FieldConversion, Initializer, Setter, |
14 | }; |
15 | |
16 | #[derive (Debug, Clone)] |
17 | enum VisibilityAttr { |
18 | /// `public` |
19 | Public(Span), |
20 | /// `private` |
21 | Private, |
22 | /// `vis = "pub(crate)"` |
23 | Explicit(syn::Visibility), |
24 | None, |
25 | } |
26 | |
27 | impl VisibilityAttr { |
28 | pub fn to_explicit_visibility(&self) -> Option<Cow<syn::Visibility>> { |
29 | match self { |
30 | Self::Public(span: &Span) => Some(Cow::Owned(syn::Visibility::Public( |
31 | parse_quote_spanned!(*span=> pub), |
32 | ))), |
33 | Self::Private => Some(Cow::Owned(syn::Visibility::Inherited)), |
34 | Self::Explicit(v: &Visibility) => Some(Cow::Borrowed(v)), |
35 | Self::None => None, |
36 | } |
37 | } |
38 | } |
39 | |
40 | impl Default for VisibilityAttr { |
41 | fn default() -> Self { |
42 | Self::None |
43 | } |
44 | } |
45 | |
46 | impl FromMeta for VisibilityAttr { |
47 | fn from_list(items: &[darling::ast::NestedMeta]) -> darling::Result<Self> { |
48 | #[derive (FromMeta)] |
49 | struct VisibilityAttrInternal { |
50 | public: Flag, |
51 | private: Flag, |
52 | vis: Option<syn::Visibility>, |
53 | } |
54 | |
55 | let VisibilityAttrInternal { |
56 | public, |
57 | private, |
58 | vis: explicit, |
59 | } = VisibilityAttrInternal::from_list(items)?; |
60 | |
61 | let mut conflicts = Error::accumulator(); |
62 | |
63 | if public.is_present() { |
64 | if private.is_present() { |
65 | conflicts.push( |
66 | Error::custom("`public` and `private` cannot be used together" ) |
67 | .with_span(&private.span()), |
68 | ); |
69 | } |
70 | |
71 | if let Some(vis) = explicit { |
72 | conflicts.push( |
73 | Error::custom("`public` and `vis` cannot be used together" ).with_span(&vis), |
74 | ); |
75 | } |
76 | |
77 | conflicts.finish_with(Self::Public(public.span())) |
78 | } else if let Some(vis) = explicit { |
79 | if private.is_present() { |
80 | conflicts.push(Error::custom("`vis` and `private` cannot be used together" )); |
81 | } |
82 | |
83 | conflicts.finish_with(Self::Explicit(vis)) |
84 | } else if private.is_present() { |
85 | conflicts.finish_with(Self::Private) |
86 | } else { |
87 | conflicts.finish_with(Self::None) |
88 | } |
89 | } |
90 | } |
91 | |
92 | #[derive (Debug, Clone, FromMeta)] |
93 | struct BuildFnErrorGenerated { |
94 | /// Indicates whether or not the generated error should have |
95 | /// a validation variant that takes a `String` as its contents. |
96 | validation_error: SpannedValue<bool>, |
97 | } |
98 | |
99 | #[derive (Debug, Clone)] |
100 | enum BuildFnError { |
101 | Existing(Path), |
102 | Generated(BuildFnErrorGenerated), |
103 | } |
104 | |
105 | impl BuildFnError { |
106 | fn as_existing(&self) -> Option<&Path> { |
107 | match self { |
108 | BuildFnError::Existing(p: &Path) => Some(p), |
109 | BuildFnError::Generated(_) => None, |
110 | } |
111 | } |
112 | |
113 | fn as_generated(&self) -> Option<&BuildFnErrorGenerated> { |
114 | match self { |
115 | BuildFnError::Generated(e: &BuildFnErrorGenerated) => Some(e), |
116 | BuildFnError::Existing(_) => None, |
117 | } |
118 | } |
119 | } |
120 | |
121 | impl FromMeta for BuildFnError { |
122 | fn from_meta(item: &Meta) -> darling::Result<Self> { |
123 | match item { |
124 | Meta::Path(_) => Err(Error::unsupported_format("word" ).with_span(node:item)), |
125 | Meta::List(_) => BuildFnErrorGenerated::from_meta(item).map(Self::Generated), |
126 | Meta::NameValue(i: &MetaNameValue) => Path::from_expr(&i.value).map(Self::Existing), |
127 | } |
128 | } |
129 | } |
130 | |
131 | /// Options for the `build_fn` property in struct-level builder options. |
132 | /// There is no inheritance for these settings from struct-level to field-level, |
133 | /// so we don't bother using `Option` for values in this struct. |
134 | #[derive (Debug, Clone, FromMeta)] |
135 | #[darling(default, and_then = Self::validation_needs_error)] |
136 | pub struct BuildFn { |
137 | skip: bool, |
138 | name: Ident, |
139 | validate: Option<Path>, |
140 | #[darling(flatten)] |
141 | visibility: VisibilityAttr, |
142 | /// Either the path to an existing error type that the build method should return or a meta |
143 | /// list of options to modify the generated error. |
144 | /// |
145 | /// Setting this to a path will prevent `derive_builder` from generating an error type for the |
146 | /// build method. |
147 | /// |
148 | /// This options supports to formats: path `error = "path::to::Error"` and meta list |
149 | /// `error(<options>)`. Supported mata list options are the following: |
150 | /// |
151 | /// * `validation_error = bool` - Whether to generate `ValidationError(String)` as a variant |
152 | /// of the build error type. Setting this to `false` will prevent `derive_builder` from |
153 | /// using the `validate` function but this also means it does not generate any usage of the |
154 | /// `alloc` crate (useful when disabling the `alloc` feature in `no_std`). |
155 | /// |
156 | /// # Type Bounds for Custom Error |
157 | /// This type's bounds depend on other settings of the builder. |
158 | /// |
159 | /// * If uninitialized fields cause `build()` to fail, then this type |
160 | /// must `impl From<UninitializedFieldError>`. Uninitialized fields do not cause errors |
161 | /// when default values are provided for every field or at the struct level. |
162 | /// * If `validate` is specified, then this type must provide a conversion from the specified |
163 | /// function's error type. |
164 | error: Option<BuildFnError>, |
165 | } |
166 | |
167 | impl BuildFn { |
168 | fn validation_needs_error(self) -> darling::Result<Self> { |
169 | let mut acc: Accumulator = Error::accumulator(); |
170 | if self.validate.is_some() { |
171 | if let Some(BuildFnError::Generated(e: &BuildFnErrorGenerated)) = &self.error { |
172 | if !*e.validation_error { |
173 | acc.push( |
174 | error:Error::custom( |
175 | "Cannot set `error(validation_error = false)` when using `validate`" , |
176 | ) |
177 | .with_span(&e.validation_error.span()), |
178 | ) |
179 | } |
180 | } |
181 | } |
182 | |
183 | acc.finish_with(self) |
184 | } |
185 | } |
186 | |
187 | impl Default for BuildFn { |
188 | fn default() -> Self { |
189 | BuildFn { |
190 | skip: false, |
191 | name: Ident::new(string:"build" , Span::call_site()), |
192 | validate: None, |
193 | visibility: Default::default(), |
194 | error: None, |
195 | } |
196 | } |
197 | } |
198 | |
199 | /// Contents of the `field` meta in `builder` attributes at the field level. |
200 | // |
201 | // This is a superset of the attributes permitted in `field` at the struct level. |
202 | #[derive (Debug, Clone, Default, FromMeta)] |
203 | pub struct FieldLevelFieldMeta { |
204 | #[darling(flatten)] |
205 | visibility: VisibilityAttr, |
206 | /// Custom builder field type |
207 | #[darling(rename = "ty" )] |
208 | builder_type: Option<syn::Type>, |
209 | /// Custom builder field method, for making target struct field value |
210 | build: Option<BlockContents>, |
211 | } |
212 | |
213 | #[derive (Debug, Clone, Default, FromMeta)] |
214 | pub struct StructLevelSetter { |
215 | prefix: Option<Ident>, |
216 | into: Option<bool>, |
217 | strip_option: Option<bool>, |
218 | skip: Option<bool>, |
219 | } |
220 | |
221 | impl StructLevelSetter { |
222 | /// Check if setters are explicitly enabled or disabled at |
223 | /// the struct level. |
224 | pub fn enabled(&self) -> Option<bool> { |
225 | self.skip.map(|x: bool| !x) |
226 | } |
227 | } |
228 | |
229 | /// Create `Each` from an attribute's `Meta`. |
230 | /// |
231 | /// Two formats are supported: |
232 | /// |
233 | /// * `each = "..."`, which provides the name of the `each` setter and otherwise uses default values |
234 | /// * `each(name = "...")`, which allows setting additional options on the `each` setter |
235 | fn parse_each(meta: &Meta) -> darling::Result<Option<Each>> { |
236 | if let Meta::NameValue(mnv: &MetaNameValue) = meta { |
237 | Ident::from_meta(meta) |
238 | .map(Each::from) |
239 | .map(Some) |
240 | .map_err(|e: Error| e.with_span(&mnv.value)) |
241 | } else { |
242 | Each::from_meta(meta).map(Some) |
243 | } |
244 | } |
245 | |
246 | /// The `setter` meta item on fields in the input type. |
247 | /// Unlike the `setter` meta item at the struct level, this allows specific |
248 | /// name overrides. |
249 | #[derive (Debug, Clone, Default, FromMeta)] |
250 | pub struct FieldLevelSetter { |
251 | prefix: Option<Ident>, |
252 | name: Option<Ident>, |
253 | into: Option<bool>, |
254 | strip_option: Option<bool>, |
255 | skip: Option<bool>, |
256 | custom: Option<bool>, |
257 | #[darling(with = parse_each)] |
258 | each: Option<Each>, |
259 | } |
260 | |
261 | impl FieldLevelSetter { |
262 | /// Get whether the setter should be emitted. The rules are the same as |
263 | /// for `field_enabled`, except we only skip the setter if `setter(custom)` is present. |
264 | pub fn setter_enabled(&self) -> Option<bool> { |
265 | if self.custom.is_some() { |
266 | return self.custom.map(|x| !x); |
267 | } |
268 | |
269 | self.field_enabled() |
270 | } |
271 | |
272 | /// Get whether or not this field-level setter indicates a setter and |
273 | /// field should be emitted. The setter shorthand rules are that the |
274 | /// presence of a `setter` with _any_ properties set forces the setter |
275 | /// to be emitted. |
276 | pub fn field_enabled(&self) -> Option<bool> { |
277 | if self.skip.is_some() { |
278 | return self.skip.map(|x| !x); |
279 | } |
280 | |
281 | if self.prefix.is_some() |
282 | || self.name.is_some() |
283 | || self.into.is_some() |
284 | || self.strip_option.is_some() |
285 | || self.each.is_some() |
286 | { |
287 | return Some(true); |
288 | } |
289 | |
290 | None |
291 | } |
292 | } |
293 | |
294 | /// `derive_builder` allows the calling code to use `setter` as a word to enable |
295 | /// setters when they've been disabled at the struct level. |
296 | fn field_setter(meta: &Meta) -> darling::Result<FieldLevelSetter> { |
297 | // it doesn't matter what the path is; the fact that this function |
298 | // has been called means that a valueless path is the shorthand case. |
299 | if let Meta::Path(_) = meta { |
300 | Ok(FieldLevelSetter { |
301 | skip: Some(false), |
302 | ..Default::default() |
303 | }) |
304 | } else { |
305 | FieldLevelSetter::from_meta(meta) |
306 | } |
307 | } |
308 | |
309 | #[derive (Debug, Clone, Default)] |
310 | struct FieldForwardedAttrs { |
311 | pub field: Vec<Attribute>, |
312 | pub setter: Vec<Attribute>, |
313 | } |
314 | |
315 | impl TryFrom<Vec<Attribute>> for FieldForwardedAttrs { |
316 | type Error = Error; |
317 | |
318 | fn try_from(value: Vec<Attribute>) -> Result<Self, Self::Error> { |
319 | let mut result: FieldForwardedAttrs = Self::default(); |
320 | distribute_and_unnest_attrs( |
321 | input:value, |
322 | &mut [ |
323 | ("builder_field_attr" , &mut result.field), |
324 | ("builder_setter_attr" , &mut result.setter), |
325 | ], |
326 | )?; |
327 | Ok(result) |
328 | } |
329 | } |
330 | |
331 | /// Data extracted from the fields of the input struct. |
332 | #[derive (Debug, Clone, FromField)] |
333 | #[darling( |
334 | attributes(builder), |
335 | forward_attrs(doc, cfg, allow, builder_field_attr, builder_setter_attr), |
336 | and_then = "Self::resolve" |
337 | )] |
338 | pub struct Field { |
339 | ident: Option<Ident>, |
340 | #[darling(with = TryFrom::try_from)] |
341 | attrs: FieldForwardedAttrs, |
342 | ty: syn::Type, |
343 | /// Field-level override for builder pattern. |
344 | /// Note that setting this may force the builder to derive `Clone`. |
345 | pattern: Option<BuilderPattern>, |
346 | #[darling(flatten)] |
347 | visibility: VisibilityAttr, |
348 | // See the documentation for `FieldSetterMeta` to understand how `darling` |
349 | // is interpreting this field. |
350 | #[darling(default, with = field_setter)] |
351 | setter: FieldLevelSetter, |
352 | /// The value for this field if the setter is never invoked. |
353 | /// |
354 | /// A field can get its default one of three ways: |
355 | /// |
356 | /// 1. An explicit `default = "..."` expression |
357 | /// 2. An explicit `default` word, in which case the field type's `Default::default()` |
358 | /// value is used |
359 | /// 3. Inherited from the field's value in the struct's `default` value. |
360 | /// |
361 | /// This property only captures the first two, the third is computed in `FieldWithDefaults`. |
362 | default: Option<DefaultExpression>, |
363 | try_setter: Flag, |
364 | #[darling(default)] |
365 | field: FieldLevelFieldMeta, |
366 | } |
367 | |
368 | impl Field { |
369 | /// Resolve and check (post-parsing) options which come from multiple darling options |
370 | /// |
371 | /// * Check that we don't have a custom field type or builder *and* a default value |
372 | fn resolve(self) -> darling::Result<Self> { |
373 | let mut errors = darling::Error::accumulator(); |
374 | |
375 | // `default` can be preempted by properties in `field`. Silently ignoring a |
376 | // `default` could cause the direct user of `derive_builder` to see unexpected |
377 | // behavior from the builder, so instead we require that the deriving struct |
378 | // not pass any ignored instructions. |
379 | if let Field { |
380 | default: Some(field_default), |
381 | .. |
382 | } = &self |
383 | { |
384 | // `field.build` is stronger than `default`, as it contains both instructions on how to |
385 | // deal with a missing value and conversions to do on the value during target type |
386 | // construction. |
387 | if self.field.build.is_some() { |
388 | errors.push( |
389 | darling::Error::custom( |
390 | r#"#[builder(default)] and #[builder(field(build="..."))] cannot be used together"# , |
391 | ) |
392 | .with_span(&field_default.span()), |
393 | ); |
394 | } |
395 | |
396 | // `field.ty` being set means `default` will not be used, since we don't know how |
397 | // to check a custom field type for the absence of a value and therefore we'll never |
398 | // know that we should use the `default` value. |
399 | if self.field.builder_type.is_some() { |
400 | errors.push( |
401 | darling::Error::custom( |
402 | r#"#[builder(default)] and #[builder(field(ty="..."))] cannot be used together"# , |
403 | ) |
404 | .with_span(&field_default.span()) |
405 | ) |
406 | } |
407 | }; |
408 | |
409 | errors.finish_with(self) |
410 | } |
411 | } |
412 | |
413 | /// Divide a list of attributes into multiple partially-overlapping output lists. |
414 | /// |
415 | /// Some attributes from the macro input will be added to the output in multiple places; |
416 | /// for example, a `cfg` attribute must be replicated to both the struct and its impl block or |
417 | /// the resulting code will not compile. |
418 | /// |
419 | /// Other attributes are scoped to a specific output by their path, e.g. `builder_field_attr`. |
420 | /// These attributes will only appear in one output list, but need that outer path removed. |
421 | /// |
422 | /// For performance reasons, we want to do this in one pass through the list instead of |
423 | /// first distributing and then iterating through each of the output lists. |
424 | /// |
425 | /// Each item in `outputs` contains the attribute name unique to that output, and the `Vec` where all attributes for that output should be inserted. |
426 | /// Attributes whose path matches any value in `outputs` will be added only to the first matching one, and will be "unnested". |
427 | /// Other attributes are not unnested, and simply copied for each decoratee. |
428 | fn distribute_and_unnest_attrs( |
429 | mut input: Vec<Attribute>, |
430 | outputs: &mut [(&'static str, &mut Vec<Attribute>)], |
431 | ) -> darling::Result<()> { |
432 | let mut errors = vec![]; |
433 | |
434 | for (name, list) in &*outputs { |
435 | assert!(list.is_empty(), "Output Vec for ' {}' was not empty" , name); |
436 | } |
437 | |
438 | for attr in input.drain(..) { |
439 | let destination = outputs |
440 | .iter_mut() |
441 | .find(|(ptattr, _)| attr.path().is_ident(ptattr)); |
442 | |
443 | if let Some((_, destination)) = destination { |
444 | match unnest_from_one_attribute(attr) { |
445 | Ok(n) => destination.push(n), |
446 | Err(e) => errors.push(e), |
447 | } |
448 | } else { |
449 | for (_, output) in outputs.iter_mut() { |
450 | output.push(attr.clone()); |
451 | } |
452 | } |
453 | } |
454 | |
455 | if !errors.is_empty() { |
456 | return Err(darling::Error::multiple(errors)); |
457 | } |
458 | |
459 | Ok(()) |
460 | } |
461 | |
462 | fn unnest_from_one_attribute(attr: syn::Attribute) -> darling::Result<Attribute> { |
463 | match &attr.style { |
464 | syn::AttrStyle::Outer => (), |
465 | syn::AttrStyle::Inner(bang) => { |
466 | return Err(darling::Error::unsupported_format(&format!( |
467 | " {} must be an outer attribute" , |
468 | attr.path() |
469 | .get_ident() |
470 | .map(Ident::to_string) |
471 | .unwrap_or_else(|| "Attribute" .to_string()) |
472 | )) |
473 | .with_span(bang)); |
474 | } |
475 | }; |
476 | |
477 | let original_span = attr.span(); |
478 | |
479 | let pound = attr.pound_token; |
480 | let meta = attr.meta; |
481 | |
482 | match meta { |
483 | Meta::Path(_) => Err(Error::unsupported_format("word" ).with_span(&meta)), |
484 | Meta::NameValue(_) => Err(Error::unsupported_format("name-value" ).with_span(&meta)), |
485 | Meta::List(list) => { |
486 | let inner = list.tokens; |
487 | Ok(parse_quote_spanned!(original_span=> #pound [ #inner ])) |
488 | } |
489 | } |
490 | } |
491 | |
492 | fn default_crate_root() -> Path { |
493 | parse_quote!(::derive_builder) |
494 | } |
495 | |
496 | fn default_create_empty() -> Ident { |
497 | Ident::new(string:"create_empty" , Span::call_site()) |
498 | } |
499 | |
500 | #[derive (Debug, Clone, Default)] |
501 | struct StructForwardedAttrs { |
502 | struct_attrs: Vec<Attribute>, |
503 | impl_attrs: Vec<Attribute>, |
504 | } |
505 | |
506 | impl TryFrom<Vec<Attribute>> for StructForwardedAttrs { |
507 | type Error = Error; |
508 | |
509 | fn try_from(value: Vec<Attribute>) -> Result<Self, Self::Error> { |
510 | let mut result: StructForwardedAttrs = Self::default(); |
511 | distribute_and_unnest_attrs( |
512 | input:value, |
513 | &mut [ |
514 | ("builder_struct_attr" , &mut result.struct_attrs), |
515 | ("builder_impl_attr" , &mut result.impl_attrs), |
516 | ], |
517 | )?; |
518 | |
519 | Ok(result) |
520 | } |
521 | } |
522 | |
523 | #[derive (Debug, Clone, FromDeriveInput)] |
524 | #[darling( |
525 | attributes(builder), |
526 | forward_attrs(cfg, allow, builder_struct_attr, builder_impl_attr), |
527 | supports(struct_named) |
528 | )] |
529 | pub struct Options { |
530 | ident: Ident, |
531 | |
532 | #[darling(with = TryFrom::try_from)] |
533 | attrs: StructForwardedAttrs, |
534 | |
535 | /// The visibility of the deriving struct. Do not confuse this with `#[builder(vis = "...")]`, |
536 | /// which is received by `Options::visibility`. |
537 | vis: syn::Visibility, |
538 | |
539 | generics: Generics, |
540 | |
541 | /// The name of the generated builder. Defaults to `#{ident}Builder`. |
542 | name: Option<Ident>, |
543 | |
544 | /// The path to the root of the derive_builder crate used in generated |
545 | /// code. |
546 | #[darling(rename = "crate" , default = default_crate_root)] |
547 | crate_root: Path, |
548 | |
549 | #[darling(default)] |
550 | pattern: BuilderPattern, |
551 | |
552 | #[darling(default)] |
553 | build_fn: BuildFn, |
554 | |
555 | /// Additional traits to derive on the builder. |
556 | #[darling(default)] |
557 | derive: PathList, |
558 | |
559 | custom_constructor: Flag, |
560 | |
561 | /// The ident of the inherent method which takes no arguments and returns |
562 | /// an instance of the builder with all fields empty. |
563 | #[darling(default = default_create_empty)] |
564 | create_empty: Ident, |
565 | |
566 | /// Setter options applied to all field setters in the struct. |
567 | #[darling(default)] |
568 | setter: StructLevelSetter, |
569 | |
570 | /// Struct-level value to use in place of any unfilled fields |
571 | default: Option<DefaultExpression>, |
572 | |
573 | /// Desired visibility of the builder struct. |
574 | /// |
575 | /// Do not confuse this with `Options::vis`, which is the visibility of the deriving struct. |
576 | #[darling(flatten)] |
577 | visibility: VisibilityAttr, |
578 | |
579 | /// The parsed body of the derived struct. |
580 | data: darling::ast::Data<darling::util::Ignored, Field>, |
581 | |
582 | no_std: Flag, |
583 | |
584 | /// When present, emit additional fallible setters alongside each regular |
585 | /// setter. |
586 | try_setter: Flag, |
587 | |
588 | #[darling(default)] |
589 | field: VisibilityAttr, |
590 | } |
591 | |
592 | /// Accessors for parsed properties. |
593 | impl Options { |
594 | pub fn builder_ident(&self) -> Ident { |
595 | if let Some(ref custom) = self.name { |
596 | return custom.clone(); |
597 | } |
598 | |
599 | format_ident!(" {}Builder" , self.ident) |
600 | } |
601 | |
602 | pub fn builder_error_ident(&self) -> Path { |
603 | if let Some(BuildFnError::Existing(existing)) = self.build_fn.error.as_ref() { |
604 | existing.clone() |
605 | } else if let Some(ref custom) = self.name { |
606 | format_ident!(" {}Error" , custom).into() |
607 | } else { |
608 | format_ident!(" {}BuilderError" , self.ident).into() |
609 | } |
610 | } |
611 | |
612 | /// The visibility of the builder struct. |
613 | /// If a visibility was declared in attributes, that will be used; |
614 | /// otherwise the struct's own visibility will be used. |
615 | pub fn builder_vis(&self) -> Cow<syn::Visibility> { |
616 | self.visibility |
617 | .to_explicit_visibility() |
618 | .unwrap_or_else(|| Cow::Borrowed(&self.vis)) |
619 | } |
620 | |
621 | /// Get the visibility of the emitted `build` method. |
622 | /// This defaults to the visibility of the parent builder, but can be overridden. |
623 | pub fn build_method_vis(&self) -> Cow<syn::Visibility> { |
624 | self.build_fn |
625 | .visibility |
626 | .to_explicit_visibility() |
627 | .unwrap_or_else(|| self.builder_vis()) |
628 | } |
629 | |
630 | pub fn raw_fields(&self) -> Vec<&Field> { |
631 | self.data |
632 | .as_ref() |
633 | .take_struct() |
634 | .expect("Only structs supported" ) |
635 | .fields |
636 | } |
637 | |
638 | /// A builder requires `Clone` to be derived if its build method or any of its setters |
639 | /// use the mutable or immutable pattern. |
640 | pub fn requires_clone(&self) -> bool { |
641 | self.pattern.requires_clone() || self.fields().any(|f| f.pattern().requires_clone()) |
642 | } |
643 | |
644 | /// Get an iterator over the input struct's fields which pulls fallback |
645 | /// values from struct-level settings. |
646 | pub fn fields(&self) -> FieldIter { |
647 | FieldIter(self, self.raw_fields().into_iter()) |
648 | } |
649 | |
650 | pub fn field_count(&self) -> usize { |
651 | self.raw_fields().len() |
652 | } |
653 | } |
654 | |
655 | /// Converters to codegen structs |
656 | impl Options { |
657 | pub fn as_builder(&self) -> Builder { |
658 | Builder { |
659 | crate_root: &self.crate_root, |
660 | enabled: true, |
661 | ident: self.builder_ident(), |
662 | pattern: self.pattern, |
663 | derives: &self.derive, |
664 | struct_attrs: &self.attrs.struct_attrs, |
665 | impl_attrs: &self.attrs.impl_attrs, |
666 | impl_default: !self.custom_constructor.is_present(), |
667 | create_empty: self.create_empty.clone(), |
668 | generics: Some(&self.generics), |
669 | visibility: self.builder_vis(), |
670 | fields: Vec::with_capacity(self.field_count()), |
671 | field_initializers: Vec::with_capacity(self.field_count()), |
672 | functions: Vec::with_capacity(self.field_count()), |
673 | generate_error: self |
674 | .build_fn |
675 | .error |
676 | .as_ref() |
677 | .and_then(BuildFnError::as_existing) |
678 | .is_none(), |
679 | generate_validation_error: self |
680 | .build_fn |
681 | .error |
682 | .as_ref() |
683 | .and_then(BuildFnError::as_generated) |
684 | .map(|e| *e.validation_error) |
685 | .unwrap_or(true), |
686 | no_alloc: cfg!(not(any(feature = "alloc" , feature = "lib_has_std" ))), |
687 | must_derive_clone: self.requires_clone(), |
688 | doc_comment: None, |
689 | std: !self.no_std.is_present(), |
690 | } |
691 | } |
692 | |
693 | pub fn as_build_method(&self) -> BuildMethod { |
694 | let (_, ty_generics, _) = self.generics.split_for_impl(); |
695 | BuildMethod { |
696 | crate_root: &self.crate_root, |
697 | enabled: !self.build_fn.skip, |
698 | ident: &self.build_fn.name, |
699 | visibility: self.build_method_vis(), |
700 | pattern: self.pattern, |
701 | target_ty: &self.ident, |
702 | target_ty_generics: Some(ty_generics), |
703 | error_ty: self.builder_error_ident(), |
704 | initializers: Vec::with_capacity(self.field_count()), |
705 | doc_comment: None, |
706 | default_struct: self.default.as_ref(), |
707 | validate_fn: self.build_fn.validate.as_ref(), |
708 | } |
709 | } |
710 | } |
711 | |
712 | /// Accessor for field data which can pull through options from the parent |
713 | /// struct. |
714 | pub struct FieldWithDefaults<'a> { |
715 | parent: &'a Options, |
716 | field: &'a Field, |
717 | } |
718 | |
719 | /// Accessors for parsed properties, with transparent pull-through from the |
720 | /// parent struct's configuration. |
721 | impl<'a> FieldWithDefaults<'a> { |
722 | /// Check if this field should emit a setter. |
723 | pub fn setter_enabled(&self) -> bool { |
724 | self.field |
725 | .setter |
726 | .setter_enabled() |
727 | .or_else(|| self.parent.setter.enabled()) |
728 | .unwrap_or(true) |
729 | } |
730 | |
731 | pub fn field_enabled(&self) -> bool { |
732 | self.field |
733 | .setter |
734 | .field_enabled() |
735 | .or_else(|| self.parent.setter.enabled()) |
736 | .unwrap_or(true) |
737 | } |
738 | |
739 | /// Check if this field should emit a fallible setter. |
740 | /// This depends on the `TryFrom` trait, which hasn't yet stabilized. |
741 | pub fn try_setter(&self) -> bool { |
742 | self.field.try_setter.is_present() || self.parent.try_setter.is_present() |
743 | } |
744 | |
745 | /// Get the prefix that should be applied to the field name to produce |
746 | /// the setter ident, if any. |
747 | pub fn setter_prefix(&self) -> Option<&Ident> { |
748 | self.field |
749 | .setter |
750 | .prefix |
751 | .as_ref() |
752 | .or(self.parent.setter.prefix.as_ref()) |
753 | } |
754 | |
755 | /// Get the ident of the emitted setter method |
756 | pub fn setter_ident(&self) -> syn::Ident { |
757 | if let Some(ref custom) = self.field.setter.name { |
758 | return custom.clone(); |
759 | } |
760 | |
761 | let ident = &self.field.ident; |
762 | |
763 | if let Some(ref prefix) = self.setter_prefix() { |
764 | return format_ident!(" {}_ {}" , prefix, ident.as_ref().unwrap()); |
765 | } |
766 | |
767 | ident.clone().unwrap() |
768 | } |
769 | |
770 | /// Checks if the emitted setter should be generic over types that impl |
771 | /// `Into<FieldType>`. |
772 | pub fn setter_into(&self) -> bool { |
773 | self.field |
774 | .setter |
775 | .into |
776 | .or(self.parent.setter.into) |
777 | .unwrap_or_default() |
778 | } |
779 | |
780 | /// Checks if the emitted setter should strip the wrapper Option over types that impl |
781 | /// `Option<FieldType>`. |
782 | pub fn setter_strip_option(&self) -> bool { |
783 | self.field |
784 | .setter |
785 | .strip_option |
786 | .or(self.parent.setter.strip_option) |
787 | .unwrap_or_default() |
788 | } |
789 | |
790 | /// Get the visibility of the emitted setter, if there will be one. |
791 | pub fn setter_vis(&self) -> Cow<syn::Visibility> { |
792 | self.field |
793 | .visibility |
794 | .to_explicit_visibility() |
795 | .or_else(|| self.parent.visibility.to_explicit_visibility()) |
796 | .unwrap_or_else(|| Cow::Owned(syn::parse_quote!(pub))) |
797 | } |
798 | |
799 | /// Get the ident of the input field. This is also used as the ident of the |
800 | /// emitted field. |
801 | pub fn field_ident(&self) -> &syn::Ident { |
802 | self.field |
803 | .ident |
804 | .as_ref() |
805 | .expect("Tuple structs are not supported" ) |
806 | } |
807 | |
808 | pub fn field_vis(&self) -> Cow<syn::Visibility> { |
809 | self.field |
810 | .field |
811 | .visibility |
812 | .to_explicit_visibility() |
813 | .or_else( |
814 | // Disabled fields become a PhantomData in the builder. We make that field |
815 | // non-public, even if the rest of the builder is public, since this field is just |
816 | // there to make sure the struct's generics are properly handled. |
817 | || { |
818 | if self.field_enabled() { |
819 | None |
820 | } else { |
821 | Some(Cow::Owned(syn::Visibility::Inherited)) |
822 | } |
823 | }, |
824 | ) |
825 | .or_else(|| self.parent.field.to_explicit_visibility()) |
826 | .unwrap_or(Cow::Owned(syn::Visibility::Inherited)) |
827 | } |
828 | |
829 | pub fn field_type(&'a self) -> BuilderFieldType<'a> { |
830 | if !self.field_enabled() { |
831 | BuilderFieldType::Phantom(&self.field.ty) |
832 | } else if let Some(custom_ty) = self.field.field.builder_type.as_ref() { |
833 | BuilderFieldType::Precise(custom_ty) |
834 | } else { |
835 | BuilderFieldType::Optional(&self.field.ty) |
836 | } |
837 | } |
838 | |
839 | pub fn conversion(&'a self) -> FieldConversion<'a> { |
840 | match (&self.field.field.builder_type, &self.field.field.build) { |
841 | (_, Some(block)) => FieldConversion::Block(block), |
842 | (Some(_), None) => FieldConversion::Move, |
843 | (None, None) => FieldConversion::OptionOrDefault, |
844 | } |
845 | } |
846 | |
847 | pub fn pattern(&self) -> BuilderPattern { |
848 | self.field.pattern.unwrap_or(self.parent.pattern) |
849 | } |
850 | |
851 | pub fn use_parent_default(&self) -> bool { |
852 | self.field.default.is_none() && self.parent.default.is_some() |
853 | } |
854 | } |
855 | |
856 | /// Converters to codegen structs |
857 | impl<'a> FieldWithDefaults<'a> { |
858 | /// Returns a `Setter` according to the options. |
859 | pub fn as_setter(&'a self) -> Setter<'a> { |
860 | Setter { |
861 | crate_root: &self.parent.crate_root, |
862 | setter_enabled: self.setter_enabled(), |
863 | try_setter: self.try_setter(), |
864 | visibility: self.setter_vis(), |
865 | pattern: self.pattern(), |
866 | attrs: &self.field.attrs.setter, |
867 | ident: self.setter_ident(), |
868 | field_ident: self.field_ident(), |
869 | field_type: self.field_type(), |
870 | generic_into: self.setter_into(), |
871 | strip_option: self.setter_strip_option(), |
872 | each: self.field.setter.each.as_ref(), |
873 | } |
874 | } |
875 | |
876 | /// Returns an `Initializer` according to the options. |
877 | /// |
878 | /// # Panics |
879 | /// |
880 | /// if `default_expression` can not be parsed as `Block`. |
881 | pub fn as_initializer(&'a self) -> Initializer<'a> { |
882 | Initializer { |
883 | crate_root: &self.parent.crate_root, |
884 | field_enabled: self.field_enabled(), |
885 | field_ident: self.field_ident(), |
886 | builder_pattern: self.pattern(), |
887 | default_value: self.field.default.as_ref(), |
888 | use_default_struct: self.use_parent_default(), |
889 | conversion: self.conversion(), |
890 | custom_error_type_span: self.parent.build_fn.error.as_ref().and_then(|err_ty| { |
891 | match err_ty { |
892 | BuildFnError::Existing(p) => Some(p.span()), |
893 | _ => None, |
894 | } |
895 | }), |
896 | } |
897 | } |
898 | |
899 | pub fn as_builder_field(&'a self) -> BuilderField<'a> { |
900 | BuilderField { |
901 | crate_root: &self.parent.crate_root, |
902 | field_ident: self.field_ident(), |
903 | field_type: self.field_type(), |
904 | field_visibility: self.field_vis(), |
905 | attrs: &self.field.attrs.field, |
906 | } |
907 | } |
908 | } |
909 | |
910 | pub struct FieldIter<'a>(&'a Options, IntoIter<&'a Field>); |
911 | |
912 | impl<'a> Iterator for FieldIter<'a> { |
913 | type Item = FieldWithDefaults<'a>; |
914 | |
915 | fn next(&mut self) -> Option<Self::Item> { |
916 | self.1.next().map(|field: &'a Field| FieldWithDefaults { |
917 | parent: self.0, |
918 | field, |
919 | }) |
920 | } |
921 | } |
922 | |