1 use darling::FromDeriveInput;
2 use syn::parse_quote;
3
4 mod foo {
5 pub mod bar {
init() -> String6 pub fn init() -> String {
7 String::from("hello")
8 }
9 }
10 }
11
12 #[derive(FromDeriveInput)]
13 #[darling(attributes(speak))]
14 pub struct SpeakerOpts {
15 #[darling(default = foo::bar::init)]
16 first_word: String,
17 }
18
19 #[test]
path_default()20 fn path_default() {
21 let speaker: SpeakerOpts = FromDeriveInput::from_derive_input(&parse_quote! {
22 struct Foo;
23 })
24 .expect("Unit struct with no attrs should parse");
25
26 assert_eq!(speaker.first_word, "hello");
27 }
28
29 /// Tests in this module capture the somewhat-confusing behavior observed when defaults
30 /// are set at both the field and container level.
31 ///
32 /// The general rule is that more-specific declarations preempt less-specific ones; this is
33 /// unsurprising and allows for granular control over what happens when parsing an AST.
34 mod stacked_defaults {
35 use darling::{FromDeriveInput, FromMeta};
36 use syn::parse_quote;
37
jane() -> String38 fn jane() -> String {
39 "Jane".into()
40 }
41
42 #[derive(FromMeta)]
43 #[darling(default)]
44 struct PersonName {
45 #[darling(default = "jane")]
46 first: String,
47 #[darling(default)]
48 middle: String,
49 last: String,
50 }
51
52 impl Default for PersonName {
default() -> Self53 fn default() -> Self {
54 Self {
55 first: "John".into(),
56 middle: "T".into(),
57 last: "Doe".into(),
58 }
59 }
60 }
61
62 #[derive(FromDeriveInput)]
63 #[darling(attributes(person))]
64 struct Person {
65 #[darling(default)]
66 name: PersonName,
67 age: u8,
68 }
69
70 #[test]
name_first_only()71 fn name_first_only() {
72 let person = Person::from_derive_input(&parse_quote! {
73 #[person(name(first = "Bill"), age = 5)]
74 struct Foo;
75 })
76 .unwrap();
77
78 assert_eq!(person.name.first, "Bill");
79 assert_eq!(
80 person.name.middle, "",
81 "Explicit field-level default should preempt container-level default"
82 );
83 assert_eq!(
84 person.name.last, "Doe",
85 "Absence of a field-level default falls back to container-level default"
86 );
87 }
88
89 /// This is the most surprising case. The presence of `name()` means we invoke
90 /// `PersonName::from_list(&[])`. When that finishes parsing each of the zero nested
91 /// items it has received, it will then start filling in missing fields, using the
92 /// explicit field-level defaults for `first` and `middle`, while for `last` it will
93 /// use the `last` field from the container-level default.
94 #[test]
name_empty_list()95 fn name_empty_list() {
96 let person = Person::from_derive_input(&parse_quote! {
97 #[person(name(), age = 5)]
98 struct Foo;
99 })
100 .unwrap();
101
102 assert_eq!(person.name.first, "Jane");
103 assert_eq!(person.name.middle, "");
104 assert_eq!(person.name.last, "Doe");
105 }
106
107 #[test]
no_name()108 fn no_name() {
109 let person = Person::from_derive_input(&parse_quote! {
110 #[person(age = 5)]
111 struct Foo;
112 })
113 .unwrap();
114
115 assert_eq!(person.age, 5);
116 assert_eq!(
117 person.name.first, "John",
118 "If `name` is not specified, `Person`'s field-level default should be used"
119 );
120 assert_eq!(person.name.middle, "T");
121 assert_eq!(person.name.last, "Doe");
122 }
123 }
124
125 mod implicit_default {
126 use darling::{util::Flag, FromDeriveInput};
127 use syn::parse_quote;
128
129 // No use of `darling(default)` here at all!
130 // This struct will fill in missing fields using FromMeta::from_none.
131 #[derive(FromDeriveInput)]
132 #[darling(attributes(person))]
133 struct Person {
134 first_name: String,
135 last_name: Option<String>,
136 lefty: Flag,
137 }
138
139 #[test]
missing_fields_fill()140 fn missing_fields_fill() {
141 let person = Person::from_derive_input(&parse_quote! {
142 #[person(first_name = "James")]
143 struct Foo;
144 })
145 .unwrap();
146
147 assert_eq!(person.first_name, "James");
148 assert_eq!(person.last_name, None);
149 assert!(!person.lefty.is_present());
150 }
151 }
152
153 /// Test that a field-level implicit default using FromMeta::from_none is superseded
154 /// by the parent declaring `#[darling(default)]`.
155 mod overridden_implicit_default {
156 use darling::{util::Flag, FromDeriveInput};
157 use syn::parse_quote;
158
159 #[derive(FromDeriveInput)]
160 #[darling(default, attributes(person))]
161 struct Person {
162 first_name: String,
163 last_name: Option<String>,
164 lefty: Flag,
165 }
166
167 impl Default for Person {
default() -> Self168 fn default() -> Self {
169 Self {
170 first_name: "Jane".into(),
171 last_name: Some("Doe".into()),
172 lefty: Flag::default(),
173 }
174 }
175 }
176
177 #[test]
fill_missing()178 fn fill_missing() {
179 let person = Person::from_derive_input(&parse_quote!(
180 #[person(last_name = "Archer")]
181 struct Foo;
182 ))
183 .unwrap();
184
185 assert_eq!(person.first_name, "Jane");
186 assert_eq!(person.last_name, Some("Archer".into()));
187 assert!(!person.lefty.is_present());
188 }
189 }
190