use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemImpl, ImplItem, ImplItemFn, Signature, FnArg, Pat, Type, Block};
#[proc_macro_attribute]
pub fn json_builder(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input_impl = parse_macro_input!(item as ItemImpl);
let transformed_impl = transform_impl_for_json_syntax(input_impl);
quote! { #transformed_impl }.into()
}
fn transform_impl_for_json_syntax(mut impl_block: ItemImpl) -> ItemImpl {
for item in &mut impl_block.items {
if let ImplItem::Fn(method) = item {
if is_json_builder_method(&method.sig.ident.to_string()) {
*method = transform_method_for_json_syntax(method.clone());
}
}
}
impl_block
}
fn is_json_builder_method(method_name: &str) -> bool {
matches!(method_name, "additional_params" | "metadata" | "new")
}
fn transform_method_for_json_syntax(mut method: ImplItemFn) -> ImplItemFn {
method
}
#[proc_macro]
pub fn with_json_syntax(input: TokenStream) -> TokenStream {
let input_tokens = proc_macro2::TokenStream::from(input);
let transformed = transform_tokens_for_json_syntax(input_tokens);
transformed.into()
}
fn transform_tokens_for_json_syntax(tokens: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
let token_string = tokens.to_string();
if token_string.contains("=>") && token_string.contains("{") && token_string.contains("}") {
let transformed = token_string
.replace("additional_params({", "additional_params(hash_map_fn!{")
.replace("metadata({", "metadata(hash_map_fn!{")
.replace("Tool::new({", "Tool::new(hash_map_fn!{");
transformed.parse().unwrap_or(tokens)
} else {
tokens
}
}