I'm toying around with Rust's procedural macros, and I wanted to make a custom funny attribute that turns all string literals in it's TokenStream into SHOUTING CASE.
Here's what I have so far in my proc-macro lib called amplify
:
// lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, File};
#[proc_macro_attribute]
pub fn amplify(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as File);
// TODO: modify string literals (LitStr) in token tree to be upper case
let quoted = quote! {#input};
println!("{:#?}", quoted); // just print at compile time to see what is produced
quoted.into()
}
When applied to a simple hello-world program, it should turn the "Hello, World!" string literal into "HELLO, WORLD!" at compile time. Example:
use amplify::amplify;
#[amplify]
pub fn main() {
println!("Hello, World!");
}
And then running the code:
cargo run
# prints: HELLO, WORLD!
Checking the strings in the binary:
strings target/debug/hello-world | grep -i hello
# prints: HELLO, WORLD! (and possibly other string garbage from the binary)
It is important to note that I want the attribute macro to recursively walk the token tree looking for all string literals. I don't know how to check whether each Item in the tree is a string literal or not, or whether the Item needs to be recursed into.
Any help would be greatly appreciated!