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