派生宏实战:TokenStream解析与属性战争
从零构建一个派生宏,处理复杂的属性参数和字段级别标记,包括syn/quote深度使用 · 难度:入门 · +10XP
派生宏实战:TokenStream解析与属性战争
多数教程只写简单的#[derive(MyTrait)],但实际项目中你需要解析自定义属性如#[my_attr(key = value)],并处理结构体/枚举的字段。本课程教你使用syn crate解析TokenStream,支持属性嵌套、类型参数、where子句等边缘情况。还将讨论proc macro hygiene和如何处理标识符冲突。最终生成一个功能完备的派生宏,可用于生产。
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, Lit, Meta};
use quote::quote;
#[proc_macro_derive(HelloMacro, attributes(hello))]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
// 解析属性 #[hello(name = "world")]
let mut prefix = String::from("Hello");
for attr in &input.attrs {
if attr.path().is_ident("hello") {
if let Meta::NameValue(nv) = &attr.meta {
if let Lit::Str(s) = &nv.value {
prefix = s.value();
}
}
}
}
let expanded = quote! {
impl HelloMacro for #name {
fn hello() -> String {
format!("{} from {}!", #prefix, stringify!(#name))
}
}
};
expanded.into()
}