Skip to content

Commit

Permalink
commit fix
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaicalinluca committed Oct 12, 2023
1 parent 3bbf856 commit 5e9b274
Show file tree
Hide file tree
Showing 16 changed files with 120 additions and 14 deletions.
1 change: 1 addition & 0 deletions framework/base/src/abi/endpoint_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub struct EndpointAbi {
pub payable_in_tokens: &'static [&'static str],
pub inputs: Vec<InputAbi>,
pub outputs: OutputAbis,
pub allow_multiple_var_args: bool
}

impl EndpointAbi {
Expand Down
1 change: 1 addition & 0 deletions framework/base/src/external_view_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ pub fn external_view_contract_constructor_abi() -> EndpointAbi {
multi_arg: false,
}].to_vec(),
outputs: OutputAbis::new(),
allow_multiple_var_args: false
}
}
5 changes: 5 additions & 0 deletions framework/base/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ macro_rules! only_owner {
};
}

#[macro_export]
macro_rules! allow_multiple_var_args {
() => {};
}

/// Converts usize to NonZeroUsize or returns SCError.
#[macro_export]
macro_rules! non_zero_usize {
Expand Down
5 changes: 5 additions & 0 deletions framework/derive/src/generate/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn generate_endpoint_snippet(
only_admin: bool,
mutability: EndpointMutabilityMetadata,
endpoint_type: EndpointTypeMetadata,
allow_multiple_var_args: bool,
) -> proc_macro2::TokenStream {
let endpoint_docs = &m.docs;
let rust_method_name = m.name.to_string();
Expand Down Expand Up @@ -65,6 +66,7 @@ fn generate_endpoint_snippet(
inputs: multiversx_sc::types::heap::Vec::new(),
outputs: multiversx_sc::types::heap::Vec::new(),
labels: &[ #(#label_names),* ],
allow_multiple_var_args: #allow_multiple_var_args,
};
#(#input_snippets)*
#output_snippet
Expand All @@ -84,6 +86,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec<proc_macro2::Toke
false,
EndpointMutabilityMetadata::Mutable,
EndpointTypeMetadata::Init,
m.is_allow_multiple_var_args(),
);
Some(quote! {
#endpoint_def
Expand All @@ -98,6 +101,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec<proc_macro2::Toke
endpoint_metadata.only_admin,
endpoint_metadata.mutability.clone(),
EndpointTypeMetadata::Endpoint,
endpoint_metadata.allow_multiple_var_args,
);
Some(quote! {
#endpoint_def
Expand All @@ -112,6 +116,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec<proc_macro2::Toke
false,
EndpointMutabilityMetadata::Mutable,
EndpointTypeMetadata::PromisesCallback,
m.is_allow_multiple_var_args(),
);
Some(quote! {
#endpoint_def
Expand Down
1 change: 1 addition & 0 deletions framework/derive/src/model/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ pub struct TraitProperties {
pub only_owner: bool,
pub only_admin: bool,
pub only_user_account: bool,
pub allow_multiple_var_args: bool
}
3 changes: 3 additions & 0 deletions framework/derive/src/model/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::{EndpointMutabilityMetadata, MethodPayableMetadata};
#[derive(Clone, Debug)]
pub struct InitMetadata {
pub payable: MethodPayableMetadata,
pub allow_multiple_var_args: bool
}

#[derive(Clone, Debug)]
Expand All @@ -13,11 +14,13 @@ pub struct EndpointMetadata {
pub only_admin: bool,
pub only_user_account: bool,
pub mutability: EndpointMutabilityMetadata,
pub allow_multiple_var_args: bool
}

#[derive(Clone, Debug)]
pub struct CallbackMetadata {
pub callback_name: syn::Ident,
pub allow_multiple_var_args: bool
}

/// Method visibility from the point of view of the smart contract
Expand Down
13 changes: 13 additions & 0 deletions framework/derive/src/model/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,17 @@ impl Method {
PublicRole::Private => MethodPayableMetadata::NotPayable,
}
}

pub fn is_allow_multiple_var_args(&self) -> bool {
match &self.public_role {
PublicRole::Init(init_metadata) => init_metadata.allow_multiple_var_args,
PublicRole::Endpoint(endpoint_metadata) => endpoint_metadata.allow_multiple_var_args,
PublicRole::Callback(callback_metadata)
| PublicRole::CallbackPromise(callback_metadata) => {
callback_metadata.allow_multiple_var_args
},
PublicRole::CallbackRaw => true,
PublicRole::Private => false,
}
}
}
1 change: 1 addition & 0 deletions framework/derive/src/parse/attributes/attr_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ pub(super) static ATTR_STORAGE_IS_EMPTY: &str = "storage_is_empty";
pub(super) static ATTR_STORAGE_CLEAR: &str = "storage_clear";
pub(super) static ATTR_PROXY: &str = "proxy";
pub(super) static ATTR_LABEL: &str = "label";
pub(super) static ATTR_ALLOW_MULTIPLE_VAR_ARGS: &str = "allow_multiple_var_args";
4 changes: 4 additions & 0 deletions framework/derive/src/parse/attributes/endpoint_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ pub fn is_proxy(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, ATTR_PROXY)
}

pub fn is_allow_multiple_var_args(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, ATTR_ALLOW_MULTIPLE_VAR_ARGS)
}

#[derive(Clone, Debug)]
pub struct EndpointAttribute {
pub endpoint_name: Option<syn::Ident>,
Expand Down
4 changes: 4 additions & 0 deletions framework/derive/src/parse/attributes/trait_argument_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ pub fn is_only_owner_prop(attr: &syn::Attribute) -> bool {
pub fn is_only_admin_prop(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, PROP_ADMIN_OWNER)
}

pub fn is_allow_multiple_var_args_prop(attr: &syn::Attribute) -> bool {
is_attribute_with_no_args(attr, PROP_ALLOW_MULTIPLE_VAR_ARGS)
}
1 change: 1 addition & 0 deletions framework/derive/src/parse/attributes/trait_prop_names.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub(super) static PROP_ONLY_OWNER: &str = "only_owner";
pub(super) static PROP_ADMIN_OWNER: &str = "only_admin";
pub(super) static PROP_ALLOW_MULTIPLE_VAR_ARGS: &str = "allow_multiple_var_args";
24 changes: 21 additions & 3 deletions framework/derive/src/parse/endpoint_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::model::{

use super::{
attributes::{
is_callback_raw, is_init, is_only_admin, is_only_owner, is_only_user_account,
CallbackAttribute, EndpointAttribute, ExternalViewAttribute, LabelAttribute,
OutputNameAttribute, PromisesCallbackAttribute, ViewAttribute,
is_allow_multiple_var_args, is_callback_raw, is_init, is_only_admin, is_only_owner,
is_only_user_account, CallbackAttribute, EndpointAttribute, ExternalViewAttribute,
LabelAttribute, OutputNameAttribute, PromisesCallbackAttribute, ViewAttribute,
},
MethodAttributesPass1,
};
Expand All @@ -27,13 +27,26 @@ pub fn process_init_attribute(
check_single_role(&*method);
method.public_role = PublicRole::Init(InitMetadata {
payable: pass_1_data.payable.clone(),
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
true
} else {
false
}
}

pub fn process_allow_multiple_var_args_attribute(
attr: &syn::Attribute,
pass_1_data: &mut MethodAttributesPass1,
) -> bool {
let is_allow_multiple_var_args = is_allow_multiple_var_args(attr);
if is_allow_multiple_var_args {
pass_1_data.allow_multiple_var_args = true;
}

is_allow_multiple_var_args
}

pub fn process_only_owner_attribute(
attr: &syn::Attribute,
pass_1_data: &mut MethodAttributesPass1,
Expand Down Expand Up @@ -86,6 +99,7 @@ pub fn process_endpoint_attribute(
only_admin: pass_1_data.only_admin,
only_user_account: pass_1_data.only_user_account,
mutability: EndpointMutabilityMetadata::Mutable,
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
})
.is_some()
Expand All @@ -110,6 +124,7 @@ pub fn process_view_attribute(
only_admin: pass_1_data.only_admin,
only_user_account: pass_1_data.only_user_account,
mutability: EndpointMutabilityMetadata::Readonly,
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
})
.is_some()
Expand All @@ -134,6 +149,7 @@ pub fn process_external_view_attribute(
only_admin: pass_1_data.only_admin,
only_user_account: pass_1_data.only_user_account,
mutability: EndpointMutabilityMetadata::Readonly,
allow_multiple_var_args: pass_1_data.allow_multiple_var_args,
});
})
.is_some()
Expand All @@ -159,6 +175,7 @@ pub fn process_callback_attribute(attr: &syn::Attribute, method: &mut Method) ->
};
method.public_role = PublicRole::Callback(CallbackMetadata {
callback_name: callback_ident,
allow_multiple_var_args: method.is_allow_multiple_var_args(),
});
})
.is_some()
Expand All @@ -174,6 +191,7 @@ pub fn process_promises_callback_attribute(attr: &syn::Attribute, method: &mut M
};
method.public_role = PublicRole::CallbackPromise(CallbackMetadata {
callback_name: callback_ident,
allow_multiple_var_args: method.is_allow_multiple_var_args(),
});
})
.is_some()
Expand Down
5 changes: 4 additions & 1 deletion framework/derive/src/parse/method_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ use super::{
process_endpoint_attribute, process_external_view_attribute, process_init_attribute,
process_label_names_attribute, process_only_admin_attribute, process_only_owner_attribute,
process_only_user_account_attribute, process_output_names_attribute, process_payable_attribute,
process_promises_callback_attribute, process_view_attribute,
process_promises_callback_attribute, process_view_attribute, process_allow_multiple_var_args_attribute
};
pub struct MethodAttributesPass1 {
pub method_name: String,
pub payable: MethodPayableMetadata,
pub only_owner: bool,
pub only_admin: bool,
pub only_user_account: bool,
pub allow_multiple_var_args: bool
}

pub fn process_method(m: &syn::TraitItemMethod, trait_attributes: &TraitProperties) -> Method {
Expand All @@ -36,6 +37,7 @@ pub fn process_method(m: &syn::TraitItemMethod, trait_attributes: &TraitProperti
only_owner: trait_attributes.only_owner,
only_admin: trait_attributes.only_admin,
only_user_account: trait_attributes.only_user_account,
allow_multiple_var_args: trait_attributes.allow_multiple_var_args
};
let mut first_pass_unprocessed_attributes = Vec::new();

Expand Down Expand Up @@ -90,6 +92,7 @@ fn process_attribute_first_pass(
|| process_only_owner_attribute(attr, first_pass_data)
|| process_only_admin_attribute(attr, first_pass_data)
|| process_only_user_account_attribute(attr, first_pass_data)
|| process_allow_multiple_var_args_attribute(attr, first_pass_data)
}

fn process_attributes_second_pass(
Expand Down
12 changes: 12 additions & 0 deletions framework/derive/src/parse/trait_argument_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fn process_trait_attribute(
) -> bool {
process_only_owner_argument(attr, trait_arg_metadata)
|| process_only_admin_argument(attr, trait_arg_metadata)
|| process_allow_multiple_var_args_argument(attr, trait_arg_metadata)
}

fn process_only_owner_argument(attr: &syn::Attribute, arg_metadata: &mut TraitProperties) -> bool {
Expand All @@ -37,3 +38,14 @@ fn process_only_admin_argument(attr: &syn::Attribute, arg_metadata: &mut TraitPr
}
has_attr
}

fn process_allow_multiple_var_args_argument(
attr: &syn::Attribute,
arg_metadata: &mut TraitProperties,
) -> bool {
let has_attr = is_allow_multiple_var_args_prop(attr);
if has_attr {
arg_metadata.allow_multiple_var_args = true;
}
has_attr
}
3 changes: 3 additions & 0 deletions framework/meta/src/abi_json/endpoint_abi_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pub struct EndpointAbiJson {
pub outputs: Vec<OutputAbiJson>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub labels: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_multiple_var_args: Option<bool>
}

impl From<&EndpointAbi> for EndpointAbiJson {
Expand All @@ -120,6 +122,7 @@ impl From<&EndpointAbi> for EndpointAbiJson {
inputs: abi.inputs.iter().map(InputAbiJson::from).collect(),
outputs: abi.outputs.iter().map(OutputAbiJson::from).collect(),
labels: abi.labels.iter().map(|&label| label.to_owned()).collect(),
allow_multiple_var_args: if abi.allow_multiple_var_args { Some(true) } else { None }
}
}
}
51 changes: 41 additions & 10 deletions framework/meta/src/cmd/contract/output_contract/oc_validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,47 @@ fn validate_contract_var_args(abi: &ContractAbi) -> Result<(), String> {
}

fn validate_endpoint_var_args(endpoint_abi: &EndpointAbi) -> Result<(), String> {
let mut var_args_encountered = false;
for arg in &endpoint_abi.inputs {
if arg.multi_arg {
var_args_encountered = true;
} else if var_args_encountered {
return Err(format!(
"Found regular arguments after var-args in method {}. This is not allowed, because it makes it impossible to parse the arguments.",
&endpoint_abi.rust_method_name));
}
let num_var_args = endpoint_abi
.inputs
.iter()
.filter(|input| input.multi_arg)
.count();
if num_var_args > 1usize && !endpoint_abi.allow_multiple_var_args {
return Err(format!(
"Multiple var args found in {}. Use #[allow_multiple_var_args] if you want to enable this feature",
&endpoint_abi.rust_method_name));
}

Ok(())
}

#[cfg(test)]
mod tests {
use multiversx_sc::abi::{InputAbi, TypeName};

use super::*;

#[test]
fn validate_endpoint_var_args_test() {
let mut endpoint_def = EndpointAbi::default();
let var_arg_1 = InputAbi {
arg_name: "arg_1",
type_name: TypeName::new(),
multi_arg: true,
};
let var_arg_2 = InputAbi {
arg_name: "arg_2",
type_name: TypeName::new(),
multi_arg: true,
};
endpoint_def.inputs.push(var_arg_1);
endpoint_def.inputs.push(var_arg_2);

assert_eq!(endpoint_def.allow_multiple_var_args, false);

Check warning on line 63 in framework/meta/src/cmd/contract/output_contract/oc_validate.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] framework/meta/src/cmd/contract/output_contract/oc_validate.rs#L63

warning: used `assert_eq!` with a literal bool --> framework/meta/src/cmd/contract/output_contract/oc_validate.rs:63:9 | 63 | assert_eq!(endpoint_def.allow_multiple_var_args, false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison = note: `#[warn(clippy::bool_assert_comparison)]` on by default help: replace it with `assert!(..)` | 63 - assert_eq!(endpoint_def.allow_multiple_var_args, false); 63 + assert!(!endpoint_def.allow_multiple_var_args); |
Raw output
framework/meta/src/cmd/contract/output_contract/oc_validate.rs:63:9:w:warning: used `assert_eq!` with a literal bool
  --> framework/meta/src/cmd/contract/output_contract/oc_validate.rs:63:9
   |
63 |         assert_eq!(endpoint_def.allow_multiple_var_args, false);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison
   = note: `#[warn(clippy::bool_assert_comparison)]` on by default
help: replace it with `assert!(..)`
   |
63 -         assert_eq!(endpoint_def.allow_multiple_var_args, false);
63 +         assert!(!endpoint_def.allow_multiple_var_args);
   |


__END__
assert_eq!(Err(format!(
"Multiple var args found in {}. Use #[allow_multiple_var_args] if you want to enable this feature",
&endpoint_def.rust_method_name)), validate_endpoint_var_args(&endpoint_def));

endpoint_def.allow_multiple_var_args = true;
assert_eq!(Ok(()), validate_endpoint_var_args(&endpoint_def));
}
}

0 comments on commit 5e9b274

Please sign in to comment.