In my proc macro (which I apply to struct) I want to get fields with specific attribute (#[dynamic_field]
) and next I want to add struct method that will call methods from the struct, where each method_name equals to filtered field name. The code below shows what I want to achieve:
let output = quote! {
impl #ident {
pub fn debug() {
for item in vec![#(#field_data),*] {
Self::#item();
}
}
}
};
but this not works:
error[E0425]: cannot find value `item` in this scope
--> proc_macro\src/lib.rs:55:28
|
55 | Self::#item();
| ^^^^ not found in this scope
This is my proc macro code:
#[proc_macro_derive(Packet, attributes(dynamic_field))]
pub fn derive(input: TokenStream) -> TokenStream {
let ItemStruct { ident, fields, .. } = parse_macro_input!(input);
let field_data = fields.iter().filter_map(|f| {
let ident = f.ident.clone().unwrap().to_string();
println!("IDENT: {:?}", ident);
let field_type = f.ty.clone();
let args = f.attrs
.iter()
.flat_map(|a| {
match a.parse_meta().unwrap() {
syn::Meta::Path(meta) => {
Some(meta.get_ident().unwrap().to_string())
},
syn::Meta::List(meta) => {
Some(meta.path.get_ident().unwrap().to_string())
},
_ => None,
}
})
.collect::<Vec<_>>();
if !args.is_empty() {
Some(f.ident.clone().unwrap().to_string())
} else {
None
}
}).collect::<Vec<_>>();
let output = quote! {
impl #ident {
pub fn debug() {
for item in vec![#(#field_data),*] {
Self::#item();
}
}
}
};
TokenStream::from(output)
}
and how I use it:
#[derive(Packet)]
struct Test {
#[dynamic_field]
size: u8,
#[dynamic_field]
size1: u8,
#[dynamic_field]
size2: u8,
field2: u8,
field3: u8,
}
impl Test {
fn size() {
println!("TEST1");
}
fn size1() {
println!("TEST2");
}
fn size2() {
println!("TEST3");
}
}
fn main() {
Test::debug();
}
Expected result: Test::debug()
should call Test::size1()
, Test::size2()
and Test::size()
.
I tried to use quote! { Self::#item() } inside parent quote!:
let output = quote! {
impl #ident {
pub fn debug() {
for item in vec![#(#field_data),*] {
quote! { Self::#item(); }
}
}
}
};
but this not helped.
Could somebody explain how to fix this ?