Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
refactor(abigen): keep and use parsed spans (#2247)
Browse files Browse the repository at this point in the history
* order

* refactor(abigen): keep and use spans

* chore: use getters instead of making fields public

* fix: tests

* docs: update abigen documentation

* chore: clippy
  • Loading branch information
DaniPopes authored Mar 13, 2023
1 parent d073930 commit c9a7b4a
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 312 deletions.
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ethers-contract/ethers-contract-abigen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ethers-etherscan = { version = "^2.0.0", path = "../../ethers-etherscan", defaul

proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0.12", default-features = false, features = ["full"] }
syn = { version = "1.0.12", default-features = false, features = ["full", "extra-traits"] }
prettyplease = "0.1.23"

Inflector = "0.11"
Expand Down
19 changes: 5 additions & 14 deletions ethers-contract/ethers-contract-abigen/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub struct Context {
}

impl Context {
/// Expands the whole rust contract
/// Generates the tokens.
pub fn expand(&self) -> Result<ExpandedContract> {
let name = &self.contract_ident;
let name_mod = util::ident(&util::safe_module_name(&self.contract_name));
Expand Down Expand Up @@ -232,8 +232,6 @@ impl Context {
}
};

let contract_ident = util::ident(&args.contract_name);

// NOTE: We only check for duplicate signatures here, since if there are
// duplicate aliases, the compiler will produce a warning because a
// method will be re-defined.
Expand Down Expand Up @@ -281,27 +279,20 @@ impl Context {
);
}

let extra_derives = args
.derives
.iter()
.map(|derive| syn::parse_str::<Path>(derive))
.collect::<Result<Vec<_>, _>>()
.wrap_err("failed to parse event derives")?;

Ok(Context {
Ok(Self {
abi,
human_readable,
abi_str: Literal::string(&abi_str),
abi_parser,
internal_structs,
contract_ident,
contract_name: args.contract_name,
contract_name: args.contract_name.to_string(),
contract_ident: args.contract_name,
contract_bytecode,
contract_deployed_bytecode,
method_aliases,
error_aliases: Default::default(),
extra_derives,
event_aliases,
extra_derives: args.derives,
})
}

Expand Down
135 changes: 101 additions & 34 deletions ethers-contract/ethers-contract-abigen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use ethers_core::types::Address;

use contract::{Context, ExpandedContract};
use eyre::{Context as _, Result};
use proc_macro2::TokenStream;
use proc_macro2::{Ident, TokenStream};
use quote::ToTokens;
use std::{collections::HashMap, fmt, fs, io, path::Path};

Expand All @@ -57,43 +57,46 @@ use std::{collections::HashMap, fmt, fs, io, path::Path};
/// which exports an `ERC20Token` struct, along with all its events.
///
/// ```no_run
/// # use ethers_contract_abigen::Abigen;
/// # fn foo() -> Result<(), Box<dyn std::error::Error>> {
/// use ethers_contract_abigen::Abigen;
///
/// Abigen::new("ERC20Token", "./abi.json")?.generate()?.write_to_file("token.rs")?;
/// # Ok(())
/// # }
/// # Ok::<_, Box<dyn std::error::Error>>(())
#[derive(Clone, Debug)]
#[must_use = "Abigen does nothing unless you generate or expand it."]
pub struct Abigen {
/// The source of the ABI JSON for the contract whose bindings are being generated.
abi_source: Source,

/// The contract's name to use for the generated type.
contract_name: String,

/// Manually specified contract method aliases.
method_aliases: HashMap<String, String>,

/// Manually specified `derive` macros added to all structs and enums.
derives: Vec<String>,
contract_name: Ident,

/// Whether to format the generated bindings using [`prettyplease`].
format: bool,

/// Manually specified contract method aliases.
method_aliases: HashMap<String, String>,

/// Manually specified event name aliases.
event_aliases: HashMap<String, String>,

/// Manually specified error name aliases.
error_aliases: HashMap<String, String>,

/// Manually specified `derive` macros added to all structs and enums.
derives: Vec<syn::Path>,
}

impl Abigen {
/// Creates a new builder with the given [ABI Source][Source].
pub fn new<T: Into<String>, S: AsRef<str>>(contract_name: T, abi_source: S) -> Result<Self> {
let abi_source = abi_source.as_ref().parse()?;
/// Creates a new builder with the given contract name and ABI source strings.
///
/// # Errors
///
/// If `contract_name` could not be parsed as a valid [Ident], or if `abi_source` could not be
/// parsed as a valid [Source].
pub fn new<T: AsRef<str>, S: AsRef<str>>(contract_name: T, abi_source: S) -> Result<Self> {
Ok(Self {
abi_source,
contract_name: contract_name.into(),
abi_source: abi_source.as_ref().parse()?,
contract_name: syn::parse_str(contract_name.as_ref())?,
format: true,
method_aliases: Default::default(),
derives: Default::default(),
Expand All @@ -102,6 +105,19 @@ impl Abigen {
})
}

/// Creates a new builder with the given contract name [Ident] and [ABI source][Source].
pub fn new_raw(contract_name: Ident, abi_source: Source) -> Self {
Self {
contract_name,
abi_source,
format: true,
method_aliases: Default::default(),
derives: Default::default(),
event_aliases: Default::default(),
error_aliases: Default::default(),
}
}

/// Attempts to load a new builder from an ABI JSON file at the specific path.
pub fn from_file(path: impl AsRef<Path>) -> Result<Self> {
let path = dunce::canonicalize(path).wrap_err("File does not exist")?;
Expand Down Expand Up @@ -155,6 +171,20 @@ impl Abigen {
self
}

#[deprecated = "Use add_derive instead"]
#[doc(hidden)]
pub fn add_event_derive<S: AsRef<str>>(self, derive: S) -> Result<Self> {
self.add_derive(derive)
}

/// Add a custom derive to the derives for all structs and enums.
///
/// For example, this makes it possible to derive serde::Serialize and serde::Deserialize.
pub fn add_derive<S: AsRef<str>>(mut self, derive: S) -> Result<Self> {
self.derives.push(syn::parse_str(derive.as_ref())?);
Ok(self)
}

#[deprecated = "Use format instead"]
#[doc(hidden)]
pub fn rustfmt(mut self, rustfmt: bool) -> Self {
Expand All @@ -171,25 +201,10 @@ impl Abigen {
self
}

#[deprecated = "Use add_derive instead"]
#[doc(hidden)]
pub fn add_event_derive<S: Into<String>>(mut self, derive: S) -> Self {
self.derives.push(derive.into());
self
}

/// Add a custom derive to the derives for all structs and enums.
///
/// For example, this makes it possible to derive serde::Serialize and serde::Deserialize.
pub fn add_derive<S: Into<String>>(mut self, derive: S) -> Self {
self.derives.push(derive.into());
self
}

/// Generates the contract bindings.
pub fn generate(self) -> Result<ContractBindings> {
let format = self.format;
let name = self.contract_name.clone();
let name = self.contract_name.to_string();
let (expanded, _) = self.expand()?;
Ok(ContractBindings { tokens: expanded.into_tokens(), format, name })
}
Expand All @@ -202,7 +217,59 @@ impl Abigen {
}
}

/// Type-safe contract bindings generated by `Abigen`.
impl Abigen {
/// Returns a reference to the contract's ABI source.
pub fn source(&self) -> &Source {
&self.abi_source
}

/// Returns a mutable reference to the contract's ABI source.
pub fn source_mut(&mut self) -> &mut Source {
&mut self.abi_source
}

/// Returns a reference to the contract's name.
pub fn name(&self) -> &Ident {
&self.contract_name
}

/// Returns a mutable reference to the contract's name.
pub fn name_mut(&mut self) -> &mut Ident {
&mut self.contract_name
}

/// Returns a reference to the contract's method aliases.
pub fn method_aliases(&self) -> &HashMap<String, String> {
&self.method_aliases
}

/// Returns a mutable reference to the contract's method aliases.
pub fn method_aliases_mut(&mut self) -> &mut HashMap<String, String> {
&mut self.method_aliases
}

/// Returns a reference to the contract's event aliases.
pub fn event_aliases(&self) -> &HashMap<String, String> {
&self.event_aliases
}

/// Returns a mutable reference to the contract's event aliases.
pub fn error_aliases_mut(&mut self) -> &mut HashMap<String, String> {
&mut self.error_aliases
}

/// Returns a reference to the contract's derives.
pub fn derives(&self) -> &Vec<syn::Path> {
&self.derives
}

/// Returns a mutable reference to the contract's derives.
pub fn derives_mut(&mut self) -> &mut Vec<syn::Path> {
&mut self.derives
}
}

/// Type-safe contract bindings generated by [Abigen].
///
/// This type can be either written to file or converted to a token stream for a procedural macro.
#[derive(Clone)]
Expand Down
2 changes: 1 addition & 1 deletion ethers-contract/ethers-contract-abigen/src/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl MultiAbigen {

/// Removes all `Abigen` items that should not be included based on the given filter
pub fn apply_filter(&mut self, filter: &ContractFilter) {
self.abigens.retain(|abi| filter.is_match(&abi.contract_name))
self.abigens.retain(|abi| filter.is_match(abi.contract_name.to_string()))
}

/// Add another Abigen to the module or lib
Expand Down
2 changes: 0 additions & 2 deletions ethers-contract/ethers-contract-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ proc-macro2 = "1.0"
quote = "1.0"
syn = "1.0.12"

serde_json = "1.0.53"
hex = { version = "0.4.3", default-features = false, features = ["std"] }
eyre = "0.6"

[package.metadata.docs.rs]
all-features = true
Expand Down
Loading

0 comments on commit c9a7b4a

Please sign in to comment.