diff --git a/tests/test_parse_stream.rs b/tests/test_parse_stream.rs index 6e4a5a505f..11dc1a6630 100644 --- a/tests/test_parse_stream.rs +++ b/tests/test_parse_stream.rs @@ -1,14 +1,175 @@ -#![allow(clippy::let_underscore_untyped)] +#![allow(clippy::items_after_statements, clippy::let_underscore_untyped)] +use proc_macro2::{Delimiter, Group, Punct, Spacing, Span, TokenStream, TokenTree}; +use quote::quote; use syn::ext::IdentExt as _; -use syn::parse::ParseStream; -use syn::{Ident, Token}; +use syn::parse::{ParseStream, Parser as _, Result}; +use syn::{parenthesized, token, Ident, Lifetime, Token}; #[test] -fn test_peek() { - let _ = |input: ParseStream| { - let _ = input.peek(Ident); - let _ = input.peek(Ident::peek_any); - let _ = input.peek(Token![::]); - }; +fn test_peek_punct() { + let tokens = quote!(+= + =); + + fn assert(input: ParseStream) -> Result<()> { + assert!(input.peek(Token![+])); + assert!(input.peek(Token![+=])); + + let _: Token![+] = input.parse()?; + + assert!(input.peek(Token![=])); + assert!(!input.peek(Token![==])); + assert!(!input.peek(Token![+])); + + let _: Token![=] = input.parse()?; + + assert!(input.peek(Token![+])); + assert!(!input.peek(Token![+=])); + + let _: Token![+] = input.parse()?; + let _: Token![=] = input.parse()?; + Ok(()) + } + + assert.parse2(tokens).unwrap(); +} + +#[test] +fn test_peek_lifetime() { + // 'static ; + let tokens = TokenStream::from_iter([ + TokenTree::Punct(Punct::new('\'', Spacing::Joint)), + TokenTree::Ident(Ident::new("static", Span::call_site())), + TokenTree::Punct(Punct::new(';', Spacing::Alone)), + ]); + + fn assert(input: ParseStream) -> Result<()> { + assert!(input.peek(Lifetime)); + assert!(input.peek2(Token![;])); + assert!(!input.peek2(Token![static])); + + let _: Lifetime = input.parse()?; + + assert!(input.peek(Token![;])); + + let _: Token![;] = input.parse()?; + Ok(()) + } + + assert.parse2(tokens).unwrap(); +} + +#[test] +fn test_peek_not_lifetime() { + // ' static + let tokens = TokenStream::from_iter([ + TokenTree::Punct(Punct::new('\'', Spacing::Alone)), + TokenTree::Ident(Ident::new("static", Span::call_site())), + ]); + + fn assert(input: ParseStream) -> Result<()> { + assert!(!input.peek(Lifetime)); + assert!(input.parse::>()?.is_none()); + + let _: TokenTree = input.parse()?; + + assert!(input.peek(Token![static])); + + let _: Token![static] = input.parse()?; + Ok(()) + } + + assert.parse2(tokens).unwrap(); +} + +#[test] +fn test_peek_ident() { + let tokens = quote!(static var); + + fn assert(input: ParseStream) -> Result<()> { + assert!(!input.peek(Ident)); + assert!(input.peek(Ident::peek_any)); + assert!(input.peek(Token![static])); + + let _: Token![static] = input.parse()?; + + assert!(input.peek(Ident)); + assert!(input.peek(Ident::peek_any)); + + let _: Ident = input.parse()?; + Ok(()) + } + + assert.parse2(tokens).unwrap(); +} + +#[test] +fn test_peek_groups() { + // pub ( :: ) «∅ ! = ∅» static + let tokens = TokenStream::from_iter([ + TokenTree::Ident(Ident::new("pub", Span::call_site())), + TokenTree::Group(Group::new( + Delimiter::Parenthesis, + TokenStream::from_iter([ + TokenTree::Punct(Punct::new(':', Spacing::Joint)), + TokenTree::Punct(Punct::new(':', Spacing::Alone)), + ]), + )), + TokenTree::Group(Group::new( + Delimiter::None, + TokenStream::from_iter([ + TokenTree::Punct(Punct::new('!', Spacing::Alone)), + TokenTree::Punct(Punct::new('=', Spacing::Alone)), + ]), + )), + TokenTree::Ident(Ident::new("static", Span::call_site())), + ]); + + fn assert(input: ParseStream) -> Result<()> { + assert!(input.peek2(token::Paren)); + assert!(input.peek3(token::Group)); + assert!(input.peek3(Token![!])); + + let _: Token![pub] = input.parse()?; + + assert!(input.peek(token::Paren)); + assert!(!input.peek(Token![::])); + assert!(!input.peek2(Token![::])); + assert!(input.peek2(Token![!])); + assert!(input.peek2(token::Group)); + assert!(!input.peek3(Token![=])); // FIXME + assert!(input.peek3(Token![static])); // FIXME + + let content; + parenthesized!(content in input); + + assert!(content.peek(Token![::])); + assert!(content.peek2(Token![:])); + assert!(!content.peek3(token::Group)); + assert!(!content.peek3(Token![!])); + + assert!(input.peek(token::Group)); + assert!(input.peek(Token![!])); + + let _: Token![::] = content.parse()?; + + assert!(input.peek(token::Group)); + assert!(input.peek(Token![!])); + assert!(input.peek2(Token![=])); + assert!(!input.peek3(Token![static])); // FIXME + assert!(input.peek2(Token![static])); // FIXME + + let _: Token![!] = input.parse()?; + + assert!(input.peek(Token![=])); + assert!(input.peek2(Token![static])); + + let _: Token![=] = input.parse()?; + + assert!(input.peek(Token![static])); + + let _: Token![static] = input.parse()?; + Ok(()) + } + + assert.parse2(tokens).unwrap(); }