hpl_toolkit_derive_gen_idl/
lib.rs1extern crate proc_macro;
2use proc_macro::TokenStream;
3#[cfg(feature = "idl-build")]
4use {
5 proc_macro2::TokenStream as TokenStream2,
6 regex::Regex
7};
8
9#[proc_macro_derive(GenIdl)]
10pub fn gen_idl(_item: TokenStream) -> TokenStream {
11 #[cfg(feature = "idl-build")]
12 {
13 use anchor_syn::idl::*;
14 println!("idl-build");
15 let parsed: syn::Item = syn::parse(_item).unwrap();
16 let name;
17 let idl_build_impl = match &parsed {
18 syn::Item::Struct(item) => {
19 name = &item.ident;
20 println!("parsed: {:?}", name);
21 impl_idl_build_struct(item)
22 }
23 syn::Item::Enum(item) => {
24 name = &item.ident;
25 println!("parsed: {:?}", name);
26 impl_idl_build_enum(item)
27 }
28 syn::Item::Union(item) => {
29 name = &item.ident;
30 println!("parsed: {:?}", name);
31 impl_idl_build_union(item)
32 }
33 _ => unreachable!(),
35 };
36 println!("idl_build_impl: {:?}", name);
37
38 return modify_insert_calls(idl_build_impl).into();
39 };
40
41 #[allow(unreachable_code)]
42 TokenStream::new()
43}
44
45#[cfg(feature = "idl-build")]
46fn modify_insert_calls(input: TokenStream2) -> TokenStream2 {
48
49 let input_str = input.to_string();
51
52 let re = Regex::new(r#"(?s)if let Some\((\w+)\)\s*=\s*<\s*([^>]+)\s*>\s*::\s*create_type\(\)\s*\{\s*types\.insert\(<\s*([^>]+)\s*>\s*::\s*get_full_path\(\),\s*(\w+)\);\s*<\s*([^>]+)\s*>\s*::\s*insert_types\(types\);\s*\}"#).unwrap();
54 let modified_str = re.replace_all(&input_str, |caps: ®ex::Captures| {
56 let ty = caps[1].trim(); let name = caps[2].trim(); if name == "Self" {
61 return "/* Replaced Self */".to_string();
62 }
63 format!(
65 r#"if let Some({0}) = < {1} > :: create_type()
66 {{
67 types.insert(< {1} > :: get_full_path(), {0}); < {1} > ::
68 insert_types(types);
69 }}"#,
70 ty, name
71 )
72 });
73
74 let modified_output: TokenStream2 = modified_str.parse().unwrap();
78
79 modified_output
81}