Skip to content

Commit

Permalink
Use from_none in codegen
Browse files Browse the repository at this point in the history
This removes the need to use #[darling(default)] on options
in deriving structs.

Fixes #161
  • Loading branch information
TedDriggs committed Apr 11, 2022
1 parent f65b10b commit 8a962ab
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
10 changes: 9 additions & 1 deletion core/src/codegen/field.rs
Expand Up @@ -191,11 +191,19 @@ impl<'a> ToTokens for CheckMissing<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
if !self.0.multiple && self.0.default_expression.is_none() {
let ident = self.0.ident;
let ty = self.0.ty;
let name_in_attr = &self.0.name_in_attr;

tokens.append_all(quote! {
if !#ident.0 {
__errors.push(::darling::Error::missing_field(#name_in_attr));
match <#ty as ::darling::FromMeta>::from_none() {
::darling::export::Some(__type_fallback) => {
#ident.1 = ::darling::export::Some(__type_fallback);
}
::darling::export::None => {
__errors.push(::darling::Error::missing_field(#name_in_attr))
}
}
}
})
}
Expand Down
66 changes: 66 additions & 0 deletions tests/defaults.rs
Expand Up @@ -121,3 +121,69 @@ mod stacked_defaults {
assert_eq!(person.name.last, "Doe");
}
}

mod implicit_default {
use darling::{util::Flag, FromDeriveInput};
use syn::parse_quote;

// No use of `darling(default)` here at all!
// This struct will fill in missing fields using FromMeta::from_none.
#[derive(FromDeriveInput)]
#[darling(attributes(person))]
struct Person {
first_name: String,
last_name: Option<String>,
lefty: Flag,
}

#[test]
fn missing_fields_fill() {
let person = Person::from_derive_input(&parse_quote! {
#[person(first_name = "James")]
struct Foo;
})
.unwrap();

assert_eq!(person.first_name, "James");
assert_eq!(person.last_name, None);
assert_eq!(person.lefty, false);
}
}

/// Test that a field-level implicit default using FromMeta::from_none is superseded
/// by the parent declaring `#[darling(default)]`.
mod overridden_implicit_default {
use darling::{util::Flag, FromDeriveInput};
use syn::parse_quote;

#[derive(FromDeriveInput)]
#[darling(default, attributes(person))]
struct Person {
first_name: String,
last_name: Option<String>,
lefty: Flag,
}

impl Default for Person {
fn default() -> Self {
Self {
first_name: "Jane".into(),
last_name: Some("Doe".into()),
lefty: Flag::default(),
}
}
}

#[test]
fn fill_missing() {
let person = Person::from_derive_input(&parse_quote!(
#[person(last_name = "Archer")]
struct Foo;
))
.unwrap();

assert_eq!(person.first_name, "Jane");
assert_eq!(person.last_name, Some("Archer".into()));
assert_eq!(person.lefty, false);
}
}

0 comments on commit 8a962ab

Please sign in to comment.