refactor(abigen): inline docs (#2090)

* refactor: abigen docs

* chore: doc

* refactor: final doc

* mergings

* fix: unremove Default
This commit is contained in:
DaniPopes 2023-01-31 06:28:57 +01:00 committed by GitHub
parent 93e1850646
commit fd02bbc418
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 73 deletions

View File

@ -62,7 +62,7 @@ where
}
pub(crate) fn imports(name: &str) -> TokenStream {
let doc = util::expand_doc(&format!("{name} was auto-generated with ethers-rs Abigen. More information at: https://github.com/gakonst/ethers-rs"));
let doc_str = format!("{name} was auto-generated with ethers-rs Abigen. More information at: https://github.com/gakonst/ethers-rs");
let ethers_core = ethers_core_crate();
let ethers_providers = ethers_providers_crate();
@ -73,7 +73,7 @@ pub(crate) fn imports(name: &str) -> TokenStream {
#![allow(dead_code)]
#![allow(clippy::type_complexity)]
#![allow(unused_imports)]
#doc
#![doc = #doc_str]
use std::sync::Arc;
use #ethers_core::{

View File

@ -59,13 +59,12 @@ impl Context {
expand_data_struct(&error_name, &fields)
};
let doc = format!(
let doc_str = format!(
"Custom Error type `{}` with signature `{}` and selector `0x{}`",
error.name,
abi_signature,
hex::encode(&error.selector()[..])
);
let abi_signature_doc = util::expand_doc(&doc);
let ethers_contract = ethers_contract_crate();
// use the same derives as for events
let derives = util::expand_derives(&self.event_derives);
@ -73,9 +72,9 @@ impl Context {
let error_name = &error.name;
Ok(quote! {
#abi_signature_doc
#[doc = #doc_str]
#[derive(Clone, Debug, Default, Eq, PartialEq, #ethers_contract::EthError, #ethers_contract::EthDisplay, #derives)]
#[etherror( name = #error_name, abi = #abi_signature )]
#[etherror(name = #error_name, abi = #abi_signature)]
pub #data_type_definition
})
}

View File

@ -217,24 +217,25 @@ impl Context {
/// Expands into a single method for contracting an event stream.
fn expand_filter(&self, event: &Event) -> TokenStream {
let ethers_contract = ethers_contract_crate();
let name = &event.name;
let alias = self.event_aliases.get(&event.abi_signature()).cloned();
let name = if let Some(id) = alias.clone() {
// append `filter` to disambiguate with potentially conflicting
// function names
let function_name = if let Some(id) = alias.clone() {
util::safe_ident(&format!("{}_filter", id.to_string().to_snake_case()))
} else {
util::safe_ident(&format!("{}_filter", event.name.to_snake_case()))
};
let struct_name = event_struct_name(name, alias);
// append `filter` to disambiguate with potentially conflicting
// function names
let doc_str = format!("Gets the contract's `{name}` event");
let result = event_struct_name(&event.name, alias);
let ethers_contract = ethers_contract_crate();
let doc = util::expand_doc(&format!("Gets the contract's `{}` event", event.name));
quote! {
#doc
pub fn #name(&self) -> #ethers_contract::builders::Event<M, #result> {
#[doc = #doc_str]
pub fn #function_name(&self) -> #ethers_contract::builders::Event<M, #struct_name> {
self.0.event()
}
}

View File

@ -124,13 +124,11 @@ impl Context {
};
let function_name = &function.name;
let abi_signature = function.abi_signature();
let doc = format!(
"Container type for all input parameters for the `{}` function with signature `{}` and selector `0x{}`",
function.name,
abi_signature,
let doc_str = format!(
"Container type for all input parameters for the `{function_name}` function with signature `{abi_signature}` and selector `0x{}`",
hex::encode(&function.selector()[..])
);
let abi_signature_doc = util::expand_doc(&doc);
let ethers_contract = ethers_contract_crate();
// use the same derives as for events
let derives = util::expand_derives(&self.event_derives);
@ -146,7 +144,7 @@ impl Context {
};
Ok(quote! {
#abi_signature_doc
#[doc = #doc_str]
#[derive(Clone, Debug, Eq, PartialEq, #ethers_contract::EthCall, #ethers_contract::EthDisplay, #derives)]
#derive_default
#[ethcall( name = #function_name, abi = #abi_signature )]
@ -160,6 +158,7 @@ impl Context {
function: &Function,
alias: Option<&MethodAlias>,
) -> Result<TokenStream> {
let name = &function.name;
let struct_name = expand_return_struct_name(function, alias);
let fields = self.expand_output_params(function)?;
// no point in having structs when there is no data returned
@ -176,13 +175,11 @@ impl Context {
expand_data_struct(&struct_name, &fields)
};
let abi_signature = function.abi_signature();
let doc = format!(
"Container type for all return fields from the `{}` function with signature `{}` and selector `0x{}`",
function.name,
abi_signature,
let doc_str = format!(
"Container type for all return fields from the `{name}` function with signature `{abi_signature}` and selector `0x{}`",
hex::encode(&function.selector()[..])
);
let abi_signature_doc = util::expand_doc(&doc);
let ethers_contract = ethers_contract_crate();
// use the same derives as for events
let derives = util::expand_derives(&self.event_derives);
@ -198,9 +195,9 @@ impl Context {
};
Ok(quote! {
#abi_signature_doc
#[doc = #doc_str]
#[derive(Clone, Debug,Eq, PartialEq, #ethers_contract::EthAbiType, #ethers_contract::EthAbiCodec, #derives)]
#derive_default
#derive_default
pub #return_type_definition
})
}
@ -436,10 +433,11 @@ impl Context {
function: &Function,
alias: Option<MethodAlias>,
) -> Result<TokenStream> {
let ethers_contract = ethers_contract_crate();
let name = &function.name;
let function_name = expand_function_name(function, alias.as_ref());
let selector = function.selector();
let name = expand_function_name(function, alias.as_ref());
let selector = expand_selector(function.selector());
let selector_tokens = expand_selector(selector);
let contract_args = self.expand_contract_call_args(function)?;
let function_params =
@ -448,18 +446,15 @@ impl Context {
let outputs = self.expand_outputs(function)?;
let result = quote! { #ethers_contract::builders::ContractCall<M, #outputs> };
let doc_str =
format!("Calls the contract's `{name}` (0x{}) function", hex::encode(selector));
let ethers_contract = ethers_contract_crate();
let doc = util::expand_doc(&format!(
"Calls the contract's `{}` (0x{}) function",
function.name,
hex::encode(function.selector())
));
Ok(quote! {
#doc
pub fn #name(&self #function_params) -> #result {
self.0.method_hash(#selector, #contract_args)
#[doc = #doc_str]
pub fn #function_name(&self #function_params) -> #ethers_contract::builders::ContractCall<M, #outputs> {
self.0.method_hash(#selector_tokens, #contract_args)
.expect("method not found (this should never happen)")
}
})
@ -470,9 +465,10 @@ impl Context {
///
/// In case of overloaded functions we would follow rust's general
/// convention of suffixing the function name with _with
// The first function or the function with the least amount of arguments should
// be named as in the ABI, the following functions suffixed with _with_ +
// additional_params[0].name + (_and_(additional_params[1+i].name))*
///
/// The first function or the function with the least amount of arguments should
/// be named as in the ABI, the following functions suffixed with _with_ +
/// additional_params[0].name + (_and_(additional_params[1+i].name))*
fn get_method_aliases(&self) -> Result<BTreeMap<String, MethodAlias>> {
let mut aliases = self.method_aliases.clone();

View File

@ -123,22 +123,18 @@ impl Context {
}
};
let sig = if let ParamType::Tuple(ref tokens) = tuple {
tokens.iter().map(|kind| kind.to_string()).collect::<Vec<_>>().join(",")
} else {
"".to_string()
let sig = match tuple {
ParamType::Tuple(ref types) if !types.is_empty() => util::abi_signature_types(types),
_ => String::new(),
};
let abi_signature = format!("{name}({sig})",);
let abi_signature_doc = util::expand_doc(&format!("`{abi_signature}`"));
let doc_str = format!("`{name}({sig})`");
// use the same derives as for events
let derives = util::expand_derives(&self.event_derives);
let ethers_contract = ethers_contract_crate();
Ok(quote! {
#abi_signature_doc
#[doc = #doc_str]
#[derive(Clone, Debug, Default, Eq, PartialEq, #ethers_contract::EthAbiType, #ethers_contract::EthAbiCodec, #derives)]
#struct_def
})
@ -178,13 +174,7 @@ impl Context {
}
}
let abi_signature = format!(
"{}({})",
name,
param_types.iter().map(|kind| kind.to_string()).collect::<Vec<_>>().join(","),
);
let abi_signature_doc = util::expand_doc(&format!("`{abi_signature}`"));
let abi_signature = util::abi_signature(name, &param_types);
let name = util::ident(name);
@ -195,7 +185,7 @@ impl Context {
let ethers_contract = ethers_contract_crate();
Ok(quote! {
#abi_signature_doc
#[doc = #abi_signature]
#[derive(Clone, Debug, Default, Eq, PartialEq, #ethers_contract::EthAbiType, #ethers_contract::EthAbiCodec, #derives)]
pub struct #name {
#( #fields ),*

View File

@ -1,7 +1,7 @@
use ethers_core::abi::{Param, ParamType};
use eyre::Result;
use inflector::Inflector;
use proc_macro2::{Ident, Literal, Span, TokenStream};
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use std::path::PathBuf;
use syn::{Ident as SynIdent, Path};
@ -81,14 +81,6 @@ pub fn expand_input_name(index: usize, name: &str) -> TokenStream {
quote! { #name }
}
/// Expands a doc string into an attribute token stream.
pub fn expand_doc(s: &str) -> TokenStream {
let doc = Literal::string(s);
quote! {
#[doc = #doc]
}
}
pub fn expand_derives(derives: &[Path]) -> TokenStream {
quote! {#(#derives),*}
}
@ -167,13 +159,16 @@ pub fn json_files(root: impl AsRef<std::path::Path>) -> Vec<PathBuf> {
.collect()
}
/// rust-std derives `Default` automatically only for arrays len <= 32
/// Returns whether all the given parameters can derive [`Default`].
///
/// Returns whether the corresponding struct can derive `Default`
pub fn can_derive_defaults(params: &[Param]) -> bool {
params.iter().map(|param| &param.kind).all(can_derive_default)
/// rust-std derives `Default` automatically only for arrays len <= 32
pub fn can_derive_defaults<'a>(params: impl IntoIterator<Item = &'a Param>) -> bool {
params.into_iter().map(|param| &param.kind).all(can_derive_default)
}
/// Returns whether the given type can derive [`Default`].
///
/// rust-std derives `Default` automatically only for arrays len <= 32
pub fn can_derive_default(param: &ParamType) -> bool {
const MAX_SUPPORTED_LEN: usize = 32;
match param {
@ -190,6 +185,21 @@ pub fn can_derive_default(param: &ParamType) -> bool {
}
}
/// Returns the formatted Solidity ABI signature.
pub fn abi_signature<'a, N, T>(name: N, types: T) -> String
where
N: std::fmt::Display,
T: IntoIterator<Item = &'a ParamType>,
{
let types = abi_signature_types(types);
format!("`{name}({types})`")
}
/// Returns the Solidity stringified ABI types joined by a single comma.
pub fn abi_signature_types<'a, T: IntoIterator<Item = &'a ParamType>>(types: T) -> String {
types.into_iter().map(ToString::to_string).collect::<Vec<_>>().join(",")
}
#[cfg(test)]
mod tests {
use super::*;