Skip to content

Commit

Permalink
refactor: disentangle bindgen code generation (#1033)
Browse files Browse the repository at this point in the history
* rename `AttrSigInfo` to `AttrSigInfoV1`
* temporarily duplicate `AttrSigInfoV1` and V2 functionality
* temporarily derive `Clone` for `AttrSigInfoV2` (Needed to let us convert from a reference to `AttrSigInfoV1`)
* hoist `returns` from `MethodKind` (The value of `returns` is not dependent on the `MethodKind` variant and all variants have it. But having it inside `MethodKind` makes it awkward to access, so this commit moves it up to `AttrSigInfo`)
* replace `AttrSigInfoV1` with V2 where structure is not affected
* add test for `handle_result` with `&mut self`
* refactor `method_wrapper` to use `AttrSigInfoV2`
* remove unused methods
* add tracking issue to refactor abi generator
  • Loading branch information
agostbiro authored Jun 28, 2023
1 parent 661766f commit c39fba3
Show file tree
Hide file tree
Showing 13 changed files with 492 additions and 295 deletions.
34 changes: 18 additions & 16 deletions near-sdk-macros/src/core_impl/abi/abi_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use syn::spanned::Spanned;
use syn::{Attribute, Lit::Str, Meta::NameValue, MetaNameValue, ReturnType, Type};

use crate::core_impl::{
utils, AttrSigInfo, BindgenArgType, ImplItemMethodInfo, ItemImplInfo, MethodType,
utils, AttrSigInfoV1, BindgenArgType, ImplItemMethodInfo, ItemImplInfo, MethodType,
SerializerType,
};

Expand Down Expand Up @@ -80,13 +80,17 @@ impl ImplItemMethodInfo {
/// ```
/// If args are serialized with Borsh it will not include `#[derive(borsh::BorshSchema)]`.
pub fn abi_struct(&self) -> TokenStream2 {
let function_name_str = self.attr_signature_info.ident.to_string();
let function_doc = match parse_rustdoc(&self.attr_signature_info.non_bindgen_attrs) {
// FIXME: Refactor to use `AttrSigInfoV2`
// Tracking issue: https://github.com/near/near-sdk-rs/issues/1032
let attr_signature_info: AttrSigInfoV1 = self.attr_signature_info.clone().into();

let function_name_str = attr_signature_info.ident.to_string();
let function_doc = match parse_rustdoc(&attr_signature_info.non_bindgen_attrs) {
Some(doc) => quote! { Some(#doc.to_string()) },
None => quote! { None },
};
let mut modifiers = vec![];
let kind = match &self.attr_signature_info.method_type {
let kind = match &attr_signature_info.method_type {
&MethodType::View => quote! { near_sdk::__private::AbiFunctionKind::View },
&MethodType::Regular => {
quote! { near_sdk::__private::AbiFunctionKind::Call }
Expand All @@ -96,21 +100,21 @@ impl ImplItemMethodInfo {
quote! { near_sdk::__private::AbiFunctionKind::Call }
}
};
if self.attr_signature_info.is_payable {
if attr_signature_info.is_payable {
modifiers.push(quote! { near_sdk::__private::AbiFunctionModifier::Payable });
}
if self.attr_signature_info.is_private {
if attr_signature_info.is_private {
modifiers.push(quote! { near_sdk::__private::AbiFunctionModifier::Private });
}
let modifiers = quote! {
vec![#(#modifiers),*]
};
let AttrSigInfo { is_handles_result, .. } = self.attr_signature_info;
let AttrSigInfoV1 { is_handles_result, .. } = attr_signature_info;

let mut params = Vec::<TokenStream2>::new();
let mut callbacks = Vec::<TokenStream2>::new();
let mut callback_vec: Option<TokenStream2> = None;
for arg in &self.attr_signature_info.args {
for arg in &attr_signature_info.args {
let typ = &arg.ty;
let arg_name = arg.ident.to_string();
match arg.bindgen_ty {
Expand Down Expand Up @@ -160,7 +164,7 @@ impl ImplItemMethodInfo {
};

let abi_type =
generate_abi_type(typ, &self.attr_signature_info.result_serializer);
generate_abi_type(typ, &attr_signature_info.result_serializer);
callback_vec = Some(quote! { Some(#abi_type) })
} else {
return syn::Error::new(
Expand All @@ -172,7 +176,7 @@ impl ImplItemMethodInfo {
}
};
}
let params = match self.attr_signature_info.input_serializer {
let params = match attr_signature_info.input_serializer {
SerializerType::JSON => quote! {
near_sdk::__private::AbiParameters::Json {
args: vec![#(#params),*]
Expand All @@ -186,14 +190,14 @@ impl ImplItemMethodInfo {
};
let callback_vec = callback_vec.unwrap_or(quote! { None });

let result = match self.attr_signature_info.method_type {
let result = match attr_signature_info.method_type {
MethodType::Init | MethodType::InitIgnoreState => {
// Init methods must return the contract state, so the return type does not matter
quote! {
None
}
}
_ => match &self.attr_signature_info.returns {
_ => match &attr_signature_info.returns {
ReturnType::Default => {
quote! {
None
Expand All @@ -209,8 +213,7 @@ impl ImplItemMethodInfo {
)
.into_compile_error();
};
let abi_type =
generate_abi_type(ty, &self.attr_signature_info.result_serializer);
let abi_type = generate_abi_type(ty, &attr_signature_info.result_serializer);
quote! { Some(#abi_type) }
}
ReturnType::Type(_, ty) if is_handles_result => {
Expand All @@ -221,8 +224,7 @@ impl ImplItemMethodInfo {
.to_compile_error();
}
ReturnType::Type(_, ty) => {
let abi_type =
generate_abi_type(ty, &self.attr_signature_info.result_serializer);
let abi_type = generate_abi_type(ty, &attr_signature_info.result_serializer);
quote! { Some(#abi_type) }
}
},
Expand Down
9 changes: 7 additions & 2 deletions near-sdk-macros/src/core_impl/code_generator/attr_sig_info.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use proc_macro2::TokenStream as TokenStream2;

use crate::core_impl::info_extractor::{ArgInfo, AttrSigInfo, BindgenArgType, SerializerType};
use crate::core_impl::info_extractor::{ArgInfo, AttrSigInfoV2, BindgenArgType, SerializerType};
use crate::core_impl::utils;
use quote::quote;

impl AttrSigInfo {
impl AttrSigInfoV2 {
/// Whether the signature has function arguments.
pub fn has_input_args(&self) -> bool {
self.input_args().next().is_some()
}

pub fn input_struct_ser(&self) -> TokenStream2 {
let args: Vec<_> = self.input_args().collect();
assert!(
Expand Down
8 changes: 4 additions & 4 deletions near-sdk-macros/src/core_impl/code_generator/ext.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::core_impl::{serializer, AttrSigInfo};
use crate::core_impl::{serializer, AttrSigInfoV2};
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 @@ -97,7 +97,7 @@ fn is_fn_attribute_to_forward(attribute: &Attribute) -> bool {
/// Generate methods on <StructName>Ext to enable calling each method.
pub(crate) fn generate_ext_function_wrappers<'a>(
ident: &Ident,
methods: impl IntoIterator<Item = &'a AttrSigInfo>,
methods: impl IntoIterator<Item = &'a AttrSigInfoV2>,
) -> TokenStream2 {
let ext_ident = format_ident!("{}Ext", ident);
let mut res = TokenStream2::new();
Expand All @@ -111,12 +111,12 @@ pub(crate) fn generate_ext_function_wrappers<'a>(
}
}

fn generate_ext_function(attr_signature_info: &AttrSigInfo) -> TokenStream2 {
fn generate_ext_function(attr_signature_info: &AttrSigInfoV2) -> TokenStream2 {
let pat_type_list = attr_signature_info.pat_type_list();
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 AttrSigInfoV2 { non_bindgen_attrs, ident, original_sig, .. } = attr_signature_info;
let ident_str = ident.to_string();
let mut new_non_bindgen_attrs = TokenStream2::new();
for attribute in non_bindgen_attrs.iter() {
Expand Down
Loading

0 comments on commit c39fba3

Please sign in to comment.