Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: aliasing for functions with duplicate names #1144

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions near-sdk-macros/src/core_impl/abi/abi_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ pub fn generate(i: &ItemImplInfo) -> TokenStream2 {
}

let functions: Vec<TokenStream2> = i.methods.iter().map(|m| m.abi_struct()).collect();
let first_function_name = &i.methods[0].attr_signature_info.ident;
let ident_ = &i.methods[0].attr_signature_info.ident;
let first_function_name = match &i.methods[0].attr_signature_info.method_kind {
MethodKind::View(m) => m
.alias
.as_ref()
.map(|alias| syn::Ident::new(alias, ident_.span()))
.unwrap_or(ident_.clone()),
_ => ident_.clone(),
};

let near_abi_symbol = format_ident!("__near_abi_{}", first_function_name);
quote! {
#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -79,7 +88,13 @@ impl ImplItemMethodInfo {
pub fn abi_struct(&self) -> TokenStream2 {
let attr_signature_info = &self.attr_signature_info;

let function_name_str = attr_signature_info.ident.to_string();
let ident_ = attr_signature_info.ident.to_string();
let function_name_str = match &attr_signature_info.method_kind {
MethodKind::View(m) => m.alias.clone().unwrap_or(ident_.to_string()),
MethodKind::Call(m) => m.alias.clone().unwrap_or(ident_.to_string()),
MethodKind::Init(_) => ident_.to_string(),
};

let function_doc = match parse_rustdoc(&attr_signature_info.non_bindgen_attrs) {
Some(doc) => quote! { ::std::option::Option::Some(::std::string::String::from(#doc)) },
None => quote! { ::std::option::Option::None },
Expand Down Expand Up @@ -324,7 +339,7 @@ mod tests {
#[handle_result]
pub fn f3(&mut self, arg0: FancyStruct, arg1: u64) -> Result<IsOk, Error> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = method_info.abi_struct();

local_insta_assert_snapshot!(pretty_print_fn_body_syn_str(actual));
Expand All @@ -339,7 +354,7 @@ mod tests {
#[handle_result]
pub fn f3(&mut self, #[serializer(borsh)] arg0: FancyStruct) -> Result<IsOk, Error> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = method_info.abi_struct();

local_insta_assert_snapshot!(pretty_print_fn_body_syn_str(actual));
Expand All @@ -355,7 +370,7 @@ mod tests {
#[callback_vec] x: Vec<String>,
) -> bool { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = method_info.abi_struct();

local_insta_assert_snapshot!(pretty_print_fn_body_syn_str(actual));
Expand All @@ -367,7 +382,7 @@ mod tests {
let mut method = parse_quote! {
pub fn method(&self, #[callback_unwrap] #[serializer(borsh)] x: &mut u64, #[serializer(borsh)] y: String, #[callback_unwrap] #[serializer(json)] z: Vec<u8>) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = method_info.abi_struct();

local_insta_assert_snapshot!(pretty_print_fn_body_syn_str(actual));
Expand All @@ -380,7 +395,7 @@ mod tests {
#[init(ignore_state)]
pub fn new() -> u64 { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = method_info.abi_struct();

local_insta_assert_snapshot!(pretty_print_fn_body_syn_str(actual));
Expand All @@ -392,7 +407,7 @@ mod tests {
let mut method = parse_quote! {
pub fn method() { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = method_info.abi_struct();

local_insta_assert_snapshot!(pretty_print_fn_body_syn_str(actual));
Expand Down
36 changes: 26 additions & 10 deletions near-sdk-macros/src/core_impl/code_generator/ext.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::core_impl::{serializer, AttrSigInfo};
use crate::{
core_impl::{serializer, AttrSigInfo},
MethodKind,
};
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
use quote::{format_ident, quote, ToTokens};
use syn::{parse_quote, Attribute, Generics, Path, Signature};
Expand Down Expand Up @@ -116,8 +119,21 @@ fn generate_ext_function(attr_signature_info: &AttrSigInfo) -> TokenStream2 {
let serialize =
serializer::generate_serializer(attr_signature_info, &attr_signature_info.input_serializer);

let AttrSigInfo { non_bindgen_attrs, ident, original_sig, .. } = attr_signature_info;
let ident_str = ident.to_string();
let AttrSigInfo { non_bindgen_attrs, ident, original_sig, method_kind, .. } =
attr_signature_info;

let ident_ = ident.clone().to_string();
let ident_str = match method_kind {
MethodKind::Call(m) => &m.alias,
MethodKind::Init(_) => &None,
MethodKind::View(m) => &m.alias,
}
.as_ref()
.unwrap_or(&ident_)
.to_string();

let ident = &Ident::new(&ident_str, ident.span());

let mut new_non_bindgen_attrs = TokenStream2::new();
for attribute in non_bindgen_attrs.iter() {
if is_fn_attribute_to_forward(attribute) {
Expand Down Expand Up @@ -154,15 +170,15 @@ mod tests {
fn ext_gen() {
let st: ItemStruct = parse_quote! { struct Test { a: u8 } };
let actual = generate_ext_structs(&st.ident, Some(&st.generics));

local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap());
}

#[test]
fn module_ext_gen() {
let ident: Ident = parse_quote! { Test };
let actual = generate_ext_structs(&ident, None);

local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap());
}

Expand All @@ -177,7 +193,7 @@ mod tests {
#[warn(unused)]
pub fn method(&self) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = generate_ext_function(&method_info.attr_signature_info);

local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap());
Expand All @@ -189,9 +205,9 @@ mod tests {
let mut method: ImplItemFn = parse_quote! {
pub fn method(&self, k: &String) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = generate_ext_function(&method_info.attr_signature_info);

local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap());
}

Expand All @@ -201,9 +217,9 @@ mod tests {
let mut method: syn::ImplItemFn = parse_quote! {
pub fn borsh_test(&mut self, #[serializer(borsh)] a: String) {}
};
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, None, impl_type).unwrap().unwrap();
let actual = generate_ext_function(&method_info.attr_signature_info);

local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ use crate::core_impl::info_extractor::{ImplItemMethodInfo, SerializerType};
use crate::core_impl::{MethodKind, ReturnKind};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::Receiver;
use syn::{Receiver, Type};

impl ImplItemMethodInfo {
/// Generate wrapper method for the given method of the contract.
pub fn method_wrapper(&self) -> TokenStream2 {
let non_bindgen_attrs = self.non_bindgen_attrs_tokens();

let ident = &self.attr_signature_info.ident;

let panic_hook = self.panic_hook_tokens();

let ident = self.abi_alias();

let arg_struct = self.arg_struct_tokens();
let arg_parsing = self.arg_parsing_tokens();

Expand Down Expand Up @@ -274,11 +274,29 @@ impl ImplItemMethodInfo {

fn method_invocation_tokens(&self) -> TokenStream2 {
use MethodKind::*;

let ident = &self.attr_signature_info.ident;
let arg_list = self.attr_signature_info.arg_list();

let method_invocation = || {
let method_invocation = |receiver: &Receiver| {
let _mut = receiver.mutability.map_or(quote! {}, |_| quote! {mut});

if let Some((_, path, _)) = &self.attr_signature_info.trait_ {
if let Some(trait_ident) = path.get_ident() {
return quote! {
#trait_ident::#ident(&#_mut contract, #arg_list)
};
};
}

if let Type::Path(val) = &self.struct_type {
if !val.path.segments.is_empty() {
let contract_ty = &val.path.segments[0].ident;
quote! {
#contract_ty::#ident(&#_mut contract, #arg_list)
};
}
}

quote! {
contract.#ident(#arg_list)
}
Expand All @@ -292,24 +310,18 @@ impl ImplItemMethodInfo {
};

match &self.attr_signature_info.method_kind {
Call(call_method) => {
if call_method.receiver.is_some() {
method_invocation()
} else {
static_invocation()
}
}
Call(call_method) => match &call_method.receiver {
Some(receiver) => method_invocation(receiver),
None => static_invocation(),
},

// The method invocation in Init methods is done in contract initialization.
Init(_) => quote! {},

View(view_method) => {
if view_method.receiver.is_some() {
method_invocation()
} else {
static_invocation()
}
}
View(view_method) => match &view_method.receiver {
Some(receiver) => method_invocation(receiver),
None => static_invocation(),
},
}
}

Expand Down Expand Up @@ -402,4 +414,15 @@ impl ImplItemMethodInfo {
}
})
}

fn abi_alias(&self) -> syn::Ident {
match &self.attr_signature_info.method_kind {
MethodKind::Call(call_method) => &call_method.alias,
MethodKind::Init(_) => &None,
MethodKind::View(view_method) => &view_method.alias,
}
.as_ref()
.map(|alias| syn::Ident::new(alias, self.attr_signature_info.ident.span()))
.unwrap_or(self.attr_signature_info.ident.clone())
}
}
Loading
Loading