diff --git a/README.md b/README.md index a8335dce..f00b2c44 100644 --- a/README.md +++ b/README.md @@ -350,6 +350,11 @@ pub struct MyContract<'a> { #[contract] #[messages(group as Group)] +// Alternatively: +// It's not needed to provide the interface's +// name if it's corresponds to the last segment +// of the module path: +// #[messages(group)] impl group::Group for MyContract<'_> { type Error = ContractError; @@ -385,7 +390,10 @@ matching the trait name, but written "snake_case" instead of CamelCase. Here I h `group` module for the `Group` trait, but the `CrossStaking` trait should be placed in its own `cross_staking` module (note the underscore). This is a requirement right now - Sylvia generates all the messages and boilerplate in this module and will try -to access them through this module. +to access them through this module. If the interface's name is a camel-case +version of the last module path's segment, the `as InterfaceName` can be omitted. +F.e. `#[messages(cw1 as Cw1)]` can be reduced to `#[messages(cw1)]` + Then there is the `Error` type embedded in the trait - it is also needed there, and the trait bound here has to be at least `From`, as Sylvia might diff --git a/sylvia-derive/src/parser.rs b/sylvia-derive/src/parser.rs index 0fb39c63..2856ac88 100644 --- a/sylvia-derive/src/parser.rs +++ b/sylvia-derive/src/parser.rs @@ -1,5 +1,6 @@ +use convert_case::{Case, Casing}; use proc_macro2::{Punct, TokenStream}; -use proc_macro_error::emit_error; +use proc_macro_error::{emit_error, emit_warning}; use quote::quote; use syn::fold::Fold; use syn::parse::{Error, Nothing, Parse, ParseBuffer, ParseStream, Parser}; @@ -349,18 +350,33 @@ impl Parse for ContractMessageAttr { let generics = extract_generics_from_path(&module); let module = StripGenerics.fold_path(module); - let _: Token![as] = input.parse()?; - let variant = input.parse()?; - + let variant = if input.parse::().is_ok() { + let variant: Ident = input.parse()?; + if Some(variant.to_string()) + == module + .segments + .last() + .map(|name| name.ident.to_string().to_case(Case::UpperCamel)) + { + emit_warning!( + variant.span(), "Redundant `as {}`.", variant; + note = "Interface name is a camel case version of the path and can be auto deduced." + ) + } + variant + } else if let Some(module_name) = &module.segments.last() { + let interface_name = module_name.ident.to_string().to_case(Case::UpperCamel); + syn::Ident::new(&interface_name, module.span()) + } else { + Ident::new("", module.span()) + }; let customs = interface_has_custom(input)?; - if !input.is_empty() { return Err(Error::new( input.span(), - "Unexpected token on the end of `message` attribtue", + "Unexpected token on the end of `messages` attribtue", )); } - Ok(Self { module, variant, diff --git a/sylvia/tests/custom_msg.rs b/sylvia/tests/custom_msg.rs index 55e6693c..0eddd1c7 100644 --- a/sylvia/tests/custom_msg.rs +++ b/sylvia/tests/custom_msg.rs @@ -50,7 +50,7 @@ mod impl_some_interface { use crate::{MyMsg, SomeResponse}; #[contract(module=crate)] - #[messages(crate::some_interface as SomeInterface)] + #[messages(crate::some_interface)] #[sv::custom(msg=MyMsg)] impl SomeInterface for crate::MyContract { type Error = StdError; @@ -93,7 +93,7 @@ mod impl_interface { use sylvia::types::ExecCtx; #[contract(module=crate)] - #[messages(crate::interface as Interface)] + #[messages(crate::interface)] #[sv::custom(msg=MyMsg)] impl Interface for crate::MyContract { type Error = StdError; @@ -127,7 +127,7 @@ mod impl_other_interface { use sylvia::types::ExecCtx; #[contract(module=crate)] - #[messages(crate::other_interface as OtherInterface)] + #[messages(crate::other_interface)] #[sv::custom(msg=crate::MyMsg)] impl OtherInterface for crate::MyContract { type Error = StdError; @@ -162,7 +162,7 @@ mod impl_associated_interface { use sylvia::types::ExecCtx; #[contract(module=crate)] - #[messages(crate::associated_interface as AssociatedInterface)] + #[messages(crate::associated_interface)] #[sv::custom(msg=MyMsg)] impl AssociatedInterface for crate::MyContract { type Error = StdError; @@ -176,10 +176,10 @@ mod impl_associated_interface { } #[contract] -#[messages(some_interface as SomeInterface)] -#[messages(other_interface as OtherInterface: custom(msg))] -#[messages(associated_interface as AssociatedInterface)] -#[messages(interface as Interface)] +#[messages(some_interface)] +#[messages(other_interface: custom(msg))] +#[messages(associated_interface)] +#[messages(interface)] #[sv::custom(msg=MyMsg)] impl MyContract { #[allow(clippy::new_without_default)] diff --git a/sylvia/tests/custom_query.rs b/sylvia/tests/custom_query.rs index 00c33d34..30d92ac3 100644 --- a/sylvia/tests/custom_query.rs +++ b/sylvia/tests/custom_query.rs @@ -49,7 +49,7 @@ mod impl_interface { use crate::{MyQuery, OtherQuery, SomeResponse}; #[contract(module=crate)] - #[messages(crate::interface as Interface)] + #[messages(crate::interface)] #[sv::custom(query=MyQuery)] impl crate::interface::Interface for crate::MyContract { type Error = StdError; @@ -97,7 +97,7 @@ mod impl_some_interface { use crate::{MyQuery, SomeResponse}; #[contract(module=crate)] - #[messages(crate::some_interface as SomeInterface)] + #[messages(crate::some_interface)] #[sv::custom(query=MyQuery)] impl super::some_interface::SomeInterface for crate::MyContract { type Error = StdError; @@ -143,7 +143,7 @@ mod impl_associated_type_interface { use sylvia_derive::contract; #[contract(module=crate)] - #[messages(crate::associated_type_interface as AssociatedTypeInterface)] + #[messages(crate::associated_type_interface)] impl AssociatedTypeInterface for crate::MyContract { type Error = StdError; type QueryC = MyQuery; @@ -188,7 +188,7 @@ mod impl_default_query_interface { use sylvia_derive::contract; #[contract(module=crate)] - #[messages(crate::default_query_interface as DefaultQueryInterface)] + #[messages(crate::default_query_interface)] #[sv::custom(query=MyQuery)] impl DefaultQueryInterface for crate::MyContract { type Error = StdError; @@ -206,10 +206,10 @@ mod impl_default_query_interface { } #[contract] -#[messages(some_interface as SomeInterface)] -#[messages(associated_type_interface as AssociatedTypeInterface)] -#[messages(interface as Interface)] -#[messages(default_query_interface as DefaultQueryInterface: custom(query))] +#[messages(some_interface)] +#[messages(associated_type_interface)] +#[messages(interface)] +#[messages(default_query_interface: custom(query))] #[sv::custom(query=MyQuery)] impl MyContract { #[allow(clippy::new_without_default)] diff --git a/sylvia/tests/dispatching.rs b/sylvia/tests/dispatching.rs index 3e0c096d..44cd548f 100644 --- a/sylvia/tests/dispatching.rs +++ b/sylvia/tests/dispatching.rs @@ -55,7 +55,7 @@ mod impl_interface { use crate::{EmptyQueryResponse, QueryResponse}; #[sylvia::contract(module = crate::contract)] - #[messages(crate::interface as Interface)] + #[messages(crate::interface)] impl crate::interface::Interface for crate::contract::Contract { type Error = StdError; @@ -115,7 +115,7 @@ mod contract { #[allow(dead_code)] #[cfg(not(tarpaulin_include))] #[contract] - #[messages(crate::interface as Interface)] + #[messages(crate::interface)] impl Contract { fn new() -> Self { Self::default() diff --git a/sylvia/tests/querier.rs b/sylvia/tests/querier.rs index 9a78ed3b..e453490e 100644 --- a/sylvia/tests/querier.rs +++ b/sylvia/tests/querier.rs @@ -46,7 +46,7 @@ pub mod impl_counter { use sylvia::types::{ExecCtx, QueryCtx}; #[contract(module=crate)] - #[messages(crate::counter as Counter)] + #[messages(crate::counter)] impl Counter for super::CounterContract<'_> { type Error = StdError; @@ -98,7 +98,7 @@ pub struct CounterContract<'a> { } #[contract] -#[messages(counter as Counter)] +#[messages(counter)] impl CounterContract<'_> { #[allow(clippy::new_without_default)] pub fn new() -> Self { diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs index 4c937085..6245d011 100644 --- a/sylvia/tests/remote.rs +++ b/sylvia/tests/remote.rs @@ -20,7 +20,7 @@ pub mod some_interface { } #[contract] -#[messages(some_interface as SomeInterface)] +#[messages(some_interface)] impl SomeContract { #[allow(clippy::new_without_default)] pub fn new() -> Self {