Skip to content

Commit

Permalink
feat: Add support for generics in interface
Browse files Browse the repository at this point in the history
  • Loading branch information
jawoznia committed Sep 18, 2023
1 parent e6131e4 commit 40c98fd
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 92 deletions.
1 change: 1 addition & 0 deletions sylvia-derive/src/check_generics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use syn::visit::Visit;
use syn::GenericParam;

#[derive(Debug)]
pub struct CheckGenerics<'g> {
generics: &'g [&'g GenericParam],
used: Vec<&'g GenericParam>,
Expand Down
79 changes: 61 additions & 18 deletions sylvia-derive/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ use syn::parse::{Parse, Parser};
use syn::spanned::Spanned;
use syn::{parse_quote, GenericParam, Ident, ItemImpl, ItemTrait, TraitItem, Type};

use crate::check_generics::CheckGenerics;
use crate::crate_module;
use crate::interfaces::Interfaces;
use crate::message::{ContractEnumMessage, EnumMessage, GlueMessage, MsgVariants, StructMessage};
use crate::multitest::{MultitestHelpers, TraitMultitestHelpers};
use crate::parser::{ContractArgs, ContractErrorAttr, Custom, MsgType, OverrideEntryPoints};
use crate::remote::Remote;
use crate::utils::filter_wheres;
use crate::variant_descs::AsVariantDescs;

/// Preprocessed `interface` macro input
Expand Down Expand Up @@ -62,7 +64,7 @@ impl<'a> TraitInput<'a> {
let messages = self.emit_messages();
let multitest_helpers = self.emit_helpers();
let remote = Remote::new(&Interfaces::default()).emit();
let querier = MsgVariants::new(self.item.as_variants(), &self.generics).emit_querier();
let querier = self.emit_queriers();

#[cfg(not(tarpaulin_include))]
{
Expand All @@ -78,6 +80,32 @@ impl<'a> TraitInput<'a> {
}
}

fn emit_queriers(&self) -> TokenStream {
let mut generics_checker = CheckGenerics::new(&self.generics);
let variants = MsgVariants::new(
self.item.as_variants(),
MsgType::Query,
&mut generics_checker,
);

let (used_generics, _) = generics_checker.used_unused();
let wheres = filter_wheres(
&self.item.generics.where_clause,
self.generics.as_slice(),
&used_generics,
);
let where_clause = if !wheres.is_empty() {
quote! { where #(#wheres),* }
} else {
quote! {}
};
let unbonded_generics = used_generics
.iter()
.map(|generic| quote! { #generic })
.collect();
variants.emit_querier(unbonded_generics, where_clause)
}

fn emit_helpers(&self) -> TokenStream {
if cfg!(feature = "mt") {
let multitest_helpers = TraitMultitestHelpers::new(self.item);
Expand Down Expand Up @@ -159,22 +187,25 @@ impl<'a> ImplInput<'a> {
quote! {}
};

let interfaces = Interfaces::new(self.item);
let variants = MsgVariants::new(self.item.as_variants(), &self.generics);
let mut generics_checker = CheckGenerics::new(&self.generics);
let variants = MsgVariants::new(
self.item.as_variants(),
MsgType::Query,
&mut generics_checker,
);

match is_trait {
true => self.process_interface(&interfaces, variants, multitest_helpers),
false => self.process_contract(&interfaces, variants, multitest_helpers),
true => self.process_interface(variants, multitest_helpers),
false => self.process_contract(variants, multitest_helpers),
}
}

fn process_interface(
&self,
interfaces: &Interfaces,
variants: MsgVariants<'a>,
multitest_helpers: TokenStream,
) -> TokenStream {
let querier_bound_for_impl = self.emit_querier_for_bound_impl(interfaces, variants);
let querier_bound_for_impl = self.emit_querier_for_bound_impl(variants);

#[cfg(not(tarpaulin_include))]
quote! {
Expand All @@ -186,14 +217,14 @@ impl<'a> ImplInput<'a> {

fn process_contract(
&self,
interfaces: &Interfaces,
variants: MsgVariants<'a>,
multitest_helpers: TokenStream,
) -> TokenStream {
let messages = self.emit_messages();
let remote = Remote::new(interfaces).emit();
let querier = variants.emit_querier();
let querier_from_impl = interfaces.emit_querier_from_impl();
let remote = Remote::new(&self.interfaces).emit();

let querier = self.emit_querier(variants);
let querier_from_impl = self.interfaces.emit_querier_from_impl();

#[cfg(not(tarpaulin_include))]
{
Expand Down Expand Up @@ -268,17 +299,29 @@ impl<'a> ImplInput<'a> {
.emit()
}

fn emit_querier_for_bound_impl(
&self,
interfaces: &Interfaces,
variants: MsgVariants<'a>,
) -> TokenStream {
let trait_module = interfaces
fn emit_querier(&self, variants: MsgVariants<'a>) -> TokenStream {
let unbonded_generics = vec![];
let where_clause = quote! {};

variants.emit_querier(unbonded_generics, where_clause)
}

fn emit_querier_for_bound_impl(&self, variants: MsgVariants<'a>) -> TokenStream {
let trait_module = self
.interfaces
.interfaces()
.first()
.map(|interface| &interface.module);
let contract_module = self.attributes.module.as_ref();

variants.emit_querier_for_bound_impl(trait_module, contract_module)
// TODO: Extract generics and where clause from Interfaces
let unbonded_generics = vec![];
let where_clause = quote! {};
variants.emit_querier_for_bound_impl(
trait_module,
contract_module,
unbonded_generics,
where_clause,
)
}
}
Loading

0 comments on commit 40c98fd

Please sign in to comment.