code in question:
lib.rs
use proc_macro::TokenStream;
mod domain_equivalent;
//domain_equivilant macro that impl From and Into to domain
#[proc_macro_derive(DomainEquivalent)]
pub fn domain_equivalent(input: TokenStream) -> TokenStream {
domain_equivalent::domain_equivalent(input)
}
domain_equivalent.rs
use convert_case::{Case, Casing};
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Item, Visibility};
pub fn domain_equivalent(input: TokenStream) -> TokenStream {
let item: Item = parse_macro_input!(input);
let struct_data = match item.clone() {
Item::Struct(e) => e,
_ => panic!("only in structs"),
};
let ident = struct_data.ident;
// panic!(
// "{}",
// check_file(ident, "./domain/src/post".into()).to_string()
// );
return check_file(ident, "./domain/src/post".into());
}
//check mod.rs
//find pub mods and structs
//check if struct is threre
//if not go to other public mod
//check if struct is there
fn check_file(name: syn::Ident, path: String) -> TokenStream {
let file = std::fs::read_to_string(format!("{}/mod.rs", path)).expect("Error reading file");
let parsed_file = syn::parse_file(&file).expect("Error parsing file");
for item in parsed_file.items {
if let Item::Struct(structure) = item {
let struct_name = structure.ident;
if struct_name == name.clone() {
return retrun_macro(struct_name, structure.fields);
}
} else if let Item::Mod(module) = item {
match module.vis {
Visibility::Public(_) => {
let tokenstream = check_file(
name.clone(),
format!("{}/{}", path, module.ident.to_string()),
);
match tokenstream.is_empty() {
true => return tokenstream,
false => continue,
};
}
_ => {}
}
}
}
quote!().into()
}
fn retrun_macro(ident: syn::Ident, fields: syn::Fields) -> TokenStream {
let fields = match fields {
syn::Fields::Named(e) => e,
_ => panic!("Only with named fields"),
};
let mut from_fields = Vec::new();
let mut into_fields = Vec::new();
for field in fields.named {
let field_ident = field.ident.expect("Failed to get Field Ident");
if field_ident.to_string().ends_with("_thing") {
from_fields.push(quote!(#field_ident: Some(value.#field_ident.into()),));
into_fields.push(quote!(#field_ident: self.#field_ident.unwrap().into(),));
} else {
from_fields.push(quote!(#field_ident: value.#field_ident,));
into_fields.push(quote!(#field_ident: self.#field_ident,));
}
}
let module: syn::Ident =
syn::parse_str(&ident.to_string().replace("Thing", "").to_case(Case::Snake))
.expect("Failed to parse module");
let output = quote! {
impl From<domain::#module::#ident> for #ident {
fn from(value: domain::#module::#ident) -> Self {
Self {
#(#from_fields)*
}
}
}
impl Into<domain::#module::#ident> for #ident {
fn into(self) -> domain::#module::#ident {
domain::#module::#ident {
#(#into_fields)*
}
}
}
};
output.into()
}
Problem:
When I try to expand I get nothing as derive output and it does not error;
if I uncomment the panic I get the result I want
can you help me?
thanks