| 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 | |