use syntax::{ast, AstNode}; use crate::ast_to_token_tree; use super::*; #[test] fn test_valid_arms() { fn check(macro_body: &str) { let m = parse_macro_arm(macro_body); m.unwrap(); } check("($i:ident) => ()"); check("($(x),*) => ()"); check("($(x)_*) => ()"); check("($(x)i*) => ()"); check("($($i:ident)*) => ($_)"); check("($($true:ident)*) => ($true)"); check("($($false:ident)*) => ($false)"); check("($) => ($)"); } #[test] fn test_invalid_arms() { fn check(macro_body: &str, err: ParseError) { let m = parse_macro_arm(macro_body); assert_eq!(m, Err(err)); } check("invalid", ParseError::Expected("expected subtree".into())); check("$i:ident => ()", ParseError::Expected("expected subtree".into())); check("($i:ident) ()", ParseError::Expected("expected `=`".into())); check("($($i:ident)_) => ()", ParseError::InvalidRepeat); check("($i) => ($i)", ParseError::UnexpectedToken("bad fragment specifier 1".into())); check("($i:) => ($i)", ParseError::UnexpectedToken("bad fragment specifier 1".into())); check("($i:_) => ()", ParseError::UnexpectedToken("bad fragment specifier 1".into())); } fn parse_macro_arm(arm_definition: &str) -> Result { let macro_definition = format!(" macro_rules! m {{ {} }} ", arm_definition); let source_file = ast::SourceFile::parse(¯o_definition).ok().unwrap(); let macro_definition = source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()); crate::MacroRules::parse(&definition_tt) }