]> git.lizzy.rs Git - rust.git/blob - src/test/ui/proc-macro/auxiliary/expand-expr.rs
Show invisible delimeters (within comments) when pretty printing.
[rust.git] / src / test / ui / proc-macro / auxiliary / expand-expr.rs
1 // force-host
2 // no-prefer-dynamic
3
4 #![crate_type = "proc-macro"]
5 #![deny(warnings)]
6 #![feature(proc_macro_expand, proc_macro_span)]
7
8 extern crate proc_macro;
9
10 use proc_macro::*;
11 use std::str::FromStr;
12
13 #[proc_macro]
14 pub fn expand_expr_is(input: TokenStream) -> TokenStream {
15     expand_expr_is_inner(input, false)
16 }
17
18 #[proc_macro]
19 pub fn expand_expr_is_trim(input: TokenStream) -> TokenStream {
20     expand_expr_is_inner(input, true)
21 }
22
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();
26     loop {
27         match iter.next() {
28             Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
29             Some(tt) => expected_tts.push(tt),
30             None => panic!("expected comma"),
31         }
32     }
33
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]
40     } else {
41         &expected[..]
42     };
43     let expanded = iter.collect::<TokenStream>().expand_expr().unwrap().to_string();
44
45     assert_eq!(expected, expanded);
46
47     TokenStream::new()
48 }
49
50 #[proc_macro]
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(),
55     }
56 }
57
58 #[proc_macro]
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!{}")
64     .unwrap()
65         .expand_expr()
66         .expect("expand_expr failed on internal macro")
67         .to_string();
68     assert_eq!(input_t, parse_t);
69
70     // Check that the literal matches `Span::call_site().source_file().path()`
71     let expect_t =
72         Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
73     assert_eq!(input_t, expect_t);
74
75     TokenStream::new()
76 }
77
78 #[proc_macro]
79 pub fn recursive_expand(_: TokenStream) -> TokenStream {
80     // Recursively call until we hit the recursion limit and get an error.
81     //
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!{}")
85         .unwrap()
86         .expand_expr()
87         .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect())
88 }
89
90 #[proc_macro]
91 pub fn echo_pm(input: TokenStream) -> TokenStream {
92     input
93 }