@@ -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,51 @@ 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
+ if attr. is_empty ( ) {
82
+ return Ok ( ( ) ) ;
83
+ }
84
+
85
+ match pub_interface_signatures. item_type {
86
+ PubInterfaceItemType :: ItemTrait => {
87
+ let implementor: syn:: Type = syn:: parse2 ( attr) ?;
88
+ pub_interface_signatures. implementor = implementor;
89
+ Ok ( ( ) )
90
+ }
91
+ PubInterfaceItemType :: ItemImpl => Err ( syn:: Error :: new_spanned (
92
+ attr,
93
+ ParseError :: CustomImplementorOnImpl ,
94
+ ) ) ,
95
+ }
96
+ }
97
+
47
98
fn generate_eng_wasm_aux_functions (
48
99
function_name_func_name : & syn:: Ident ,
49
100
args_func_name : & syn:: Ident ,
@@ -250,6 +301,107 @@ fn generate_dispatch_function(
250
301
mod tests {
251
302
use super :: * ;
252
303
304
+ #[ test]
305
+ fn apply_macro_attr_works_on_trait ( ) {
306
+ let attr_tokens = quote ! ( Bar ) ;
307
+
308
+ let mut pub_interface_signatures = PubInterfaceSignatures {
309
+ signatures : vec ! [ ] ,
310
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
311
+ item_type : PubInterfaceItemType :: ItemTrait ,
312
+ } ;
313
+
314
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap ( ) ;
315
+
316
+ assert_eq ! (
317
+ syn:: parse2:: <syn:: Type >( attr_tokens) . unwrap( ) ,
318
+ pub_interface_signatures. implementor
319
+ ) ;
320
+ }
321
+
322
+ #[ test]
323
+ fn apply_macro_attr_with_empty_input_works_on_trait ( ) {
324
+ let attr_tokens = quote ! ( ) ; // This is empty
325
+
326
+ let mut pub_interface_signatures = PubInterfaceSignatures {
327
+ signatures : vec ! [ ] ,
328
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
329
+ item_type : PubInterfaceItemType :: ItemTrait ,
330
+ } ;
331
+
332
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap ( ) ;
333
+
334
+ // Check that the implementor did not change
335
+ assert_eq ! (
336
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
337
+ pub_interface_signatures. implementor
338
+ ) ;
339
+ }
340
+
341
+ #[ test]
342
+ fn apply_macro_attr_with_bad_input_fails_on_trait ( ) {
343
+ let attr_tokens = quote ! ( this is not a valid type ) ;
344
+
345
+ let mut pub_interface_signatures = PubInterfaceSignatures {
346
+ signatures : vec ! [ ] ,
347
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
348
+ item_type : PubInterfaceItemType :: ItemTrait ,
349
+ } ;
350
+
351
+ let error =
352
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap_err ( ) ;
353
+
354
+ assert_eq ! ( error. to_string( ) , "unexpected token" ) ;
355
+ // Check that the implementor did not change
356
+ assert_eq ! (
357
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
358
+ pub_interface_signatures. implementor
359
+ ) ;
360
+ }
361
+
362
+ #[ test]
363
+ fn apply_macro_attr_with_empty_input_works_on_impl ( ) {
364
+ let attr_tokens = quote ! ( ) ; // This is empty
365
+
366
+ let mut pub_interface_signatures = PubInterfaceSignatures {
367
+ signatures : vec ! [ ] ,
368
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
369
+ item_type : PubInterfaceItemType :: ItemImpl ,
370
+ } ;
371
+
372
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap ( ) ;
373
+
374
+ // Check that the implementor did not change
375
+ assert_eq ! (
376
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
377
+ pub_interface_signatures. implementor
378
+ ) ;
379
+ }
380
+
381
+ #[ test]
382
+ fn apply_macro_attr_fails_on_impl ( ) {
383
+ let attr_tokens = quote ! ( Bar ) ;
384
+
385
+ let mut pub_interface_signatures = PubInterfaceSignatures {
386
+ signatures : vec ! [ ] ,
387
+ implementor : syn:: parse2 ( quote ! ( Foo ) ) . unwrap ( ) ,
388
+ item_type : PubInterfaceItemType :: ItemImpl ,
389
+ } ;
390
+
391
+ let error =
392
+ apply_macro_attr ( attr_tokens. clone ( ) , & mut pub_interface_signatures) . unwrap_err ( ) ;
393
+
394
+ assert_eq ! (
395
+ error. to_string( ) ,
396
+ ParseError :: CustomImplementorOnImpl . to_string( )
397
+ ) ;
398
+ // Check that the implementor did not change
399
+ assert_eq ! (
400
+ syn:: parse2:: <syn:: Type >( quote!( Foo ) ) . unwrap( ) ,
401
+ pub_interface_signatures. implementor
402
+ ) ;
403
+ }
404
+
253
405
#[ test]
254
406
fn deploy_generation ( ) -> syn:: Result < ( ) > {
255
407
let input = quote ! (
0 commit comments