Skip to content

Commit

Permalink
chore: move formatting logic to foundry-macros (#4936)
Browse files Browse the repository at this point in the history
* chore: move formatting logic to foundry-macros

* fixes
  • Loading branch information
DaniPopes committed May 13, 2023
1 parent 82df0e9 commit 56e8da4
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 74 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ repository = "https://github.com/foundry-rs/foundry"
[dependencies]
# foundry internal
foundry-config = { path = "../config" }
foundry-macros = { path = "../macros" }

# eth
ethers-core = { workspace = true }
Expand Down
50 changes: 50 additions & 0 deletions common/src/fmt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//! Helpers for formatting ethereum types

use crate::TransactionReceiptWithRevertReason;

pub use foundry_macros::fmt::*;

impl UIfmt for TransactionReceiptWithRevertReason {
fn pretty(&self) -> String {
if let Some(revert_reason) = &self.revert_reason {
format!(
"{}
revertReason {}",
self.receipt.pretty(),
revert_reason
)
} else {
self.receipt.pretty()
}
}
}

/// Returns the ``UiFmt::pretty()` formatted attribute of the transaction receipt
pub fn get_pretty_tx_receipt_attr(
receipt: &TransactionReceiptWithRevertReason,
attr: &str,
) -> Option<String> {
match attr {
"blockHash" | "block_hash" => Some(receipt.receipt.block_hash.pretty()),
"blockNumber" | "block_number" => Some(receipt.receipt.block_number.pretty()),
"contractAddress" | "contract_address" => Some(receipt.receipt.contract_address.pretty()),
"cumulativeGasUsed" | "cumulative_gas_used" => {
Some(receipt.receipt.cumulative_gas_used.pretty())
}
"effectiveGasPrice" | "effective_gas_price" => {
Some(receipt.receipt.effective_gas_price.pretty())
}
"gasUsed" | "gas_used" => Some(receipt.receipt.gas_used.pretty()),
"logs" => Some(receipt.receipt.logs.pretty()),
"logsBloom" | "logs_bloom" => Some(receipt.receipt.logs_bloom.pretty()),
"root" => Some(receipt.receipt.root.pretty()),
"status" => Some(receipt.receipt.status.pretty()),
"transactionHash" | "transaction_hash" => Some(receipt.receipt.transaction_hash.pretty()),
"transactionIndex" | "transaction_index" => {
Some(receipt.receipt.transaction_index.pretty())
}
"type" | "transaction_type" => Some(receipt.receipt.transaction_type.pretty()),
"revertReason" | "revert_reason" => Some(receipt.revert_reason.pretty()),
_ => None,
}
}
5 changes: 3 additions & 2 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ pub mod fs;
pub mod provider;
pub mod selectors;
pub mod shell;
pub use provider::*;
pub mod term;
pub mod traits;
pub mod transactions;

pub use constants::*;
pub use contracts::*;
pub use provider::*;
pub use traits::*;
pub mod transactions;
pub use transactions::*;
3 changes: 2 additions & 1 deletion macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repository = "https://github.com/foundry-rs/foundry"

[dependencies]
foundry-macros-impl = { path = "./impl" }
foundry-common = { path = "../common" }

ethers-core = { workspace = true }
serde = "1.0"
serde_json = "1.0"
10 changes: 7 additions & 3 deletions macros/src/console_fmt.rs → macros/src/fmt/console_fmt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::UIfmt;
use ethers_core::types::{Address, Bytes, H256, I256, U256};
use foundry_common::fmt::UIfmt;

/// A format specifier.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
Expand Down Expand Up @@ -167,10 +167,14 @@ impl<const N: usize> ConsoleFmt for [u8; N] {
/// Formatting rules are the same as Hardhat. The supported format specifiers are as follows:
/// - %s: Converts the value using its String representation. This is equivalent to applying
/// [`UIfmt::pretty()`] on the format string.
/// - %d, %i: Converts the value to an integer. If a non-numeric value, such as String or Address,
/// is passed, then the spec is formatted as `NaN`.
/// - %o: Treats the format value as a javascript "object" and converts it to its string
/// representation.
/// - %d, %i: Converts the value to an integer. If a non-numeric value, such as String or Address,
/// is passed, then the spec is formatted as `NaN`.
/// - %x: Converts the value to a hexadecimal string. If a non-numeric value, such as String or
/// Address, is passed, then the spec is formatted as `NaN`.
/// - %e: Converts the value to an exponential notation string. If a non-numeric value, such as
/// String or Address, is passed, then the spec is formatted as `NaN`.
/// - %%: This is parsed as a single percent sign ('%') without consuming any input value.
///
/// Unformatted values are appended to the end of the formatted output using [`UIfmt::pretty()`].
Expand Down
3 changes: 3 additions & 0 deletions common/src/fmt/mod.rs → macros/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ pub use ui::*;

mod token;
pub use token::*;

mod console_fmt;
pub use console_fmt::{console_format, ConsoleFmt, FormatSpec};
5 changes: 3 additions & 2 deletions common/src/fmt/token.rs → macros/src/fmt/token.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! Formatting helpers for [`Token`](ethers_core::abi::Token)
//! Formatting helpers for [`Token`]s.

use ethers_core::{abi::Token, types::I256, utils, utils::hex};
use std::{fmt, fmt::Write};

/// Wrapper that pretty formats a token
pub struct TokenDisplay<'a>(pub &'a Token);

impl<'a> fmt::Display for TokenDisplay<'a> {
impl fmt::Display for TokenDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt_token(f, self.0)
}
}

/// Recursively formats an ABI token.
fn fmt_token(f: &mut fmt::Formatter, item: &Token) -> fmt::Result {
match item {
Token::Address(inner) => {
Expand Down
78 changes: 17 additions & 61 deletions common/src/fmt/ui.rs → macros/src/fmt/ui.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
//! Contains a helper pretty() function to print human redeable string versions of usual ethers
//! types
//! Helper trait and functions to format ethers types.

use ethers_core::{
types::*,
utils::{hex, to_checksum},
};
use serde::Deserialize;

use crate::TransactionReceiptWithRevertReason;

/// length of the name column for pretty formatting `{:>20}{value}`
const NAME_COLUMN_LEN: usize = 20usize;

/// Helper trait to format ethers types.
///
/// # Examples
///
/// Uifmt is a helper trait to format the usual ethers types
/// It offers a `pretty()` function that returns a human readable String of the value
/// # Example
/// ```
/// use foundry_common::fmt::UIfmt;
/// use foundry_macros::fmt::UIfmt;
/// let boolean: bool = true;
/// let string = boolean.pretty();
/// ```
Expand Down Expand Up @@ -102,10 +100,17 @@ impl<T: UIfmt> UIfmt for Option<T> {
impl<T: UIfmt> UIfmt for Vec<T> {
fn pretty(&self) -> String {
if !self.is_empty() {
format!(
"[\n{}]",
self.iter().fold("".to_string(), |s, x| s + tab_paragraph(x.pretty()).as_str())
)
let mut s = String::with_capacity(self.len() * 64);
s.push_str("[\n");
for item in self {
for line in item.pretty().lines() {
s.push('\t');
s.push_str(line);
s.push('\n');
}
}
s.push(']');
s
} else {
"[]".to_string()
}
Expand Down Expand Up @@ -146,21 +151,6 @@ type {}",
}
}

impl UIfmt for TransactionReceiptWithRevertReason {
fn pretty(&self) -> String {
if let Some(ref revert_reason) = self.revert_reason {
format!(
"{}
revertReason {}",
self.receipt.pretty(),
revert_reason
)
} else {
self.receipt.pretty()
}
}
}

impl UIfmt for Log {
fn pretty(&self) -> String {
format!(
Expand Down Expand Up @@ -341,10 +331,6 @@ value {}{}",
}
}

fn tab_paragraph(paragraph: String) -> String {
paragraph.lines().fold("".to_string(), |acc, x| acc + "\t" + x + "\n")
}

/// Convert a U256 to bytes
pub fn to_bytes(uint: U256) -> Bytes {
let mut buffer: [u8; 4 * 8] = [0; 4 * 8];
Expand Down Expand Up @@ -410,36 +396,6 @@ pub fn get_pretty_block_attr<TX>(block: &Block<TX>, attr: &str) -> Option<String
}
}

/// Returns the ``UiFmt::pretty()` formatted attribute of the transaction receipt
pub fn get_pretty_tx_receipt_attr(
receipt: &TransactionReceiptWithRevertReason,
attr: &str,
) -> Option<String> {
match attr {
"blockHash" | "block_hash" => Some(receipt.receipt.block_hash.pretty()),
"blockNumber" | "block_number" => Some(receipt.receipt.block_number.pretty()),
"contractAddress" | "contract_address" => Some(receipt.receipt.contract_address.pretty()),
"cumulativeGasUsed" | "cumulative_gas_used" => {
Some(receipt.receipt.cumulative_gas_used.pretty())
}
"effectiveGasPrice" | "effective_gas_price" => {
Some(receipt.receipt.effective_gas_price.pretty())
}
"gasUsed" | "gas_used" => Some(receipt.receipt.gas_used.pretty()),
"logs" => Some(receipt.receipt.logs.pretty()),
"logsBloom" | "logs_bloom" => Some(receipt.receipt.logs_bloom.pretty()),
"root" => Some(receipt.receipt.root.pretty()),
"status" => Some(receipt.receipt.status.pretty()),
"transactionHash" | "transaction_hash" => Some(receipt.receipt.transaction_hash.pretty()),
"transactionIndex" | "transaction_index" => {
Some(receipt.receipt.transaction_index.pretty())
}
"type" | "transaction_type" => Some(receipt.receipt.transaction_type.pretty()),
"revertReason" | "revert_reason" => Some(receipt.revert_reason.pretty()),
_ => None,
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
9 changes: 5 additions & 4 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Foundry's procedural macros.
//!
//! Also includes traits and other utilities used by the macros.

// TODO: Remove dependency on foundry-common (currently only used for the UIfmt trait).

mod console_fmt;
pub use console_fmt::{console_format, ConsoleFmt, FormatSpec};
pub mod fmt;
pub use fmt::{console_format, ConsoleFmt, FormatSpec, TokenDisplay, UIfmt};

#[doc(inline)]
pub use foundry_macros_impl::ConsoleFmt;

0 comments on commit 56e8da4

Please sign in to comment.