1fad3a1d3Sopenharmony_ci#![allow(clippy::single_element_loop, clippy::uninlined_format_args)]
2fad3a1d3Sopenharmony_ci
3fad3a1d3Sopenharmony_ci#[macro_use]
4fad3a1d3Sopenharmony_cimod macros;
5fad3a1d3Sopenharmony_ci
6fad3a1d3Sopenharmony_ciuse proc_macro2::{Delimiter, Group};
7fad3a1d3Sopenharmony_ciuse quote::{quote, ToTokens as _};
8fad3a1d3Sopenharmony_ciuse syn::punctuated::Punctuated;
9fad3a1d3Sopenharmony_ciuse syn::{parse_quote, token, Expr, ExprRange, ExprTuple, Stmt, Token};
10fad3a1d3Sopenharmony_ci
11fad3a1d3Sopenharmony_ci#[test]
12fad3a1d3Sopenharmony_cifn test_expr_parse() {
13fad3a1d3Sopenharmony_ci    let tokens = quote!(..100u32);
14fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
15fad3a1d3Sopenharmony_ci    Expr::Range {
16fad3a1d3Sopenharmony_ci        limits: RangeLimits::HalfOpen,
17fad3a1d3Sopenharmony_ci        end: Some(Expr::Lit {
18fad3a1d3Sopenharmony_ci            lit: 100u32,
19fad3a1d3Sopenharmony_ci        }),
20fad3a1d3Sopenharmony_ci    }
21fad3a1d3Sopenharmony_ci    "###);
22fad3a1d3Sopenharmony_ci
23fad3a1d3Sopenharmony_ci    let tokens = quote!(..100u32);
24fad3a1d3Sopenharmony_ci    snapshot!(tokens as ExprRange, @r###"
25fad3a1d3Sopenharmony_ci    ExprRange {
26fad3a1d3Sopenharmony_ci        limits: RangeLimits::HalfOpen,
27fad3a1d3Sopenharmony_ci        end: Some(Expr::Lit {
28fad3a1d3Sopenharmony_ci            lit: 100u32,
29fad3a1d3Sopenharmony_ci        }),
30fad3a1d3Sopenharmony_ci    }
31fad3a1d3Sopenharmony_ci    "###);
32fad3a1d3Sopenharmony_ci}
33fad3a1d3Sopenharmony_ci
34fad3a1d3Sopenharmony_ci#[test]
35fad3a1d3Sopenharmony_cifn test_await() {
36fad3a1d3Sopenharmony_ci    // Must not parse as Expr::Field.
37fad3a1d3Sopenharmony_ci    let tokens = quote!(fut.await);
38fad3a1d3Sopenharmony_ci
39fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
40fad3a1d3Sopenharmony_ci    Expr::Await {
41fad3a1d3Sopenharmony_ci        base: Expr::Path {
42fad3a1d3Sopenharmony_ci            path: Path {
43fad3a1d3Sopenharmony_ci                segments: [
44fad3a1d3Sopenharmony_ci                    PathSegment {
45fad3a1d3Sopenharmony_ci                        ident: "fut",
46fad3a1d3Sopenharmony_ci                    },
47fad3a1d3Sopenharmony_ci                ],
48fad3a1d3Sopenharmony_ci            },
49fad3a1d3Sopenharmony_ci        },
50fad3a1d3Sopenharmony_ci    }
51fad3a1d3Sopenharmony_ci    "###);
52fad3a1d3Sopenharmony_ci}
53fad3a1d3Sopenharmony_ci
54fad3a1d3Sopenharmony_ci#[rustfmt::skip]
55fad3a1d3Sopenharmony_ci#[test]
56fad3a1d3Sopenharmony_cifn test_tuple_multi_index() {
57fad3a1d3Sopenharmony_ci    let expected = snapshot!("tuple.0.0" as Expr, @r###"
58fad3a1d3Sopenharmony_ci    Expr::Field {
59fad3a1d3Sopenharmony_ci        base: Expr::Field {
60fad3a1d3Sopenharmony_ci            base: Expr::Path {
61fad3a1d3Sopenharmony_ci                path: Path {
62fad3a1d3Sopenharmony_ci                    segments: [
63fad3a1d3Sopenharmony_ci                        PathSegment {
64fad3a1d3Sopenharmony_ci                            ident: "tuple",
65fad3a1d3Sopenharmony_ci                        },
66fad3a1d3Sopenharmony_ci                    ],
67fad3a1d3Sopenharmony_ci                },
68fad3a1d3Sopenharmony_ci            },
69fad3a1d3Sopenharmony_ci            member: Member::Unnamed(Index {
70fad3a1d3Sopenharmony_ci                index: 0,
71fad3a1d3Sopenharmony_ci            }),
72fad3a1d3Sopenharmony_ci        },
73fad3a1d3Sopenharmony_ci        member: Member::Unnamed(Index {
74fad3a1d3Sopenharmony_ci            index: 0,
75fad3a1d3Sopenharmony_ci        }),
76fad3a1d3Sopenharmony_ci    }
77fad3a1d3Sopenharmony_ci    "###);
78fad3a1d3Sopenharmony_ci
79fad3a1d3Sopenharmony_ci    for &input in &[
80fad3a1d3Sopenharmony_ci        "tuple .0.0",
81fad3a1d3Sopenharmony_ci        "tuple. 0.0",
82fad3a1d3Sopenharmony_ci        "tuple.0 .0",
83fad3a1d3Sopenharmony_ci        "tuple.0. 0",
84fad3a1d3Sopenharmony_ci        "tuple . 0 . 0",
85fad3a1d3Sopenharmony_ci    ] {
86fad3a1d3Sopenharmony_ci        assert_eq!(expected, syn::parse_str(input).unwrap());
87fad3a1d3Sopenharmony_ci    }
88fad3a1d3Sopenharmony_ci
89fad3a1d3Sopenharmony_ci    for tokens in [
90fad3a1d3Sopenharmony_ci        quote!(tuple.0.0),
91fad3a1d3Sopenharmony_ci        quote!(tuple .0.0),
92fad3a1d3Sopenharmony_ci        quote!(tuple. 0.0),
93fad3a1d3Sopenharmony_ci        quote!(tuple.0 .0),
94fad3a1d3Sopenharmony_ci        quote!(tuple.0. 0),
95fad3a1d3Sopenharmony_ci        quote!(tuple . 0 . 0),
96fad3a1d3Sopenharmony_ci    ] {
97fad3a1d3Sopenharmony_ci        assert_eq!(expected, syn::parse2(tokens).unwrap());
98fad3a1d3Sopenharmony_ci    }
99fad3a1d3Sopenharmony_ci}
100fad3a1d3Sopenharmony_ci
101fad3a1d3Sopenharmony_ci#[test]
102fad3a1d3Sopenharmony_cifn test_macro_variable_func() {
103fad3a1d3Sopenharmony_ci    // mimics the token stream corresponding to `$fn()`
104fad3a1d3Sopenharmony_ci    let path = Group::new(Delimiter::None, quote!(f));
105fad3a1d3Sopenharmony_ci    let tokens = quote!(#path());
106fad3a1d3Sopenharmony_ci
107fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
108fad3a1d3Sopenharmony_ci    Expr::Call {
109fad3a1d3Sopenharmony_ci        func: Expr::Group {
110fad3a1d3Sopenharmony_ci            expr: Expr::Path {
111fad3a1d3Sopenharmony_ci                path: Path {
112fad3a1d3Sopenharmony_ci                    segments: [
113fad3a1d3Sopenharmony_ci                        PathSegment {
114fad3a1d3Sopenharmony_ci                            ident: "f",
115fad3a1d3Sopenharmony_ci                        },
116fad3a1d3Sopenharmony_ci                    ],
117fad3a1d3Sopenharmony_ci                },
118fad3a1d3Sopenharmony_ci            },
119fad3a1d3Sopenharmony_ci        },
120fad3a1d3Sopenharmony_ci    }
121fad3a1d3Sopenharmony_ci    "###);
122fad3a1d3Sopenharmony_ci
123fad3a1d3Sopenharmony_ci    let path = Group::new(Delimiter::None, quote! { #[inside] f });
124fad3a1d3Sopenharmony_ci    let tokens = quote!(#[outside] #path());
125fad3a1d3Sopenharmony_ci
126fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
127fad3a1d3Sopenharmony_ci    Expr::Call {
128fad3a1d3Sopenharmony_ci        attrs: [
129fad3a1d3Sopenharmony_ci            Attribute {
130fad3a1d3Sopenharmony_ci                style: AttrStyle::Outer,
131fad3a1d3Sopenharmony_ci                meta: Meta::Path {
132fad3a1d3Sopenharmony_ci                    segments: [
133fad3a1d3Sopenharmony_ci                        PathSegment {
134fad3a1d3Sopenharmony_ci                            ident: "outside",
135fad3a1d3Sopenharmony_ci                        },
136fad3a1d3Sopenharmony_ci                    ],
137fad3a1d3Sopenharmony_ci                },
138fad3a1d3Sopenharmony_ci            },
139fad3a1d3Sopenharmony_ci        ],
140fad3a1d3Sopenharmony_ci        func: Expr::Group {
141fad3a1d3Sopenharmony_ci            expr: Expr::Path {
142fad3a1d3Sopenharmony_ci                attrs: [
143fad3a1d3Sopenharmony_ci                    Attribute {
144fad3a1d3Sopenharmony_ci                        style: AttrStyle::Outer,
145fad3a1d3Sopenharmony_ci                        meta: Meta::Path {
146fad3a1d3Sopenharmony_ci                            segments: [
147fad3a1d3Sopenharmony_ci                                PathSegment {
148fad3a1d3Sopenharmony_ci                                    ident: "inside",
149fad3a1d3Sopenharmony_ci                                },
150fad3a1d3Sopenharmony_ci                            ],
151fad3a1d3Sopenharmony_ci                        },
152fad3a1d3Sopenharmony_ci                    },
153fad3a1d3Sopenharmony_ci                ],
154fad3a1d3Sopenharmony_ci                path: Path {
155fad3a1d3Sopenharmony_ci                    segments: [
156fad3a1d3Sopenharmony_ci                        PathSegment {
157fad3a1d3Sopenharmony_ci                            ident: "f",
158fad3a1d3Sopenharmony_ci                        },
159fad3a1d3Sopenharmony_ci                    ],
160fad3a1d3Sopenharmony_ci                },
161fad3a1d3Sopenharmony_ci            },
162fad3a1d3Sopenharmony_ci        },
163fad3a1d3Sopenharmony_ci    }
164fad3a1d3Sopenharmony_ci    "###);
165fad3a1d3Sopenharmony_ci}
166fad3a1d3Sopenharmony_ci
167fad3a1d3Sopenharmony_ci#[test]
168fad3a1d3Sopenharmony_cifn test_macro_variable_macro() {
169fad3a1d3Sopenharmony_ci    // mimics the token stream corresponding to `$macro!()`
170fad3a1d3Sopenharmony_ci    let mac = Group::new(Delimiter::None, quote!(m));
171fad3a1d3Sopenharmony_ci    let tokens = quote!(#mac!());
172fad3a1d3Sopenharmony_ci
173fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
174fad3a1d3Sopenharmony_ci    Expr::Macro {
175fad3a1d3Sopenharmony_ci        mac: Macro {
176fad3a1d3Sopenharmony_ci            path: Path {
177fad3a1d3Sopenharmony_ci                segments: [
178fad3a1d3Sopenharmony_ci                    PathSegment {
179fad3a1d3Sopenharmony_ci                        ident: "m",
180fad3a1d3Sopenharmony_ci                    },
181fad3a1d3Sopenharmony_ci                ],
182fad3a1d3Sopenharmony_ci            },
183fad3a1d3Sopenharmony_ci            delimiter: MacroDelimiter::Paren,
184fad3a1d3Sopenharmony_ci            tokens: TokenStream(``),
185fad3a1d3Sopenharmony_ci        },
186fad3a1d3Sopenharmony_ci    }
187fad3a1d3Sopenharmony_ci    "###);
188fad3a1d3Sopenharmony_ci}
189fad3a1d3Sopenharmony_ci
190fad3a1d3Sopenharmony_ci#[test]
191fad3a1d3Sopenharmony_cifn test_macro_variable_struct() {
192fad3a1d3Sopenharmony_ci    // mimics the token stream corresponding to `$struct {}`
193fad3a1d3Sopenharmony_ci    let s = Group::new(Delimiter::None, quote! { S });
194fad3a1d3Sopenharmony_ci    let tokens = quote!(#s {});
195fad3a1d3Sopenharmony_ci
196fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
197fad3a1d3Sopenharmony_ci    Expr::Struct {
198fad3a1d3Sopenharmony_ci        path: Path {
199fad3a1d3Sopenharmony_ci            segments: [
200fad3a1d3Sopenharmony_ci                PathSegment {
201fad3a1d3Sopenharmony_ci                    ident: "S",
202fad3a1d3Sopenharmony_ci                },
203fad3a1d3Sopenharmony_ci            ],
204fad3a1d3Sopenharmony_ci        },
205fad3a1d3Sopenharmony_ci    }
206fad3a1d3Sopenharmony_ci    "###);
207fad3a1d3Sopenharmony_ci}
208fad3a1d3Sopenharmony_ci
209fad3a1d3Sopenharmony_ci#[test]
210fad3a1d3Sopenharmony_cifn test_macro_variable_unary() {
211fad3a1d3Sopenharmony_ci    // mimics the token stream corresponding to `$expr.method()` where expr is `&self`
212fad3a1d3Sopenharmony_ci    let inner = Group::new(Delimiter::None, quote!(&self));
213fad3a1d3Sopenharmony_ci    let tokens = quote!(#inner.method());
214fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
215fad3a1d3Sopenharmony_ci    Expr::MethodCall {
216fad3a1d3Sopenharmony_ci        receiver: Expr::Group {
217fad3a1d3Sopenharmony_ci            expr: Expr::Reference {
218fad3a1d3Sopenharmony_ci                expr: Expr::Path {
219fad3a1d3Sopenharmony_ci                    path: Path {
220fad3a1d3Sopenharmony_ci                        segments: [
221fad3a1d3Sopenharmony_ci                            PathSegment {
222fad3a1d3Sopenharmony_ci                                ident: "self",
223fad3a1d3Sopenharmony_ci                            },
224fad3a1d3Sopenharmony_ci                        ],
225fad3a1d3Sopenharmony_ci                    },
226fad3a1d3Sopenharmony_ci                },
227fad3a1d3Sopenharmony_ci            },
228fad3a1d3Sopenharmony_ci        },
229fad3a1d3Sopenharmony_ci        method: "method",
230fad3a1d3Sopenharmony_ci    }
231fad3a1d3Sopenharmony_ci    "###);
232fad3a1d3Sopenharmony_ci}
233fad3a1d3Sopenharmony_ci
234fad3a1d3Sopenharmony_ci#[test]
235fad3a1d3Sopenharmony_cifn test_macro_variable_match_arm() {
236fad3a1d3Sopenharmony_ci    // mimics the token stream corresponding to `match v { _ => $expr }`
237fad3a1d3Sopenharmony_ci    let expr = Group::new(Delimiter::None, quote! { #[a] () });
238fad3a1d3Sopenharmony_ci    let tokens = quote!(match v { _ => #expr });
239fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
240fad3a1d3Sopenharmony_ci    Expr::Match {
241fad3a1d3Sopenharmony_ci        expr: Expr::Path {
242fad3a1d3Sopenharmony_ci            path: Path {
243fad3a1d3Sopenharmony_ci                segments: [
244fad3a1d3Sopenharmony_ci                    PathSegment {
245fad3a1d3Sopenharmony_ci                        ident: "v",
246fad3a1d3Sopenharmony_ci                    },
247fad3a1d3Sopenharmony_ci                ],
248fad3a1d3Sopenharmony_ci            },
249fad3a1d3Sopenharmony_ci        },
250fad3a1d3Sopenharmony_ci        arms: [
251fad3a1d3Sopenharmony_ci            Arm {
252fad3a1d3Sopenharmony_ci                pat: Pat::Wild,
253fad3a1d3Sopenharmony_ci                body: Expr::Group {
254fad3a1d3Sopenharmony_ci                    expr: Expr::Tuple {
255fad3a1d3Sopenharmony_ci                        attrs: [
256fad3a1d3Sopenharmony_ci                            Attribute {
257fad3a1d3Sopenharmony_ci                                style: AttrStyle::Outer,
258fad3a1d3Sopenharmony_ci                                meta: Meta::Path {
259fad3a1d3Sopenharmony_ci                                    segments: [
260fad3a1d3Sopenharmony_ci                                        PathSegment {
261fad3a1d3Sopenharmony_ci                                            ident: "a",
262fad3a1d3Sopenharmony_ci                                        },
263fad3a1d3Sopenharmony_ci                                    ],
264fad3a1d3Sopenharmony_ci                                },
265fad3a1d3Sopenharmony_ci                            },
266fad3a1d3Sopenharmony_ci                        ],
267fad3a1d3Sopenharmony_ci                    },
268fad3a1d3Sopenharmony_ci                },
269fad3a1d3Sopenharmony_ci            },
270fad3a1d3Sopenharmony_ci        ],
271fad3a1d3Sopenharmony_ci    }
272fad3a1d3Sopenharmony_ci    "###);
273fad3a1d3Sopenharmony_ci
274fad3a1d3Sopenharmony_ci    let expr = Group::new(Delimiter::None, quote!(loop {} + 1));
275fad3a1d3Sopenharmony_ci    let tokens = quote!(match v { _ => #expr });
276fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
277fad3a1d3Sopenharmony_ci    Expr::Match {
278fad3a1d3Sopenharmony_ci        expr: Expr::Path {
279fad3a1d3Sopenharmony_ci            path: Path {
280fad3a1d3Sopenharmony_ci                segments: [
281fad3a1d3Sopenharmony_ci                    PathSegment {
282fad3a1d3Sopenharmony_ci                        ident: "v",
283fad3a1d3Sopenharmony_ci                    },
284fad3a1d3Sopenharmony_ci                ],
285fad3a1d3Sopenharmony_ci            },
286fad3a1d3Sopenharmony_ci        },
287fad3a1d3Sopenharmony_ci        arms: [
288fad3a1d3Sopenharmony_ci            Arm {
289fad3a1d3Sopenharmony_ci                pat: Pat::Wild,
290fad3a1d3Sopenharmony_ci                body: Expr::Group {
291fad3a1d3Sopenharmony_ci                    expr: Expr::Binary {
292fad3a1d3Sopenharmony_ci                        left: Expr::Loop {
293fad3a1d3Sopenharmony_ci                            body: Block {
294fad3a1d3Sopenharmony_ci                                stmts: [],
295fad3a1d3Sopenharmony_ci                            },
296fad3a1d3Sopenharmony_ci                        },
297fad3a1d3Sopenharmony_ci                        op: BinOp::Add,
298fad3a1d3Sopenharmony_ci                        right: Expr::Lit {
299fad3a1d3Sopenharmony_ci                            lit: 1,
300fad3a1d3Sopenharmony_ci                        },
301fad3a1d3Sopenharmony_ci                    },
302fad3a1d3Sopenharmony_ci                },
303fad3a1d3Sopenharmony_ci            },
304fad3a1d3Sopenharmony_ci        ],
305fad3a1d3Sopenharmony_ci    }
306fad3a1d3Sopenharmony_ci    "###);
307fad3a1d3Sopenharmony_ci}
308fad3a1d3Sopenharmony_ci
309fad3a1d3Sopenharmony_ci// https://github.com/dtolnay/syn/issues/1019
310fad3a1d3Sopenharmony_ci#[test]
311fad3a1d3Sopenharmony_cifn test_closure_vs_rangefull() {
312fad3a1d3Sopenharmony_ci    #[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/4808
313fad3a1d3Sopenharmony_ci    let tokens = quote!(|| .. .method());
314fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
315fad3a1d3Sopenharmony_ci    Expr::MethodCall {
316fad3a1d3Sopenharmony_ci        receiver: Expr::Closure {
317fad3a1d3Sopenharmony_ci            output: ReturnType::Default,
318fad3a1d3Sopenharmony_ci            body: Expr::Range {
319fad3a1d3Sopenharmony_ci                limits: RangeLimits::HalfOpen,
320fad3a1d3Sopenharmony_ci            },
321fad3a1d3Sopenharmony_ci        },
322fad3a1d3Sopenharmony_ci        method: "method",
323fad3a1d3Sopenharmony_ci    }
324fad3a1d3Sopenharmony_ci    "###);
325fad3a1d3Sopenharmony_ci}
326fad3a1d3Sopenharmony_ci
327fad3a1d3Sopenharmony_ci#[test]
328fad3a1d3Sopenharmony_cifn test_postfix_operator_after_cast() {
329fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("|| &x as T[0]").unwrap_err();
330fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("|| () as ()()").unwrap_err();
331fad3a1d3Sopenharmony_ci}
332fad3a1d3Sopenharmony_ci
333fad3a1d3Sopenharmony_ci#[test]
334fad3a1d3Sopenharmony_cifn test_ranges() {
335fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("..").unwrap();
336fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("..hi").unwrap();
337fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("lo..").unwrap();
338fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("lo..hi").unwrap();
339fad3a1d3Sopenharmony_ci
340fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("..=").unwrap_err();
341fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("..=hi").unwrap();
342fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("lo..=").unwrap_err();
343fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("lo..=hi").unwrap();
344fad3a1d3Sopenharmony_ci
345fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("...").unwrap_err();
346fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("...hi").unwrap_err();
347fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("lo...").unwrap_err();
348fad3a1d3Sopenharmony_ci    syn::parse_str::<Expr>("lo...hi").unwrap_err();
349fad3a1d3Sopenharmony_ci}
350fad3a1d3Sopenharmony_ci
351fad3a1d3Sopenharmony_ci#[test]
352fad3a1d3Sopenharmony_cifn test_ambiguous_label() {
353fad3a1d3Sopenharmony_ci    for stmt in [
354fad3a1d3Sopenharmony_ci        quote! {
355fad3a1d3Sopenharmony_ci            return 'label: loop { break 'label 42; };
356fad3a1d3Sopenharmony_ci        },
357fad3a1d3Sopenharmony_ci        quote! {
358fad3a1d3Sopenharmony_ci            break ('label: loop { break 'label 42; });
359fad3a1d3Sopenharmony_ci        },
360fad3a1d3Sopenharmony_ci        quote! {
361fad3a1d3Sopenharmony_ci            break 1 + 'label: loop { break 'label 42; };
362fad3a1d3Sopenharmony_ci        },
363fad3a1d3Sopenharmony_ci        quote! {
364fad3a1d3Sopenharmony_ci            break 'outer 'inner: loop { break 'inner 42; };
365fad3a1d3Sopenharmony_ci        },
366fad3a1d3Sopenharmony_ci    ] {
367fad3a1d3Sopenharmony_ci        syn::parse2::<Stmt>(stmt).unwrap();
368fad3a1d3Sopenharmony_ci    }
369fad3a1d3Sopenharmony_ci
370fad3a1d3Sopenharmony_ci    for stmt in [
371fad3a1d3Sopenharmony_ci        // Parentheses required. See https://github.com/rust-lang/rust/pull/87026.
372fad3a1d3Sopenharmony_ci        quote! {
373fad3a1d3Sopenharmony_ci            break 'label: loop { break 'label 42; };
374fad3a1d3Sopenharmony_ci        },
375fad3a1d3Sopenharmony_ci    ] {
376fad3a1d3Sopenharmony_ci        syn::parse2::<Stmt>(stmt).unwrap_err();
377fad3a1d3Sopenharmony_ci    }
378fad3a1d3Sopenharmony_ci}
379fad3a1d3Sopenharmony_ci
380fad3a1d3Sopenharmony_ci#[test]
381fad3a1d3Sopenharmony_cifn test_extended_interpolated_path() {
382fad3a1d3Sopenharmony_ci    let path = Group::new(Delimiter::None, quote!(a::b));
383fad3a1d3Sopenharmony_ci
384fad3a1d3Sopenharmony_ci    let tokens = quote!(if #path {});
385fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
386fad3a1d3Sopenharmony_ci    Expr::If {
387fad3a1d3Sopenharmony_ci        cond: Expr::Group {
388fad3a1d3Sopenharmony_ci            expr: Expr::Path {
389fad3a1d3Sopenharmony_ci                path: Path {
390fad3a1d3Sopenharmony_ci                    segments: [
391fad3a1d3Sopenharmony_ci                        PathSegment {
392fad3a1d3Sopenharmony_ci                            ident: "a",
393fad3a1d3Sopenharmony_ci                        },
394fad3a1d3Sopenharmony_ci                        Token![::],
395fad3a1d3Sopenharmony_ci                        PathSegment {
396fad3a1d3Sopenharmony_ci                            ident: "b",
397fad3a1d3Sopenharmony_ci                        },
398fad3a1d3Sopenharmony_ci                    ],
399fad3a1d3Sopenharmony_ci                },
400fad3a1d3Sopenharmony_ci            },
401fad3a1d3Sopenharmony_ci        },
402fad3a1d3Sopenharmony_ci        then_branch: Block {
403fad3a1d3Sopenharmony_ci            stmts: [],
404fad3a1d3Sopenharmony_ci        },
405fad3a1d3Sopenharmony_ci    }
406fad3a1d3Sopenharmony_ci    "###);
407fad3a1d3Sopenharmony_ci
408fad3a1d3Sopenharmony_ci    let tokens = quote!(#path {});
409fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
410fad3a1d3Sopenharmony_ci    Expr::Struct {
411fad3a1d3Sopenharmony_ci        path: Path {
412fad3a1d3Sopenharmony_ci            segments: [
413fad3a1d3Sopenharmony_ci                PathSegment {
414fad3a1d3Sopenharmony_ci                    ident: "a",
415fad3a1d3Sopenharmony_ci                },
416fad3a1d3Sopenharmony_ci                Token![::],
417fad3a1d3Sopenharmony_ci                PathSegment {
418fad3a1d3Sopenharmony_ci                    ident: "b",
419fad3a1d3Sopenharmony_ci                },
420fad3a1d3Sopenharmony_ci            ],
421fad3a1d3Sopenharmony_ci        },
422fad3a1d3Sopenharmony_ci    }
423fad3a1d3Sopenharmony_ci    "###);
424fad3a1d3Sopenharmony_ci
425fad3a1d3Sopenharmony_ci    let tokens = quote!(#path :: c);
426fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
427fad3a1d3Sopenharmony_ci    Expr::Path {
428fad3a1d3Sopenharmony_ci        path: Path {
429fad3a1d3Sopenharmony_ci            segments: [
430fad3a1d3Sopenharmony_ci                PathSegment {
431fad3a1d3Sopenharmony_ci                    ident: "a",
432fad3a1d3Sopenharmony_ci                },
433fad3a1d3Sopenharmony_ci                Token![::],
434fad3a1d3Sopenharmony_ci                PathSegment {
435fad3a1d3Sopenharmony_ci                    ident: "b",
436fad3a1d3Sopenharmony_ci                },
437fad3a1d3Sopenharmony_ci                Token![::],
438fad3a1d3Sopenharmony_ci                PathSegment {
439fad3a1d3Sopenharmony_ci                    ident: "c",
440fad3a1d3Sopenharmony_ci                },
441fad3a1d3Sopenharmony_ci            ],
442fad3a1d3Sopenharmony_ci        },
443fad3a1d3Sopenharmony_ci    }
444fad3a1d3Sopenharmony_ci    "###);
445fad3a1d3Sopenharmony_ci
446fad3a1d3Sopenharmony_ci    let nested = Group::new(Delimiter::None, quote!(a::b || true));
447fad3a1d3Sopenharmony_ci    let tokens = quote!(if #nested && false {});
448fad3a1d3Sopenharmony_ci    snapshot!(tokens as Expr, @r###"
449fad3a1d3Sopenharmony_ci    Expr::If {
450fad3a1d3Sopenharmony_ci        cond: Expr::Binary {
451fad3a1d3Sopenharmony_ci            left: Expr::Group {
452fad3a1d3Sopenharmony_ci                expr: Expr::Binary {
453fad3a1d3Sopenharmony_ci                    left: Expr::Path {
454fad3a1d3Sopenharmony_ci                        path: Path {
455fad3a1d3Sopenharmony_ci                            segments: [
456fad3a1d3Sopenharmony_ci                                PathSegment {
457fad3a1d3Sopenharmony_ci                                    ident: "a",
458fad3a1d3Sopenharmony_ci                                },
459fad3a1d3Sopenharmony_ci                                Token![::],
460fad3a1d3Sopenharmony_ci                                PathSegment {
461fad3a1d3Sopenharmony_ci                                    ident: "b",
462fad3a1d3Sopenharmony_ci                                },
463fad3a1d3Sopenharmony_ci                            ],
464fad3a1d3Sopenharmony_ci                        },
465fad3a1d3Sopenharmony_ci                    },
466fad3a1d3Sopenharmony_ci                    op: BinOp::Or,
467fad3a1d3Sopenharmony_ci                    right: Expr::Lit {
468fad3a1d3Sopenharmony_ci                        lit: Lit::Bool {
469fad3a1d3Sopenharmony_ci                            value: true,
470fad3a1d3Sopenharmony_ci                        },
471fad3a1d3Sopenharmony_ci                    },
472fad3a1d3Sopenharmony_ci                },
473fad3a1d3Sopenharmony_ci            },
474fad3a1d3Sopenharmony_ci            op: BinOp::And,
475fad3a1d3Sopenharmony_ci            right: Expr::Lit {
476fad3a1d3Sopenharmony_ci                lit: Lit::Bool {
477fad3a1d3Sopenharmony_ci                    value: false,
478fad3a1d3Sopenharmony_ci                },
479fad3a1d3Sopenharmony_ci            },
480fad3a1d3Sopenharmony_ci        },
481fad3a1d3Sopenharmony_ci        then_branch: Block {
482fad3a1d3Sopenharmony_ci            stmts: [],
483fad3a1d3Sopenharmony_ci        },
484fad3a1d3Sopenharmony_ci    }
485fad3a1d3Sopenharmony_ci    "###);
486fad3a1d3Sopenharmony_ci}
487fad3a1d3Sopenharmony_ci
488fad3a1d3Sopenharmony_ci#[test]
489fad3a1d3Sopenharmony_cifn test_tuple_comma() {
490fad3a1d3Sopenharmony_ci    let mut expr = ExprTuple {
491fad3a1d3Sopenharmony_ci        attrs: Vec::new(),
492fad3a1d3Sopenharmony_ci        paren_token: token::Paren::default(),
493fad3a1d3Sopenharmony_ci        elems: Punctuated::new(),
494fad3a1d3Sopenharmony_ci    };
495fad3a1d3Sopenharmony_ci    snapshot!(expr.to_token_stream() as Expr, @"Expr::Tuple");
496fad3a1d3Sopenharmony_ci
497fad3a1d3Sopenharmony_ci    expr.elems.push_value(parse_quote!(continue));
498fad3a1d3Sopenharmony_ci    // Must not parse to Expr::Paren
499fad3a1d3Sopenharmony_ci    snapshot!(expr.to_token_stream() as Expr, @r###"
500fad3a1d3Sopenharmony_ci    Expr::Tuple {
501fad3a1d3Sopenharmony_ci        elems: [
502fad3a1d3Sopenharmony_ci            Expr::Continue,
503fad3a1d3Sopenharmony_ci            Token![,],
504fad3a1d3Sopenharmony_ci        ],
505fad3a1d3Sopenharmony_ci    }
506fad3a1d3Sopenharmony_ci    "###);
507fad3a1d3Sopenharmony_ci
508fad3a1d3Sopenharmony_ci    expr.elems.push_punct(<Token![,]>::default());
509fad3a1d3Sopenharmony_ci    snapshot!(expr.to_token_stream() as Expr, @r###"
510fad3a1d3Sopenharmony_ci    Expr::Tuple {
511fad3a1d3Sopenharmony_ci        elems: [
512fad3a1d3Sopenharmony_ci            Expr::Continue,
513fad3a1d3Sopenharmony_ci            Token![,],
514fad3a1d3Sopenharmony_ci        ],
515fad3a1d3Sopenharmony_ci    }
516fad3a1d3Sopenharmony_ci    "###);
517fad3a1d3Sopenharmony_ci
518fad3a1d3Sopenharmony_ci    expr.elems.push_value(parse_quote!(continue));
519fad3a1d3Sopenharmony_ci    snapshot!(expr.to_token_stream() as Expr, @r###"
520fad3a1d3Sopenharmony_ci    Expr::Tuple {
521fad3a1d3Sopenharmony_ci        elems: [
522fad3a1d3Sopenharmony_ci            Expr::Continue,
523fad3a1d3Sopenharmony_ci            Token![,],
524fad3a1d3Sopenharmony_ci            Expr::Continue,
525fad3a1d3Sopenharmony_ci        ],
526fad3a1d3Sopenharmony_ci    }
527fad3a1d3Sopenharmony_ci    "###);
528fad3a1d3Sopenharmony_ci
529fad3a1d3Sopenharmony_ci    expr.elems.push_punct(<Token![,]>::default());
530fad3a1d3Sopenharmony_ci    snapshot!(expr.to_token_stream() as Expr, @r###"
531fad3a1d3Sopenharmony_ci    Expr::Tuple {
532fad3a1d3Sopenharmony_ci        elems: [
533fad3a1d3Sopenharmony_ci            Expr::Continue,
534fad3a1d3Sopenharmony_ci            Token![,],
535fad3a1d3Sopenharmony_ci            Expr::Continue,
536fad3a1d3Sopenharmony_ci            Token![,],
537fad3a1d3Sopenharmony_ci        ],
538fad3a1d3Sopenharmony_ci    }
539fad3a1d3Sopenharmony_ci    "###);
540fad3a1d3Sopenharmony_ci}
541