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}