4 #![crate_type = "proc-macro"]
6 #![feature(proc_macro_expand, proc_macro_span)]
8 extern crate proc_macro;
11 use std::str::FromStr;
14 pub fn expand_expr_is(input: TokenStream) -> TokenStream {
15 expand_expr_is_inner(input, false)
19 pub fn expand_expr_is_trim(input: TokenStream) -> TokenStream {
20 expand_expr_is_inner(input, true)
23 fn expand_expr_is_inner(input: TokenStream, trim_invisible: bool) -> TokenStream {
24 let mut iter = input.into_iter();
25 let mut expected_tts = Vec::new();
28 Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
29 Some(tt) => expected_tts.push(tt),
30 None => panic!("expected comma"),
34 // If requested, trim the "invisible" delimiters at the start and end.
35 let expected = expected_tts.into_iter().collect::<TokenStream>().to_string();
36 let expected = if trim_invisible {
37 let len1 = "/*«*/ ".len();
38 let len2 = " /*»*/".len();
39 &expected[len1..expected.len() - len2]
43 let expanded = iter.collect::<TokenStream>().expand_expr().unwrap().to_string();
45 assert_eq!(expected, expanded);
51 pub fn expand_expr_fail(input: TokenStream) -> TokenStream {
52 match input.expand_expr() {
53 Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts),
54 Err(_) => TokenStream::new(),
59 pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream {
60 // Check that the passed in `file!()` invocation and a parsed `file!`
61 // invocation expand to the same literal.
62 let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string();
63 let parse_t = TokenStream::from_str("file!{}")
66 .expect("expand_expr failed on internal macro")
68 assert_eq!(input_t, parse_t);
70 // Check that the literal matches `Span::call_site().source_file().path()`
72 Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
73 assert_eq!(input_t, expect_t);
79 pub fn recursive_expand(_: TokenStream) -> TokenStream {
80 // Recursively call until we hit the recursion limit and get an error.
82 // NOTE: This doesn't panic if expansion fails because that'll cause a very
83 // large number of errors to fill the output.
84 TokenStream::from_str("recursive_expand!{}")
87 .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect())
91 pub fn echo_pm(input: TokenStream) -> TokenStream {