You write attribute macros by defining a procedural macro in a separate crate with the proc-macro crate type and using the #[proc_macro_attribute] function attribute to process the attribute and generate code.
// In a crate with `proc-macro = true` in Cargo.toml
use proc_macro::TokenStream;
use quote::quote;
#[proc_macro_attribute]
pub fn my_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut ast = syn::parse_macro_input!(item as syn::ItemFn);
ast.sig.ident = syn::Ident::new(&format!("{}_wrapper", ast.sig.ident), ast.sig.ident.span());
TokenStream::from(quote! { #ast })
}
Apply it to your code like this:
use my_macro_crate::my_attr;
#[my_attr]
fn hello() {
println!("Hello!");
}
The macro renames hello to hello_wrapper at compile time.