fadroma_proc_derive/
lib.rs1use quote::quote;
2use syn::{parse_macro_input, parse_quote, AttributeArgs, ItemTrait, TraitItemMethod};
3
4use crate::contract::{Contract, ContractType};
5
6mod args;
7mod attr;
8mod contract;
9mod utils;
10
11#[proc_macro_attribute]
12pub fn contract(
13 args: proc_macro::TokenStream,
14 trait_: proc_macro::TokenStream,
15) -> proc_macro::TokenStream {
16 generate_contract(args, trait_, ContractType::Contract)
17}
18
19#[proc_macro_attribute]
20pub fn interface(
21 args: proc_macro::TokenStream,
22 trait_: proc_macro::TokenStream,
23) -> proc_macro::TokenStream {
24 generate_contract(args, trait_, ContractType::Interface)
25}
26
27#[proc_macro_attribute]
28pub fn contract_impl(
29 args: proc_macro::TokenStream,
30 trait_: proc_macro::TokenStream,
31) -> proc_macro::TokenStream {
32 generate_contract(args, trait_, ContractType::Impl)
33}
34
35#[proc_macro_attribute]
36pub fn init(
37 _args: proc_macro::TokenStream,
38 func: proc_macro::TokenStream,
39) -> proc_macro::TokenStream {
40 let mut ast = parse_macro_input!(func as TraitItemMethod);
41
42 add_fn_args(&mut ast, true, false, false);
43
44 let result = quote! {
45 #ast
46 };
47
48 proc_macro::TokenStream::from(result)
49}
50
51#[proc_macro_attribute]
52pub fn execute(
53 _args: proc_macro::TokenStream,
54 func: proc_macro::TokenStream,
55) -> proc_macro::TokenStream {
56 let mut ast = parse_macro_input!(func as TraitItemMethod);
57
58 add_fn_args(&mut ast, true, false, false);
59
60 let result = quote! {
61 #ast
62 };
63
64 proc_macro::TokenStream::from(result)
65}
66
67#[proc_macro_attribute]
68pub fn query(
69 _args: proc_macro::TokenStream,
70 func: proc_macro::TokenStream,
71) -> proc_macro::TokenStream {
72 let mut ast = parse_macro_input!(func as TraitItemMethod);
73
74 add_fn_args(&mut ast, false, false, false);
75
76 let result = quote! {
77 #ast
78 };
79
80 proc_macro::TokenStream::from(result)
81}
82
83#[proc_macro_attribute]
84pub fn execute_guard(
85 _args: proc_macro::TokenStream,
86 func: proc_macro::TokenStream,
87) -> proc_macro::TokenStream {
88 let mut ast = parse_macro_input!(func as TraitItemMethod);
89
90 if ast.sig.inputs.len() != 1 {
91 let err = syn::Error::new(
92 ast.sig.paren_token.span,
93 format!(
94 "Expecting one parameter with the type: &{}",
95 contract::EXECUTE_MSG
96 ),
97 )
98 .to_compile_error();
99
100 return proc_macro::TokenStream::from(err);
101 }
102
103 add_fn_args(&mut ast, true, true, true);
104
105 let result = quote! {
106 #ast
107 };
108
109 proc_macro::TokenStream::from(result)
110}
111
112fn generate_contract(
113 args: proc_macro::TokenStream,
114 trait_: proc_macro::TokenStream,
115 ty: ContractType,
116) -> proc_macro::TokenStream {
117 let args = parse_macro_input!(args as AttributeArgs);
118 let ast = parse_macro_input!(trait_ as ItemTrait);
119
120 let item_trait = quote!(#ast);
121
122 let contract = Contract::parse(args, ast, ty);
123
124 let boilerplate = match contract {
125 Ok(contract) => contract
126 .generate_boilerplate()
127 .unwrap_or_else(|x| x.into_compile_error()),
128 Err(err) => err.to_compile_error(),
129 };
130
131 let result = quote! {
132 #item_trait
133 #boilerplate
134 };
135
136 proc_macro::TokenStream::from(result)
137}
138
139fn add_fn_args(func: &mut TraitItemMethod, is_tx: bool, ref_env: bool, ref_info: bool) {
140 func.sig.inputs.insert(0, parse_quote!(&self));
141
142 if is_tx {
143 if func.default.is_none() {
144 func.sig
145 .inputs
146 .push(parse_quote!(deps: cosmwasm_std::DepsMut));
147 } else {
148 func.sig
149 .inputs
150 .push(parse_quote!(mut deps: cosmwasm_std::DepsMut));
151 }
152 if ref_env {
153 func.sig.inputs.push(parse_quote!(env: &cosmwasm_std::Env));
154 } else {
155 func.sig.inputs.push(parse_quote!(env: cosmwasm_std::Env));
156 }
157 if ref_info {
158 func.sig
159 .inputs
160 .push(parse_quote!(info: &cosmwasm_std::MessageInfo));
161 } else {
162 func.sig
163 .inputs
164 .push(parse_quote!(info: cosmwasm_std::MessageInfo));
165 }
166 } else {
167 func.sig.inputs.push(parse_quote!(deps: cosmwasm_std::Deps));
168 func.sig.inputs.push(parse_quote!(env: cosmwasm_std::Env));
169 }
170}