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