1 use indoc::indoc;
2 use proc_macro2::{Delimiter, Group, TokenStream};
3 use quote::quote;
4
5 #[track_caller]
test(tokens: TokenStream, expected: &str)6 fn test(tokens: TokenStream, expected: &str) {
7 let syntax_tree: syn::File = syn::parse2(tokens).unwrap();
8 let pretty = prettyplease::unparse(&syntax_tree);
9 assert_eq!(pretty, expected);
10 }
11
12 #[test]
test_parenthesize_cond()13 fn test_parenthesize_cond() {
14 let s = Group::new(Delimiter::None, quote!(Struct {}));
15 test(
16 quote! {
17 fn main() {
18 if #s == #s {}
19 }
20 },
21 indoc! {"
22 fn main() {
23 if (Struct {} == Struct {}) {}
24 }
25 "},
26 );
27 }
28
29 #[test]
test_parenthesize_match_guard()30 fn test_parenthesize_match_guard() {
31 let expr_struct = Group::new(Delimiter::None, quote!(Struct {}));
32 let expr_binary = Group::new(Delimiter::None, quote!(true && false));
33 test(
34 quote! {
35 fn main() {
36 match () {
37 () if let _ = #expr_struct => {}
38 () if let _ = #expr_binary => {}
39 }
40 }
41 },
42 // FIXME: no parens around `Struct {}` because anything until the `=>`
43 // is considered part of the match guard expression. Parsing of the
44 // expression is not terminated by `{` in that position.
45 //
46 // FIXME: the `true && false` needs parens. Otherwise the precedence is
47 // `(let _ = true) && false` which means something different.
48 indoc! {"
49 fn main() {
50 match () {
51 () if let _ = (Struct {}) => {}
52 () if let _ = true && false => {}
53 }
54 }
55 "},
56 );
57 }
58