1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
extern crate proc_macro;
use proc_macro::{TokenStream, TokenTree};
#[proc_macro_attribute]
pub fn trace(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut prefix: TokenStream = "
use backtrace::{Backtrace, BacktraceFrame};
let (trace, curr_file, curr_line) = (Backtrace::new(), file!(), line!());
let frames = trace.frames();
let previous_symbol = frames
.iter()
.flat_map(BacktraceFrame::symbols)
.skip_while(|s| {
s.filename()
.map(|p| !p.ends_with(curr_file))
.unwrap_or(true)
|| s.lineno() != Some(curr_line)
})
.nth(1 as usize)
.unwrap();
println!(\"Called from {:?} at line {:?}\",
previous_symbol.filename().unwrap(), previous_symbol.lineno().unwrap());
"
.parse()
.unwrap();
item.into_iter()
.map(|tt| match tt {
TokenTree::Group(ref g) if g.delimiter() == proc_macro::Delimiter::Brace => {
prefix.extend(g.stream());
TokenTree::Group(proc_macro::Group::new(
proc_macro::Delimiter::Brace,
prefix.clone(),
))
}
other => other,
})
.collect()
}