@@ -22,7 +22,7 @@ fn scan_to_string_fn(field: &Field) -> Result<Option<proc_macro2::TokenStream>>
22
22
if filtered. is_empty ( ) {
23
23
Ok ( None )
24
24
} else {
25
- Ok ( Some ( filtered[ 0 ] . tokens . clone ( ) ) )
25
+ Ok ( Some ( filtered[ 0 ] . parse_args ( ) ? ) )
26
26
}
27
27
}
28
28
@@ -35,7 +35,7 @@ fn has_use_to_string(field: &Field) -> Result<bool> {
35
35
if filtered. clone ( ) . any ( |a| !a. tokens . is_empty ( ) ) {
36
36
return Err ( Error :: new (
37
37
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." ,
39
39
) ) ;
40
40
}
41
41
Ok ( filtered. next ( ) . is_some ( ) )
@@ -88,23 +88,143 @@ fn make_init_from_struct(id: Ident, struct_data: DataStruct) -> Result<proc_macr
88
88
Ok ( gen)
89
89
}
90
90
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 {
93
92
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
+ }
97
96
syn:: Data :: Enum ( enum_data) => Error :: new (
98
97
enum_data. enum_token . span ,
99
98
"[IntoEvent] `derive(IntoEvent)` cannot be applied to Enum." ,
100
99
)
101
- . to_compile_error ( )
102
- . into ( ) ,
100
+ . to_compile_error ( ) ,
103
101
syn:: Data :: Union ( union_data) => Error :: new (
104
102
union_data. union_token . span ,
105
103
"[IntoEvent] `derive(IntoEvent)` cannot be applied to Union." ,
106
104
)
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
+ ) ;
109
229
}
110
230
}
0 commit comments