1use quote::quote;
2use syn::ItemFn;
3
4#[proc_macro_attribute]
5pub fn public(
6 _attr: proc_macro::TokenStream,
7 item: proc_macro::TokenStream,
8) -> proc_macro::TokenStream {
9 let module = syn::parse_macro_input!(item as syn::ItemMod);
10
11 let mod_ident = &module.ident; let mut new_content = Vec::new();
13
14 if let Some((_, items)) = &module.content {
16 for item in items {
17 if let syn::Item::Fn(func) = item {
18 new_content.push(process_function(func));
20 } else {
21 new_content.push(quote! { #item });
23 }
24 }
25 }
26
27 quote! {
29 mod #mod_ident {
30 #( #new_content )*
31 }
32
33 ic_cdk::export_candid!();
34 }
35 .into()
36}
37
38fn process_function(func: &ItemFn) -> proc_macro2::TokenStream {
39 let mut transformed_func = func.clone();
40
41 let has_function_attr = func
42 .attrs
43 .iter()
44 .any(|attr| attr.path().is_ident("function"));
45 if has_function_attr {
46 transformed_func
48 .attrs
49 .push(syn::parse_quote!(#[ic_cdk::update]));
50 transformed_func
51 .attrs
52 .retain(|attr| !attr.path().is_ident("function"));
53 }
54
55 quote! {
57 #transformed_func
58 }
59}