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