1 #![allow(clippy::non_ascii_literal)]
2 
3 use proc_macro2::{Delimiter, Group, Punct, Spacing, TokenStream, TokenTree};
4 use syn::parse::discouraged::Speculative as _;
5 use syn::parse::{Parse, ParseStream, Parser, Result};
6 use syn::{parenthesized, Token};
7 
8 #[test]
9 #[should_panic(expected = "Fork was not derived from the advancing parse stream")]
smuggled_speculative_cursor_between_sources()10 fn smuggled_speculative_cursor_between_sources() {
11     struct BreakRules;
12     impl Parse for BreakRules {
13         fn parse(input1: ParseStream) -> Result<Self> {
14             let nested = |input2: ParseStream| {
15                 input1.advance_to(input2);
16                 Ok(Self)
17             };
18             nested.parse_str("")
19         }
20     }
21 
22     syn::parse_str::<BreakRules>("").unwrap();
23 }
24 
25 #[test]
26 #[should_panic(expected = "Fork was not derived from the advancing parse stream")]
smuggled_speculative_cursor_between_brackets()27 fn smuggled_speculative_cursor_between_brackets() {
28     struct BreakRules;
29     impl Parse for BreakRules {
30         fn parse(input: ParseStream) -> Result<Self> {
31             let a;
32             let b;
33             parenthesized!(a in input);
34             parenthesized!(b in input);
35             a.advance_to(&b);
36             Ok(Self)
37         }
38     }
39 
40     syn::parse_str::<BreakRules>("()()").unwrap();
41 }
42 
43 #[test]
44 #[should_panic(expected = "Fork was not derived from the advancing parse stream")]
smuggled_speculative_cursor_into_brackets()45 fn smuggled_speculative_cursor_into_brackets() {
46     struct BreakRules;
47     impl Parse for BreakRules {
48         fn parse(input: ParseStream) -> Result<Self> {
49             let a;
50             parenthesized!(a in input);
51             input.advance_to(&a);
52             Ok(Self)
53         }
54     }
55 
56     syn::parse_str::<BreakRules>("()").unwrap();
57 }
58 
59 #[test]
trailing_empty_none_group()60 fn trailing_empty_none_group() {
61     fn parse(input: ParseStream) -> Result<()> {
62         input.parse::<Token![+]>()?;
63 
64         let content;
65         parenthesized!(content in input);
66         content.parse::<Token![+]>()?;
67 
68         Ok(())
69     }
70 
71     // `+ ( + <Ø Ø> ) <Ø <Ø Ø> Ø>`
72     let tokens = TokenStream::from_iter(vec![
73         TokenTree::Punct(Punct::new('+', Spacing::Alone)),
74         TokenTree::Group(Group::new(
75             Delimiter::Parenthesis,
76             TokenStream::from_iter(vec![
77                 TokenTree::Punct(Punct::new('+', Spacing::Alone)),
78                 TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())),
79             ]),
80         )),
81         TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())),
82         TokenTree::Group(Group::new(
83             Delimiter::None,
84             TokenStream::from_iter(vec![TokenTree::Group(Group::new(
85                 Delimiter::None,
86                 TokenStream::new(),
87             ))]),
88         )),
89     ]);
90 
91     parse.parse2(tokens).unwrap();
92 }
93