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