cw_core_macros/lib.rs
1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, AttributeArgs, DataEnum, DeriveInput, Variant};
4
5/// Adds the nesecary fields to an such that the enum implements the
6/// interface needed to be a cw-governance voting module.
7///
8/// For example:
9///
10/// ```
11/// use cw_core_macros::voting_query;
12///
13/// #[voting_query]
14/// enum QueryMsg {}
15/// ```
16///
17/// Will transform the enum to:
18///
19/// ```
20/// enum QueryMsg {
21/// VotingPowerAtHeight {
22/// address: String,
23/// height: Option<u64>
24/// },
25/// TotalPowerAtHeight {
26/// height: Option<u64>
27/// },
28/// Info {},
29/// }
30/// ```
31///
32/// Note that other derive macro invocations must occur after this
33/// procedural macro as they may depend on the new fields. For
34/// example, the following will fail becase the `Clone` derivation
35/// occurs before the addition of the field.
36///
37/// ```compile_fail
38/// use cw_core_macros::voting_query;
39///
40/// #[derive(Clone)]
41/// #[voting_query]
42/// #[allow(dead_code)]
43/// enum Test {
44/// Foo,
45/// Bar(u64),
46/// Baz { foo: u64 },
47/// }
48/// ```
49#[proc_macro_attribute]
50pub fn voting_query(metadata: TokenStream, input: TokenStream) -> TokenStream {
51 // Make sure that no arguments were passed in.
52 let args = parse_macro_input!(metadata as AttributeArgs);
53 if let Some(first_arg) = args.first() {
54 return syn::Error::new_spanned(first_arg, "voting query macro takes no arguments")
55 .to_compile_error()
56 .into();
57 }
58
59 let mut ast: DeriveInput = parse_macro_input!(input);
60 match &mut ast.data {
61 syn::Data::Enum(DataEnum { variants, .. }) => {
62 let voting_power: Variant = syn::parse2(quote! { VotingPowerAtHeight {
63 address: ::std::string::String,
64 height: ::std::option::Option<::std::primitive::u64>
65 } })
66 .unwrap();
67
68 let total_power: Variant = syn::parse2(quote! { TotalPowerAtHeight {
69 height: ::std::option::Option<::std::primitive::u64>
70 } })
71 .unwrap();
72
73 let info: Variant = syn::parse2(quote! { Info {} }).unwrap();
74
75 variants.push(voting_power);
76 variants.push(total_power);
77 variants.push(info);
78 }
79 _ => {
80 return syn::Error::new(
81 ast.ident.span(),
82 "voting query types can not be only be derived for enums",
83 )
84 .to_compile_error()
85 .into()
86 }
87 };
88
89 quote! {
90 #ast
91 }
92 .into()
93}
94
95/// Adds the nesecary fields to an enum such that it implements the
96/// interface needed to be a cw-governance voting module with a token.
97///
98/// For example:
99///
100/// ```
101/// use cw_core_macros::token_query;
102///
103/// #[token_query]
104/// enum QueryMsg {}
105/// ```
106///
107/// Will transform the enum to:
108///
109/// ```
110/// enum QueryMsg {
111/// TokenContract {},
112/// }
113/// ```
114///
115/// Note that other derive macro invocations must occur after this
116/// procedural macro as they may depend on the new fields. For
117/// example, the following will fail becase the `Clone` derivation
118/// occurs before the addition of the field.
119///
120/// ```compile_fail
121/// use cw_core_macros::govmod_query;
122///
123/// #[derive(Clone)]
124/// #[token_query]
125/// #[allow(dead_code)]
126/// enum Test {
127/// Foo,
128/// Bar(u64),
129/// Baz { foo: u64 },
130/// }
131/// ```
132#[proc_macro_attribute]
133pub fn token_query(metadata: TokenStream, input: TokenStream) -> TokenStream {
134 // Make sure that no arguments were passed in.
135 let args = parse_macro_input!(metadata as AttributeArgs);
136 if let Some(first_arg) = args.first() {
137 return syn::Error::new_spanned(first_arg, "token query macro takes no arguments")
138 .to_compile_error()
139 .into();
140 }
141
142 let mut ast: DeriveInput = parse_macro_input!(input);
143 match &mut ast.data {
144 syn::Data::Enum(DataEnum { variants, .. }) => {
145 let info: Variant = syn::parse2(quote! { TokenContract {} }).unwrap();
146
147 variants.push(info);
148 }
149 _ => {
150 return syn::Error::new(
151 ast.ident.span(),
152 "token query types can not be only be derived for enums",
153 )
154 .to_compile_error()
155 .into()
156 }
157 };
158
159 quote! {
160 #ast
161 }
162 .into()
163}
164
165/// Adds the nesecary fields to an enum such that it implements the
166/// interface needed to be a cw-governance voting module that has an
167/// active check threshold.
168///
169/// For example:
170///
171/// ```
172/// use cw_core_macros::active_query;
173///
174/// #[active_query]
175/// enum QueryMsg {}
176/// ```
177///
178/// Will transform the enum to:
179///
180/// ```
181/// enum QueryMsg {
182/// IsActive {},
183/// }
184/// ```
185///
186/// Note that other derive macro invocations must occur after this
187/// procedural macro as they may depend on the new fields. For
188/// example, the following will fail becase the `Clone` derivation
189/// occurs before the addition of the field.
190///
191/// ```compile_fail
192/// use cw_core_macros::active_query;
193///
194/// #[derive(Clone)]
195/// #[active_query]
196/// #[allow(dead_code)]
197/// enum Test {
198/// Foo,
199/// Bar(u64),
200/// Baz { foo: u64 },
201/// }
202/// ```
203#[proc_macro_attribute]
204pub fn active_query(metadata: TokenStream, input: TokenStream) -> TokenStream {
205 // Make sure that no arguments were passed in.
206 let args = parse_macro_input!(metadata as AttributeArgs);
207 if let Some(first_arg) = args.first() {
208 return syn::Error::new_spanned(first_arg, "token query macro takes no arguments")
209 .to_compile_error()
210 .into();
211 }
212
213 let mut ast: DeriveInput = parse_macro_input!(input);
214 match &mut ast.data {
215 syn::Data::Enum(DataEnum { variants, .. }) => {
216 let info: Variant = syn::parse2(quote! { IsActive {} }).unwrap();
217
218 variants.push(info);
219 }
220 _ => {
221 return syn::Error::new(
222 ast.ident.span(),
223 "token query types can not be only be derived for enums",
224 )
225 .to_compile_error()
226 .into()
227 }
228 };
229
230 quote! {
231 #ast
232 }
233 .into()
234}
235
236/// Adds the nesecary fields to an enum such that it implements the
237/// interface needed to be a cw-governance governance module.
238///
239/// For example:
240///
241/// ```
242/// use cw_core_macros::govmod_query;
243///
244/// #[govmod_query]
245/// enum QueryMsg {}
246/// ```
247///
248/// Will transform the enum to:
249///
250/// ```
251/// enum QueryMsg {
252/// Info {},
253/// }
254/// ```
255///
256/// Note that other derive macro invocations must occur after this
257/// procedural macro as they may depend on the new fields. For
258/// example, the following will fail becase the `Clone` derivation
259/// occurs before the addition of the field.
260///
261/// ```compile_fail
262/// use cw_core_macros::govmod_query;
263///
264/// #[derive(Clone)]
265/// #[govmod_query]
266/// #[allow(dead_code)]
267/// enum Test {
268/// Foo,
269/// Bar(u64),
270/// Baz { foo: u64 },
271/// }
272/// ```
273#[proc_macro_attribute]
274pub fn govmod_query(metadata: TokenStream, input: TokenStream) -> TokenStream {
275 // Make sure that no arguments were passed in.
276 let args = parse_macro_input!(metadata as AttributeArgs);
277 if let Some(first_arg) = args.first() {
278 return syn::Error::new_spanned(first_arg, "govmod query macro takes no arguments")
279 .to_compile_error()
280 .into();
281 }
282
283 let mut ast: DeriveInput = parse_macro_input!(input);
284 match &mut ast.data {
285 syn::Data::Enum(DataEnum { variants, .. }) => {
286 let info: Variant = syn::parse2(quote! { Info {} }).unwrap();
287
288 variants.push(info);
289 }
290 _ => {
291 return syn::Error::new(
292 ast.ident.span(),
293 "govmod query types can not be only be derived for enums",
294 )
295 .to_compile_error()
296 .into()
297 }
298 };
299
300 quote! {
301 #ast
302 }
303 .into()
304}