3个版本 (破坏性更新)
使用旧的Rust 2015
0.3.0 | 2018年9月14日 |
---|---|
0.2.0 | 2018年6月2日 |
0.1.0 | 2018年5月29日 |
在进程宏中排名1864
7KB
173 行
进程宏助手
自1.15.0(2017-02-02)以来,基本进程宏允许自定义 #[derive]
。要使用它,你可以分配一个函数作为处理程序,这个处理程序接受目标 Struct
或 Enum
的 TokenStream
。
但是直接从 TokenStream
读取很麻烦,相反,你可以通过 syn
读取它,这是一个将Rust令牌流解析为Rust源代码语法树的解析库。
但是为了通用性,syn
非常复杂。在你的代码中,必须有大量噪声
#[proc_macro_derive(Table1, attributes(PrimaryKey))]
pub fn table1(input: TokenStream) -> TokenStream {
let derive_input = syn::parse::<DeriveInput>(input).unwrap();
let data_struct = if let Data::Struct(ref data) = derive_input.data {
data
} else {
unreachable!();
};
let primary_field_idents: Vec<String> = data_struct
.fields
.iter()
.filter(|field| {
field
.attrs
.iter()
.find(|x| x.interpret_meta().unwrap().name() == "PrimaryKey")
.is_some()
})
.map(|x| x.ident.unwrap().to_string())
.collect();
let result_len = primary_field_idents.len();
quote!(const PRIMARY_FIELDS1: [&'static str; #result_len] = [
#(#primary_field_idents),*
];)
.into()
}
使用这个仓库,你的代码可以是
use proc_macro_helper::prelude::*;
#[proc_macro_derive(Table2, attributes(PrimaryKey))]
pub fn table2(input: TokenStream) -> TokenStream {
let derive_input = syn::parse::<DeriveInput>(input).unwrap();
let target_struct: Struct = Struct::parse(&derive_input);
let primary_field_idents = target_struct
.fields
.iter()
.filter(|x| x.attributes.iter().find(|x| x.name == "PrimaryKey").is_some())
.map(|x| x.name.clone().unwrap())
.collect::<Vec<String>>();
let result_len = primary_field_idents.len();
quote!(const PRIMARY_FIELDS2: [&'static str; #result_len] = [
#(#primary_field_idents),*
];)
.into()
}
当前状态
- 需要更多测试用例。
- 需要更多功能请求。
- 需要更多错误报告。
待办事项
- 实现枚举助手
- 移除对
quote
的依赖
依赖
~2MB
~46K SLoC