Repository: CosmWasm/sylvia
Pull request #222 (2023-09-18 15:54:59)

feat: Generate migrate entry point if message defined on contract

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/CosmWasm/sylvia/pull/222?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) Report
> Merging [#222](https://app.codecov.io/gh/CosmWasm/sylvia/pull/222?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) (c55379e) into [main](https://app.codecov.io/gh/CosmWasm/sylvia/commit/d1c0d6e7a00eefaf3cbcd0f141bdd4c174628af1?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) (d1c0d6e) will **decrease** coverage by `0.07%`.
> The diff coverage is `0.00%`.

```diff
@@            Coverage Diff             @@
##             main     #222      +/-   ##
==========================================
- Coverage   87.78%   87.72%   -0.07%     
==========================================
  Files          24       24              
  Lines        1302     1303       +1     
==========================================
  Hits         1143     1143              
- Misses        159      160       +1     
```


| [Files Changed](https://app.codecov.io/gh/CosmWasm/sylvia/pull/222?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) | Coverage Δ | |
|---|---|---|
| [sylvia-derive/src/message.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/222?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhLWRlcml2ZS9zcmMvbWVzc2FnZS5ycw==) | `83.51% <0.00%> (-0.23%)` | :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: > LGTM, but I would like to see tests for that.
> 
> The easiest way to verify that it is working is to add in one of the tests something like:
> 
> ```
> use entry_points::{instantiate, execute, query, migrate, reply};
> ```
> 
> You would do that for a single test that emits entry points. I checked manually they are correctly generated, but adding the verification wouldn't hurt.

Agree, but I think better way is to create `cw_multi_test::ContractWrapper`. This way we will also check if structure of these entry points is correct.

Patch:
diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs
index 9990d57..3bb14c5 100644
--- a/sylvia-derive/src/message.rs
+++ b/sylvia-derive/src/message.rs
@@ -1041,9 +1041,9 @@ impl<'a> GlueMessage<'a> {
 pub struct EntryPoints<'a> {
     name: Type,
     error: Type,
-    reply: Option<Ident>,
     custom: Custom<'a>,
     override_entry_points: OverrideEntryPoints,
+    variants: MsgVariants<'a>,
 }
 
 impl<'a> EntryPoints<'a> {
@@ -1068,19 +1068,16 @@ impl<'a> EntryPoints<'a> {
             .unwrap_or_else(|| parse_quote! { #sylvia ::cw_std::StdError });
 
         let generics: Vec<_> = source.generics.params.iter().collect();
-        let reply = MsgVariants::new(source.as_variants(), &generics)
-            .0
-            .into_iter()
-            .find(|variant| variant.msg_type == MsgType::Reply)
-            .map(|variant| variant.function_name.clone());
+
+        let variants = MsgVariants::new(source.as_variants(), &generics);
         let custom = Custom::new(&source.attrs);
 
         Self {
             name,
             error,
-            reply,
             custom,
             override_entry_points,
+            variants,
         }
     }
 
@@ -1088,14 +1085,19 @@ impl<'a> EntryPoints<'a> {
         let Self {
             name,
             error,
-            reply,
             custom,
             override_entry_points,
+            variants,
         } = self;
         let sylvia = crate_module();
 
         let custom_msg = custom.msg_or_default();
         let custom_query = custom.query_or_default();
+        let reply = variants
+            .0
+            .iter()
+            .find(|variant| variant.msg_type == MsgType::Reply)
+            .map(|variant| variant.function_name.clone());
 
         #[cfg(not(tarpaulin_include))]
         {
@@ -1114,6 +1116,26 @@ impl<'a> EntryPoints<'a> {
                     },
                 );
 
+            let migrate_not_overridden = override_entry_points
+                .get_entry_point(MsgType::Migrate)
+                .is_none();
+            let migrate_msg_defined = variants
+                .0
+                .iter()
+                .any(|variant| variant.msg_type == MsgType::Migrate);
+
+            let migrate = if migrate_not_overridden && migrate_msg_defined {
+                OverrideEntryPoint::emit_default_entry_point(
+                    &custom_msg,
+                    &custom_query,
+                    name,
+                    error,
+                    MsgType::Migrate,
+                )
+            } else {
+                quote! {}
+            };
+
             let reply_ep = override_entry_points
                 .get_entry_point(MsgType::Reply)
                 .map(|_| quote! {})
@@ -1137,6 +1159,8 @@ impl<'a> EntryPoints<'a> {
 
                     #(#entry_points)*
 
+                    #migrate
+
                     #reply_ep
                 }
             }


Test patch:
diff --git a/sylvia/tests/messages_generation.rs b/sylvia/tests/messages_generation.rs
index 7cb34e0..2495fc6 100644
--- a/sylvia/tests/messages_generation.rs
+++ b/sylvia/tests/messages_generation.rs
@@ -46,15 +46,17 @@ mod interface {
 }
 
 mod contract {
-    use cosmwasm_std::{Addr, Response, StdResult};
+    use cosmwasm_std::{Addr, Reply, Response, StdResult};
     use sylvia::contract;
-    use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx};
+    use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx};
+    use sylvia_derive::entry_points;
 
     use crate::{MyQuery, QueryResult};
 
     pub struct Contract {}
 
     #[cfg(not(tarpaulin_include))]
+    #[entry_points]
     #[contract]
     #[allow(dead_code)]
     #[sv::custom(query=MyQuery)]
@@ -100,6 +102,11 @@ mod contract {
         fn argumented_query(&self, _ctx: QueryCtx<MyQuery>, _user: Addr) -> StdResult<QueryResult> {
             Ok(QueryResult {})
         }
+
+        #[msg(reply)]
+        fn my_reply(&self, _ctx: ReplyCtx<MyQuery>, _reply: Reply) -> StdResult<Response> {
+            Ok(Response::new())
+        }
     }
 }
 
@@ -154,3 +161,16 @@ fn contract_messages_constructible() {
         contract::QueryMsg::ArgumentedQuery { .. } => (),
     }
 }
+
+#[test]
+fn entry_points_generation() {
+    use contract::entry_points;
+
+    let _ = cw_multi_test::ContractWrapper::new(
+        entry_points::execute,
+        entry_points::instantiate,
+        entry_points::query,
+    )
+    .with_migrate(entry_points::migrate)
+    .with_reply(entry_points::reply);
+}