xref: /third_party/rust/crates/syn/tests/test_stmt.rs (revision fad3a1d3)
1#![allow(
2    clippy::assertions_on_result_states,
3    clippy::non_ascii_literal,
4    clippy::uninlined_format_args
5)]
6
7#[macro_use]
8mod macros;
9
10use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
11use quote::{quote, ToTokens as _};
12use syn::parse::Parser as _;
13use syn::{Block, Stmt};
14
15#[test]
16fn test_raw_operator() {
17    let stmt = syn::parse_str::<Stmt>("let _ = &raw const x;").unwrap();
18
19    snapshot!(stmt, @r###"
20    Stmt::Local {
21        pat: Pat::Wild,
22        init: Some(LocalInit {
23            expr: Expr::Verbatim(`& raw const x`),
24        }),
25    }
26    "###);
27}
28
29#[test]
30fn test_raw_variable() {
31    let stmt = syn::parse_str::<Stmt>("let _ = &raw;").unwrap();
32
33    snapshot!(stmt, @r###"
34    Stmt::Local {
35        pat: Pat::Wild,
36        init: Some(LocalInit {
37            expr: Expr::Reference {
38                expr: Expr::Path {
39                    path: Path {
40                        segments: [
41                            PathSegment {
42                                ident: "raw",
43                            },
44                        ],
45                    },
46                },
47            },
48        }),
49    }
50    "###);
51}
52
53#[test]
54fn test_raw_invalid() {
55    assert!(syn::parse_str::<Stmt>("let _ = &raw x;").is_err());
56}
57
58#[test]
59fn test_none_group() {
60    // <Ø async fn f() {} Ø>
61    let tokens = TokenStream::from_iter(vec![TokenTree::Group(Group::new(
62        Delimiter::None,
63        TokenStream::from_iter(vec![
64            TokenTree::Ident(Ident::new("async", Span::call_site())),
65            TokenTree::Ident(Ident::new("fn", Span::call_site())),
66            TokenTree::Ident(Ident::new("f", Span::call_site())),
67            TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
68            TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
69        ]),
70    ))]);
71    snapshot!(tokens as Stmt, @r###"
72    Stmt::Item(Item::Fn {
73        vis: Visibility::Inherited,
74        sig: Signature {
75            asyncness: Some,
76            ident: "f",
77            generics: Generics,
78            output: ReturnType::Default,
79        },
80        block: Block {
81            stmts: [],
82        },
83    })
84    "###);
85
86    let tokens = Group::new(Delimiter::None, quote!(let None = None)).to_token_stream();
87    let stmts = Block::parse_within.parse2(tokens).unwrap();
88    snapshot!(stmts, @r###"
89    [
90        Stmt::Expr(
91            Expr::Group {
92                expr: Expr::Let {
93                    pat: Pat::Ident {
94                        ident: "None",
95                    },
96                    expr: Expr::Path {
97                        path: Path {
98                            segments: [
99                                PathSegment {
100                                    ident: "None",
101                                },
102                            ],
103                        },
104                    },
105                },
106            },
107            None,
108        ),
109    ]
110    "###);
111}
112
113#[test]
114fn test_let_dot_dot() {
115    let tokens = quote! {
116        let .. = 10;
117    };
118
119    snapshot!(tokens as Stmt, @r###"
120    Stmt::Local {
121        pat: Pat::Rest,
122        init: Some(LocalInit {
123            expr: Expr::Lit {
124                lit: 10,
125            },
126        }),
127    }
128    "###);
129}
130
131#[test]
132fn test_let_else() {
133    let tokens = quote! {
134        let Some(x) = None else { return 0; };
135    };
136
137    snapshot!(tokens as Stmt, @r###"
138    Stmt::Local {
139        pat: Pat::TupleStruct {
140            path: Path {
141                segments: [
142                    PathSegment {
143                        ident: "Some",
144                    },
145                ],
146            },
147            elems: [
148                Pat::Ident {
149                    ident: "x",
150                },
151            ],
152        },
153        init: Some(LocalInit {
154            expr: Expr::Path {
155                path: Path {
156                    segments: [
157                        PathSegment {
158                            ident: "None",
159                        },
160                    ],
161                },
162            },
163            diverge: Some(Expr::Block {
164                block: Block {
165                    stmts: [
166                        Stmt::Expr(
167                            Expr::Return {
168                                expr: Some(Expr::Lit {
169                                    lit: 0,
170                                }),
171                            },
172                            Some,
173                        ),
174                    ],
175                },
176            }),
177        }),
178    }
179    "###);
180}
181
182#[test]
183fn test_macros() {
184    let tokens = quote! {
185        fn main() {
186            macro_rules! mac {}
187            thread_local! { static FOO }
188            println!("");
189            vec![]
190        }
191    };
192
193    snapshot!(tokens as Stmt, @r###"
194    Stmt::Item(Item::Fn {
195        vis: Visibility::Inherited,
196        sig: Signature {
197            ident: "main",
198            generics: Generics,
199            output: ReturnType::Default,
200        },
201        block: Block {
202            stmts: [
203                Stmt::Item(Item::Macro {
204                    ident: Some("mac"),
205                    mac: Macro {
206                        path: Path {
207                            segments: [
208                                PathSegment {
209                                    ident: "macro_rules",
210                                },
211                            ],
212                        },
213                        delimiter: MacroDelimiter::Brace,
214                        tokens: TokenStream(``),
215                    },
216                }),
217                Stmt::Macro {
218                    mac: Macro {
219                        path: Path {
220                            segments: [
221                                PathSegment {
222                                    ident: "thread_local",
223                                },
224                            ],
225                        },
226                        delimiter: MacroDelimiter::Brace,
227                        tokens: TokenStream(`static FOO`),
228                    },
229                },
230                Stmt::Macro {
231                    mac: Macro {
232                        path: Path {
233                            segments: [
234                                PathSegment {
235                                    ident: "println",
236                                },
237                            ],
238                        },
239                        delimiter: MacroDelimiter::Paren,
240                        tokens: TokenStream(`""`),
241                    },
242                    semi_token: Some,
243                },
244                Stmt::Expr(
245                    Expr::Macro {
246                        mac: Macro {
247                            path: Path {
248                                segments: [
249                                    PathSegment {
250                                        ident: "vec",
251                                    },
252                                ],
253                            },
254                            delimiter: MacroDelimiter::Bracket,
255                            tokens: TokenStream(``),
256                        },
257                    },
258                    None,
259                ),
260            ],
261        },
262    })
263    "###);
264}
265
266#[test]
267fn test_early_parse_loop() {
268    // The following is an Expr::Loop followed by Expr::Tuple. It is not an
269    // Expr::Call.
270    let tokens = quote! {
271        loop {}
272        ()
273    };
274
275    let stmts = Block::parse_within.parse2(tokens).unwrap();
276
277    snapshot!(stmts, @r###"
278    [
279        Stmt::Expr(
280            Expr::Loop {
281                body: Block {
282                    stmts: [],
283                },
284            },
285            None,
286        ),
287        Stmt::Expr(
288            Expr::Tuple,
289            None,
290        ),
291    ]
292    "###);
293
294    let tokens = quote! {
295        'a: loop {}
296        ()
297    };
298
299    let stmts = Block::parse_within.parse2(tokens).unwrap();
300
301    snapshot!(stmts, @r###"
302    [
303        Stmt::Expr(
304            Expr::Loop {
305                label: Some(Label {
306                    name: Lifetime {
307                        ident: "a",
308                    },
309                }),
310                body: Block {
311                    stmts: [],
312                },
313            },
314            None,
315        ),
316        Stmt::Expr(
317            Expr::Tuple,
318            None,
319        ),
320    ]
321    "###);
322}
323