Repository: CosmWasm/sylvia
Pull request #176 (2023-06-14 09:50:16)

feat: support for custom attribute in messages

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/CosmWasm/sylvia/pull/176?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) Report
> Merging [#176](https://app.codecov.io/gh/CosmWasm/sylvia/pull/176?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) (c9baa6c) into [custom_msg_support](https://app.codecov.io/gh/CosmWasm/sylvia/commit/1d6331a612e60486b2b85e743f83d852d3b1eb40?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) (1d6331a) will **decrease** coverage by `0.25%`.
> The diff coverage is `45.45%`.

```diff
@@                  Coverage Diff                   @@
##           custom_msg_support     #176      +/-   ##
======================================================
- Coverage               81.91%   81.66%   -0.25%     
======================================================
  Files                      36       36              
  Lines                    1780     1789       +9     
======================================================
+ Hits                     1458     1461       +3     
- Misses                    322      328       +6     
```


| [Impacted Files](https://app.codecov.io/gh/CosmWasm/sylvia/pull/176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) | Coverage Δ | |
|---|---|---|
| [sylvia-derive/src/parser.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhLWRlcml2ZS9zcmMvcGFyc2VyLnJz) | `81.57% <ø> (ø)` | |
| [sylvia/tests/custom\_msg.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhL3Rlc3RzL2N1c3RvbV9tc2cucnM=) | `84.61% <0.00%> (-15.39%)` | :arrow_down: |
| [sylvia-derive/src/message.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhLWRlcml2ZS9zcmMvbWVzc2FnZS5ycw==) | `73.94% <55.55%> (-0.59%)` | :arrow_down: |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm)

jawoznia: close #159 


Patch:
diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs
index 517015b..f4b8acc 100644
--- a/sylvia-derive/src/message.rs
+++ b/sylvia-derive/src/message.rs
@@ -894,6 +894,7 @@ impl<'a> GlueMessage<'a> {
                 exec_generic_params,
                 query_generic_params,
                 variant,
+                ..
             } = interface;
 
             let generics = match msg_ty {
@@ -921,9 +922,18 @@ impl<'a> GlueMessage<'a> {
         let interfaces_cnt = interface_names.len();
 
         let dispatch_arms = interfaces.iter().map(|interface| {
-            let ContractMessageAttr { variant, .. } = interface;
+            let ContractMessageAttr {
+                variant,
+                has_custom_msg,
+                ..
+            } = interface;
+
+            match *has_custom_msg&& msg_ty == &MsgType::Exec
+            {
+                true => quote! { #contract_name :: #variant(msg) => Ok( #sylvia ::into_response::IntoResponse::into_response(msg.dispatch(contract, Into::into(ctx))?)?) },
+                false => quote! { #contract_name :: #variant(msg) => msg.dispatch(contract, Into::into(ctx)) }
+            }
 
-            quote! { #contract_name :: #variant(msg) => msg.dispatch(contract, Into::into(ctx)) }
         });
 
         let dispatch_arm = quote! {#contract_name :: #contract (msg) =>msg.dispatch(contract, ctx)};
diff --git a/sylvia-derive/src/parser.rs b/sylvia-derive/src/parser.rs
index edb7c8d..27d6236 100644
--- a/sylvia-derive/src/parser.rs
+++ b/sylvia-derive/src/parser.rs
@@ -181,6 +181,7 @@ pub struct ContractMessageAttr {
     pub exec_generic_params: Vec<Path>,
     pub query_generic_params: Vec<Path>,
     pub variant: Ident,
+    pub has_custom_msg: bool,
 }
 
 #[cfg(not(tarpaulin_include))]
@@ -219,6 +220,7 @@ impl Parse for ContractMessageAttr {
         let generics_open: Option<Token![:]> = content.parse()?;
         let mut exec_generic_params = vec![];
         let mut query_generic_params = vec![];
+        let mut has_custom_msg = false;
 
         if generics_open.is_some() {
             loop {
@@ -242,9 +244,19 @@ impl Parse for ContractMessageAttr {
         }
 
         let _: Token![as] = content.parse()?;
-
         let variant = content.parse()?;
 
+        if content.peek(Token![:]) {
+            let _: Token![:] = content.parse()?;
+            let attr: Ident = content.parse()?;
+            if attr == "custom" {
+                let custom_content;
+                parenthesized!(custom_content in content);
+                let custom = custom_content.parse::<Path>()?;
+                has_custom_msg = custom.is_ident("msg");
+            }
+        }
+
         if !content.is_empty() {
             return Err(Error::new(
                 content.span(),
@@ -257,6 +269,7 @@ impl Parse for ContractMessageAttr {
             exec_generic_params,
             query_generic_params,
             variant,
+            has_custom_msg,
         })
     }
 }


Test patch:
diff --git a/sylvia/tests/custom_msg.rs b/sylvia/tests/custom_msg.rs
index 3eb2a4b..952e255 100644
--- a/sylvia/tests/custom_msg.rs
+++ b/sylvia/tests/custom_msg.rs
@@ -57,8 +57,36 @@ mod some_interface {
     }
 }
 
+mod other_interface {
+    use crate::MyMsg;
+    use cosmwasm_std::{Response, StdError, StdResult};
+    use sylvia::types::ExecCtx;
+    use sylvia::{contract, interface};
+
+    #[interface]
+    pub trait OtherInterface {
+        type Error: From<StdError>;
+
+        #[cfg(not(tarpaulin_include))]
+        #[msg(exec)]
+        fn other_interface_exec(&self, ctx: ExecCtx) -> StdResult<Response>;
+    }
+
+    #[contract(module=super)]
+    #[sv::custom(msg=MyMsg)]
+    impl OtherInterface for crate::MyContract {
+        type Error = StdError;
+
+        #[msg(exec)]
+        fn other_interface_exec(&self, _ctx: ExecCtx) -> StdResult<Response> {
+            Ok(Response::default())
+        }
+    }
+}
+
 #[contract]
 #[messages(some_interface as SomeInterface)]
+#[messages(other_interface as OtherInterface: custom(msg))]
 #[sv::custom(msg=MyMsg, query=MyQuery)]
 impl MyContract {
     #[allow(clippy::new_without_default)]
@@ -93,6 +121,7 @@ mod tests {
     use crate::MyContract;
     use sylvia::multitest::App;
 
+    use crate::other_interface::test_utils::OtherInterface;
     use crate::some_interface::test_utils::SomeInterface;
     use crate::MyMsg;
 
@@ -120,5 +149,12 @@ mod tests {
             .interface_exec()
             .call(owner)
             .unwrap();
+
+        // Other interface messages
+        contract
+            .other_interface_proxy()
+            .other_interface_exec()
+            .call(owner)
+            .unwrap();
     }
 }