From edafa4df7c11854a8f4b3cc3c136e2a52e9449d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Mon, 2 Sep 2024 16:11:36 +0200 Subject: [PATCH 1/2] chore: Make `MsgAttr` a struct Remove redundancy between `MsgAttr` and `MsgType` --- sylvia-derive/src/parser/attributes/mod.rs | 5 +- sylvia-derive/src/parser/attributes/msg.rs | 69 ++++++++-------------- sylvia-derive/src/types/msg_type.rs | 18 +++++- sylvia-derive/src/types/msg_variant.rs | 3 +- 4 files changed, 48 insertions(+), 47 deletions(-) diff --git a/sylvia-derive/src/parser/attributes/mod.rs b/sylvia-derive/src/parser/attributes/mod.rs index d0d00ff9..c3b3cb5f 100644 --- a/sylvia-derive/src/parser/attributes/mod.rs +++ b/sylvia-derive/src/parser/attributes/mod.rs @@ -81,12 +81,13 @@ impl ParsedSylviaAttributes { } if let Some(attr) = result.variant_attrs_forward.first() { - if let Some(MsgAttr::Instantiate) = result.msg_attr { + let msg_type = result.msg_attr.as_ref().map(MsgAttr::msg_type); + if let Some(MsgType::Instantiate) = msg_type { emit_error!( attr.span, "The attribute `sv::attr` is not supported for `instantiate`"; note = "Message `instantiate` is a structure, use `#[sv::msg_attr] instead`"; ); - } else if let Some(MsgAttr::Migrate) = result.msg_attr { + } else if let Some(MsgType::Migrate) = msg_type { emit_error!( attr.span, "The attribute `sv::attr` is not supported for `migrate`"; note = "Message `migrate` is a structure, use `#[sv::msg_attr] instead`"; diff --git a/sylvia-derive/src/parser/attributes/msg.rs b/sylvia-derive/src/parser/attributes/msg.rs index c415f53a..446dd334 100644 --- a/sylvia-derive/src/parser/attributes/msg.rs +++ b/sylvia-derive/src/parser/attributes/msg.rs @@ -2,7 +2,8 @@ use proc_macro_error::emit_error; use syn::parse::{Error, Parse, ParseStream, Parser}; use syn::{bracketed, Ident, MetaList, Result, Token}; -/// Type of message to be generated +/// Supported message types. +/// Representation of the first parameter in `#[sv::msg(..)] attribute. #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum MsgType { Exec, @@ -16,7 +17,7 @@ pub enum MsgType { /// ArgumentParser holds `resp` parameter parsed from `sv::msg` attribute. #[derive(Default)] struct ArgumentParser { - pub resp_type: Option, + pub query_resp_type: Option, pub reply_handlers: Vec, pub reply_on: Option, } @@ -32,7 +33,7 @@ impl Parse for ArgumentParser { "resp" => { let _: Token![=] = input.parse()?; let resp_type: Ident = input.parse()?; - result.resp_type = Some(resp_type); + result.query_resp_type = Some(resp_type); } "handlers" => { let _: Token![=] = input.parse()?; @@ -91,18 +92,11 @@ impl ReplyOn { /// Parsed representation of `#[sv::msg(...)]` attribute. #[derive(Clone)] -pub enum MsgAttr { - Exec, - Query { - resp_type: Option, - }, - Instantiate, - Migrate, - Reply { - _handlers: Vec, - _reply_on: ReplyOn, - }, - Sudo, +pub struct MsgAttr { + msg_type: MsgType, + query_resp_type: Option, + _reply_handlers: Vec, + _reply_on: ReplyOn, } impl MsgAttr { @@ -112,6 +106,14 @@ impl MsgAttr { err }) } + + pub fn msg_type(&self) -> MsgType { + self.msg_type + } + + pub fn resp_type(&self) -> &Option { + &self.query_resp_type + } } impl PartialEq for MsgAttr { @@ -120,40 +122,21 @@ impl PartialEq for MsgAttr { } } -impl MsgAttr { - pub fn msg_type(&self) -> MsgType { - match self { - Self::Exec { .. } => MsgType::Exec, - Self::Query { .. } => MsgType::Query, - Self::Instantiate { .. } => MsgType::Instantiate, - Self::Migrate { .. } => MsgType::Migrate, - Self::Reply { .. } => MsgType::Reply, - Self::Sudo { .. } => MsgType::Sudo, - } - } -} - impl Parse for MsgAttr { fn parse(input: ParseStream) -> Result { - let ty: Ident = input.parse()?; + let msg_type: Ident = input.parse()?; + let msg_type = MsgType::new(&msg_type)?; let ArgumentParser { - resp_type, + query_resp_type, reply_handlers, reply_on, } = ArgumentParser::parse(input)?; - let result = match ty.to_string().as_str() { - "exec" => Self::Exec, - "query" => Self::Query { resp_type }, - "instantiate" => Self::Instantiate, - "migrate" => Self::Migrate, - "reply" => Self::Reply {_handlers: reply_handlers, _reply_on: reply_on.unwrap_or_default()}, - "sudo" => Self::Sudo, - _ => return Err(Error::new( - input.span(), - "Invalid message type, expected one of: `exec`, `query`, `instantiate`, `migrate`, `reply` or `sudo`.", - )) - }; - Ok(result) + Ok(Self { + msg_type, + query_resp_type, + _reply_handlers: reply_handlers, + _reply_on: reply_on.unwrap_or_default(), + }) } } diff --git a/sylvia-derive/src/types/msg_type.rs b/sylvia-derive/src/types/msg_type.rs index b89edf05..182ad197 100644 --- a/sylvia-derive/src/types/msg_type.rs +++ b/sylvia-derive/src/types/msg_type.rs @@ -2,7 +2,8 @@ use proc_macro2::TokenStream; use proc_macro_error::emit_error; use quote::quote; use syn::fold::Fold; -use syn::{parse_quote, GenericParam, Ident, Type}; +use syn::parse::Error; +use syn::{parse_quote, GenericParam, Ident, Result, Type}; use crate::crate_module; use crate::fold::StripSelfPath; @@ -10,6 +11,21 @@ use crate::parser::attributes::msg::MsgType; use crate::parser::Customs; impl MsgType { + pub fn new(msg_type: &Ident) -> Result { + match msg_type.to_string().as_str() { + "exec" => Ok(Self::Exec), + "query" => Ok(Self::Query ), + "instantiate" => Ok(Self::Instantiate), + "migrate" => Ok(Self::Migrate), + "reply" => Ok(Self::Reply ), + "sudo" => Ok(Self::Sudo), + _ => return Err(Error::new( + msg_type.span(), + "Invalid message type, expected one of: `exec`, `query`, `instantiate`, `migrate`, `reply` or `sudo`.", + )) + } + } + pub fn emit_ctx_type(self, query_type: &Type) -> TokenStream { use MsgType::*; diff --git a/sylvia-derive/src/types/msg_variant.rs b/sylvia-derive/src/types/msg_variant.rs index 75f06f4c..55b426c5 100644 --- a/sylvia-derive/src/types/msg_variant.rs +++ b/sylvia-derive/src/types/msg_variant.rs @@ -44,7 +44,8 @@ impl<'a> MsgVariant<'a> { let fields = process_fields(sig, generics_checker); let msg_type = msg_attr.msg_type(); - let return_type = if let MsgAttr::Query { resp_type, .. } = msg_attr { + let return_type = if msg_attr.msg_type() == MsgType::Query { + let resp_type = &msg_attr.resp_type(); match resp_type { Some(resp_type) => { let resp_type = parse_quote! { #resp_type }; From 15164b7f2e95f27ca9132d9d6d0a8b8e6895eba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Mon, 2 Sep 2024 16:15:39 +0200 Subject: [PATCH 2/2] chore: Store `MsgAttr` in `MsgVariant` --- sylvia-derive/src/parser/attributes/msg.rs | 4 ++-- sylvia-derive/src/types/msg_type.rs | 2 +- sylvia-derive/src/types/msg_variant.rs | 17 ++++++++--------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sylvia-derive/src/parser/attributes/msg.rs b/sylvia-derive/src/parser/attributes/msg.rs index 446dd334..faf22436 100644 --- a/sylvia-derive/src/parser/attributes/msg.rs +++ b/sylvia-derive/src/parser/attributes/msg.rs @@ -68,7 +68,7 @@ impl Parse for ArgumentParser { } /// Representation of `reply_on` parameter in `#[sv::msg(reply(...))]` attribute. -#[derive(Default, Clone)] +#[derive(Debug, Default, Clone)] pub enum ReplyOn { Success, Failure, @@ -91,7 +91,7 @@ impl ReplyOn { } /// Parsed representation of `#[sv::msg(...)]` attribute. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct MsgAttr { msg_type: MsgType, query_resp_type: Option, diff --git a/sylvia-derive/src/types/msg_type.rs b/sylvia-derive/src/types/msg_type.rs index 182ad197..562fe396 100644 --- a/sylvia-derive/src/types/msg_type.rs +++ b/sylvia-derive/src/types/msg_type.rs @@ -19,7 +19,7 @@ impl MsgType { "migrate" => Ok(Self::Migrate), "reply" => Ok(Self::Reply ), "sudo" => Ok(Self::Sudo), - _ => return Err(Error::new( + _ => Err(Error::new( msg_type.span(), "Invalid message type, expected one of: `exec`, `query`, `instantiate`, `migrate`, `reply` or `sudo`.", )) diff --git a/sylvia-derive/src/types/msg_variant.rs b/sylvia-derive/src/types/msg_variant.rs index 55b426c5..0432f7a2 100644 --- a/sylvia-derive/src/types/msg_variant.rs +++ b/sylvia-derive/src/types/msg_variant.rs @@ -23,7 +23,7 @@ pub struct MsgVariant<'a> { /// Type extracted only in case of `Query` and used in `cosmwasm_schema::QueryResponses` /// `returns` attribute. return_type: Option, - msg_type: MsgType, + msg_attr: MsgAttr, attrs_to_forward: Vec, } @@ -42,7 +42,6 @@ impl<'a> MsgVariant<'a> { let name = function_name.to_case(Case::UpperCamel); let fields = process_fields(sig, generics_checker); - let msg_type = msg_attr.msg_type(); let return_type = if msg_attr.msg_type() == MsgType::Query { let resp_type = &msg_attr.resp_type(); @@ -68,7 +67,7 @@ impl<'a> MsgVariant<'a> { function_name, fields, return_type, - msg_type, + msg_attr, attrs_to_forward, } } @@ -78,13 +77,13 @@ impl<'a> MsgVariant<'a> { let Self { name, fields, - msg_type, + msg_attr, return_type, attrs_to_forward, .. } = self; let fields = fields.iter().map(MsgField::emit); - let returns_attribute = msg_type.emit_returns_attribute(return_type); + let returns_attribute = msg_attr.msg_type().emit_returns_attribute(return_type); let attrs_to_forward = attrs_to_forward.iter().map(|attr| &attr.attrs); quote! { @@ -104,7 +103,7 @@ impl<'a> MsgVariant<'a> { name, fields, function_name, - msg_type, + msg_attr, .. } = self; @@ -120,7 +119,7 @@ impl<'a> MsgVariant<'a> { .zip(args.clone()) .map(|(field, num_field)| quote!(#field : #num_field)); - let method_call = msg_type.emit_dispatch_leg(function_name, &args); + let method_call = msg_attr.msg_type().emit_dispatch_leg(function_name, &args); quote! { #name { @@ -167,8 +166,8 @@ impl<'a> MsgVariant<'a> { &self.fields } - pub fn msg_type(&self) -> &MsgType { - &self.msg_type + pub fn msg_type(&self) -> MsgType { + self.msg_attr.msg_type() } pub fn return_type(&self) -> &Option {