use crate::*; use std::fmt::{Debug, Display}; #[track_caller] pub(crate) fn assert_parse_ok_eq( input: &str, result: Result, expected: T, parse_method: &str, ) { match result { Ok(actual) if actual == expected => { if actual.to_string() != input { panic!( "formatting does not yield original input `{}`: {:?}", input, actual, ); } } Ok(actual) => { panic!( "unexpected parsing result (with `{}`) for `{}`:\nactual: {:?}\nexpected: {:?}", parse_method, input, actual, expected, ); } Err(e) => { panic!( "expected `{}` to be parsed (with `{}`) successfully, but it failed: {:?}", input, parse_method, e, ); } } } // This is not ideal, but to perform this check we need `proc-macro2`. So we // just don't do anything if that feature is not enabled. #[cfg(not(feature = "proc-macro2"))] pub(crate) fn assert_roundtrip(_: T, _: &str) {} #[cfg(feature = "proc-macro2")] #[track_caller] pub(crate) fn assert_roundtrip(ours: T, input: &str) where T: std::convert::TryFrom + fmt::Debug + PartialEq + Clone, proc_macro2::Literal: From, >::Error: std::fmt::Display, { let pm_lit = input.parse::() .expect("failed to parse input as proc_macro2::Literal"); let t_name = std::any::type_name::(); // Unfortunately, `proc_macro2::Literal` does not implement `PartialEq`, so // this is the next best thing. if proc_macro2::Literal::from(ours.clone()).to_string() != pm_lit.to_string() { panic!( "Converting {} to proc_macro2::Literal has unexpected result:\ \nconverted: {:?}\nexpected: {:?}", t_name, proc_macro2::Literal::from(ours), pm_lit, ); } match T::try_from(pm_lit) { Err(e) => { panic!("Trying to convert proc_macro2::Literal to {} results in error: {}", t_name, e); } Ok(res) => { if res != ours { panic!( "Converting proc_macro2::Literal to {} has unexpected result:\ \nactual: {:?}\nexpected: {:?}", t_name, res, ours, ); } } } } macro_rules! assert_err { ($ty:ident, $input:literal, $kind:ident, $( $span:tt )+ ) => { assert_err_single!($ty::parse($input), $kind, $($span)+); assert_err_single!($crate::Literal::parse($input), $kind, $($span)+); }; } macro_rules! assert_err_single { ($expr:expr, $kind:ident, $( $span:tt )+ ) => { let res = $expr; let err = match res { Err(e) => e, Ok(v) => panic!( "Expected `{}` to return an error, but it returned Ok({:?})", stringify!($expr), v, ), }; if err.kind != $crate::err::ParseErrorKind::$kind { panic!( "Expected error kind {} for `{}` but got {:?}", stringify!($kind), stringify!($expr), err.kind, ) } let expected_span = assert_err_single!(@span $($span)+); if err.span != expected_span { panic!( "Expected error span {:?} for `{}` but got {:?}", expected_span, stringify!($expr), err.span, ) } }; (@span $start:literal .. $end:literal) => { Some($start .. $end) }; (@span $at:literal) => { Some($at.. $at + 1) }; (@span None) => { None }; }