From 8a59b36c4d42f6f5123a65cda7eab7e44a20de39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= <jnwznk@gmail.com>
Date: Thu, 18 Apr 2024 15:41:27 +0200
Subject: [PATCH] chore: Remove duplicated `querier` related code from
 `MsgVariant`

---
 sylvia-derive/src/message.rs | 74 ------------------------------------
 sylvia-derive/src/querier.rs | 61 +++++++++++++++++++++++++----
 2 files changed, 53 insertions(+), 82 deletions(-)

diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs
index a2dd3825..40845242 100644
--- a/sylvia-derive/src/message.rs
+++ b/sylvia-derive/src/message.rs
@@ -405,8 +405,6 @@ impl<'a> ContractEnumMessage<'a> {
 pub struct MsgVariant<'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>>,
     return_type: TokenStream,
     stripped_return_type: TokenStream,
@@ -544,69 +542,6 @@ impl<'a> MsgVariant<'a> {
         }
     }
 
-    pub fn emit_trait_querier_impl(&self, associated_name: &[TokenStream]) -> TokenStream {
-        let sylvia = crate_module();
-        let Self {
-            name,
-            fields,
-            return_type,
-            ..
-        } = self;
-
-        let parameters = fields.iter().map(MsgField::emit_method_field_assoc_type);
-        let fields_names = fields.iter().map(MsgField::name);
-        let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
-        let bracketed_generics = emit_bracketed_generics(associated_name);
-
-        quote! {
-            fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError> {
-                let query = <Api #bracketed_generics as sylvia::types::InterfaceApi>::Query:: #variant_name (#(#fields_names),*);
-                self.querier().query_wasm_smart(self.contract(), &query)
-            }
-        }
-    }
-
-    pub fn emit_querier_impl<Generic>(&self, api_path: &TokenStream) -> TokenStream
-    where
-        Generic: ToTokens + GetPath,
-    {
-        let sylvia = crate_module();
-        let Self {
-            name,
-            fields,
-            return_type,
-            ..
-        } = self;
-
-        let parameters = fields.iter().map(|field| field.emit_method_field_folded());
-        let fields_names = fields.iter().map(MsgField::name);
-        let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
-
-        quote! {
-            fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError> {
-                let query = #api_path :: #variant_name (#(#fields_names),*);
-                self.querier().query_wasm_smart(self.contract(), &query)
-            }
-        }
-    }
-
-    pub fn emit_querier_declaration(&self) -> TokenStream {
-        let sylvia = crate_module();
-        let Self {
-            name,
-            fields,
-            return_type,
-            ..
-        } = self;
-
-        let parameters = fields.iter().map(|field| field.emit_method_field_folded());
-        let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
-
-        quote! {
-            fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError>;
-        }
-    }
-
     pub fn as_fields_names(&self) -> Vec<&Ident> {
         self.fields.iter().map(MsgField::name).collect()
     }
@@ -879,15 +814,6 @@ impl<'a> MsgField<'a> {
         }
     }
 
-    /// Emits method field
-    pub fn emit_method_field_assoc_type(&self) -> TokenStream {
-        let Self { name, ty, .. } = self;
-
-        quote! {
-            #name: #ty
-        }
-    }
-
     pub fn emit_method_field_folded(&self) -> TokenStream {
         let Self { name, ty, .. } = self;
 
diff --git a/sylvia-derive/src/querier.rs b/sylvia-derive/src/querier.rs
index 8558d0cb..53d6e41b 100644
--- a/sylvia-derive/src/querier.rs
+++ b/sylvia-derive/src/querier.rs
@@ -1,3 +1,4 @@
+use convert_case::{Case, Casing};
 use proc_macro2::TokenStream;
 use quote::{quote, ToTokens};
 use syn::{GenericParam, Ident, ItemImpl};
@@ -5,8 +6,9 @@ use syn::{GenericParam, Ident, ItemImpl};
 use crate::associated_types::{AssociatedTypes, EmitAssociated, ItemType};
 use crate::check_generics::GetPath;
 use crate::crate_module;
-use crate::message::MsgVariants;
+use crate::message::{MsgField, MsgVariant, MsgVariants};
 use crate::parser::attributes::msg::MsgType;
+use crate::utils::emit_bracketed_generics;
 use crate::variant_descs::AsVariantDescs;
 
 pub struct TraitQuerier<'a, Generic> {
@@ -43,17 +45,19 @@ where
             .without_special()
             .map(ItemType::as_name)
             .collect();
-
         let all_generics: Vec<_> = associated_types.all_names().collect();
-
-        let assoc_types: Vec<_> = associated_types
-            .without_special()
-            .map(ItemType::as_name)
+        let assoc_types: Vec<_> = generics
+            .iter()
             .map(|assoc| quote! {Self:: #assoc})
             .collect();
+        let bracketed_generics = emit_bracketed_generics(&assoc_types);
+        let accessor = MsgType::Query.as_accessor_name();
+        let api_path =
+            quote! { < Api #bracketed_generics as #sylvia ::types::InterfaceApi>:: #accessor };
+
         let methods_trait_impl = variants
             .variants()
-            .map(|variant| variant.emit_trait_querier_impl(&assoc_types))
+            .map(|variant| variant.emit_querier_impl(&api_path))
             .collect::<Vec<_>>();
 
         let methods_declaration = variants
@@ -110,7 +114,7 @@ impl<'a> ContractQuerier<'a> {
         let api_path = quote! { < #contract as #sylvia ::types::ContractApi>:: #accessor };
         let methods_impl = variants
             .variants()
-            .map(|variant| variant.emit_querier_impl::<GenericParam>(&api_path));
+            .map(|variant| variant.emit_querier_impl(&api_path));
 
         let methods_declaration = variants
             .variants()
@@ -149,3 +153,44 @@ impl<'a> ContractQuerier<'a> {
         }
     }
 }
+
+trait EmitMethod {
+    fn emit_querier_impl(&self, api_path: &TokenStream) -> TokenStream;
+    fn emit_querier_declaration(&self) -> TokenStream;
+}
+
+impl EmitMethod for MsgVariant<'_> {
+    fn emit_querier_impl(&self, api_path: &TokenStream) -> TokenStream {
+        let sylvia = crate_module();
+        let name = self.name();
+        let fields = self.fields();
+        let return_type = self.return_type();
+
+        let parameters = fields.iter().map(MsgField::emit_method_field_folded);
+        let fields_names = fields.iter().map(MsgField::name);
+        let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
+
+        quote! {
+            fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError> {
+                let query = #api_path :: #variant_name (#(#fields_names),*);
+                self.querier().query_wasm_smart(self.contract(), &query)
+            }
+        }
+    }
+
+    fn emit_querier_declaration(&self) -> TokenStream {
+        let sylvia = crate_module();
+        let name = self.name();
+        let return_type = self.return_type();
+
+        let parameters = self
+            .fields()
+            .iter()
+            .map(|field| field.emit_method_field_folded());
+        let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
+
+        quote! {
+            fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError>;
+        }
+    }
+}