1 | #![allow (clippy::non_ascii_literal)] |
2 | |
3 | use proc_macro2::{Delimiter, Group, Punct, Spacing, TokenStream, TokenTree}; |
4 | use std::iter::FromIterator; |
5 | use syn::parse::{discouraged::Speculative, 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" )] |
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" )] |
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" )] |
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] |
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 | |