Repository: CosmWasm/sylvia
Pull request #41 (2022-09-09 13:37:36)

Rename msgs and remove duplication


Patch:
diff --git a/contracts/cw1-whitelist/src/contract.rs b/contracts/cw1-whitelist/src/contract.rs
index e37108e..4d0ed84 100644
--- a/contracts/cw1-whitelist/src/contract.rs
+++ b/contracts/cw1-whitelist/src/contract.rs
@@ -253,7 +253,7 @@ mod tests {
             )
             .unwrap();
 
-        let freeze = ImplExecMsg::Freeze {};
+        let freeze = ExecMsg::Freeze {};
         let msgs = vec![
             BankMsg::Send {
                 to_address: bob.to_string(),
@@ -354,15 +354,18 @@ mod tests {
     mod msgs {
         use cosmwasm_std::{from_binary, from_slice, to_binary, BankMsg};
 
-        use crate::contract::{ExecMsg, ImplExecMsg, ImplQueryMsg, QueryMsg};
+        use crate::contract::{ContractExecMsg, ContractQueryMsg, ExecMsg, QueryMsg};
 
         #[test]
         fn freeze() {
-            let original = ImplExecMsg::Freeze {};
+            let original = ExecMsg::Freeze {};
             let serialized = to_binary(&original).unwrap();
             let deserialized = from_binary(&serialized).unwrap();
 
-            assert_eq!(ExecMsg::Cw1WhitelistContract(original), deserialized);
+            assert_eq!(
+                ContractExecMsg::Cw1WhitelistContract(original),
+                deserialized
+            );
 
             let json = br#"{
                 "freeze": {}
@@ -370,20 +373,23 @@ mod tests {
             let deserialized = from_slice(json).unwrap();
 
             assert_eq!(
-                ExecMsg::Cw1WhitelistContract(ImplExecMsg::Freeze {}),
+                ContractExecMsg::Cw1WhitelistContract(ExecMsg::Freeze {}),
                 deserialized
             );
         }
 
         #[test]
         fn update_admins() {
-            let original = ImplExecMsg::UpdateAdmins {
+            let original = ExecMsg::UpdateAdmins {
                 admins: vec!["admin1".to_owned(), "admin2".to_owned()],
             };
             let serialized = to_binary(&original).unwrap();
             let deserialized = from_binary(&serialized).unwrap();
 
-            assert_eq!(ExecMsg::Cw1WhitelistContract(original), deserialized);
+            assert_eq!(
+                ContractExecMsg::Cw1WhitelistContract(original),
+                deserialized
+            );
 
             let json = br#"{
                 "update_admins": {
@@ -393,7 +399,7 @@ mod tests {
             let deserialized = from_slice(json).unwrap();
 
             assert_eq!(
-                ExecMsg::Cw1WhitelistContract(ImplExecMsg::UpdateAdmins {
+                ContractExecMsg::Cw1WhitelistContract(ExecMsg::UpdateAdmins {
                     admins: vec!["admin1".to_owned(), "admin3".to_owned()]
                 }),
                 deserialized
@@ -402,11 +408,14 @@ mod tests {
 
         #[test]
         fn admin_list() {
-            let original = ImplQueryMsg::AdminList {};
+            let original = QueryMsg::AdminList {};
             let serialized = to_binary(&original).unwrap();
             let deserialized = from_binary(&serialized).unwrap();
 
-            assert_eq!(QueryMsg::Cw1WhitelistContract(original), deserialized);
+            assert_eq!(
+                ContractQueryMsg::Cw1WhitelistContract(original),
+                deserialized
+            );
 
             let json = br#"{
                 "admin_list": {}
@@ -414,7 +423,7 @@ mod tests {
             let deserialized = from_slice(json).unwrap();
 
             assert_eq!(
-                QueryMsg::Cw1WhitelistContract(ImplQueryMsg::AdminList {}),
+                ContractQueryMsg::Cw1WhitelistContract(QueryMsg::AdminList {}),
                 deserialized
             );
         }
@@ -430,7 +439,7 @@ mod tests {
             };
             let serialized = to_binary(&original).unwrap();
             let deserialized = from_binary(&serialized).unwrap();
-            assert_eq!(ExecMsg::Cw1(original), deserialized);
+            assert_eq!(ContractExecMsg::Cw1(original), deserialized);
         }
 
         #[test]
@@ -445,7 +454,7 @@ mod tests {
             };
             let serialized = to_binary(&original).unwrap();
             let deserialized = from_binary(&serialized).unwrap();
-            assert_eq!(QueryMsg::Cw1(original), deserialized);
+            assert_eq!(ContractQueryMsg::Cw1(original), deserialized);
         }
     }
 }
diff --git a/contracts/cw1-whitelist/src/lib.rs b/contracts/cw1-whitelist/src/lib.rs
index 74803fe..6d26f03 100644
--- a/contracts/cw1-whitelist/src/lib.rs
+++ b/contracts/cw1-whitelist/src/lib.rs
@@ -11,7 +11,9 @@ mod entry_points {
         entry_point, from_slice, Binary, Deps, DepsMut, Env, MessageInfo, Response,
     };
 
-    use crate::contract::{Cw1WhitelistContract, ExecMsg, InstantiateMsg, QueryMsg};
+    use crate::contract::{
+        ContractExecMsg, ContractQueryMsg, Cw1WhitelistContract, InstantiateMsg,
+    };
     use crate::error::ContractError;
 
     const CONTRACT: Cw1WhitelistContract = Cw1WhitelistContract::new();
@@ -33,12 +35,12 @@ mod entry_points {
         info: MessageInfo,
         msg: Binary,
     ) -> Result<Response, ContractError> {
-        from_slice::<ExecMsg>(&msg)?.dispatch(&CONTRACT, (deps, env, info))
+        from_slice::<ContractExecMsg>(&msg)?.dispatch(&CONTRACT, (deps, env, info))
     }
 
     #[entry_point]
     pub fn query(deps: Deps, env: Env, msg: Binary) -> Result<Binary, ContractError> {
-        from_slice::<QueryMsg>(&msg)?.dispatch(&CONTRACT, (deps, env))
+        from_slice::<ContractQueryMsg>(&msg)?.dispatch(&CONTRACT, (deps, env))
     }
 }
 
diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs
index d4417e6..c19c385 100644
--- a/sylvia-derive/src/input.rs
+++ b/sylvia-derive/src/input.rs
@@ -3,7 +3,7 @@ use proc_macro_error::emit_error;
 use quote::quote;
 use syn::{GenericParam, Ident, ItemImpl, ItemTrait, TraitItem};
 
-use crate::message::{EnumMessage, GlueMessage, ImplEnumMessage, StructMessage};
+use crate::message::{ContractEnumMessage, EnumMessage, GlueMessage, StructMessage};
 use crate::parser::{ContractArgs, InterfaceArgs, MsgType};
 
 /// Preprocessed `interface` macro input
@@ -112,14 +112,10 @@ impl<'a> ImplInput<'a> {
 
     fn emit_messages(&self) -> TokenStream {
         let instantiate = self.emit_struct_msg(MsgType::Instantiate);
-        let exec_impl = self.emit_enum_msg(
-            &Ident::new("ImplExecMsg", Span::mixed_site()),
-            MsgType::Exec,
-        );
-        let query_impl = self.emit_enum_msg(
-            &Ident::new("ImplQueryMsg", Span::mixed_site()),
-            MsgType::Query,
-        );
+        let exec_impl =
+            self.emit_enum_msg(&Ident::new("ExecMsg", Span::mixed_site()), MsgType::Exec);
+        let query_impl =
+            self.emit_enum_msg(&Ident::new("QueryMsg", Span::mixed_site()), MsgType::Query);
         let exec = self.emit_glue_msg(&Ident::new("ExecMsg", Span::mixed_site()), MsgType::Exec);
         let query = self.emit_glue_msg(&Ident::new("QueryMsg", Span::mixed_site()), MsgType::Query);
 
@@ -141,7 +137,7 @@ impl<'a> ImplInput<'a> {
     }
 
     fn emit_enum_msg(&self, name: &Ident, msg_ty: MsgType) -> TokenStream {
-        ImplEnumMessage::new(name, self.item, msg_ty, &self.generics, self.attributes).emit()
+        ContractEnumMessage::new(name, self.item, msg_ty, &self.generics, self.attributes).emit()
     }
 
     fn emit_glue_msg(&self, name: &Ident, msg_ty: MsgType) -> TokenStream {
diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs
index 7ba82c0..7b47fe1 100644
--- a/sylvia-derive/src/message.rs
+++ b/sylvia-derive/src/message.rs
@@ -11,8 +11,8 @@ use syn::parse::{Parse, Parser};
 use syn::spanned::Spanned;
 use syn::visit::Visit;
 use syn::{
-    parse_quote, FnArg, GenericParam, Ident, ImplItem, ImplItemMethod, ItemImpl, ItemTrait, Pat,
-    PatType, ReturnType, Signature, TraitItem, TraitItemMethod, Type, WhereClause, WherePredicate,
+    parse_quote, FnArg, GenericParam, Ident, ImplItem, ItemImpl, ItemTrait, Pat, PatType,
+    ReturnType, Signature, TraitItem, Type, WhereClause, WherePredicate,
 };
 
 fn filter_wheres<'a>(
@@ -247,7 +247,7 @@ impl<'a> EnumMessage<'a> {
                     };
 
                     if attr == ty {
-                        Some(MsgVariant::new(method, &mut generics_checker))
+                        Some(MsgVariant::new(&method.sig, &mut generics_checker))
                     } else {
                         None
                     }
@@ -349,15 +349,15 @@ impl<'a> EnumMessage<'a> {
 }
 
 /// Representation of single enum message
-pub struct ImplEnumMessage<'a> {
+pub struct ContractEnumMessage<'a> {
     name: &'a Ident,
-    variants: Vec<ImplMsgVariant<'a>>,
+    variants: Vec<MsgVariant<'a>>,
     msg_ty: MsgType,
     contract: &'a Type,
     error: &'a Type,
 }
 
-impl<'a> ImplEnumMessage<'a> {
+impl<'a> ContractEnumMessage<'a> {
     pub fn new(
         name: &'a Ident,
         source: &'a ItemImpl,
@@ -381,7 +381,7 @@ impl<'a> ImplEnumMessage<'a> {
                     };
 
                     if attr == ty {
-                        Some(ImplMsgVariant::new(method, &mut generics_checker))
+                        Some(MsgVariant::new(&method.sig, &mut generics_checker))
                     } else {
                         None
                     }
@@ -419,7 +419,7 @@ impl<'a> ImplEnumMessage<'a> {
             .collect();
         msgs.sort();
         let msgs_cnt = msgs.len();
-        let variants = variants.iter().map(ImplMsgVariant::emit);
+        let variants = variants.iter().map(MsgVariant::emit);
 
         let ctx_type = msg_ty.emit_ctx_type();
         let contract = StripGenerics.fold_type((*contract).clone());
@@ -449,80 +449,6 @@ impl<'a> ImplEnumMessage<'a> {
     }
 }
 
-/// Representation of whole message variant
-pub struct ImplMsgVariant<'a> {
-    name: Ident,
-    function_name: &'a Ident,
-    // With https://github.com/rust-lang/rust/issues/63063 this could be just an iterator over
-    // `MsgField<'a>`
-    fields: Vec<MsgField<'a>>,
-}
-
-impl<'a> ImplMsgVariant<'a> {
-    /// Creates new message variant from trait method
-    pub fn new(
-        method: &'a ImplItemMethod,
-        generics_checker: &mut CheckGenerics,
-    ) -> ImplMsgVariant<'a> {
-        let function_name = &method.sig.ident;
-        let name = Ident::new(
-            &function_name.to_string().to_case(Case::UpperCamel),
-            function_name.span(),
-        );
-        let fields = process_fields(&method.sig, generics_checker);
-
-        Self {
-            name,
-            function_name,
-            fields,
-        }
-    }
-
-    /// Emits message variant
-    pub fn emit(&self) -> TokenStream {
-        let Self { name, fields, .. } = self;
-        let fields = fields.iter().map(MsgField::emit);
-
-        quote! {
-            #name {
-                #(#fields,)*
-            }
-        }
-    }
-
-    /// Emits match leg dispatching against this variant. Assumes enum variants are imported into the
-    /// scope. Dispatching is performed by calling the function this variant is build from on the
-    /// `contract` variable, with `ctx` as its first argument - both of them should be in scope.
-    pub fn emit_dispatch_leg(&self, msg_attr: MsgType) -> TokenStream {
-        use MsgType::*;
-
-        let Self {
-            name,
-            fields,
-            function_name,
-        } = self;
-        let args = fields.iter().map(|field| field.name);
-        let fields = fields.iter().map(|field| field.name);
-
-        match msg_attr {
-            Exec => quote! {
-                #name {
-                    #(#fields,)*
-                } => contract.#function_name(ctx.into(), #(#args),*).map_err(Into::into)
-            },
-            Query => quote! {
-                #name {
-                    #(#fields,)*
-                } => cosmwasm_std::to_binary(&contract.#function_name(ctx.into(), #(#args),*)?).map_err(Into::into)
-            },
-            Instantiate => {
-                emit_error!(name.span(), "Instantiation messages not supported on traits, they should be defined on contracts directly");
-                quote! {}
-            }
-        }
-    }
-}
-
 /// Representation of whole message variant
 pub struct MsgVariant<'a> {
     name: Ident,
@@ -534,16 +460,13 @@ pub struct MsgVariant<'a> {
 
 impl<'a> MsgVariant<'a> {
     /// Creates new message variant from trait method
-    pub fn new(
-        method: &'a TraitItemMethod,
-        generics_checker: &mut CheckGenerics,
-    ) -> MsgVariant<'a> {
-        let function_name = &method.sig.ident;
+    pub fn new(sig: &'a Signature, generics_checker: &mut CheckGenerics) -> MsgVariant<'a> {
+        let function_name = &sig.ident;
         let name = Ident::new(
             &function_name.to_string().to_case(Case::UpperCamel),
             function_name.span(),
         );
-        let fields = process_fields(&method.sig, generics_checker);
+        let fields = process_fields(sig, generics_checker);
 
         Self {
             name,
@@ -650,19 +573,6 @@ impl<'a> MsgField<'a> {
     }
 }
 
-// pub struct EnumMessage<'a> {
-//     name: &'a Ident,
-//     trait_name: &'a Ident,
-//     variants: Vec<MsgVariant<'a>>,
-//     generics: Vec<&'a GenericParam>,
-//     unused_generics: Vec<&'a GenericParam>,
-//     all_generics: &'a [&'a GenericParam],
-//     wheres: Vec<&'a WherePredicate>,
-//     full_where: Option<&'a WhereClause>,
-//     msg_ty: MsgType,
-//     args: &'a InterfaceArgs,
-// }
-
 /// Glue message is the message composing Exec/Query messages from several traits
 #[derive(Debug)]
 pub struct GlueMessage<'a> {
@@ -712,6 +622,7 @@ impl<'a> GlueMessage<'a> {
             error,
         } = self;
         let contract = StripGenerics.fold_type((*contract).clone());
+        let contract_name = Ident::new(&format!("Contract{}", name), name.span());
 
         let variants = interfaces.iter().map(|interface| {
             let ContractMessageAttr {
@@ -730,19 +641,7 @@ impl<'a> GlueMessage<'a> {
             quote! { #variant(#module :: #name<#(#generics,)*>) }
         });
 
-        let impl_msg = match msg_ty {
-            MsgType::Exec => Ident::new("ImplExecMsg", Span::call_site()),
-            MsgType::Query => Ident::new("ImplQueryMsg", Span::call_site()),
-            MsgType::Instantiate => {
-                emit_error!(
-                    name.span(),
-                    "Do not emit InstantiateMsg using GlueMessage. Use StructMessage instead!"
-                );
-                Ident::new("", Span::call_site())
-            }
-        };
-        let impl_msg_name = quote! {#contract ( #impl_msg)};
-
+        let msg_name = quote! {#contract ( #name)};
         let mut interface_names: Vec<TokenStream> = interfaces
             .iter()
             .map(|interface| {
@@ -752,15 +651,16 @@ impl<'a> GlueMessage<'a> {
             })
             .collect();
 
-        interface_names.push(quote! {&#impl_msg :: messages()});
+        interface_names.push(quote! {&#name :: messages()});
         let interfaces_cnt = interface_names.len();
 
         let dispatch_arms = interfaces.iter().map(|interface| {
             let ContractMessageAttr { variant, .. } = interface;
 
-            quote! { #name :: #variant(msg) => msg.dispatch(contract, ctx) }
+            quote! { #contract_name :: #variant(msg) => msg.dispatch(contract, ctx) }
         });
-        let impl_dispatch_arm = quote! {#name :: #contract (msg) =>msg.dispatch(contract, ctx)};
+
+        let dispatch_arm = quote! {#contract_name :: #contract (msg) =>msg.dispatch(contract, ctx)};
 
         let deserialization_attempts = interfaces.iter().map(|interface| {
             let ContractMessageAttr { variant, .. } = interface;
@@ -774,9 +674,9 @@ impl<'a> GlueMessage<'a> {
             }
         });
 
-        let impl_var = Ident::new("contract", Span::mixed_site());
-        let impl_deserialization_attempt = quote! {
-            let #impl_var = match val.clone().deserialize_into() {
+        let contract_variant = Ident::new("contract", Span::mixed_site());
+        let contract_deserialization_attempt = quote! {
+            let #contract_variant = match val.clone().deserialize_into() {
                 Ok(msg) => return Ok(Self:: #contract (msg)),
                 Err(err) => err,
             };
@@ -789,8 +689,8 @@ impl<'a> GlueMessage<'a> {
             quote! { format!("As {}: {}", stringify!(#variant), #var) }
         });
 
-        let impl_deser_errors =
-            quote! { format!("As {}: {}", stringify!(#impl_msg_name), #impl_var) };
+        let contract_deser_errors =
+            quote! { format!("As {}: {}", stringify!(#msg_name), #contract_variant) };
 
         let messages_type = interfaces.iter().map(|interface| &interface.variant);
 
@@ -801,12 +701,12 @@ impl<'a> GlueMessage<'a> {
             #[allow(clippy::derive_partial_eq_without_eq)]
             #[derive(#sylvia ::serde::Serialize, Clone, Debug, PartialEq, #sylvia ::schemars::JsonSchema)]
             #[serde(rename_all="snake_case", untagged)]
-            pub enum #name {
+            pub enum #contract_name {
                 #(#variants,)*
-                #impl_msg_name
+                #msg_name
             }
 
-            impl #name {
+            impl #contract_name {
                 pub fn dispatch(
                     self,
                     contract: &#contract,
@@ -819,12 +719,12 @@ impl<'a> GlueMessage<'a> {
 
                     match self {
                         #(#dispatch_arms,)*
-                        #impl_dispatch_arm
+                        #dispatch_arm
                     }
                 }
             }
 
-            impl<'de> serde::Deserialize<'de> for #name {
+            impl<'de> serde::Deserialize<'de> for #contract_name {
                 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                     where D: serde::Deserializer<'de>,
                 {
@@ -832,13 +732,13 @@ impl<'a> GlueMessage<'a> {
                     let val = #sylvia ::serde_value::Value::deserialize(deserializer)?;
 
                     #(#deserialization_attempts)*
-                    #impl_deserialization_attempt
+                    #contract_deserialization_attempt
 
                     Err(D::Error::custom(format!(
                         "Expected any of {} or {} messages, but cannot deserialize to neither of those\n{}",
                         stringify!(#(#messages_type),*),
-                        stringify!(#impl_msg_name),
-                        [#(#deser_errors,)* #impl_deser_errors].join("\n")
+                        stringify!(#msg_name),
+                        [#(#deser_errors,)* #contract_deser_errors].join("\n")
                     )))
                 }
             }


Test patch:
diff --git a/contracts/cw1-whitelist/src/multitest.rs b/contracts/cw1-whitelist/src/multitest.rs
index 87aeb76..f09db5f 100644
--- a/contracts/cw1-whitelist/src/multitest.rs
+++ b/contracts/cw1-whitelist/src/multitest.rs
@@ -2,7 +2,7 @@ use anyhow::{bail, Result as AnyResult};
 use cosmwasm_std::{from_slice, Binary, DepsMut, Empty, Env, MessageInfo, Reply, Response};
 use cw_multi_test::Contract;
 
-use crate::contract::{Cw1WhitelistContract, ExecMsg, InstantiateMsg, QueryMsg};
+use crate::contract::{ContractExecMsg, ContractQueryMsg, Cw1WhitelistContract, InstantiateMsg};
 
 impl Contract<Empty> for Cw1WhitelistContract<'_> {
     fn instantiate(
@@ -24,13 +24,13 @@ impl Contract<Empty> for Cw1WhitelistContract<'_> {
         info: MessageInfo,
         msg: Vec<u8>,
     ) -> AnyResult<Response<Empty>> {
-        from_slice::<ExecMsg>(&msg)?
+        from_slice::<ContractExecMsg>(&msg)?
             .dispatch(self, (deps, env, info))
             .map_err(Into::into)
     }
 
     fn query(&self, deps: cosmwasm_std::Deps, env: Env, msg: Vec<u8>) -> AnyResult<Binary> {
-        from_slice::<QueryMsg>(&msg)?
+        from_slice::<ContractQueryMsg>(&msg)?
             .dispatch(self, (deps, env))
             .map_err(Into::into)
     }
@@ -53,7 +53,7 @@ mod test {
     use cosmwasm_std::{to_binary, Addr, WasmMsg};
     use cw_multi_test::{App, Executor};
 
-    use crate::contract::{ImplExecMsg, ImplQueryMsg};
+    use crate::contract::{ExecMsg, QueryMsg};
     use crate::responses::AdminListResponse;
     use assert_matches::assert_matches;
 
@@ -96,7 +96,7 @@ mod test {
             .unwrap();
         assert_ne!(second_contract, first_contract);
 
-        let freeze = ImplExecMsg::Freeze {};
+        let freeze = ExecMsg::Freeze {};
         let freeze = WasmMsg::Execute {
             contract_addr: second_contract.to_string(),
             msg: to_binary(&freeze).unwrap(),
@@ -114,7 +114,7 @@ mod test {
 
         let resp = app
             .wrap()
-            .query_wasm_smart(second_contract, &ImplQueryMsg::AdminList {})
+            .query_wasm_smart(second_contract, &QueryMsg::AdminList {})
             .unwrap();
 
         assert_matches!(