diff --git a/src/lib.rs b/src/lib.rs index 60d80c0..8d7b511 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,6 @@ mod types; mod types_edition; pub use error::Error; -pub use parse::parse_declaration; +pub use parse::{consume_declaration, parse_declaration}; pub use punctuated::Punctuated; pub use types::*; diff --git a/src/parse.rs b/src/parse.rs index 020fffe..6daae94 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -14,9 +14,6 @@ use proc_macro2::token_stream::IntoIter; use proc_macro2::{Delimiter, TokenStream, TokenTree}; use std::iter::Peekable; -// TODO - Return Result<...>, handle case where TokenStream is valid declaration, -// but not a type or function. - /// Parses the token stream of a type declaration. /// /// For instance, if you're implementing a derive macro, you can pass the @@ -29,6 +26,8 @@ use std::iter::Peekable; /// macro, there should be no way for this to happen, as Rust will emit an /// error instead of calling this macro. /// +/// Panics if there are leftover tokens. +/// /// ## Example /// /// ``` @@ -57,15 +56,34 @@ use std::iter::Peekable; /// E = (FOO + BAR), // Ok /// } /// ``` - pub fn parse_declaration(tokens: TokenStream) -> Result { let mut tokens = tokens.into_iter().peekable(); - parse_declaration_tokens(&mut tokens) + let declaration = consume_declaration(&mut tokens); + + if tokens.peek().is_some() { + panic!( + "unexpected trailing tokens after declaration: {}", + tokens.collect::() + ); + } + + declaration } -pub(crate) fn parse_declaration_tokens( - tokens: &mut Peekable, -) -> Result { +/// Consume a type declaration from a token stream. +/// +/// This is the same as [parse_declaration], except it doesn't panic if there are +/// leftover tokens. +/// +/// ## Panics +/// +/// Panics if given a token stream that doesn't parse as a valid Rust +/// type declaration. +/// +/// ## Errors +/// +/// Venial doesn't support enum discriminants with multiple non-grouped tokens. +pub fn consume_declaration(tokens: &mut Peekable) -> Result { let attributes = consume_outer_attributes(tokens); let vis_marker = consume_vis_marker(tokens); diff --git a/src/parse_mod.rs b/src/parse_mod.rs index 0c845a7..13a9ff5 100644 --- a/src/parse_mod.rs +++ b/src/parse_mod.rs @@ -1,4 +1,4 @@ -use crate::parse::parse_declaration_tokens; +use crate::parse::consume_declaration; use crate::parse_type::consume_declaration_name; use crate::parse_utils::{ consume_ident, consume_inner_attributes, consume_stuff_until, parse_ident, parse_punct, @@ -43,7 +43,7 @@ pub(crate) fn parse_mod( if tokens.peek().is_none() { break; } - let item = parse_declaration_tokens(&mut tokens) + let item = consume_declaration(&mut tokens) .unwrap_or_else(|e| panic!("declaration in mod: {}", e)); mod_members.push(item); } diff --git a/src/tests.rs b/src/tests.rs index 4a0f738..45856a6 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -122,6 +122,17 @@ fn parse_empty_enum() { assert_debug_snapshot!(enum_type); } +#[test] +#[should_panic = "unexpected trailing tokens after declaration"] +fn reject_trailing_tokens() { + let declaration = parse_declaration_checked(quote::quote! { + struct Good {} + trailing junk + }); + + println!("This should have panicked: {:#?}", declaration); +} + // ========== // VISIBILITY // ==========