Skip to content

Commit 66028ce

Browse files
authored
Merge pull request #2070 from CosmWasm/aw/cosmwasm-schema-configurable
Make crate for `cosmwasm-schema` configurable
2 parents 763d852 + 77e2134 commit 66028ce

File tree

5 files changed

+303
-72
lines changed

5 files changed

+303
-72
lines changed

packages/schema-derive/src/cw_serde.rs

Lines changed: 120 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,59 @@
11
use crate::error::bail;
22
use quote::{quote, ToTokens};
3-
use syn::DeriveInput;
3+
use syn::{
4+
parse::{Parse, ParseStream},
5+
parse_quote,
6+
punctuated::Punctuated,
7+
DeriveInput, MetaNameValue, Token,
8+
};
9+
10+
pub struct Options {
11+
crate_path: syn::Path,
12+
}
13+
14+
impl Default for Options {
15+
fn default() -> Self {
16+
Self {
17+
crate_path: parse_quote!(::cosmwasm_schema),
18+
}
19+
}
20+
}
21+
22+
impl Parse for Options {
23+
fn parse(input: ParseStream) -> syn::Result<Self> {
24+
let mut acc = Self::default();
25+
let params = Punctuated::<MetaNameValue, Token![,]>::parse_terminated(input)?;
26+
for param in params {
27+
if param.path.is_ident("crate") {
28+
let path_as_string: syn::LitStr = syn::parse2(param.value.to_token_stream())?;
29+
acc.crate_path = path_as_string.parse()?
30+
} else {
31+
bail!(param, "unknown option");
32+
}
33+
}
34+
35+
Ok(acc)
36+
}
37+
}
38+
39+
pub fn cw_serde_impl(options: Options, input: DeriveInput) -> syn::Result<DeriveInput> {
40+
let crate_path = &options.crate_path;
41+
let crate_path_displayable = crate_path.to_token_stream();
42+
let serde_path = format!("{crate_path_displayable}::serde");
43+
let schemars_path = format!("{crate_path_displayable}::schemars");
444

5-
pub fn cw_serde_impl(input: DeriveInput) -> syn::Result<DeriveInput> {
645
let mut stream = quote! {
746
#[derive(
8-
::cosmwasm_schema::serde::Serialize,
9-
::cosmwasm_schema::serde::Deserialize,
47+
#crate_path::serde::Serialize,
48+
#crate_path::serde::Deserialize,
1049
::std::clone::Clone,
1150
::std::fmt::Debug,
1251
::std::cmp::PartialEq,
13-
::cosmwasm_schema::schemars::JsonSchema
52+
#crate_path::schemars::JsonSchema
1453
)]
1554
#[allow(clippy::derive_partial_eq_without_eq)] // Allow users of `#[cw_serde]` to not implement Eq without clippy complaining
16-
#[serde(deny_unknown_fields, crate = "::cosmwasm_schema::serde")]
17-
#[schemars(crate = "::cosmwasm_schema::schemars")]
55+
#[serde(deny_unknown_fields, crate = #serde_path)]
56+
#[schemars(crate = #schemars_path)]
1857
};
1958

2059
match input.data {
@@ -35,13 +74,52 @@ mod tests {
3574
use syn::parse_quote;
3675

3776
#[test]
38-
fn structs() {
39-
let expanded = cw_serde_impl(parse_quote! {
77+
fn crate_rename() {
78+
let expanded = cw_serde_impl(
79+
Options {
80+
crate_path: parse_quote!(::my_crate::cw_schema),
81+
},
82+
parse_quote! {
83+
pub struct InstantiateMsg {
84+
pub verifier: String,
85+
pub beneficiary: String,
86+
}
87+
},
88+
)
89+
.unwrap();
90+
91+
let expected = parse_quote! {
92+
#[derive(
93+
::my_crate::cw_schema::serde::Serialize,
94+
::my_crate::cw_schema::serde::Deserialize,
95+
::std::clone::Clone,
96+
::std::fmt::Debug,
97+
::std::cmp::PartialEq,
98+
::my_crate::cw_schema::schemars::JsonSchema
99+
)]
100+
#[allow(clippy::derive_partial_eq_without_eq)]
101+
#[serde(deny_unknown_fields, crate = ":: my_crate :: cw_schema::serde")]
102+
#[schemars(crate = ":: my_crate :: cw_schema::schemars")]
40103
pub struct InstantiateMsg {
41104
pub verifier: String,
42105
pub beneficiary: String,
43106
}
44-
})
107+
};
108+
109+
assert_eq!(expanded, expected);
110+
}
111+
112+
#[test]
113+
fn structs() {
114+
let expanded = cw_serde_impl(
115+
Options::default(),
116+
parse_quote! {
117+
pub struct InstantiateMsg {
118+
pub verifier: String,
119+
pub beneficiary: String,
120+
}
121+
},
122+
)
45123
.unwrap();
46124

47125
let expected = parse_quote! {
@@ -54,8 +132,8 @@ mod tests {
54132
::cosmwasm_schema::schemars::JsonSchema
55133
)]
56134
#[allow(clippy::derive_partial_eq_without_eq)]
57-
#[serde(deny_unknown_fields, crate = "::cosmwasm_schema::serde")]
58-
#[schemars(crate = "::cosmwasm_schema::schemars")]
135+
#[serde(deny_unknown_fields, crate = ":: cosmwasm_schema::serde")]
136+
#[schemars(crate = ":: cosmwasm_schema::schemars")]
59137
pub struct InstantiateMsg {
60138
pub verifier: String,
61139
pub beneficiary: String,
@@ -67,9 +145,12 @@ mod tests {
67145

68146
#[test]
69147
fn empty_struct() {
70-
let expanded = cw_serde_impl(parse_quote! {
71-
pub struct InstantiateMsg {}
72-
})
148+
let expanded = cw_serde_impl(
149+
Options::default(),
150+
parse_quote! {
151+
pub struct InstantiateMsg {}
152+
},
153+
)
73154
.unwrap();
74155

75156
let expected = parse_quote! {
@@ -82,8 +163,8 @@ mod tests {
82163
::cosmwasm_schema::schemars::JsonSchema
83164
)]
84165
#[allow(clippy::derive_partial_eq_without_eq)]
85-
#[serde(deny_unknown_fields, crate = "::cosmwasm_schema::serde")]
86-
#[schemars(crate = "::cosmwasm_schema::schemars")]
166+
#[serde(deny_unknown_fields, crate = ":: cosmwasm_schema::serde")]
167+
#[schemars(crate = ":: cosmwasm_schema::schemars")]
87168
pub struct InstantiateMsg {}
88169
};
89170

@@ -92,14 +173,17 @@ mod tests {
92173

93174
#[test]
94175
fn enums() {
95-
let expanded = cw_serde_impl(parse_quote! {
96-
pub enum SudoMsg {
97-
StealFunds {
98-
recipient: String,
99-
amount: Vec<Coin>,
100-
},
101-
}
102-
})
176+
let expanded = cw_serde_impl(
177+
Options::default(),
178+
parse_quote! {
179+
pub enum SudoMsg {
180+
StealFunds {
181+
recipient: String,
182+
amount: Vec<Coin>,
183+
},
184+
}
185+
},
186+
)
103187
.unwrap();
104188

105189
let expected = parse_quote! {
@@ -112,8 +196,8 @@ mod tests {
112196
::cosmwasm_schema::schemars::JsonSchema
113197
)]
114198
#[allow(clippy::derive_partial_eq_without_eq)]
115-
#[serde(deny_unknown_fields, crate = "::cosmwasm_schema::serde")]
116-
#[schemars(crate = "::cosmwasm_schema::schemars")]
199+
#[serde(deny_unknown_fields, crate = ":: cosmwasm_schema::serde")]
200+
#[schemars(crate = ":: cosmwasm_schema::schemars")]
117201
#[serde(rename_all = "snake_case")]
118202
pub enum SudoMsg {
119203
StealFunds {
@@ -129,12 +213,15 @@ mod tests {
129213
#[test]
130214
#[should_panic(expected = "unions are not supported")]
131215
fn unions() {
132-
cw_serde_impl(parse_quote! {
133-
pub union SudoMsg {
134-
x: u32,
135-
y: u32,
136-
}
137-
})
216+
cw_serde_impl(
217+
Options::default(),
218+
parse_quote! {
219+
pub union SudoMsg {
220+
x: u32,
221+
y: u32,
222+
}
223+
},
224+
)
138225
.unwrap();
139226
}
140227
}

packages/schema-derive/src/generate_api.rs

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use syn::{
1010

1111
pub fn write_api_impl(input: Options) -> Block {
1212
let api_object = generate_api_impl(&input);
13+
let crate_name = input.crate_name;
1314
let name = input.name;
1415

1516
parse_quote! {
@@ -19,7 +20,7 @@ pub fn write_api_impl(input: Options) -> Block {
1920
use ::std::env;
2021
use ::std::fs::{create_dir_all, write};
2122

22-
use ::cosmwasm_schema::{remove_schemas, Api, QueryResponses};
23+
use #crate_name::{remove_schemas, Api, QueryResponses};
2324

2425
let mut out_dir = env::current_dir().unwrap();
2526
out_dir.push("schema");
@@ -50,6 +51,7 @@ pub fn write_api_impl(input: Options) -> Block {
5051

5152
pub fn generate_api_impl(input: &Options) -> ExprStruct {
5253
let Options {
54+
crate_name,
5355
name,
5456
version,
5557
instantiate,
@@ -61,7 +63,7 @@ pub fn generate_api_impl(input: &Options) -> ExprStruct {
6163
} = input;
6264

6365
parse_quote! {
64-
::cosmwasm_schema::Api {
66+
#crate_name::Api {
6567
contract_name: #name.to_string(),
6668
contract_version: #version.to_string(),
6769
instantiate: #instantiate,
@@ -121,6 +123,7 @@ impl Parse for Pair {
121123

122124
#[derive(Debug)]
123125
pub struct Options {
126+
crate_name: TokenStream,
124127
name: TokenStream,
125128
version: TokenStream,
126129
instantiate: TokenStream,
@@ -136,6 +139,13 @@ impl Parse for Options {
136139
let pairs = input.parse_terminated(Pair::parse, Token![,])?;
137140
let mut map: BTreeMap<_, _> = pairs.into_iter().map(|p| p.0).collect();
138141

142+
let crate_name = if let Some(crate_name_override) = map.remove(&parse_quote!(crate_name)) {
143+
let crate_name_override = crate_name_override.get_type()?;
144+
quote! { #crate_name_override }
145+
} else {
146+
quote! { ::cosmwasm_schema }
147+
};
148+
139149
let name = if let Some(name_override) = map.remove(&parse_quote!(name)) {
140150
let name_override = name_override.get_str()?;
141151
quote! {
@@ -161,15 +171,15 @@ impl Parse for Options {
161171
let instantiate = match map.remove(&parse_quote!(instantiate)) {
162172
Some(ty) => {
163173
let ty = ty.get_type()?;
164-
quote! {Some(::cosmwasm_schema::schema_for!(#ty))}
174+
quote! {Some(#crate_name::schema_for!(#ty))}
165175
}
166176
None => quote! { None },
167177
};
168178

169179
let execute = match map.remove(&parse_quote!(execute)) {
170180
Some(ty) => {
171181
let ty = ty.get_type()?;
172-
quote! {Some(::cosmwasm_schema::schema_for!(#ty))}
182+
quote! {Some(#crate_name::schema_for!(#ty))}
173183
}
174184
None => quote! { None },
175185
};
@@ -178,8 +188,8 @@ impl Parse for Options {
178188
Some(ty) => {
179189
let ty = ty.get_type()?;
180190
(
181-
quote! {Some(::cosmwasm_schema::schema_for!(#ty))},
182-
quote! { Some(<#ty as ::cosmwasm_schema::QueryResponses>::response_schemas().unwrap()) },
191+
quote! {Some(#crate_name::schema_for!(#ty))},
192+
quote! { Some(<#ty as #crate_name::QueryResponses>::response_schemas().unwrap()) },
183193
)
184194
}
185195
None => (quote! { None }, quote! { None }),
@@ -188,15 +198,15 @@ impl Parse for Options {
188198
let migrate = match map.remove(&parse_quote!(migrate)) {
189199
Some(ty) => {
190200
let ty = ty.get_type()?;
191-
quote! {Some(::cosmwasm_schema::schema_for!(#ty))}
201+
quote! {Some(#crate_name::schema_for!(#ty))}
192202
}
193203
None => quote! { None },
194204
};
195205

196206
let sudo = match map.remove(&parse_quote!(sudo)) {
197207
Some(ty) => {
198208
let ty = ty.get_type()?;
199-
quote! {Some(::cosmwasm_schema::schema_for!(#ty))}
209+
quote! {Some(#crate_name::schema_for!(#ty))}
200210
}
201211
None => quote! { None },
202212
};
@@ -206,6 +216,7 @@ impl Parse for Options {
206216
}
207217

208218
Ok(Self {
219+
crate_name,
209220
name,
210221
version,
211222
instantiate,
@@ -222,6 +233,32 @@ impl Parse for Options {
222233
mod tests {
223234
use super::*;
224235

236+
#[test]
237+
fn crate_rename() {
238+
assert_eq!(
239+
generate_api_impl(&parse_quote! {
240+
crate_name: ::my_crate::cw_schema,
241+
instantiate: InstantiateMsg,
242+
execute: ExecuteMsg,
243+
query: QueryMsg,
244+
migrate: MigrateMsg,
245+
sudo: SudoMsg,
246+
}),
247+
parse_quote! {
248+
::my_crate::cw_schema::Api {
249+
contract_name: ::std::env!("CARGO_PKG_NAME").to_string(),
250+
contract_version: ::std::env!("CARGO_PKG_VERSION").to_string(),
251+
instantiate: Some(::my_crate::cw_schema::schema_for!(InstantiateMsg)),
252+
execute: Some(::my_crate::cw_schema::schema_for!(ExecuteMsg)),
253+
query: Some(::my_crate::cw_schema::schema_for!(QueryMsg)),
254+
migrate: Some(::my_crate::cw_schema::schema_for!(MigrateMsg)),
255+
sudo: Some(::my_crate::cw_schema::schema_for!(SudoMsg)),
256+
responses: Some(<QueryMsg as ::my_crate::cw_schema::QueryResponses>::response_schemas().unwrap()),
257+
}
258+
}
259+
);
260+
}
261+
225262
#[test]
226263
fn api_object_minimal() {
227264
assert_eq!(

packages/schema-derive/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,14 @@ pub fn generate_api(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3838
fallible_macro! {
3939
#[proc_macro_attribute]
4040
pub fn cw_serde(
41-
_attr: proc_macro::TokenStream,
41+
attr: proc_macro::TokenStream,
4242
input: proc_macro::TokenStream,
4343
) -> syn::Result<proc_macro::TokenStream> {
44+
let options = syn::parse(attr)?;
4445
let input = syn::parse(input)?;
45-
let expanded = cw_serde::cw_serde_impl(input)?;
46+
47+
let expanded = cw_serde::cw_serde_impl(options, input)?;
48+
4649
Ok(expanded.into_token_stream().into())
4750
}
4851
}

0 commit comments

Comments
 (0)