@@ -4,7 +4,7 @@ use syn::spanned::Spanned;
4
4
mod parse_signatures;
5
5
6
6
use super :: into_ident:: IntoIdent ;
7
- use parse_signatures:: PubInterfaceSignatures ;
7
+ use parse_signatures:: { ParseError , PubInterfaceItemType , PubInterfaceSignatures } ;
8
8
9
9
const DEFAULT_IMPLEMENTOR_NAME : & str = "Contract" ;
10
10
const CONSTRUCTOR_NAME : & str = "construct" ;
@@ -15,9 +15,15 @@ const FUNCTION_NAME_FUNC_NAME: &str = "function_name";
15
15
const ARGS_FUNC_NAME : & str = "args" ;
16
16
const CALL_FUNC_NAME : & str = "call" ;
17
17
18
- pub ( crate ) fn impl_pub_interface ( item : proc_macro2:: TokenStream ) -> proc_macro2:: TokenStream {
18
+ pub ( crate ) fn impl_pub_interface (
19
+ attr : proc_macro2:: TokenStream ,
20
+ item : proc_macro2:: TokenStream ,
21
+ ) -> proc_macro2:: TokenStream {
19
22
let cloned_item = item. clone ( ) ;
20
- let pub_interface_signatures = parse_macro_input2 ! ( cloned_item as PubInterfaceSignatures ) ;
23
+ let mut pub_interface_signatures = parse_macro_input2 ! ( cloned_item as PubInterfaceSignatures ) ;
24
+ if let Err ( error) = apply_macro_attr ( attr, & mut pub_interface_signatures) {
25
+ return error. to_compile_error ( ) ;
26
+ }
21
27
22
28
let deploy_func_name = DEPLOY_FUNC_NAME . into_ident ( ) ;
23
29
let dispatch_func_name = DISPATCH_FUNC_NAME . into_ident ( ) ;
@@ -44,6 +50,48 @@ pub(crate) fn impl_pub_interface(item: proc_macro2::TokenStream) -> proc_macro2:
44
50
}
45
51
}
46
52
53
+ /// Parse the arguments to the macro and apply them to the `PubInterfaceSignatures`
54
+ ///
55
+ /// The arguments to the macro are the parts written between parenthesis in the macro invocation.
56
+ ///
57
+ /// # Examples:
58
+ ///
59
+ /// (This never actually gets compiled for some reason. You can try doing
60
+ /// `rustdoc --test src/lib.rs` but that generated compilation errors.
61
+ /// Probably because this is a pro-macro crate.)
62
+ ///
63
+ /// ```
64
+ /// # use eng_wasm_derive::pub_interface;
65
+ ///
66
+ /// #[pub_interface(MyContract)]
67
+ /// trait ContractInterface {
68
+ /// fn foo();
69
+ /// }
70
+ ///
71
+ /// struct MyContract;
72
+ ///
73
+ /// impl ContractInterface for MyContract {
74
+ /// fn foo() {}
75
+ /// }
76
+ /// ```
77
+ fn apply_macro_attr (
78
+ attr : proc_macro2:: TokenStream ,
79
+ pub_interface_signatures : & mut PubInterfaceSignatures ,
80
+ ) -> syn:: Result < ( ) > {
81
+ match pub_interface_signatures. item_type {
82
+ PubInterfaceItemType :: ItemTrait => {
83
+ let implementor: syn:: Type = syn:: parse2 ( attr) ?;
84
+ pub_interface_signatures. implementor = implementor;
85
+ Ok ( ( ) )
86
+ }
87
+ PubInterfaceItemType :: ItemImpl if !attr. is_empty ( ) => Err ( syn:: Error :: new_spanned (
88
+ attr,
89
+ ParseError :: CustomImplementorOnImpl ,
90
+ ) ) ,
91
+ _ => Ok ( ( ) ) ,
92
+ }
93
+ }
94
+
47
95
fn generate_eng_wasm_aux_functions (
48
96
function_name_func_name : & syn:: Ident ,
49
97
args_func_name : & syn:: Ident ,
@@ -250,6 +298,88 @@ fn generate_dispatch_function(
250
298
mod tests {
251
299
use super :: * ;
252
300
301
+ #[ test]
302
+ fn apply_macro_attr_works_on_trait ( ) {
303
+ let attr_tokens = quote ! ( Bar ) ;
304
+
305
+ let mut pub_interface_signatures = PubInterfaceSignatures {
306
+ signatures : vec ! [ ] ,
307
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
308
+ item_type : PubInterfaceItemType :: ItemTrait ,
309
+ } ;
310
+
311
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap ( ) ;
312
+
313
+ assert_eq ! (
314
+ syn:: parse2:: <syn:: Type >( attr_tokens) . unwrap( ) ,
315
+ pub_interface_signatures. implementor
316
+ ) ;
317
+ }
318
+
319
+ #[ test]
320
+ fn apply_macro_attr_with_bad_input_fails_on_trait ( ) {
321
+ let attr_tokens = quote ! ( this is not a valid type ) ;
322
+
323
+ let mut pub_interface_signatures = PubInterfaceSignatures {
324
+ signatures : vec ! [ ] ,
325
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
326
+ item_type : PubInterfaceItemType :: ItemTrait ,
327
+ } ;
328
+
329
+ let error =
330
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap_err ( ) ;
331
+
332
+ assert_eq ! ( error. to_string( ) , "unexpected token" ) ;
333
+ // Check that the implementor did not change
334
+ assert_eq ! (
335
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
336
+ pub_interface_signatures. implementor
337
+ ) ;
338
+ }
339
+
340
+ #[ test]
341
+ fn apply_macro_attr_with_empty_input_works_on_impl ( ) {
342
+ let attr_tokens = quote ! ( ) ; // This is empty
343
+
344
+ let mut pub_interface_signatures = PubInterfaceSignatures {
345
+ signatures : vec ! [ ] ,
346
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
347
+ item_type : PubInterfaceItemType :: ItemImpl ,
348
+ } ;
349
+
350
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap ( ) ;
351
+
352
+ // Check that the implementor did not change
353
+ assert_eq ! (
354
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
355
+ pub_interface_signatures. implementor
356
+ ) ;
357
+ }
358
+
359
+ #[ test]
360
+ fn apply_macro_attr_fails_on_impl ( ) {
361
+ let attr_tokens = quote ! ( Bar ) ;
362
+
363
+ let mut pub_interface_signatures = PubInterfaceSignatures {
364
+ signatures : vec ! [ ] ,
365
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
366
+ item_type : PubInterfaceItemType :: ItemImpl ,
367
+ } ;
368
+
369
+ let error =
370
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap_err ( ) ;
371
+
372
+ assert_eq ! (
373
+ error. to_string( ) ,
374
+ ParseError :: CustomImplementorOnImpl . to_string( )
375
+ ) ;
376
+ // Check that the implementor did not change
377
+ assert_eq ! (
378
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
379
+ pub_interface_signatures. implementor
380
+ ) ;
381
+ }
382
+
253
383
#[ test]
254
384
fn deploy_generation ( ) -> syn:: Result < ( ) > {
255
385
let input = quote ! (
0 commit comments