Skip to content

Commit

Permalink
refactored arg_info to collect all results and match them against dif…
Browse files Browse the repository at this point in the history
…ferent outcomes later, wrote compilation test for combined errors for arg_info too.
  • Loading branch information
jaswinder6991 committed Aug 23, 2023
1 parent 9b41078 commit 5eca06c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 48 deletions.
85 changes: 43 additions & 42 deletions near-sdk-macros/src/core_impl/info_extractor/arg_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,28 @@ impl ArgInfo {
/// Extract near-sdk specific argument info.
pub fn new(original: &mut PatType, source_type: &TokenStream) -> syn::Result<Self> {
let mut non_bindgen_attrs = vec![];
let pat_reference;
let pat_mutability;
let mut errors = vec![];
let ident = match original.pat.as_ref() {
let pat_info = match original.pat.as_ref() {
Pat::Ident(pat_ident) => {
pat_reference = pat_ident.by_ref;
pat_mutability = pat_ident.mutability;
pat_ident.ident.clone()
}
_ => {
errors.push(Error::new(
original.span(),
"Only identity patterns are supported in function arguments.",
));
//Providing dummy variables.
//Their value won't have any effect as they are not used later in the code except return.
pat_reference = None;
pat_mutability = None;
Ident::new("DUMMY", Span::call_site())
Ok((pat_ident.by_ref, pat_ident.mutability, pat_ident.ident.clone()))
}
_ => Err(Error::new(
original.span(),
"Only identity patterns are supported in function arguments.",
)),
};

let sanitize_self = utils::sanitize_self(&original.ty, source_type)?;
*original.ty.as_mut() = sanitize_self.ty;
let (reference, mutability, ty) =
utils::extract_ref_mut(original.ty.as_ref(), original.span())?;
let result_sanitize_and_ty = (|| {
let sanitize_self = utils::sanitize_self(&original.ty, source_type)?;
*original.ty.as_mut() = sanitize_self.ty.clone();
let ty_info = utils::extract_ref_mut(original.ty.as_ref(), original.span())?;
Ok((sanitize_self, ty_info))
})();

// In the absence of callback attributes this is a regular argument.
let mut bindgen_ty = BindgenArgType::Regular;
// In the absence of serialization attributes this is a JSON serialization.
let mut serializer_ty = SerializerType::JSON;
let mut more_errors: Vec<Error> = Vec::new();
for attr in &original.attrs {
let attr_str = attr.path.to_token_stream().to_string();
match attr_str.as_str() {
Expand All @@ -91,8 +83,8 @@ impl ArgInfo {
Ok(serializer) => {
serializer_ty = serializer.serializer_type;
}
Err(err) => {
errors.push(err);
Err(e) => {
more_errors.push(e);
}
},
_ => {
Expand All @@ -110,28 +102,37 @@ impl ArgInfo {
&& attr_str != "callback_unwrap"
});

if errors.is_empty() {
Ok(Self {
match (&pat_info, &result_sanitize_and_ty, more_errors.is_empty()) {
(
Ok((pat_reference, pat_mutability, ident)),
Ok((sanitize_self, (reference, mutability, ty))),
true,
) => Ok(Self {
non_bindgen_attrs,
ident,
pat_reference,
pat_mutability,
reference,
mutability,
ty,
ident: ident.clone(),
pat_reference: *pat_reference,
pat_mutability: *pat_mutability,
reference: *reference,
mutability: *mutability,
ty: ty.clone(),
bindgen_ty,
serializer_ty,
self_occurrences: sanitize_self.self_occurrences,
self_occurrences: sanitize_self.self_occurrences.clone(),
original: original.clone(),
})
} else {
Err(errors
.into_iter()
.reduce(|mut l, r| {
l.combine(r);
l
})
.unwrap())
}),
_ => {
more_errors.extend(pat_info.err());
more_errors.extend(result_sanitize_and_ty.err());
Err(Self::combine_errors(more_errors).unwrap())
}
}
}

// helper function
fn combine_errors(errors: impl IntoIterator<Item = Error>) -> Option<Error> {
errors.into_iter().reduce(|mut acc, e| {
acc.combine(syn::Error::new(e.span(), e.to_string()));
acc
})
}
}
10 changes: 7 additions & 3 deletions near-sdk/compilation_tests/invalid_arg_pat.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! Method with non-deserializable argument type.

// //! Method with non-deserializable argument type.
//This tests also checks whether argument errors gets combined or not.
//faulty_method checks a combination of serialiser and type not not supported
//faulty_method1 checks a combination of serialiser and only Identity pattern allowed.
//It is not possible to check Identity pattern and Type not supported together.
use borsh::{BorshDeserialize, BorshSerialize};
use near_sdk::{near_bindgen, PanicOnDefault};

Expand All @@ -9,7 +12,8 @@ struct Storage {}

#[near_bindgen]
impl Storage {
pub fn insert(&mut self, (a, b): (u8, u32)) {}
pub fn faulty_method(&mut self, #[serializer(SomeNonExistentSerializer)] _a: *mut u32) {}
pub fn faulty_method1(&mut self, #[serializer(SomeNonExistentSerializer)] (a, b): (u8, u32)) {}
}

fn main() {}
20 changes: 17 additions & 3 deletions near-sdk/compilation_tests/invalid_arg_pat.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
error: Unsupported serializer type.
--> compilation_tests/invalid_arg_pat.rs:25:1
|
25 | #[near_bindgen]
| ^^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `near_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Unsupported contract API type.
--> compilation_tests/invalid_arg_pat.rs:27:38
|
27 | pub fn faulty_method(&mut self, #[serializer(SomeNonExistentSerializer)] _a: *mut u32,) {}
| ^

error: Only identity patterns are supported in function arguments.
--> compilation_tests/invalid_arg_pat.rs:12:30
--> compilation_tests/invalid_arg_pat.rs:28:38
|
12 | pub fn insert(&mut self, (a, b): (u8, u32)) {}
| ^^^^^^
28 | pub fn faulty_method1(&mut self, #[serializer(SomeNonExistentSerializer)] (a, b): (u8, u32)) {}
| ^

0 comments on commit 5eca06c

Please sign in to comment.