From 57a63a9cfcc0fe0b3c46d74a4968085aec9f9e66 Mon Sep 17 00:00:00 2001 From: Tomasz Kulik Date: Thu, 29 Feb 2024 09:32:21 +0100 Subject: [PATCH] feat: multitests does not need #[contract(module=...)] --- .../contracts/custom/src/multitest/tests.rs | 3 +- .../cw1-subkeys/src/multitest/tests.rs | 4 +- .../contracts/cw1-whitelist/src/multitest.rs | 5 +- .../src/multitest/allowances_tests.rs | 4 +- .../cw20-base/src/multitest/base_tests.rs | 4 +- .../src/multitest/marketing_tests.rs | 2 +- .../cw20-base/src/multitest/minting_tests.rs | 4 +- .../entry-points-overriding/src/multitest.rs | 2 +- .../generic_contract/src/contract.rs | 1 + .../src/custom_and_generic.rs | 2 +- .../contracts/generic_contract/src/cw1.rs | 2 +- .../contracts/generic_contract/src/generic.rs | 2 +- .../generic_iface_on_contract/src/contract.rs | 6 +- .../generics_forwarded/src/contract.rs | 1 + .../src/custom_and_generic.rs | 2 +- .../contracts/generics_forwarded/src/cw1.rs | 2 +- .../generics_forwarded/src/generic.rs | 2 +- sylvia-derive/src/associated_types.rs | 39 +-- sylvia-derive/src/input.rs | 50 +-- sylvia-derive/src/interfaces.rs | 20 -- sylvia-derive/src/lib.rs | 9 +- sylvia-derive/src/message.rs | 144 +++++---- sylvia-derive/src/multitest.rs | 303 +++++++----------- sylvia-derive/src/parser/mod.rs | 1 - sylvia-derive/src/querier.rs | 22 +- sylvia-derive/src/strip_self_path.rs | 57 +--- sylvia/src/multitest.rs | 28 ++ sylvia/tests/custom_msg.rs | 9 +- sylvia/tests/custom_query.rs | 9 +- sylvia/tests/entry_points.rs | 2 +- sylvia/tests/multitest.rs | 2 +- sylvia/tests/querier.rs | 11 +- sylvia/tests/replies.rs | 2 + 33 files changed, 307 insertions(+), 449 deletions(-) diff --git a/examples/contracts/custom/src/multitest/tests.rs b/examples/contracts/custom/src/multitest/tests.rs index 29818be9..ff189af3 100644 --- a/examples/contracts/custom/src/multitest/tests.rs +++ b/examples/contracts/custom/src/multitest/tests.rs @@ -4,9 +4,10 @@ use crate::contract::sv::multitest_utils::CodeId; use super::custom_module::CustomModule; -use crate::cw1::sv::test_utils::Cw1; +use crate::contract::sv::multitest_utils::ContractImpl; use cosmwasm_std::CosmosMsg; +use cw1::sv::test_utils::Cw1Proxy; #[test] fn test_custom() { diff --git a/examples/contracts/cw1-subkeys/src/multitest/tests.rs b/examples/contracts/cw1-subkeys/src/multitest/tests.rs index fff65243..9894dfa5 100644 --- a/examples/contracts/cw1-subkeys/src/multitest/tests.rs +++ b/examples/contracts/cw1-subkeys/src/multitest/tests.rs @@ -6,6 +6,9 @@ use sylvia::multitest::App; use crate::contract::sv::multitest_utils::CodeId; use crate::contract::{CONTRACT_NAME, CONTRACT_VERSION}; +use crate::contract::sv::multitest_utils::ContractImpl; +use cw1::sv::test_utils::Cw1Proxy; + const ATOM: &str = "atom"; /// Helper function for comparing vectors or another slice-like object as they would represent @@ -370,7 +373,6 @@ mod permissions { } mod cw1_execute { - use crate::cw1::sv::test_utils::Cw1; use cosmwasm_std::BankMsg; use super::*; diff --git a/examples/contracts/cw1-whitelist/src/multitest.rs b/examples/contracts/cw1-whitelist/src/multitest.rs index 551535f8..73f93f96 100644 --- a/examples/contracts/cw1-whitelist/src/multitest.rs +++ b/examples/contracts/cw1-whitelist/src/multitest.rs @@ -4,12 +4,13 @@ mod test { use whitelist::responses::AdminListResponse; use crate::contract::sv::multitest_utils::CodeId; - use crate::cw1::sv::test_utils::Cw1; use crate::error::ContractError; - use crate::whitelist::sv::test_utils::Whitelist; use assert_matches::assert_matches; use sylvia::multitest::App; + use cw1::sv::test_utils::Cw1Proxy; + use whitelist::sv::test_utils::WhitelistProxy; + #[test] fn proxy_freeze_message() { let app = App::default(); diff --git a/examples/contracts/cw20-base/src/multitest/allowances_tests.rs b/examples/contracts/cw20-base/src/multitest/allowances_tests.rs index ed5e696a..8266459f 100644 --- a/examples/contracts/cw20-base/src/multitest/allowances_tests.rs +++ b/examples/contracts/cw20-base/src/multitest/allowances_tests.rs @@ -7,13 +7,15 @@ use cw_multi_test::next_block; use cw_utils::Expiration; use sylvia::multitest::App; -use crate::allowances::sv::test_utils::Cw20Allowances; use crate::contract::sv::multitest_utils::CodeId; use crate::contract::InstantiateMsgData; use crate::error::ContractError; use crate::multitest::receiver_contract::sv::multitest_utils::CodeId as ReceiverCodeId; use crate::responses::Cw20Coin; +use crate::contract::sv::multitest_utils::ContractImpl; +use cw20_allowances::sv::test_utils::Cw20AllowancesProxy; + #[test] fn increase_decrease_allowances() { let app = App::default(); diff --git a/examples/contracts/cw20-base/src/multitest/base_tests.rs b/examples/contracts/cw20-base/src/multitest/base_tests.rs index d0f615c6..ffebbc11 100644 --- a/examples/contracts/cw20-base/src/multitest/base_tests.rs +++ b/examples/contracts/cw20-base/src/multitest/base_tests.rs @@ -3,12 +3,12 @@ use cw20_allowances::responses::{AllAllowancesResponse, SpenderAllowanceInfo}; use cw_utils::Expiration; use sylvia::multitest::App; -use crate::allowances::sv::test_utils::Cw20Allowances; -use crate::contract::sv::multitest_utils::CodeId; +use crate::contract::sv::multitest_utils::{CodeId, ContractImpl}; use crate::contract::InstantiateMsgData; use crate::error::ContractError; use crate::multitest::receiver_contract::sv::multitest_utils::CodeId as ReceiverCodeId; use crate::responses::{BalanceResponse, Cw20Coin, TokenInfoResponse}; +use cw20_allowances::sv::test_utils::Cw20AllowancesProxy; #[test] fn basic() { diff --git a/examples/contracts/cw20-base/src/multitest/marketing_tests.rs b/examples/contracts/cw20-base/src/multitest/marketing_tests.rs index 1c105fb2..4aed0845 100644 --- a/examples/contracts/cw20-base/src/multitest/marketing_tests.rs +++ b/examples/contracts/cw20-base/src/multitest/marketing_tests.rs @@ -6,7 +6,7 @@ use sylvia::multitest::App; use crate::contract::sv::multitest_utils::CodeId; use crate::contract::{InstantiateMarketingInfo, InstantiateMsgData}; use crate::error::ContractError; -use crate::marketing::sv::test_utils::Cw20Marketing; +use cw20_marketing::sv::test_utils::Cw20MarketingProxy; const PNG_HEADER: [u8; 8] = [0x89, b'P', b'N', b'G', 0x0d, 0x0a, 0x1a, 0x0a]; diff --git a/examples/contracts/cw20-base/src/multitest/minting_tests.rs b/examples/contracts/cw20-base/src/multitest/minting_tests.rs index 60d03c51..263f44e9 100644 --- a/examples/contracts/cw20-base/src/multitest/minting_tests.rs +++ b/examples/contracts/cw20-base/src/multitest/minting_tests.rs @@ -2,11 +2,11 @@ use cosmwasm_std::{StdError, Uint128}; use cw20_minting::responses::MinterResponse; use sylvia::multitest::App; -use crate::contract::sv::multitest_utils::CodeId; +use crate::contract::sv::multitest_utils::{CodeId, ContractImpl}; use crate::contract::InstantiateMsgData; use crate::error::ContractError; -use crate::minting::sv::test_utils::Cw20Minting; use crate::responses::{Cw20Coin, TokenInfoResponse}; +use cw20_minting::sv::test_utils::Cw20MintingProxy; #[test] fn mintable() { diff --git a/examples/contracts/entry-points-overriding/src/multitest.rs b/examples/contracts/entry-points-overriding/src/multitest.rs index 9efda4e8..d6089ff3 100644 --- a/examples/contracts/entry-points-overriding/src/multitest.rs +++ b/examples/contracts/entry-points-overriding/src/multitest.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod test { - use crate::contract::sv::multitest_utils::CodeId; + use crate::contract::sv::multitest_utils::{CodeId, ContractImpl}; use crate::contract::sv::{ContractExecMsg, ExecMsg}; use crate::messages::{CustomExecMsg, SudoMsg, UserExecMsg}; use cosmwasm_std::Addr; diff --git a/examples/contracts/generic_contract/src/contract.rs b/examples/contracts/generic_contract/src/contract.rs index 3dfbf654..60a33a7d 100644 --- a/examples/contracts/generic_contract/src/contract.rs +++ b/examples/contracts/generic_contract/src/contract.rs @@ -189,6 +189,7 @@ where #[cfg(test)] mod tests { use super::sv::multitest_utils::CodeId; + use crate::contract::sv::multitest_utils::ContractImpl; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generic_contract/src/custom_and_generic.rs b/examples/contracts/generic_contract/src/custom_and_generic.rs index 8eee247c..015a4dce 100644 --- a/examples/contracts/generic_contract/src/custom_and_generic.rs +++ b/examples/contracts/generic_contract/src/custom_and_generic.rs @@ -111,8 +111,8 @@ impl< #[cfg(test)] mod tests { - use super::sv::test_utils::CustomAndGeneric; use crate::contract::sv::multitest_utils::CodeId; + use custom_and_generic::sv::test_utils::CustomAndGenericProxy; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generic_contract/src/cw1.rs b/examples/contracts/generic_contract/src/cw1.rs index fae6b68e..92486e72 100644 --- a/examples/contracts/generic_contract/src/cw1.rs +++ b/examples/contracts/generic_contract/src/cw1.rs @@ -54,9 +54,9 @@ impl< #[cfg(test)] mod tests { - use super::sv::test_utils::Cw1; use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::{CosmosMsg, Empty}; + use cw1::sv::test_utils::Cw1Proxy; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generic_contract/src/generic.rs b/examples/contracts/generic_contract/src/generic.rs index 39e5b360..0bb9d38a 100644 --- a/examples/contracts/generic_contract/src/generic.rs +++ b/examples/contracts/generic_contract/src/generic.rs @@ -123,9 +123,9 @@ where #[cfg(test)] mod tests { - use super::sv::test_utils::Generic; use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::CosmosMsg; + use generic::sv::test_utils::GenericProxy; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generic_iface_on_contract/src/contract.rs b/examples/contracts/generic_iface_on_contract/src/contract.rs index 214f6d1c..7b848f34 100644 --- a/examples/contracts/generic_iface_on_contract/src/contract.rs +++ b/examples/contracts/generic_iface_on_contract/src/contract.rs @@ -35,9 +35,9 @@ mod tests { use sylvia::types::{SvCustomMsg, SvCustomQuery}; use super::NonGenericContract; - use crate::custom_and_generic::sv::test_utils::CustomAndGeneric; - use crate::cw1::sv::test_utils::Cw1; - use crate::generic::sv::test_utils::Generic; + use custom_and_generic::sv::test_utils::CustomAndGenericProxy; + use cw1::sv::test_utils::Cw1Proxy; + use generic::sv::test_utils::GenericProxy; #[test] fn mt_helpers() { diff --git a/examples/contracts/generics_forwarded/src/contract.rs b/examples/contracts/generics_forwarded/src/contract.rs index 89aff242..60743344 100644 --- a/examples/contracts/generics_forwarded/src/contract.rs +++ b/examples/contracts/generics_forwarded/src/contract.rs @@ -198,6 +198,7 @@ where #[cfg(test)] mod tests { use super::sv::multitest_utils::CodeId; + use crate::contract::sv::multitest_utils::ContractImpl; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generics_forwarded/src/custom_and_generic.rs b/examples/contracts/generics_forwarded/src/custom_and_generic.rs index 8781e79a..c55bf7f5 100644 --- a/examples/contracts/generics_forwarded/src/custom_and_generic.rs +++ b/examples/contracts/generics_forwarded/src/custom_and_generic.rs @@ -131,9 +131,9 @@ where #[cfg(test)] mod tests { - use super::sv::test_utils::CustomAndGeneric; use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::CosmosMsg; + use custom_and_generic::sv::test_utils::CustomAndGenericProxy; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generics_forwarded/src/cw1.rs b/examples/contracts/generics_forwarded/src/cw1.rs index 04108c55..432514a2 100644 --- a/examples/contracts/generics_forwarded/src/cw1.rs +++ b/examples/contracts/generics_forwarded/src/cw1.rs @@ -76,9 +76,9 @@ where #[cfg(test)] mod tests { - use super::sv::test_utils::Cw1; use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::{CosmosMsg, Empty}; + use cw1::sv::test_utils::Cw1Proxy; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/examples/contracts/generics_forwarded/src/generic.rs b/examples/contracts/generics_forwarded/src/generic.rs index 38b5b6cc..26a8d992 100644 --- a/examples/contracts/generics_forwarded/src/generic.rs +++ b/examples/contracts/generics_forwarded/src/generic.rs @@ -129,9 +129,9 @@ where #[cfg(test)] mod tests { - use super::sv::test_utils::Generic; use crate::contract::sv::multitest_utils::CodeId; use cosmwasm_std::CosmosMsg; + use generic::sv::test_utils::GenericProxy; use sylvia::multitest::App; use sylvia::types::{SvCustomMsg, SvCustomQuery}; diff --git a/sylvia-derive/src/associated_types.rs b/sylvia-derive/src/associated_types.rs index a95a586a..7225fe7c 100644 --- a/sylvia-derive/src/associated_types.rs +++ b/sylvia-derive/src/associated_types.rs @@ -1,9 +1,6 @@ use proc_macro2::{Ident, TokenStream}; use quote::quote; -use syn::{ - parse_quote, ImplItem, ImplItemType, ItemImpl, ItemTrait, TraitItem, TraitItemType, Type, - WhereClause, WherePredicate, -}; +use syn::{parse_quote, ItemTrait, TraitItem, TraitItemType, WhereClause, WherePredicate}; pub const ERROR_TYPE: &str = "Error"; pub const EXEC_TYPE: &str = "ExecC"; @@ -97,40 +94,6 @@ impl<'a> AssociatedTypes<'a> { } } -#[derive(Default)] -pub struct ImplAssociatedTypes<'a>(Vec<&'a ImplItemType>); - -impl<'a> ImplAssociatedTypes<'a> { - pub fn new(source: &'a ItemImpl) -> Self { - let associated_types: Vec<_> = source - .items - .iter() - .filter_map(|item| match item { - ImplItem::Type(ty) => Some(ty), - _ => None, - }) - .collect(); - - Self(associated_types) - } - - pub fn as_types(&self) -> Vec<&Type> { - self.filtered().map(|associated| &associated.ty).collect() - } - - pub fn as_item_types(&self) -> Vec<&ImplItemType> { - self.filtered().copied().collect() - } - - pub fn filtered(&self) -> impl Iterator { - self.0.iter().filter(|associated| { - !RESERVED_TYPES - .iter() - .any(|reserved| reserved == &associated.ident.to_string().as_str()) - }) - } -} - pub trait ItemType { fn as_name(&self) -> &Ident; fn as_where_predicate(&self) -> WherePredicate; diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index dbb74d0e..feb9b2b7 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -11,9 +11,7 @@ use crate::message::{ }; use crate::multitest::{ContractMtHelpers, ImplMtHelpers}; use crate::parser::attributes::msg::MsgType; -use crate::parser::{ - ContractArgs, ContractErrorAttr, Custom, OverrideEntryPoint, ParsedSylviaAttributes, -}; +use crate::parser::{ContractErrorAttr, Custom, OverrideEntryPoint, ParsedSylviaAttributes}; use crate::querier::{ContractQuerier, TraitQuerier}; use crate::variant_descs::AsVariantDescs; @@ -73,6 +71,8 @@ impl<'a> TraitInput<'a> { let interface_messages = InterfaceApi::new(item, associated_types, custom).emit(); + let multitest_helpers = self.emit_multitest_helpers(); + quote! { pub mod sv { use super::*; @@ -81,6 +81,8 @@ impl<'a> TraitInput<'a> { #querier #interface_messages + + #multitest_helpers } } } @@ -122,52 +124,16 @@ impl<'a> TraitInput<'a> { ) .emit() } -} - -/// Preprocessed `contract` macro input for impl trait block -pub struct ImplTraitInput<'a> { - attributes: &'a ContractArgs, - item: &'a ItemImpl, - generics: Vec<&'a GenericParam>, - interfaces: Interfaces, -} - -impl<'a> ImplTraitInput<'a> { - pub fn new(attributes: &'a ContractArgs, item: &'a ItemImpl) -> Self { - let generics = item.generics.params.iter().collect(); - let interfaces = Interfaces::new(item); - - Self { - attributes, - item, - generics, - interfaces, - } - } - - pub fn process(&self) -> TokenStream { - let multitest_helpers = self.emit_multitest_helpers(); - - quote! { - pub mod sv { - use super::*; - - #multitest_helpers - } - } - } fn emit_multitest_helpers(&self) -> TokenStream { if !cfg!(feature = "mt") { return quote! {}; } - let Self { - item, interfaces, .. - } = self; - let generic_params = &self.generics; + let Self { item, .. } = self; + let associated_types = &self.associated_types; - ImplMtHelpers::new(item, generic_params, interfaces, &self.attributes.module).emit() + ImplMtHelpers::new(item, associated_types).emit() } } diff --git a/sylvia-derive/src/interfaces.rs b/sylvia-derive/src/interfaces.rs index f4e87cba..518b1597 100644 --- a/sylvia-derive/src/interfaces.rs +++ b/sylvia-derive/src/interfaces.rs @@ -1,5 +1,4 @@ use proc_macro2::{Ident, TokenStream}; -use proc_macro_error::emit_error; use quote::quote; use syn::spanned::Spanned; use syn::{GenericArgument, ItemImpl}; @@ -138,23 +137,4 @@ impl Interfaces { .flat_map(|interface| &interface.generics) .collect() } - - pub fn get_only_interface(&self) -> Option<&ContractMessageAttr> { - let interfaces = &self.interfaces; - match interfaces.len() { - 0 => None, - 1 => Some(&interfaces[0]), - _ => { - let first = &interfaces[0]; - for redefined in &interfaces[1..] { - emit_error!( - redefined.module, "The attribute `sv::messages` is redefined"; - note = first.module.span() => "Previous definition of the attribute `sv::messages`"; - note = "Only one `sv::messages` attribute can exist on an interface implementation on contract" - ); - } - None - } - } - } } diff --git a/sylvia-derive/src/lib.rs b/sylvia-derive/src/lib.rs index e6c70eca..98419872 100644 --- a/sylvia-derive/src/lib.rs +++ b/sylvia-derive/src/lib.rs @@ -1,4 +1,4 @@ -use input::{ImplInput, ImplTraitInput, TraitInput}; +use input::{ImplInput, TraitInput}; use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use proc_macro_error::proc_macro_error; @@ -235,11 +235,10 @@ pub fn contract(attr: TokenStream, item: TokenStream) -> TokenStream { fn contract_impl(attr: TokenStream2, item: TokenStream2) -> TokenStream2 { fn inner(attr: TokenStream2, item: TokenStream2) -> syn::Result { let input: ItemImpl = parse2(item)?; - let expanded = if input.trait_.is_some() { - let attrs: parser::ContractArgs = parse2(attr)?; - ImplTraitInput::new(&attrs, &input).process() - } else { + let expanded = if attr.is_empty() { ImplInput::new(&input).process() + } else { + quote! {} }; let input = StripInput.fold_item_impl(input); diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 077b6f27..3a93f9a0 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -7,7 +7,7 @@ use crate::parser::{ FilteredOverrideEntryPoints, MsgAttr, MsgType, OverrideEntryPoint, ParsedSylviaAttributes, }; use crate::strip_generics::StripGenerics; -use crate::strip_self_path::{AddSelfPath, ReplaceAssociatedType, StripSelfPath}; +use crate::strip_self_path::StripSelfPath; use crate::utils::{ as_where_clause, emit_bracketed_generics, extract_return_type, filter_generics, filter_wheres, process_fields, @@ -23,9 +23,8 @@ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::visit::Visit; use syn::{ - parse_quote, Attribute, GenericArgument, GenericParam, Ident, ImplItem, ImplItemFn, - ImplItemType, ItemImpl, ItemTrait, Pat, PatType, ReturnType, Signature, Token, Type, - WhereClause, WherePredicate, + parse_quote, Attribute, GenericArgument, GenericParam, Ident, ImplItem, ImplItemFn, ItemImpl, + ItemTrait, Pat, PatType, ReturnType, Signature, Token, Type, WhereClause, WherePredicate, }; /// Representation of single struct message @@ -564,11 +563,7 @@ impl<'a> MsgVariant<'a> { } } - pub fn emit_querier_impl( - &self, - api_path: &TokenStream, - generics: &[&Generic], - ) -> TokenStream + pub fn emit_querier_impl(&self, api_path: &TokenStream) -> TokenStream where Generic: ToTokens + GetPath, { @@ -580,10 +575,7 @@ impl<'a> MsgVariant<'a> { .. } = self; - let mut fold = AddSelfPath::new(generics); - let parameters = fields - .iter() - .map(|field| field.emit_method_field_folded(&mut fold)); + 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()); @@ -595,10 +587,7 @@ impl<'a> MsgVariant<'a> { } } - pub fn emit_querier_declaration(&self, generics: &[&Generic]) -> TokenStream - where - Generic: ToTokens + GetPath, - { + pub fn emit_querier_declaration(&self) -> TokenStream { let sylvia = crate_module(); let Self { name, @@ -607,10 +596,7 @@ impl<'a> MsgVariant<'a> { .. } = self; - let mut fold = AddSelfPath::new(generics); - let parameters = fields - .iter() - .map(|field| field.emit_method_field_folded(&mut fold)); + 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! { @@ -618,6 +604,53 @@ impl<'a> MsgVariant<'a> { } } + pub fn emit_multitest_proxy_methods_declaration( + &self, + msg_ty: &MsgType, + custom_msg: &Type, + mt_app: &Type, + error_type: &Type, + generics: &[&Generic], + ) -> TokenStream + where + Generic: ToTokens, + { + let sylvia = crate_module(); + let Self { + name, + fields, + stripped_return_type, + .. + } = self; + + let params = fields.iter().map(|field| field.emit_method_field()); + let name = Ident::new(&name.to_string().to_case(Case::Snake), name.span()); + let enum_name = msg_ty.emit_msg_name(); + let enum_name: Type = if !generics.is_empty() { + parse_quote! { #enum_name ::< #(#generics,)* > } + } else { + parse_quote! { #enum_name } + }; + + match msg_ty { + MsgType::Exec => quote! { + #[track_caller] + fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::< #error_type, #enum_name, #mt_app, #custom_msg>; + }, + MsgType::Migrate => quote! { + #[track_caller] + fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::MigrateProxy::< #error_type, #enum_name, #mt_app, #custom_msg>; + }, + MsgType::Query => quote! { + fn #name (&self, #(#params,)* ) -> Result<#stripped_return_type, #error_type>; + }, + MsgType::Sudo => quote! { + fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type>; + }, + _ => quote! {}, + } + } + pub fn emit_multitest_proxy_methods( &self, msg_ty: &MsgType, @@ -650,7 +683,7 @@ impl<'a> MsgVariant<'a> { match msg_ty { MsgType::Exec => quote! { #[track_caller] - pub fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::<#error_type, #enum_name, #mt_app, #custom_msg> { + fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::< #error_type, #enum_name, #mt_app, #custom_msg> { let msg = #enum_name :: #name ( #(#arguments),* ); #sylvia ::multitest::ExecProxy::new(&self.contract_addr, msg, &self.app) @@ -658,14 +691,14 @@ impl<'a> MsgVariant<'a> { }, MsgType::Migrate => quote! { #[track_caller] - pub fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::MigrateProxy::<#error_type, #enum_name, #mt_app, #custom_msg> { + fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::MigrateProxy::< #error_type, #enum_name, #mt_app, #custom_msg> { let msg = #enum_name ::new( #(#arguments),* ); #sylvia ::multitest::MigrateProxy::new(&self.contract_addr, msg, &self.app) } }, MsgType::Query => quote! { - pub fn #name (&self, #(#params,)* ) -> Result<#stripped_return_type, #error_type> { + fn #name (&self, #(#params,)* ) -> Result<#stripped_return_type, #error_type> { let msg = #enum_name :: #name ( #(#arguments),* ); (*self.app) @@ -676,7 +709,7 @@ impl<'a> MsgVariant<'a> { } }, MsgType::Sudo => quote! { - pub fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type> { + fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type> { let msg = #enum_name :: #name ( #(#arguments),* ); (*self.app) @@ -696,20 +729,18 @@ impl<'a> MsgVariant<'a> { mt_app: &Type, error_type: &Type, interface_api: &TokenStream, - associated_items: &'a [&'a ImplItemType], ) -> TokenStream { let sylvia = crate_module(); let Self { name, fields, - stripped_return_type, + return_type, .. } = self; - let mut fold = ReplaceAssociatedType::new(associated_items); let params: Vec<_> = fields .iter() - .map(|field| field.emit_method_field_folded(&mut fold)) + .map(|field| field.emit_method_field_folded()) .collect(); let arguments = fields.iter().map(MsgField::name); let type_name = msg_ty.as_accessor_name(); @@ -718,16 +749,15 @@ impl<'a> MsgVariant<'a> { match msg_ty { MsgType::Exec => quote! { #[track_caller] - fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::<#error_type, #interface_api :: #type_name, #mt_app, #custom_msg> { + fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy:: { let msg = #interface_api :: #type_name :: #name ( #(#arguments),* ); #sylvia ::multitest::ExecProxy::new(&self.contract_addr, msg, &self.app) } }, MsgType::Query => { - let return_type = fold.fold_type(parse_quote! { #stripped_return_type }); quote! { - fn #name (&self, #(#params,)* ) -> Result<#return_type, #error_type> { + fn #name (&self, #(#params,)* ) -> Result<#return_type, Self:: #error_type> { let msg = #interface_api :: #type_name :: #name ( #(#arguments),* ); (*self.app) @@ -739,7 +769,7 @@ impl<'a> MsgVariant<'a> { } } MsgType::Sudo => quote! { - fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type> { + fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, Self:: #error_type> { let msg = #interface_api :: #type_name :: #name ( #(#arguments),* ); (*self.app) @@ -758,36 +788,33 @@ impl<'a> MsgVariant<'a> { custom_msg: &Type, error_type: &Type, interface_enum: &TokenStream, - associated_items: &'a [&'a ImplItemType], ) -> TokenStream { let sylvia = crate_module(); let Self { name, fields, - stripped_return_type, + return_type, .. } = self; - let mut fold = ReplaceAssociatedType::new(associated_items); let params: Vec<_> = fields .iter() - .map(|field| field.emit_method_field_folded(&mut fold)) + .map(|field| field.emit_method_field_folded()) .collect(); let type_name = msg_ty.as_accessor_name(); let name = Ident::new(&name.to_string().to_case(Case::Snake), name.span()); match msg_ty { MsgType::Exec => quote! { - fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::<#error_type, #interface_enum :: #type_name, MtApp, #custom_msg>; + fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::< Self:: #error_type, #interface_enum :: #type_name, MtApp, #custom_msg>; }, MsgType::Query => { - let return_type = fold.fold_type(parse_quote! { #stripped_return_type }); quote! { - fn #name (&self, #(#params,)* ) -> Result<#return_type, #error_type>; + fn #name (&self, #(#params,)* ) -> Result<#return_type, Self:: #error_type>; } } MsgType::Sudo => quote! { - fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type>; + fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, Self:: #error_type>; }, _ => quote! {}, } @@ -910,6 +937,26 @@ where } } + pub fn emit_multitest_proxy_methods_declaration( + &self, + custom_msg: &Type, + mt_app: &Type, + error_type: &Type, + ) -> Vec { + self.variants + .iter() + .map(|variant| { + variant.emit_multitest_proxy_methods_declaration( + &self.msg_ty, + custom_msg, + mt_app, + error_type, + &self.used_generics, + ) + }) + .collect() + } + pub fn emit_multitest_proxy_methods( &self, custom_msg: &Type, @@ -936,7 +983,6 @@ where mt_app: &Type, error_type: &Type, interface_api: &TokenStream, - associated_items: &'a [&'a ImplItemType], ) -> Vec { self.variants .iter() @@ -947,7 +993,6 @@ where mt_app, error_type, interface_api, - associated_items, ) }) .collect() @@ -958,7 +1003,6 @@ where custom_msg: &Type, error_type: &Type, interface_enum: &TokenStream, - associated_items: &'a [&'a ImplItemType], ) -> Vec { self.variants .iter() @@ -968,7 +1012,6 @@ where custom_msg, error_type, interface_enum, - associated_items, ) }) .collect() @@ -1126,15 +1169,8 @@ impl<'a> MsgField<'a> { } } - pub fn emit_method_field_folded(&self, fold: &mut FoldT) -> TokenStream - where - FoldT: Fold, - { - let Self { - name, stripped_ty, .. - } = self; - - let ty = fold.fold_type((*stripped_ty).clone()); + pub fn emit_method_field_folded(&self) -> TokenStream { + let Self { name, ty, .. } = self; quote! { #name: #ty diff --git a/sylvia-derive/src/multitest.rs b/sylvia-derive/src/multitest.rs index c3071ca7..b56d1b85 100644 --- a/sylvia-derive/src/multitest.rs +++ b/sylvia-derive/src/multitest.rs @@ -1,11 +1,10 @@ use convert_case::{Case, Casing}; use proc_macro2::{Ident, TokenStream}; use quote::quote; -use syn::{parse_quote, GenericParam, ImplItem, ItemImpl, Path, Type}; +use syn::{parse_quote, GenericParam, ItemImpl, ItemTrait, TraitItem, Type}; -use crate::associated_types::ImplAssociatedTypes; +use crate::associated_types::AssociatedTypes; use crate::crate_module; -use crate::interfaces::Interfaces; use crate::message::{MsgVariant, MsgVariants}; use crate::parser::attributes::msg::MsgType; use crate::parser::{ @@ -14,37 +13,12 @@ use crate::parser::{ use crate::utils::emit_bracketed_generics; use crate::variant_descs::AsVariantDescs; -fn interface_name(source: &ItemImpl) -> &Ident { - let trait_name = &source.trait_; - let Some(trait_name) = trait_name else { - unreachable!() - }; - let (_, Path { segments, .. }, _) = &trait_name; - - match segments.last() { - Some(segment) => &segment.ident, - None => unreachable!(), - } -} - -fn extract_contract_name(contract: &Type) -> &Ident { - let Type::Path(type_path) = contract else { - unreachable!() - }; - let segments = &type_path.path.segments; - assert!(!segments.is_empty()); - let segment = &segments.last().unwrap(); - &segment.ident -} - pub struct ContractMtHelpers<'a> { error_type: Type, - contract: &'a Type, + contract_name: &'a Type, source: &'a ItemImpl, generic_params: &'a [&'a GenericParam], where_clause: &'a Option, - contract_name: &'a Ident, - proxy_name: Ident, custom: &'a Custom, override_entry_points: Vec, instantiate_variants: MsgVariants<'a, GenericParam>, @@ -106,19 +80,14 @@ impl<'a> ContractMtHelpers<'a> { .error; let error_type = parse_quote! { #error_type }; - let contract = &source.self_ty; - let contract_name = extract_contract_name(contract); - - let proxy_name = Ident::new(&format!("{}Proxy", contract_name), contract_name.span()); + let contract_name = &source.self_ty; Self { error_type, - contract, source, generic_params, where_clause, contract_name, - proxy_name, custom, override_entry_points, instantiate_variants, @@ -133,7 +102,7 @@ impl<'a> ContractMtHelpers<'a> { pub fn emit(&self) -> TokenStream { let Self { error_type, - proxy_name, + contract_name, custom, exec_variants, query_variants, @@ -168,6 +137,25 @@ impl<'a> ContractMtHelpers<'a> { sudo_variants.emit_multitest_proxy_methods(&custom_msg, &mt_app, error_type); let migrate_methods = migrate_variants.emit_multitest_proxy_methods(&custom_msg, &mt_app, error_type); + + let exec_methods_delcaration = exec_variants.emit_multitest_proxy_methods_declaration( + &custom_msg, + &mt_app, + error_type, + ); + let query_methods_delcaration = query_variants.emit_multitest_proxy_methods_declaration( + &custom_msg, + &mt_app, + error_type, + ); + let sudo_methods_delcaration = sudo_variants.emit_multitest_proxy_methods_declaration( + &custom_msg, + &mt_app, + error_type, + ); + let migrate_methods_delcaration = migrate_variants + .emit_multitest_proxy_methods_declaration(&custom_msg, &mt_app, error_type); + let where_predicates = where_clause .as_ref() .map(|where_clause| &where_clause.predicates); @@ -178,18 +166,19 @@ impl<'a> ContractMtHelpers<'a> { pub mod multitest_utils { use super::*; use #sylvia ::cw_multi_test::Executor; - use #sylvia ::derivative::Derivative; - - #[derive(Derivative)] - #[derivative(Debug)] - pub struct #proxy_name <'app, MtApp, #(#generic_params,)* > { - pub contract_addr: #sylvia ::cw_std::Addr, - #[derivative(Debug="ignore")] - pub app: &'app #sylvia ::multitest::App, - _phantom: std::marker::PhantomData<( #(#generic_params,)* )>, + + pub trait ContractImpl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > + #where_clause + { + #( #exec_methods_delcaration )* + #( #migrate_methods_delcaration )* + #( #query_methods_delcaration )* + #( #sudo_methods_delcaration )* } - impl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > #proxy_name <'app, #mt_app, #(#generic_params,)* > + impl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > + ContractImpl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > + for #sylvia ::multitest::Proxy <'app, #mt_app, super:: #contract_name > where CustomT: #sylvia ::cw_multi_test::Module, CustomT::ExecT: std::fmt::Debug @@ -210,48 +199,12 @@ impl<'a> ContractMtHelpers<'a> { #mt_app : Executor< #custom_msg >, #where_predicates { - pub fn new(contract_addr: #sylvia ::cw_std::Addr, app: &'app #sylvia ::multitest::App< #mt_app >) -> Self { - #proxy_name { contract_addr, app, _phantom: std::marker::PhantomData::default() } - } - #( #exec_methods )* #( #migrate_methods )* #( #query_methods )* #( #sudo_methods )* } - impl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > - From<( - #sylvia ::cw_std::Addr, - &'app #sylvia ::multitest::App<#mt_app>, - )> - for #proxy_name <'app, #mt_app, #(#generic_params,)* > - where - CustomT: #sylvia ::cw_multi_test::Module, - CustomT::ExecT: std::fmt::Debug - + PartialEq - + Clone - + #sylvia ::schemars::JsonSchema - + #sylvia ::serde::de::DeserializeOwned - + 'static, - CustomT::QueryT: #sylvia ::cw_std::CustomQuery + #sylvia ::serde::de::DeserializeOwned + 'static, - WasmT: #sylvia ::cw_multi_test::Wasm, - BankT: #sylvia ::cw_multi_test::Bank, - ApiT: #sylvia ::cw_std::Api, - StorageT: #sylvia ::cw_std::Storage, - StakingT: #sylvia ::cw_multi_test::Staking, - DistrT: #sylvia ::cw_multi_test::Distribution, - IbcT: #sylvia ::cw_multi_test::Ibc, - GovT: #sylvia ::cw_multi_test::Gov, - #mt_app : Executor< #custom_msg >, - #where_predicates - { - fn from(input: (#sylvia ::cw_std::Addr, &'app #sylvia ::multitest::App< #mt_app >)) - -> #proxy_name<'app, #mt_app, #(#generic_params,)* > { - #proxy_name::new(input.0, input.1) - } - } - #contract_block } } @@ -264,7 +217,6 @@ impl<'a> ContractMtHelpers<'a> { generic_params, where_clause, contract_name, - proxy_name, instantiate_variants, .. } = self; @@ -285,10 +237,20 @@ impl<'a> ContractMtHelpers<'a> { let where_predicates = where_clause .as_ref() .map(|where_clause| &where_clause.predicates); + + let contract = { + let Type::Path(type_path) = contract_name else { + unreachable!() + }; + let segments = &type_path.path.segments; + assert!(!segments.is_empty()); + let segment = &segments.last().unwrap(); + &segment.ident + }; let contract = if !generic_params.is_empty() { - quote! { #contract_name ::< #(#generic_params,)* > } + quote! { super:: #contract ::< #(#generic_params,)* > } } else { - quote! { #contract_name } + quote! { super:: #contract } }; let instantiate_msg = if !used_generics.is_empty() { @@ -337,7 +299,7 @@ impl<'a> ContractMtHelpers<'a> { #sylvia:: cw_utils::parse_instantiate_response_data(app_response.data.unwrap().as_slice()) .map_err(|err| Into::into( #sylvia ::cw_std::StdError::generic_err(err.to_string()))) - .map(|data| #proxy_name { + .map(|data| #sylvia ::multitest::Proxy { contract_addr: #sylvia ::cw_std::Addr::unchecked(data.contract_address), app: code_id.app, _phantom: std::marker::PhantomData::default(), @@ -445,7 +407,7 @@ impl<'a> ContractMtHelpers<'a> { } #[track_caller] - pub fn call(self, sender: &str) -> Result<#proxy_name<'app, MtApp, #(#generic_params,)* >, #error_type> { + pub fn call(self, sender: &str) -> Result<#sylvia ::multitest::Proxy<'app, MtApp, super:: #contract_name >, #error_type> { let Self {code_id, funds, label, admin, salt, msg} = self; match salt { @@ -463,7 +425,7 @@ impl<'a> ContractMtHelpers<'a> { admin, ) .map_err(|err| err.downcast().unwrap()) - .map(|addr| #proxy_name { + .map(|addr| #sylvia ::multitest::Proxy { contract_addr: addr, app: code_id.app, _phantom: std::marker::PhantomData::default(), @@ -477,7 +439,7 @@ impl<'a> ContractMtHelpers<'a> { fn generate_impl_contract(&self) -> TokenStream { let Self { source, - contract, + contract_name, custom, override_entry_points, generic_params, @@ -493,27 +455,27 @@ impl<'a> ContractMtHelpers<'a> { let instantiate_body = override_entry_points .get_entry_point(MsgType::Instantiate) .map(OverrideEntryPoint::emit_multitest_dispatch) - .unwrap_or_else(|| emit_default_dispatch(&MsgType::Instantiate, contract)); + .unwrap_or_else(|| emit_default_dispatch(&MsgType::Instantiate, contract_name)); let exec_body = override_entry_points .get_entry_point(MsgType::Exec) .map(OverrideEntryPoint::emit_multitest_dispatch) - .unwrap_or_else(|| emit_default_dispatch(&MsgType::Exec, contract)); + .unwrap_or_else(|| emit_default_dispatch(&MsgType::Exec, contract_name)); let query_body = override_entry_points .get_entry_point(MsgType::Query) .map(OverrideEntryPoint::emit_multitest_dispatch) - .unwrap_or_else(|| emit_default_dispatch(&MsgType::Query, contract)); + .unwrap_or_else(|| emit_default_dispatch(&MsgType::Query, contract_name)); let sudo_body = override_entry_points .get_entry_point(MsgType::Sudo) .map(OverrideEntryPoint::emit_multitest_dispatch) - .unwrap_or_else(|| emit_default_dispatch(&MsgType::Sudo, contract)); + .unwrap_or_else(|| emit_default_dispatch(&MsgType::Sudo, contract_name)); let migrate_body = match override_entry_points.get_entry_point(MsgType::Migrate) { Some(entry_point) => entry_point.emit_multitest_dispatch(), None if migrate_variants.get_only_variant().is_some() => { - emit_default_dispatch(&MsgType::Migrate, contract) + emit_default_dispatch(&MsgType::Migrate, contract_name) } None => quote! { #sylvia ::anyhow::bail!("migrate not implemented for contract") }, }; @@ -544,16 +506,16 @@ impl<'a> ContractMtHelpers<'a> { let custom_query = custom.query_or_default(); quote! { - impl #bracketed_generics #sylvia ::cw_multi_test::Contract<#custom_msg, #custom_query> for #contract #full_where_clause { - fn execute( - &self, - deps: #sylvia ::cw_std::DepsMut< #custom_query >, - env: #sylvia ::cw_std::Env, - info: #sylvia ::cw_std::MessageInfo, - msg: Vec, - ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> { - #exec_body - } + impl #bracketed_generics #sylvia ::cw_multi_test::Contract<#custom_msg, #custom_query> for super:: #contract_name #full_where_clause { + fn execute( + &self, + deps: #sylvia ::cw_std::DepsMut< #custom_query >, + env: #sylvia ::cw_std::Env, + info: #sylvia ::cw_std::MessageInfo, + msg: Vec, + ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> { + #exec_body + } fn instantiate( &self, @@ -606,98 +568,60 @@ impl<'a> ContractMtHelpers<'a> { } pub struct ImplMtHelpers<'a> { - source: &'a ItemImpl, + source: &'a ItemTrait, error_type: Type, - interfaces: &'a Interfaces, - generic_params: &'a [&'a GenericParam], + associated_types: &'a AssociatedTypes<'a>, exec_variants: MsgVariants<'a, GenericParam>, query_variants: MsgVariants<'a, GenericParam>, sudo_variants: MsgVariants<'a, GenericParam>, where_clause: &'a Option, - contract_module: &'a Path, - contract_name: &'a Ident, } impl<'a> ImplMtHelpers<'a> { - pub fn new( - source: &'a ItemImpl, - generic_params: &'a [&'a GenericParam], - interfaces: &'a Interfaces, - contract_module: &'a Path, - ) -> Self { + pub fn new(source: &'a ItemTrait, associated_types: &'a AssociatedTypes) -> Self { let where_clause = &source.generics.where_clause; - let exec_variants = MsgVariants::new( - source.as_variants(), - MsgType::Exec, - generic_params, - where_clause, - ); - let query_variants = MsgVariants::new( - source.as_variants(), - MsgType::Query, - generic_params, - where_clause, - ); - let sudo_variants = MsgVariants::new( - source.as_variants(), - MsgType::Sudo, - generic_params, - where_clause, - ); + let exec_variants = + MsgVariants::new(source.as_variants(), MsgType::Exec, &[], where_clause); + let query_variants = + MsgVariants::new(source.as_variants(), MsgType::Query, &[], where_clause); let associated_error = source.items.iter().find_map(|item| match item { - ImplItem::Type(ty) if ty.ident == "Error" => Some(&ty.ty), + TraitItem::Type(ty) if ty.ident == "Error" => Some(&ty.ident), _ => None, }); + let sudo_variants = + MsgVariants::new(source.as_variants(), MsgType::Sudo, &[], where_clause); let error_type: Type = match associated_error { Some(error) => parse_quote!(#error), // This should never happen as the `interface` macro requires the trait to have an associated `Error` type None => unreachable!(), }; - let contract = &source.self_ty; - let contract_name = extract_contract_name(contract); - Self { error_type, source, - generic_params, + associated_types, where_clause, - contract_name, - interfaces, exec_variants, query_variants, sudo_variants, - contract_module, } } pub fn emit(&self) -> TokenStream { let Self { - source, error_type, - interfaces, - generic_params, + source, + associated_types, + where_clause, exec_variants, query_variants, sudo_variants, - where_clause, - contract_module, - contract_name, } = self; let sylvia = crate_module(); - let associated_types = ImplAssociatedTypes::new(source); - let interface_name = interface_name(self.source); - let trait_name = Ident::new(&format!("{}", interface_name), interface_name.span()); - - let module = interfaces - .get_only_interface() - .map(|interface| { - let module = &interface.module; - quote! { #module :: } - }) - .unwrap_or(quote! {}); + let interface_name = &source.ident; + let trait_name = Ident::new(&format!("{}Proxy", interface_name), interface_name.span()); let custom_msg: Type = parse_quote! { MultitestExecCustomType }; @@ -715,54 +639,50 @@ impl<'a> ImplMtHelpers<'a> { > }; - let associated_args: Vec<_> = associated_types.as_types(); - let associated_items = associated_types.as_item_types(); + let associated_args: Vec<_> = associated_types + .without_error() + .map(|associated| &associated.ident) + .collect(); + + let associated_args_for_api: Vec<_> = associated_types + .without_special() + .map(|associated| { + let assoc = &associated.ident; + quote! { Self:: #assoc } + }) + .collect(); - let bracketed_generics = emit_bracketed_generics(&associated_args); - let interface_api = - quote! { < #module sv::Api #bracketed_generics as #sylvia ::types::InterfaceApi> }; + let bracketed_generics = emit_bracketed_generics(&associated_args_for_api); + let interface_api = quote! { < Api #bracketed_generics as #sylvia ::types::InterfaceApi> }; + + let associated_types_delcaration = associated_types.without_error(); let exec_methods = exec_variants.emit_interface_multitest_proxy_methods( &custom_msg, &mt_app, error_type, &interface_api, - &associated_items, ); let query_methods = query_variants.emit_interface_multitest_proxy_methods( &custom_msg, &mt_app, error_type, &interface_api, - &associated_items, ); + + let sudo_methods_declarations = + sudo_variants.emit_proxy_methods_declarations(&custom_msg, error_type, &interface_api); let sudo_methods = sudo_variants.emit_interface_multitest_proxy_methods( &custom_msg, &mt_app, error_type, &interface_api, - &associated_items, - ); - let exec_methods_declarations = exec_variants.emit_proxy_methods_declarations( - &custom_msg, - error_type, - &interface_api, - &associated_items, - ); - let query_methods_declarations = query_variants.emit_proxy_methods_declarations( - &custom_msg, - error_type, - &interface_api, - &associated_items, - ); - let sudo_methods_declarations = sudo_variants.emit_proxy_methods_declarations( - &custom_msg, - error_type, - &interface_api, - &associated_items, ); - let contract_proxy = Ident::new(&format!("{}Proxy", contract_name), contract_name.span()); + let exec_methods_declarations = + exec_variants.emit_proxy_methods_declarations(&custom_msg, error_type, &interface_api); + let query_methods_declarations = + query_variants.emit_proxy_methods_declarations(&custom_msg, error_type, &interface_api); let where_predicates = where_clause .as_ref() @@ -772,14 +692,18 @@ impl<'a> ImplMtHelpers<'a> { pub mod test_utils { use super::*; - pub trait #trait_name #where_clause { + pub trait #trait_name #where_clause { + type #error_type: std::fmt::Debug + std::fmt::Display + Send + Sync + 'static; + #(#associated_types_delcaration)* + #(#query_methods_declarations)* #(#exec_methods_declarations)* #(#sudo_methods_declarations)* } - impl #trait_name< #mt_app, #custom_msg, #(#generic_params,)* > for #contract_module :: sv::multitest_utils:: #contract_proxy <'_, #mt_app, #(#generic_params,)* > + impl #trait_name < #mt_app, #custom_msg > for #sylvia ::multitest::Proxy<'_, #mt_app, Contract > where + Contract:: #error_type : std::fmt::Debug + std::fmt::Display + Send + Sync + 'static, #custom_msg: Clone + std::fmt::Debug + std::cmp::PartialEq + cosmwasm_schema::schemars::JsonSchema + 'static, CustomT: #sylvia ::cw_multi_test::Module, WasmT: #sylvia ::cw_multi_test::Wasm, @@ -801,6 +725,9 @@ impl<'a> ImplMtHelpers<'a> { #mt_app : #sylvia ::cw_multi_test::Executor< #custom_msg >, #where_predicates { + type #error_type = :: #error_type ; + #(type #associated_args = :: #associated_args ;)* + #(#query_methods)* #(#exec_methods)* #(#sudo_methods)* @@ -815,7 +742,7 @@ fn emit_default_dispatch(msg_ty: &MsgType, contract_name: &Type) -> TokenStream let values = msg_ty.emit_ctx_values(); let msg_name = msg_ty.as_accessor_wrapper_name(); - let api_msg = quote! { < #contract_name as #sylvia ::types::ContractApi> :: #msg_name }; + let api_msg = quote! { < super:: #contract_name as #sylvia ::types::ContractApi> :: #msg_name }; quote! { #sylvia ::cw_std::from_json::< #api_msg >(&msg)? diff --git a/sylvia-derive/src/parser/mod.rs b/sylvia-derive/src/parser/mod.rs index 5925ede2..6c319075 100644 --- a/sylvia-derive/src/parser/mod.rs +++ b/sylvia-derive/src/parser/mod.rs @@ -6,7 +6,6 @@ pub use attributes::{ ContractErrorAttr, ContractMessageAttr, Custom, Customs, FilteredOverrideEntryPoints, MsgAttr, MsgType, OverrideEntryPoint, ParsedSylviaAttributes, SylviaAttribute, }; -pub use contract::ContractArgs; pub use entry_point::EntryPointArgs; use proc_macro_error::emit_error; diff --git a/sylvia-derive/src/querier.rs b/sylvia-derive/src/querier.rs index cdfb8ae5..f624db04 100644 --- a/sylvia-derive/src/querier.rs +++ b/sylvia-derive/src/querier.rs @@ -59,7 +59,7 @@ where let methods_declaration = variants .variants() .iter() - .map(|variant| variant.emit_querier_declaration(&generics)); + .map(|variant| variant.emit_querier_declaration()); let types_declaration = associated_types.filtered().cloned(); let where_clause = associated_types.as_where_clause(); @@ -115,14 +115,12 @@ impl<'a> ContractQuerier<'a> { let methods_impl = variants .variants() .iter() - .map(|variant| variant.emit_querier_impl::(&api_path, &generics)); - - let methods_impl_copy = methods_impl.clone(); + .map(|variant| variant.emit_querier_impl::(&api_path)); let methods_declaration = variants .variants() .iter() - .map(|variant| variant.emit_querier_declaration(&generics)); + .map(|variant| variant.emit_querier_declaration()); let types_declaration = where_clause .as_ref() @@ -136,20 +134,26 @@ impl<'a> ContractQuerier<'a> { let contract_name = *source.self_ty.clone(); + let bracketed_generics = if !generics.is_empty() { + quote! { < #(#generics,)* > } + } else { + quote! {} + }; + quote! { - pub use #sylvia ::types::{BoundQuerier, Remote}; + pub use #sylvia ::types::BoundQuerier; use std::marker::PhantomData; - pub trait Querier { + pub trait Querier #bracketed_generics { #(#types_declaration)* #(#methods_declaration)* } - impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)*> Querier for BoundQuerier<'a, C, #contract_name > #where_clause { + impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#generics,)*> Querier #bracketed_generics for BoundQuerier<'a, C, #contract_name > #where_clause { #(#types_implementation)* - #(#methods_impl_copy)* + #(#methods_impl)* } } } diff --git a/sylvia-derive/src/strip_self_path.rs b/sylvia-derive/src/strip_self_path.rs index 51572c3c..b31ba5e5 100644 --- a/sylvia-derive/src/strip_self_path.rs +++ b/sylvia-derive/src/strip_self_path.rs @@ -1,7 +1,5 @@ use syn::fold::Fold; -use syn::{parse_quote, ImplItemType, Path}; - -use crate::check_generics::GetPath; +use syn::Path; pub struct StripSelfPath; @@ -15,56 +13,3 @@ impl Fold for StripSelfPath { syn::fold::fold_path(self, Path { segments, ..path }) } } - -pub struct AddSelfPath<'a, GenericT>(&'a [&'a GenericT]); - -impl<'a, GenericT> AddSelfPath<'a, GenericT> { - pub fn new(generics: &'a [&'a GenericT]) -> AddSelfPath { - AddSelfPath(generics) - } -} - -impl<'a, GenericT> Fold for AddSelfPath<'a, GenericT> -where - GenericT: GetPath, -{ - fn fold_path(&mut self, mut path: Path) -> Path { - if let Some(pos) = path.segments.iter().position(|segment| { - self.0.iter().any(|generic| match generic.get_path() { - Some(path) => Some(&segment.ident) == path.get_ident(), - None => false, - }) - }) { - path.segments.insert(pos, parse_quote! { Self }); - } - - syn::fold::fold_path(self, path) - } -} - -pub struct ReplaceAssociatedType<'a>(&'a [&'a ImplItemType]); - -impl<'a> ReplaceAssociatedType<'a> { - pub fn new(associated_types: &'a [&'a ImplItemType]) -> ReplaceAssociatedType<'a> { - ReplaceAssociatedType(associated_types) - } -} - -impl<'a> Fold for ReplaceAssociatedType<'a> { - fn fold_path(&mut self, path: Path) -> Path { - let segments = path - .segments - .into_iter() - .map( - |segment| match self.0.iter().find(|generic| segment.ident == generic.ident) { - Some(generic) => { - let ty = &generic.ty; - parse_quote! { #ty } - } - None => segment, - }, - ) - .collect(); - syn::fold::fold_path(self, Path { segments, ..path }) - } -} diff --git a/sylvia/src/multitest.rs b/sylvia/src/multitest.rs index 312b4cde..20176295 100644 --- a/sylvia/src/multitest.rs +++ b/sylvia/src/multitest.rs @@ -10,10 +10,38 @@ use cw_multi_test::{ GovFailingModule, Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, StargateFailing, Wasm, WasmKeeper, }; +use derivative::Derivative; use schemars::JsonSchema; use serde::de::DeserializeOwned; use serde::Serialize; +#[derive(Derivative)] +#[derivative(Debug)] +pub struct Proxy<'a, MtApp, Contract> { + pub contract_addr: cosmwasm_std::Addr, + #[derivative(Debug = "ignore")] + pub app: &'a crate::multitest::App, + pub _phantom: std::marker::PhantomData<(MtApp, Contract)>, +} + +impl<'a, MtApp, Contract> Proxy<'a, MtApp, Contract> { + pub fn new(contract_addr: cosmwasm_std::Addr, app: &'a App) -> Self { + Proxy { + contract_addr, + app, + _phantom: std::marker::PhantomData::<(MtApp, Contract)>::default(), + } + } +} + +impl<'app, MtApp, Contract> From<(cosmwasm_std::Addr, &'app App)> + for Proxy<'app, MtApp, Contract> +{ + fn from(input: (cosmwasm_std::Addr, &'app App)) -> Self { + Self::new(input.0, input.1) + } +} + pub struct App { app: RefCell, } diff --git a/sylvia/tests/custom_msg.rs b/sylvia/tests/custom_msg.rs index 371e1155..017a6f4e 100644 --- a/sylvia/tests/custom_msg.rs +++ b/sylvia/tests/custom_msg.rs @@ -263,10 +263,11 @@ impl MyContract { #[cfg(all(test, feature = "mt"))] mod tests { - use crate::impl_associated_interface::sv::test_utils::AssociatedInterface; - use crate::impl_interface::sv::test_utils::Interface; - use crate::impl_other_interface::sv::test_utils::OtherInterface; - use crate::impl_some_interface::sv::test_utils::SomeInterface; + use crate::associated_interface::sv::test_utils::AssociatedInterfaceProxy; + use crate::interface::sv::test_utils::InterfaceProxy; + use crate::other_interface::sv::test_utils::OtherInterfaceProxy; + use crate::some_interface::sv::test_utils::SomeInterfaceProxy; + use crate::sv::multitest_utils::ContractImpl; use crate::{MyContract, MyMsg}; use sylvia::multitest::App; diff --git a/sylvia/tests/custom_query.rs b/sylvia/tests/custom_query.rs index 596797df..493016ec 100644 --- a/sylvia/tests/custom_query.rs +++ b/sylvia/tests/custom_query.rs @@ -268,10 +268,11 @@ impl MyContract { #[cfg(all(test, feature = "mt"))] mod tests { - use crate::impl_associated_type_interface::sv::test_utils::AssociatedTypeInterface; - use crate::impl_default_query_interface::sv::test_utils::DefaultQueryInterface; - use crate::impl_interface::sv::test_utils::Interface; - use crate::impl_some_interface::sv::test_utils::SomeInterface; + use crate::associated_type_interface::sv::test_utils::AssociatedTypeInterfaceProxy; + use crate::default_query_interface::sv::test_utils::DefaultQueryInterfaceProxy; + use crate::interface::sv::test_utils::InterfaceProxy; + use crate::some_interface::sv::test_utils::SomeInterfaceProxy; + use crate::sv::multitest_utils::ContractImpl; use crate::{MyContract, MyQuery}; use cosmwasm_std::Empty; diff --git a/sylvia/tests/entry_points.rs b/sylvia/tests/entry_points.rs index 81fcef53..9e06bd2f 100644 --- a/sylvia/tests/entry_points.rs +++ b/sylvia/tests/entry_points.rs @@ -215,7 +215,7 @@ mod tests { use cw_multi_test::Executor; use sylvia::multitest::App; - use crate::contract::sv::multitest_utils::CodeId; + use crate::contract::sv::multitest_utils::{CodeId, ContractImpl}; use crate::contract::sv::{ContractExecMsg, ExecMsg}; use crate::exec::{CustomExecMsg, UserExecMsg}; use crate::sudo::SudoWrapperMsg; diff --git a/sylvia/tests/multitest.rs b/sylvia/tests/multitest.rs index 6bd80037..6bd10207 100644 --- a/sylvia/tests/multitest.rs +++ b/sylvia/tests/multitest.rs @@ -36,7 +36,7 @@ fn instantiate_with_salt() { let code_id = sv::multitest_utils::CodeId::::store_code(&app); - let _: sv::multitest_utils::SomeContractProxy<_, Empty> = code_id + let _: sylvia::multitest::Proxy<_, SomeContract> = code_id .instantiate(Empty {}) .with_salt(salt) .call(owner) diff --git a/sylvia/tests/querier.rs b/sylvia/tests/querier.rs index e88adbc8..d90c0185 100644 --- a/sylvia/tests/querier.rs +++ b/sylvia/tests/querier.rs @@ -96,7 +96,7 @@ pub mod impl_counter { pub struct CounterContract<'a> { pub count: Item<'static, u64>, - pub remote: Item<'static, sv::Remote<'a, CounterContract<'a>>>, + pub remote: Item<'static, sylvia::types::Remote<'a, CounterContract<'a>>>, } #[contract] @@ -114,18 +114,18 @@ impl CounterContract<'_> { fn instantiate(&self, ctx: InstantiateCtx, remote_addr: Addr) -> StdResult { self.count.save(ctx.deps.storage, &0)?; self.remote - .save(ctx.deps.storage, &sv::Remote::new(remote_addr))?; + .save(ctx.deps.storage, &sylvia::types::Remote::new(remote_addr))?; Ok(Response::new()) } } #[cfg(test)] mod tests { + use crate::counter::sv::test_utils::CounterProxy; use cosmwasm_std::testing::mock_dependencies; use cosmwasm_std::{Addr, Empty, QuerierWrapper}; use sylvia::multitest::App; - use crate::impl_counter::sv::test_utils::Counter; use crate::sv::multitest_utils::CodeId; #[test] @@ -135,10 +135,9 @@ mod tests { let remote_addr = Addr::unchecked("remote"); // Remote generation - let remote = - super::counter::sv::Remote::>::new(remote_addr.clone()); + let remote = sylvia::types::Remote::>::new(remote_addr.clone()); let _: super::counter::sv::BoundQuerier<_, _> = remote.querier(&querier_wrapper); - let remote = super::sv::Remote::>::new(remote_addr.clone()); + let remote = sylvia::types::Remote::>::new(remote_addr.clone()); let _: super::sv::BoundQuerier<_, _> = remote.querier(&querier_wrapper); // Querier generation diff --git a/sylvia/tests/replies.rs b/sylvia/tests/replies.rs index 4f75b3d6..ea43b22d 100644 --- a/sylvia/tests/replies.rs +++ b/sylvia/tests/replies.rs @@ -73,6 +73,8 @@ mod reply_contract { } } +use crate::reply_contract::sv::multitest_utils::ContractImpl; + #[test] fn entry_point_generation() { let msg = Reply {