Skip to content

Commit 940fb33

Browse files
committed
improve code and add tests
1 parent 908b554 commit 940fb33

File tree

2 files changed

+137
-17
lines changed

2 files changed

+137
-17
lines changed

packages/derive/src/into_event.rs

+131-11
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn scan_to_string_fn(field: &Field) -> Result<Option<proc_macro2::TokenStream>>
2222
if filtered.is_empty() {
2323
Ok(None)
2424
} else {
25-
Ok(Some(filtered[0].tokens.clone()))
25+
Ok(Some(filtered[0].parse_args()?))
2626
}
2727
}
2828

@@ -35,7 +35,7 @@ fn has_use_to_string(field: &Field) -> Result<bool> {
3535
if filtered.clone().any(|a| !a.tokens.is_empty()) {
3636
return Err(Error::new(
3737
field.span(),
38-
"[IntoEvent] attribute `use_to_string` has some value. If you intend to specify the cast function to string, use `to_string_fn` instead.",
38+
"[IntoEvent] An attribute `use_to_string` has some value. If you intend to specify the cast function to string, use `to_string_fn` instead.",
3939
));
4040
}
4141
Ok(filtered.next().is_some())
@@ -88,23 +88,143 @@ fn make_init_from_struct(id: Ident, struct_data: DataStruct) -> Result<proc_macr
8888
Ok(gen)
8989
}
9090

91-
/// derive `IntoEvent` from a derive input. The input needs to be a struct.
92-
pub fn derive_into_event(input: DeriveInput) -> TokenStream {
91+
fn derive_into_event_impl(input: DeriveInput) -> proc_macro2::TokenStream {
9392
match input.data {
94-
syn::Data::Struct(struct_data) => make_init_from_struct(input.ident, struct_data)
95-
.unwrap_or_else(|e| e.to_compile_error())
96-
.into(),
93+
syn::Data::Struct(struct_data) => {
94+
make_init_from_struct(input.ident, struct_data).unwrap_or_else(|e| e.to_compile_error())
95+
}
9796
syn::Data::Enum(enum_data) => Error::new(
9897
enum_data.enum_token.span,
9998
"[IntoEvent] `derive(IntoEvent)` cannot be applied to Enum.",
10099
)
101-
.to_compile_error()
102-
.into(),
100+
.to_compile_error(),
103101
syn::Data::Union(union_data) => Error::new(
104102
union_data.union_token.span,
105103
"[IntoEvent] `derive(IntoEvent)` cannot be applied to Union.",
106104
)
107-
.to_compile_error()
108-
.into(),
105+
.to_compile_error(),
106+
}
107+
}
108+
109+
/// derive `IntoEvent` from a derive input. The input needs to be a struct.
110+
pub fn derive_into_event(input: DeriveInput) -> TokenStream {
111+
derive_into_event_impl(input).into()
112+
}
113+
114+
#[cfg(test)]
115+
mod tests {
116+
use super::*;
117+
use proc_macro2::TokenStream;
118+
use syn::parse_quote;
119+
120+
fn expect_compile_error(ts: TokenStream, msg: &str) {
121+
assert!(
122+
ts.to_string().starts_with("compile_error ! {"),
123+
"Code does not raise compile error: `{}`",
124+
ts
125+
);
126+
127+
assert!(
128+
ts.to_string().contains(msg),
129+
"Error does not have expected message \"{}\": `{}`",
130+
msg,
131+
ts
132+
);
133+
}
134+
135+
#[test]
136+
fn test_doc_example() {
137+
let input: DeriveInput = parse_quote! {
138+
struct StructName {
139+
field_name_1: field_type_1,
140+
#[use_to_string]
141+
field_name_2: field_type_2,
142+
#[to_string_fn(cast_fn_3)]
143+
field_name_3: field_type_3,
144+
}
145+
};
146+
let result_implement = derive_into_event_impl(input);
147+
let expected: TokenStream = parse_quote! {
148+
impl Into<cosmwasm_std::Event> for StructName {
149+
fn into(self) -> cosmwasm_std::Event {
150+
cosmwasm_std::Event::new("struct_name")
151+
.add_attribute(stringify!(field_name_1), self.field_name_1)
152+
.add_attribute(stringify!(field_name_2), self.field_name_2.to_string())
153+
.add_attribute(stringify!(field_name_3), cast_fn_3 (self.field_name_3))
154+
}
155+
}
156+
};
157+
assert_eq!(expected.to_string(), result_implement.to_string())
158+
}
159+
160+
#[test]
161+
fn test_error_multiple_to_string_functions() {
162+
let input: DeriveInput = parse_quote! {
163+
struct StructName {
164+
#[to_string_fn(cast_fn_1)]
165+
#[to_string_fn(cast_fn_1)]
166+
field_name_1: field_type_1,
167+
}
168+
};
169+
let result_implement = derive_into_event_impl(input);
170+
expect_compile_error(
171+
result_implement,
172+
"[IntoEvent] Only one or zero `to_string_fn`",
173+
);
174+
}
175+
176+
#[test]
177+
fn test_error_use_to_string_has_value() {
178+
let input: DeriveInput = parse_quote! {
179+
struct StructName {
180+
#[use_to_string(foo)]
181+
field_name_1: field_type_1,
182+
}
183+
};
184+
let result_implement = derive_into_event_impl(input);
185+
expect_compile_error(
186+
result_implement,
187+
"[IntoEvent] An attribute `use_to_string` has some value",
188+
);
189+
}
190+
191+
#[test]
192+
fn test_error_both_two_attributes_is_used() {
193+
let input: DeriveInput = parse_quote! {
194+
struct StructName {
195+
#[use_to_string]
196+
#[to_string_fn(cast_fn_1)]
197+
field_name_1: field_type_1,
198+
}
199+
};
200+
let result_implement = derive_into_event_impl(input);
201+
expect_compile_error(
202+
result_implement,
203+
"[IntoEvent] Both `use_to_string` and `to_string_fn`",
204+
);
205+
}
206+
207+
#[test]
208+
fn test_error_derive_enum() {
209+
let input: DeriveInput = parse_quote! {
210+
enum Enum {}
211+
};
212+
let result_implement = derive_into_event_impl(input);
213+
expect_compile_error(
214+
result_implement,
215+
"[IntoEvent] `derive(IntoEvent)` cannot be applied to Enum",
216+
);
217+
}
218+
219+
#[test]
220+
fn test_error_derive_union() {
221+
let input: DeriveInput = parse_quote! {
222+
union Union {}
223+
};
224+
let result_implement = derive_into_event_impl(input);
225+
expect_compile_error(
226+
result_implement,
227+
"[IntoEvent] `derive(IntoEvent)` cannot be applied to Union",
228+
);
109229
}
110230
}

packages/derive/src/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ pub fn entry_point(_attr: TokenStream, mut item: TokenStream) -> TokenStream {
109109
/// Output AST:
110110
///
111111
/// ```no_test
112-
/// impl Into<cosmwasm::Event> for `StructName` {
113-
/// fn into(self) -> Event {
114-
/// Event::new("struct_name")
115-
/// .add_attribute("field_name_1", self.field_value_1)
116-
/// .add_attribute("field_name_2", self.field_value_2.to_string())
117-
/// .add_attribute("field_name_3", casting_fn(self.field_value_3))
112+
/// impl Into<cosmwasm_std::Event> for StructName {
113+
/// fn into(self) -> cosmwasm_std::Event {
114+
/// cosmwasm_std::Event::new("struct_name")
115+
/// .add_attribute("field_name_1", self.field_name_1)
116+
/// .add_attribute("field_name_2", self.field_name_2.to_string())
117+
/// .add_attribute("field_name_3", cast_fn_3(self.field_name_3))
118118
/// }
119119
/// }
120120
/// ```

0 commit comments

Comments
 (0)