I am learning proc macroses and trying to implement proc macro that will allow to display data about each struct's field: field name, field type and attributes. For this purpose I implemented next struct:
#[derive(Debug)]
struct Item {
name: String,
item_type: String,
attrs: Vec<String>,
}
and I want to display info as vector of Item
instances. But for now I got an error:
error: proc-macro derive panicked
--> src\main.rs:3:10
|
3 | #[derive(Debugger)]
| ^^^^^^^^
|
= help: message: not yet implemented
error[E0599]: no function or associated item named `debug` found for struct `Test` in the current scope
--> src\main.rs:22:11
|
4 | struct Test {
| ----------- function or associated item `debug` not found for this struct
...
22 | Test::debug();
| ^^^^^ function or associated item not found in `Test`
I assume I require to impl ToTokens trait on Item, but it's not clear what exactly I need to do.
This is my macro code:
use proc_macro::{TokenStream};
use std::io::{Error, ErrorKind};
use std::io::ErrorKind::Other;
use proc_macro2::Ident;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, DeriveInput, ItemStruct, Token, punctuated::Punctuated, NestedMeta};
#[proc_macro_derive(Debugger, attributes(dynamic_field))]
pub fn derive(input: TokenStream) -> TokenStream {
let ItemStruct { ident, fields, .. } = parse_macro_input!(input);
let field_data = fields.iter().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<_>>();
Item {
name: f.ident.clone().unwrap().to_string(),
item_type: quote!(#field_type).to_string(),
attrs: args,
}
}).collect::<Vec<_>>();
let output = quote! {
impl #ident {
pub fn debug() {
println!("{:#?}", vec![#(#field_data),*]);
}
}
};
TokenStream::from(output)
}
and how I use it:
use my_proc_macros_lib::Debugger;
#[derive(Debugger)]
struct Test {
#[dynamic_field]
size: u8,
#[dynamic_field]
size1: u8,
#[dynamic_field]
size2: u8,
field2: u8,
field3: u8,
}
impl Test {
fn size() {}
fn size1() {}
fn size2() {}
}
fn main() {
Test::debug();
}
I am not sure if it's possible to implement sandbox for proc macro on play-rust, so I created test repo for reproduce.
Could somebody explain what have I missed and how to fix this ?
P.S. forgot to say, I need to store fields data in structs because I want to use this data later.