| extern crate proc_macro; | |
| use proc_macro::*; | |
| #[proc_macro] | |
| pub fn a_proc_macro(_item: TokenStream) -> TokenStream { | |
| "fn ex() { foobar::f(); }".parse().unwrap() | |
| } | |
| // inserts foobar::f() to the end of the function | |
| #[proc_macro_attribute] | |
| pub fn an_attr_macro(attr: TokenStream, item: TokenStream) -> TokenStream { | |
| let new_call: TokenStream = "foobar::f();".parse().unwrap(); | |
| let mut tokens = item.into_iter(); | |
| let fn_tok = tokens.next().unwrap(); | |
| let ident_tok = tokens.next().unwrap(); | |
| let args_tok = tokens.next().unwrap(); | |
| let body = match tokens.next().unwrap() { | |
| TokenTree::Group(g) => { | |
| let new_g = Group::new(g.delimiter(), new_call); | |
| let mut outer_g = Group::new( | |
| g.delimiter(), | |
| [TokenTree::Group(g.clone()), TokenTree::Group(new_g)].into_iter().collect(), | |
| ); | |
| if attr.to_string() == "with_span" { | |
| outer_g.set_span(g.span()); | |
| } | |
| TokenTree::Group(outer_g) | |
| } | |
| _ => unreachable!(), | |
| }; | |
| let tokens = vec![fn_tok, ident_tok, args_tok, body].into_iter().collect::<TokenStream>(); | |
| tokens | |
| } |