1 use crate::*;
2 use std::fmt::{Debug, Display};
3 
4 
5 #[track_caller]
assert_parse_ok_eq<T: PartialEq + Debug + Display>( input: &str, result: Result<T, ParseError>, expected: T, parse_method: &str, )6 pub(crate) fn assert_parse_ok_eq<T: PartialEq + Debug + Display>(
7     input: &str,
8     result: Result<T, ParseError>,
9     expected: T,
10     parse_method: &str,
11 ) {
12     match result {
13         Ok(actual) if actual == expected => {
14             if actual.to_string() != input {
15                 panic!(
16                     "formatting does not yield original input `{}`: {:?}",
17                     input,
18                     actual,
19                 );
20             }
21         }
22         Ok(actual) => {
23             panic!(
24                 "unexpected parsing result (with `{}`) for `{}`:\nactual:    {:?}\nexpected:  {:?}",
25                 parse_method,
26                 input,
27                 actual,
28                 expected,
29             );
30         }
31         Err(e) => {
32             panic!(
33                 "expected `{}` to be parsed (with `{}`) successfully, but it failed: {:?}",
34                 input,
35                 parse_method,
36                 e,
37             );
38         }
39     }
40 }
41 
42 // This is not ideal, but to perform this check we need `proc-macro2`. So we
43 // just don't do anything if that feature is not enabled.
44 #[cfg(not(feature = "proc-macro2"))]
assert_roundtrip<T>(_: T, _: &str)45 pub(crate) fn assert_roundtrip<T>(_: T, _: &str) {}
46 
47 #[cfg(feature = "proc-macro2")]
48 #[track_caller]
assert_roundtrip<T>(ours: T, input: &str) where T: std::convert::TryFrom<proc_macro2::Literal> + fmt::Debug + PartialEq + Clone, proc_macro2::Literal: From<T>, <T as std::convert::TryFrom<proc_macro2::Literal>>::Error: std::fmt::Display,49 pub(crate) fn assert_roundtrip<T>(ours: T, input: &str)
50 where
51     T: std::convert::TryFrom<proc_macro2::Literal> + fmt::Debug + PartialEq + Clone,
52     proc_macro2::Literal: From<T>,
53     <T as std::convert::TryFrom<proc_macro2::Literal>>::Error: std::fmt::Display,
54 {
55     let pm_lit = input.parse::<proc_macro2::Literal>()
56         .expect("failed to parse input as proc_macro2::Literal");
57     let t_name = std::any::type_name::<T>();
58 
59     // Unfortunately, `proc_macro2::Literal` does not implement `PartialEq`, so
60     // this is the next best thing.
61     if proc_macro2::Literal::from(ours.clone()).to_string() != pm_lit.to_string() {
62         panic!(
63             "Converting {} to proc_macro2::Literal has unexpected result:\
64                 \nconverted: {:?}\nexpected:  {:?}",
65             t_name,
66             proc_macro2::Literal::from(ours),
67             pm_lit,
68         );
69     }
70 
71     match T::try_from(pm_lit) {
72         Err(e) => {
73             panic!("Trying to convert proc_macro2::Literal to {} results in error: {}", t_name, e);
74         }
75         Ok(res) => {
76             if res != ours {
77                 panic!(
78                     "Converting proc_macro2::Literal to {} has unexpected result:\
79                         \nactual:    {:?}\nexpected:  {:?}",
80                     t_name,
81                     res,
82                     ours,
83                 );
84             }
85         }
86     }
87 }
88 
89 macro_rules! assert_err {
90     ($ty:ident, $input:literal, $kind:ident, $( $span:tt )+ ) => {
91         assert_err_single!($ty::parse($input), $kind, $($span)+);
92         assert_err_single!($crate::Literal::parse($input), $kind, $($span)+);
93     };
94 }
95 
96 macro_rules! assert_err_single {
97     ($expr:expr, $kind:ident, $( $span:tt )+ ) => {
98         let res = $expr;
99         let err = match res {
100             Err(e) => e,
101             Ok(v) => panic!(
102                 "Expected `{}` to return an error, but it returned Ok({:?})",
103                 stringify!($expr),
104                 v,
105             ),
106         };
107         if err.kind != $crate::err::ParseErrorKind::$kind {
108             panic!(
109                 "Expected error kind {} for `{}` but got {:?}",
110                 stringify!($kind),
111                 stringify!($expr),
112                 err.kind,
113             )
114         }
115         let expected_span = assert_err_single!(@span $($span)+);
116         if err.span != expected_span {
117             panic!(
118                 "Expected error span {:?} for `{}` but got {:?}",
119                 expected_span,
120                 stringify!($expr),
121                 err.span,
122             )
123         }
124     };
125     (@span $start:literal .. $end:literal) => { Some($start .. $end) };
126     (@span $at:literal) => { Some($at.. $at + 1) };
127     (@span None) => { None };
128 }
129