1 //! Tests for `FromGenerics`, and - indirectly - `FromGenericParam`.
2 //! These tests assume `FromTypeParam` is working and only look at whether the wrappers for magic
3 //! fields are working as expected.
4
5 use darling::{
6 ast::{self, GenericParamExt},
7 util::{Ignored, WithOriginal},
8 FromDeriveInput, FromTypeParam, Result,
9 };
10
11 #[derive(FromDeriveInput)]
12 #[darling(attributes(lorem))]
13 struct MyReceiver {
14 pub generics: ast::Generics<ast::GenericParam<MyTypeParam>>,
15 }
16
17 #[derive(FromTypeParam)]
18 #[darling(attributes(lorem))]
19 struct MyTypeParam {
20 pub ident: syn::Ident,
21 #[darling(default)]
22 pub foo: bool,
23 pub bar: Option<String>,
24 }
25
fdi<T: FromDeriveInput>(src: &str) -> Result<T>26 fn fdi<T: FromDeriveInput>(src: &str) -> Result<T> {
27 FromDeriveInput::from_derive_input(&syn::parse_str(src).expect("Source parses"))
28 }
29
30 /// Verify that `ast::Generics` is populated correctly when there is no generics declaration
31 #[test]
no_generics()32 fn no_generics() {
33 let rec: MyReceiver = fdi("struct Baz;").expect("Input is well-formed");
34 assert!(rec.generics.where_clause.is_none());
35 assert_eq!(rec.generics.params.len(), 0);
36 }
37
38 #[test]
39 #[allow(clippy::bool_assert_comparison)]
expand_some()40 fn expand_some() {
41 let rec: MyReceiver = fdi(r#"
42 struct Baz<
43 'a,
44 #[lorem(foo)] T,
45 #[lorem(bar = "x")] U: Eq + ?Sized
46 >(&'a T, U);
47 "#)
48 .expect("Input is well-formed");
49 assert!(rec.generics.where_clause.is_none());
50
51 // Make sure we've preserved the lifetime param, though we don't do anything with it.
52 assert!(rec.generics.params[0].as_lifetime_param().is_some());
53
54 let mut ty_param_iter = rec.generics.type_params();
55
56 let first = ty_param_iter
57 .next()
58 .expect("type_params should not be empty");
59 assert!(first.bar.is_none());
60 assert!(first.foo);
61 assert_eq!(first.ident, "T");
62
63 let second = ty_param_iter
64 .next()
65 .expect("type_params should have a second value");
66 assert_eq!(
67 second
68 .bar
69 .as_ref()
70 .expect("Second type param should set bar"),
71 "x"
72 );
73 assert_eq!(second.foo, false);
74 assert_eq!(second.ident, "U");
75 }
76
77 /// Verify ≤0.4.1 behavior - where `generics` had to be `syn::Generics` - keeps working.
78 #[test]
passthrough()79 fn passthrough() {
80 #[derive(FromDeriveInput)]
81 struct PassthroughReceiver {
82 pub generics: syn::Generics,
83 }
84
85 let rec: PassthroughReceiver = fdi(r#"
86 struct Baz<
87 'a,
88 #[lorem(foo)] T,
89 #[lorem(bar = "x")] U: Eq + ?Sized
90 >(&'a T, U);
91 "#)
92 .expect("Input is well-formed");
93
94 let mut type_param_iter = rec.generics.type_params();
95 assert!(type_param_iter.next().is_some());
96 }
97
98 /// Verify that `where_clause` is passed through when it exists.
99 /// As of 0.4.1, there is no `FromWhereClause` trait, so other types aren't supported
100 /// for that field.
101 #[test]
where_clause()102 fn where_clause() {
103 let rec: MyReceiver = fdi(r#"
104 struct Baz<
105 'a,
106 #[lorem(foo)] T,
107 #[lorem(bar = "x")] U: Eq + ?Sized
108 >(&'a T, U) where T: Into<String>;
109 "#)
110 .expect("Input is well-formed");
111
112 assert!(rec.generics.where_clause.is_some());
113 }
114
115 /// Test that `WithOriginal` works for generics.
116 #[test]
with_original()117 fn with_original() {
118 #[derive(FromDeriveInput)]
119 struct WorigReceiver {
120 generics: WithOriginal<ast::Generics<ast::GenericParam<MyTypeParam>>, syn::Generics>,
121 }
122
123 let rec: WorigReceiver = fdi(r#"
124 struct Baz<
125 'a,
126 #[lorem(foo)] T,
127 #[lorem(bar = "x")] U: Eq + ?Sized
128 >(&'a T, U) where T: Into<String>;
129 "#)
130 .expect("Input is well-formed");
131
132 // Make sure we haven't lost anything in the conversion
133 assert_eq!(rec.generics.parsed.params.len(), 3);
134 assert_eq!(rec.generics.original.params.len(), 3);
135
136 let parsed_t: &MyTypeParam = rec.generics.parsed.params[1]
137 .as_type_param()
138 .expect("Second argument should be type param");
139
140 // Make sure the first type param in each case is T
141 assert_eq!(parsed_t.ident, "T");
142 assert_eq!(
143 rec.generics
144 .original
145 .type_params()
146 .next()
147 .expect("First type param should exist")
148 .ident,
149 "T"
150 );
151
152 // Make sure we actually parsed the first type param
153 assert!(parsed_t.foo);
154 assert!(parsed_t.bar.is_none());
155 }
156
157 /// Make sure generics can be ignored
158 #[test]
ignored()159 fn ignored() {
160 #[derive(FromDeriveInput)]
161 struct IgnoredReceiver {
162 generics: Ignored,
163 }
164
165 let rec: IgnoredReceiver = fdi(r#"
166 struct Baz<
167 'a,
168 #[lorem(foo)] T,
169 #[lorem(bar = "x")] U: Eq + ?Sized
170 >(&'a T, U) where T: Into<String>;
171 "#)
172 .expect("Input is well-formed");
173
174 assert_eq!(Ignored, rec.generics);
175 }
176