]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
1 | #[macro_use] |
2 | mod macros; | |
3 | ||
f035d41b XL |
4 | use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; |
5 | use quote::quote; | |
6 | use std::iter::FromIterator; | |
e74abb32 XL |
7 | use syn::{Expr, ExprRange}; |
8 | ||
9 | #[test] | |
10 | fn test_expr_parse() { | |
f035d41b XL |
11 | let tokens = quote!(..100u32); |
12 | snapshot!(tokens as Expr, @r###" | |
13 | Expr::Range { | |
14 | limits: HalfOpen, | |
15 | to: Some(Expr::Lit { | |
16 | lit: 100u32, | |
17 | }), | |
18 | } | |
19 | "###); | |
20 | ||
21 | let tokens = quote!(..100u32); | |
22 | snapshot!(tokens as ExprRange, @r###" | |
23 | ExprRange { | |
24 | limits: HalfOpen, | |
25 | to: Some(Expr::Lit { | |
26 | lit: 100u32, | |
27 | }), | |
28 | } | |
29 | "###); | |
e74abb32 XL |
30 | } |
31 | ||
32 | #[test] | |
33 | fn test_await() { | |
34 | // Must not parse as Expr::Field. | |
f035d41b | 35 | let tokens = quote!(fut.await); |
e74abb32 | 36 | |
f035d41b | 37 | snapshot!(tokens as Expr, @r###" |
60c5eb7d XL |
38 | Expr::Await { |
39 | base: Expr::Path { | |
40 | path: Path { | |
41 | segments: [ | |
42 | PathSegment { | |
43 | ident: "fut", | |
44 | arguments: None, | |
45 | }, | |
46 | ], | |
47 | }, | |
48 | }, | |
49 | } | |
e74abb32 XL |
50 | "###); |
51 | } | |
f035d41b | 52 | |
3dfed10e | 53 | #[rustfmt::skip] |
f035d41b XL |
54 | #[test] |
55 | fn test_tuple_multi_index() { | |
3dfed10e XL |
56 | for &input in &[ |
57 | "tuple.0.0", | |
58 | "tuple .0.0", | |
59 | "tuple. 0.0", | |
60 | "tuple.0 .0", | |
61 | "tuple.0. 0", | |
62 | "tuple . 0 . 0", | |
63 | ] { | |
64 | snapshot!(input as Expr, @r###" | |
65 | Expr::Field { | |
66 | base: Expr::Field { | |
67 | base: Expr::Path { | |
68 | path: Path { | |
69 | segments: [ | |
70 | PathSegment { | |
71 | ident: "tuple", | |
72 | arguments: None, | |
73 | }, | |
74 | ], | |
75 | }, | |
f035d41b | 76 | }, |
3dfed10e XL |
77 | member: Unnamed(Index { |
78 | index: 0, | |
79 | }), | |
f035d41b XL |
80 | }, |
81 | member: Unnamed(Index { | |
82 | index: 0, | |
83 | }), | |
3dfed10e XL |
84 | } |
85 | "###); | |
f035d41b | 86 | } |
f035d41b | 87 | |
3dfed10e XL |
88 | for tokens in vec![ |
89 | quote!(tuple.0.0), | |
90 | quote!(tuple .0.0), | |
91 | quote!(tuple. 0.0), | |
92 | quote!(tuple.0 .0), | |
93 | quote!(tuple.0. 0), | |
94 | quote!(tuple . 0 . 0), | |
95 | ] { | |
96 | snapshot!(tokens as Expr, @r###" | |
97 | Expr::Field { | |
98 | base: Expr::Field { | |
99 | base: Expr::Path { | |
100 | path: Path { | |
101 | segments: [ | |
102 | PathSegment { | |
103 | ident: "tuple", | |
104 | arguments: None, | |
105 | }, | |
106 | ], | |
107 | }, | |
f035d41b | 108 | }, |
3dfed10e XL |
109 | member: Unnamed(Index { |
110 | index: 0, | |
111 | }), | |
f035d41b XL |
112 | }, |
113 | member: Unnamed(Index { | |
114 | index: 0, | |
115 | }), | |
3dfed10e XL |
116 | } |
117 | "###); | |
f035d41b | 118 | } |
f035d41b XL |
119 | } |
120 | ||
121 | #[test] | |
122 | fn test_macro_variable_func() { | |
123 | // mimics the token stream corresponding to `$fn()` | |
124 | let tokens = TokenStream::from_iter(vec![ | |
125 | TokenTree::Group(Group::new(Delimiter::None, quote! { f })), | |
126 | TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), | |
127 | ]); | |
128 | ||
129 | snapshot!(tokens as Expr, @r###" | |
130 | Expr::Call { | |
131 | func: Expr::Group { | |
132 | expr: Expr::Path { | |
133 | path: Path { | |
134 | segments: [ | |
135 | PathSegment { | |
136 | ident: "f", | |
137 | arguments: None, | |
138 | }, | |
139 | ], | |
140 | }, | |
141 | }, | |
142 | }, | |
143 | } | |
144 | "###); | |
145 | ||
146 | let tokens = TokenStream::from_iter(vec![ | |
147 | TokenTree::Punct(Punct::new('#', Spacing::Alone)), | |
148 | TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })), | |
149 | TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })), | |
150 | TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), | |
151 | ]); | |
152 | ||
153 | snapshot!(tokens as Expr, @r###" | |
154 | Expr::Call { | |
155 | attrs: [ | |
156 | Attribute { | |
157 | style: Outer, | |
158 | path: Path { | |
159 | segments: [ | |
160 | PathSegment { | |
161 | ident: "outside", | |
162 | arguments: None, | |
163 | }, | |
164 | ], | |
165 | }, | |
166 | tokens: TokenStream(``), | |
167 | }, | |
168 | ], | |
169 | func: Expr::Group { | |
170 | expr: Expr::Path { | |
171 | attrs: [ | |
172 | Attribute { | |
173 | style: Outer, | |
174 | path: Path { | |
175 | segments: [ | |
176 | PathSegment { | |
177 | ident: "inside", | |
178 | arguments: None, | |
179 | }, | |
180 | ], | |
181 | }, | |
182 | tokens: TokenStream(``), | |
183 | }, | |
184 | ], | |
185 | path: Path { | |
186 | segments: [ | |
187 | PathSegment { | |
188 | ident: "f", | |
189 | arguments: None, | |
190 | }, | |
191 | ], | |
192 | }, | |
193 | }, | |
194 | }, | |
195 | } | |
196 | "###); | |
197 | } | |
198 | ||
199 | #[test] | |
200 | fn test_macro_variable_macro() { | |
201 | // mimics the token stream corresponding to `$macro!()` | |
202 | let tokens = TokenStream::from_iter(vec![ | |
203 | TokenTree::Group(Group::new(Delimiter::None, quote! { m })), | |
204 | TokenTree::Punct(Punct::new('!', Spacing::Alone)), | |
205 | TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), | |
206 | ]); | |
207 | ||
208 | snapshot!(tokens as Expr, @r###" | |
209 | Expr::Macro { | |
210 | mac: Macro { | |
211 | path: Path { | |
212 | segments: [ | |
213 | PathSegment { | |
214 | ident: "m", | |
215 | arguments: None, | |
216 | }, | |
217 | ], | |
218 | }, | |
219 | delimiter: Paren, | |
220 | tokens: TokenStream(``), | |
221 | }, | |
222 | } | |
223 | "###); | |
224 | } | |
225 | ||
226 | #[test] | |
227 | fn test_macro_variable_struct() { | |
228 | // mimics the token stream corresponding to `$struct {}` | |
229 | let tokens = TokenStream::from_iter(vec![ | |
230 | TokenTree::Group(Group::new(Delimiter::None, quote! { S })), | |
231 | TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), | |
232 | ]); | |
233 | ||
234 | snapshot!(tokens as Expr, @r###" | |
235 | Expr::Struct { | |
236 | path: Path { | |
237 | segments: [ | |
238 | PathSegment { | |
239 | ident: "S", | |
240 | arguments: None, | |
241 | }, | |
242 | ], | |
243 | }, | |
244 | } | |
245 | "###); | |
246 | } | |
247 | ||
248 | #[test] | |
249 | fn test_macro_variable_match_arm() { | |
250 | // mimics the token stream corresponding to `match v { _ => $expr }` | |
251 | let tokens = TokenStream::from_iter(vec![ | |
252 | TokenTree::Ident(Ident::new("match", Span::call_site())), | |
253 | TokenTree::Ident(Ident::new("v", Span::call_site())), | |
254 | TokenTree::Group(Group::new( | |
255 | Delimiter::Brace, | |
256 | TokenStream::from_iter(vec![ | |
257 | TokenTree::Punct(Punct::new('_', Spacing::Alone)), | |
258 | TokenTree::Punct(Punct::new('=', Spacing::Joint)), | |
259 | TokenTree::Punct(Punct::new('>', Spacing::Alone)), | |
260 | TokenTree::Group(Group::new(Delimiter::None, quote! { #[a] () })), | |
261 | ]), | |
262 | )), | |
263 | ]); | |
264 | ||
265 | snapshot!(tokens as Expr, @r###" | |
266 | Expr::Match { | |
267 | expr: Expr::Path { | |
268 | path: Path { | |
269 | segments: [ | |
270 | PathSegment { | |
271 | ident: "v", | |
272 | arguments: None, | |
273 | }, | |
274 | ], | |
275 | }, | |
276 | }, | |
277 | arms: [ | |
278 | Arm { | |
279 | pat: Pat::Wild, | |
280 | body: Expr::Group { | |
281 | expr: Expr::Tuple { | |
282 | attrs: [ | |
283 | Attribute { | |
284 | style: Outer, | |
285 | path: Path { | |
286 | segments: [ | |
287 | PathSegment { | |
288 | ident: "a", | |
289 | arguments: None, | |
290 | }, | |
291 | ], | |
292 | }, | |
293 | tokens: TokenStream(``), | |
294 | }, | |
295 | ], | |
296 | }, | |
297 | }, | |
298 | }, | |
299 | ], | |
300 | } | |
301 | "###); | |
302 | } | |
cdc7bbd5 XL |
303 | |
304 | // https://github.com/dtolnay/syn/issues/1019 | |
305 | #[test] | |
306 | fn test_closure_vs_rangefull() { | |
307 | #[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/4808 | |
308 | let tokens = quote!(|| .. .method()); | |
309 | snapshot!(tokens as Expr, @r###" | |
310 | Expr::MethodCall { | |
311 | receiver: Expr::Closure { | |
312 | output: Default, | |
313 | body: Expr::Range { | |
314 | limits: HalfOpen, | |
315 | }, | |
316 | }, | |
317 | method: "method", | |
318 | } | |
319 | "###); | |
320 | } | |
ee023bcb FG |
321 | |
322 | #[test] | |
323 | fn test_postfix_operator_after_cast() { | |
324 | syn::parse_str::<Expr>("|| &x as T[0]").unwrap_err(); | |
325 | syn::parse_str::<Expr>("|| () as ()()").unwrap_err(); | |
326 | } |