• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(clippy::uninlined_format_args)]
2 
3 #[macro_use]
4 mod macros;
5 
6 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
7 use quote::quote;
8 use syn::Type;
9 
10 #[test]
test_mut_self()11 fn test_mut_self() {
12     syn::parse_str::<Type>("fn(mut self)").unwrap();
13     syn::parse_str::<Type>("fn(mut self,)").unwrap();
14     syn::parse_str::<Type>("fn(mut self: ())").unwrap();
15     syn::parse_str::<Type>("fn(mut self: ...)").unwrap_err();
16     syn::parse_str::<Type>("fn(mut self: mut self)").unwrap_err();
17     syn::parse_str::<Type>("fn(mut self::T)").unwrap_err();
18 }
19 
20 #[test]
test_macro_variable_type()21 fn test_macro_variable_type() {
22     // mimics the token stream corresponding to `$ty<T>`
23     let tokens = TokenStream::from_iter(vec![
24         TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
25         TokenTree::Punct(Punct::new('<', Spacing::Alone)),
26         TokenTree::Ident(Ident::new("T", Span::call_site())),
27         TokenTree::Punct(Punct::new('>', Spacing::Alone)),
28     ]);
29 
30     snapshot!(tokens as Type, @r###"
31     Type::Path {
32         path: Path {
33             segments: [
34                 PathSegment {
35                     ident: "ty",
36                     arguments: PathArguments::AngleBracketed {
37                         args: [
38                             GenericArgument::Type(Type::Path {
39                                 path: Path {
40                                     segments: [
41                                         PathSegment {
42                                             ident: "T",
43                                         },
44                                     ],
45                                 },
46                             }),
47                         ],
48                     },
49                 },
50             ],
51         },
52     }
53     "###);
54 
55     // mimics the token stream corresponding to `$ty::<T>`
56     let tokens = TokenStream::from_iter(vec![
57         TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
58         TokenTree::Punct(Punct::new(':', Spacing::Joint)),
59         TokenTree::Punct(Punct::new(':', Spacing::Alone)),
60         TokenTree::Punct(Punct::new('<', Spacing::Alone)),
61         TokenTree::Ident(Ident::new("T", Span::call_site())),
62         TokenTree::Punct(Punct::new('>', Spacing::Alone)),
63     ]);
64 
65     snapshot!(tokens as Type, @r###"
66     Type::Path {
67         path: Path {
68             segments: [
69                 PathSegment {
70                     ident: "ty",
71                     arguments: PathArguments::AngleBracketed {
72                         colon2_token: Some,
73                         args: [
74                             GenericArgument::Type(Type::Path {
75                                 path: Path {
76                                     segments: [
77                                         PathSegment {
78                                             ident: "T",
79                                         },
80                                     ],
81                                 },
82                             }),
83                         ],
84                     },
85                 },
86             ],
87         },
88     }
89     "###);
90 }
91 
92 #[test]
test_group_angle_brackets()93 fn test_group_angle_brackets() {
94     // mimics the token stream corresponding to `Option<$ty>`
95     let tokens = TokenStream::from_iter(vec![
96         TokenTree::Ident(Ident::new("Option", Span::call_site())),
97         TokenTree::Punct(Punct::new('<', Spacing::Alone)),
98         TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
99         TokenTree::Punct(Punct::new('>', Spacing::Alone)),
100     ]);
101 
102     snapshot!(tokens as Type, @r###"
103     Type::Path {
104         path: Path {
105             segments: [
106                 PathSegment {
107                     ident: "Option",
108                     arguments: PathArguments::AngleBracketed {
109                         args: [
110                             GenericArgument::Type(Type::Group {
111                                 elem: Type::Path {
112                                     path: Path {
113                                         segments: [
114                                             PathSegment {
115                                                 ident: "Vec",
116                                                 arguments: PathArguments::AngleBracketed {
117                                                     args: [
118                                                         GenericArgument::Type(Type::Path {
119                                                             path: Path {
120                                                                 segments: [
121                                                                     PathSegment {
122                                                                         ident: "u8",
123                                                                     },
124                                                                 ],
125                                                             },
126                                                         }),
127                                                     ],
128                                                 },
129                                             },
130                                         ],
131                                     },
132                                 },
133                             }),
134                         ],
135                     },
136                 },
137             ],
138         },
139     }
140     "###);
141 }
142 
143 #[test]
test_group_colons()144 fn test_group_colons() {
145     // mimics the token stream corresponding to `$ty::Item`
146     let tokens = TokenStream::from_iter(vec![
147         TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
148         TokenTree::Punct(Punct::new(':', Spacing::Joint)),
149         TokenTree::Punct(Punct::new(':', Spacing::Alone)),
150         TokenTree::Ident(Ident::new("Item", Span::call_site())),
151     ]);
152 
153     snapshot!(tokens as Type, @r###"
154     Type::Path {
155         path: Path {
156             segments: [
157                 PathSegment {
158                     ident: "Vec",
159                     arguments: PathArguments::AngleBracketed {
160                         args: [
161                             GenericArgument::Type(Type::Path {
162                                 path: Path {
163                                     segments: [
164                                         PathSegment {
165                                             ident: "u8",
166                                         },
167                                     ],
168                                 },
169                             }),
170                         ],
171                     },
172                 },
173                 PathSegment {
174                     ident: "Item",
175                 },
176             ],
177         },
178     }
179     "###);
180 
181     let tokens = TokenStream::from_iter(vec![
182         TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })),
183         TokenTree::Punct(Punct::new(':', Spacing::Joint)),
184         TokenTree::Punct(Punct::new(':', Spacing::Alone)),
185         TokenTree::Ident(Ident::new("Element", Span::call_site())),
186     ]);
187 
188     snapshot!(tokens as Type, @r###"
189     Type::Path {
190         qself: Some(QSelf {
191             ty: Type::Slice {
192                 elem: Type::Path {
193                     path: Path {
194                         segments: [
195                             PathSegment {
196                                 ident: "T",
197                             },
198                         ],
199                     },
200                 },
201             },
202             position: 0,
203         }),
204         path: Path {
205             leading_colon: Some,
206             segments: [
207                 PathSegment {
208                     ident: "Element",
209                 },
210             ],
211         },
212     }
213     "###);
214 }
215 
216 #[test]
test_trait_object()217 fn test_trait_object() {
218     let tokens = quote!(dyn for<'a> Trait<'a> + 'static);
219     snapshot!(tokens as Type, @r###"
220     Type::TraitObject {
221         dyn_token: Some,
222         bounds: [
223             TypeParamBound::Trait(TraitBound {
224                 lifetimes: Some(BoundLifetimes {
225                     lifetimes: [
226                         GenericParam::Lifetime(LifetimeParam {
227                             lifetime: Lifetime {
228                                 ident: "a",
229                             },
230                         }),
231                     ],
232                 }),
233                 path: Path {
234                     segments: [
235                         PathSegment {
236                             ident: "Trait",
237                             arguments: PathArguments::AngleBracketed {
238                                 args: [
239                                     GenericArgument::Lifetime(Lifetime {
240                                         ident: "a",
241                                     }),
242                                 ],
243                             },
244                         },
245                     ],
246                 },
247             }),
248             TypeParamBound::Lifetime {
249                 ident: "static",
250             },
251         ],
252     }
253     "###);
254 
255     let tokens = quote!(dyn 'a + Trait);
256     snapshot!(tokens as Type, @r###"
257     Type::TraitObject {
258         dyn_token: Some,
259         bounds: [
260             TypeParamBound::Lifetime {
261                 ident: "a",
262             },
263             TypeParamBound::Trait(TraitBound {
264                 path: Path {
265                     segments: [
266                         PathSegment {
267                             ident: "Trait",
268                         },
269                     ],
270                 },
271             }),
272         ],
273     }
274     "###);
275 
276     // None of the following are valid Rust types.
277     syn::parse_str::<Type>("for<'a> dyn Trait<'a>").unwrap_err();
278     syn::parse_str::<Type>("dyn for<'a> 'a + Trait").unwrap_err();
279 }
280 
281 #[test]
test_trailing_plus()282 fn test_trailing_plus() {
283     #[rustfmt::skip]
284     let tokens = quote!(impl Trait +);
285     snapshot!(tokens as Type, @r###"
286     Type::ImplTrait {
287         bounds: [
288             TypeParamBound::Trait(TraitBound {
289                 path: Path {
290                     segments: [
291                         PathSegment {
292                             ident: "Trait",
293                         },
294                     ],
295                 },
296             }),
297         ],
298     }
299     "###);
300 
301     #[rustfmt::skip]
302     let tokens = quote!(dyn Trait +);
303     snapshot!(tokens as Type, @r###"
304     Type::TraitObject {
305         dyn_token: Some,
306         bounds: [
307             TypeParamBound::Trait(TraitBound {
308                 path: Path {
309                     segments: [
310                         PathSegment {
311                             ident: "Trait",
312                         },
313                     ],
314                 },
315             }),
316         ],
317     }
318     "###);
319 
320     #[rustfmt::skip]
321     let tokens = quote!(Trait +);
322     snapshot!(tokens as Type, @r###"
323     Type::TraitObject {
324         bounds: [
325             TypeParamBound::Trait(TraitBound {
326                 path: Path {
327                     segments: [
328                         PathSegment {
329                             ident: "Trait",
330                         },
331                     ],
332                 },
333             }),
334         ],
335     }
336     "###);
337 }
338