• 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, Span, TokenStream, TokenTree};
7 use quote::quote;
8 use syn::{Item, ItemTrait};
9 
10 #[test]
test_macro_variable_attr()11 fn test_macro_variable_attr() {
12     // mimics the token stream corresponding to `$attr fn f() {}`
13     let tokens = TokenStream::from_iter(vec![
14         TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
15         TokenTree::Ident(Ident::new("fn", Span::call_site())),
16         TokenTree::Ident(Ident::new("f", Span::call_site())),
17         TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
18         TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
19     ]);
20 
21     snapshot!(tokens as Item, @r###"
22     Item::Fn {
23         attrs: [
24             Attribute {
25                 style: AttrStyle::Outer,
26                 meta: Meta::Path {
27                     segments: [
28                         PathSegment {
29                             ident: "test",
30                         },
31                     ],
32                 },
33             },
34         ],
35         vis: Visibility::Inherited,
36         sig: Signature {
37             ident: "f",
38             generics: Generics,
39             output: ReturnType::Default,
40         },
41         block: Block,
42     }
43     "###);
44 }
45 
46 #[test]
test_negative_impl()47 fn test_negative_impl() {
48     // Rustc parses all of the following.
49 
50     #[cfg(any())]
51     impl ! {}
52     let tokens = quote! {
53         impl ! {}
54     };
55     snapshot!(tokens as Item, @r###"
56     Item::Impl {
57         generics: Generics,
58         self_ty: Type::Never,
59     }
60     "###);
61 
62     #[cfg(any())]
63     #[rustfmt::skip]
64     impl !Trait {}
65     let tokens = quote! {
66         impl !Trait {}
67     };
68     snapshot!(tokens as Item, @r###"
69     Item::Impl {
70         generics: Generics,
71         self_ty: Type::Verbatim(`! Trait`),
72     }
73     "###);
74 
75     #[cfg(any())]
76     impl !Trait for T {}
77     let tokens = quote! {
78         impl !Trait for T {}
79     };
80     snapshot!(tokens as Item, @r###"
81     Item::Impl {
82         generics: Generics,
83         trait_: Some((
84             Some,
85             Path {
86                 segments: [
87                     PathSegment {
88                         ident: "Trait",
89                     },
90                 ],
91             },
92         )),
93         self_ty: Type::Path {
94             path: Path {
95                 segments: [
96                     PathSegment {
97                         ident: "T",
98                     },
99                 ],
100             },
101         },
102     }
103     "###);
104 
105     #[cfg(any())]
106     #[rustfmt::skip]
107     impl !! {}
108     let tokens = quote! {
109         impl !! {}
110     };
111     snapshot!(tokens as Item, @r###"
112     Item::Impl {
113         generics: Generics,
114         self_ty: Type::Verbatim(`! !`),
115     }
116     "###);
117 }
118 
119 #[test]
test_macro_variable_impl()120 fn test_macro_variable_impl() {
121     // mimics the token stream corresponding to `impl $trait for $ty {}`
122     let tokens = TokenStream::from_iter(vec![
123         TokenTree::Ident(Ident::new("impl", Span::call_site())),
124         TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
125         TokenTree::Ident(Ident::new("for", Span::call_site())),
126         TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
127         TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
128     ]);
129 
130     snapshot!(tokens as Item, @r###"
131     Item::Impl {
132         generics: Generics,
133         trait_: Some((
134             None,
135             Path {
136                 segments: [
137                     PathSegment {
138                         ident: "Trait",
139                     },
140                 ],
141             },
142         )),
143         self_ty: Type::Group {
144             elem: Type::Path {
145                 path: Path {
146                     segments: [
147                         PathSegment {
148                             ident: "Type",
149                         },
150                     ],
151                 },
152             },
153         },
154     }
155     "###);
156 }
157 
158 #[test]
test_supertraits()159 fn test_supertraits() {
160     // Rustc parses all of the following.
161 
162     #[rustfmt::skip]
163     let tokens = quote!(trait Trait where {});
164     snapshot!(tokens as ItemTrait, @r###"
165     ItemTrait {
166         vis: Visibility::Inherited,
167         ident: "Trait",
168         generics: Generics {
169             where_clause: Some(WhereClause),
170         },
171     }
172     "###);
173 
174     #[rustfmt::skip]
175     let tokens = quote!(trait Trait: where {});
176     snapshot!(tokens as ItemTrait, @r###"
177     ItemTrait {
178         vis: Visibility::Inherited,
179         ident: "Trait",
180         generics: Generics {
181             where_clause: Some(WhereClause),
182         },
183         colon_token: Some,
184     }
185     "###);
186 
187     #[rustfmt::skip]
188     let tokens = quote!(trait Trait: Sized where {});
189     snapshot!(tokens as ItemTrait, @r###"
190     ItemTrait {
191         vis: Visibility::Inherited,
192         ident: "Trait",
193         generics: Generics {
194             where_clause: Some(WhereClause),
195         },
196         colon_token: Some,
197         supertraits: [
198             TypeParamBound::Trait(TraitBound {
199                 path: Path {
200                     segments: [
201                         PathSegment {
202                             ident: "Sized",
203                         },
204                     ],
205                 },
206             }),
207         ],
208     }
209     "###);
210 
211     #[rustfmt::skip]
212     let tokens = quote!(trait Trait: Sized + where {});
213     snapshot!(tokens as ItemTrait, @r###"
214     ItemTrait {
215         vis: Visibility::Inherited,
216         ident: "Trait",
217         generics: Generics {
218             where_clause: Some(WhereClause),
219         },
220         colon_token: Some,
221         supertraits: [
222             TypeParamBound::Trait(TraitBound {
223                 path: Path {
224                     segments: [
225                         PathSegment {
226                             ident: "Sized",
227                         },
228                     ],
229                 },
230             }),
231         ],
232     }
233     "###);
234 }
235 
236 #[test]
test_type_empty_bounds()237 fn test_type_empty_bounds() {
238     #[rustfmt::skip]
239     let tokens = quote! {
240         trait Foo {
241             type Bar: ;
242         }
243     };
244 
245     snapshot!(tokens as ItemTrait, @r###"
246     ItemTrait {
247         vis: Visibility::Inherited,
248         ident: "Foo",
249         generics: Generics,
250         items: [
251             TraitItem::Type {
252                 ident: "Bar",
253                 generics: Generics,
254                 colon_token: Some,
255             },
256         ],
257     }
258     "###);
259 }
260 
261 #[test]
test_impl_visibility()262 fn test_impl_visibility() {
263     let tokens = quote! {
264         pub default unsafe impl union {}
265     };
266 
267     snapshot!(tokens as Item, @"Item::Verbatim(`pub default unsafe impl union { }`)");
268 }
269 
270 #[test]
test_impl_type_parameter_defaults()271 fn test_impl_type_parameter_defaults() {
272     #[cfg(any())]
273     impl<T = ()> () {}
274     let tokens = quote! {
275         impl<T = ()> () {}
276     };
277     snapshot!(tokens as Item, @r###"
278     Item::Impl {
279         generics: Generics {
280             lt_token: Some,
281             params: [
282                 GenericParam::Type(TypeParam {
283                     ident: "T",
284                     eq_token: Some,
285                     default: Some(Type::Tuple),
286                 }),
287             ],
288             gt_token: Some,
289         },
290         self_ty: Type::Tuple,
291     }
292     "###);
293 }
294 
295 #[test]
test_impl_trait_trailing_plus()296 fn test_impl_trait_trailing_plus() {
297     let tokens = quote! {
298         fn f() -> impl Sized + {}
299     };
300 
301     snapshot!(tokens as Item, @r###"
302     Item::Fn {
303         vis: Visibility::Inherited,
304         sig: Signature {
305             ident: "f",
306             generics: Generics,
307             output: ReturnType::Type(
308                 Type::ImplTrait {
309                     bounds: [
310                         TypeParamBound::Trait(TraitBound {
311                             path: Path {
312                                 segments: [
313                                     PathSegment {
314                                         ident: "Sized",
315                                     },
316                                 ],
317                             },
318                         }),
319                     ],
320                 },
321             ),
322         },
323         block: Block,
324     }
325     "###);
326 }
327