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