Skip to content
Merged
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
2 changes: 1 addition & 1 deletion benches/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl BenchmarkProject {

// Clone the repository
let repo_url = format!("https://github.com/{}/{}.git", config.org, config.repo);
clone_remote(&repo_url, root);
clone_remote(&repo_url, root, true);

// Checkout specific revision if provided
if !config.rev.is_empty() && config.rev != "main" && config.rev != "master" {
Expand Down
32 changes: 21 additions & 11 deletions crates/fmt/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ impl CallStack {
}

pub(super) struct State<'sess, 'ast> {
debug: bool,
pub(super) s: pp::Printer,
ind: isize,

Expand Down Expand Up @@ -204,7 +203,6 @@ impl<'sess> State<'sess, '_> {
comments: Comments,
) -> Self {
Self {
debug: false,
s: pp::Printer::new(
config.line_length,
if matches!(config.style, IndentStyle::Tab) {
Expand Down Expand Up @@ -369,20 +367,27 @@ impl State<'_, '_> {

fn estimate_size(&self, span: Span) -> usize {
if let Ok(snip) = self.sm.span_to_snippet(span) {
let (mut size, mut prev_needs_space) = (0, false);
let (mut size, mut first, mut prev_needs_space) = (0, true, false);

for line in snip.lines() {
let line = line.trim();

if prev_needs_space {
// Previous line ended with a bracket and config with bracket spacing.
// Previous line ended with ',' a hardbreak or a space are required.
// Previous line ended with ';' a hardbreak is required.
size += 1;
} else if !first
&& let Some(c) = line.chars().next()
&& matches!(c, '&' | '|' | '=' | '>' | '<' | '+' | '-' | '*' | '/' | '%' | '^')
{
// if the line starts with an operator, a space or a line break are required.
size += 1
}
first = false;

// trim spaces before and after mixed comments
let mut search = line;
loop {
if let Some((lhs, comment)) = search.split_once(r#"/*"#) {
size += lhs.trim().len() + 2;
size += lhs.trim_end().len() + 2;
search = comment;
} else if let Some((comment, rhs)) = search.split_once(r#"*/"#) {
size += comment.len() + 2;
Expand All @@ -393,10 +398,15 @@ impl State<'_, '_> {
}
}

prev_needs_space = (self.config.bracket_spacing
&& (line.ends_with('(') || line.ends_with('{')))
|| line.ends_with(',')
|| line.ends_with(';');
// Next line requires a line break if this one:
// - ends with a bracket and fmt config forces bracket spacing.
// - ends with ',' a line break or a space are required.
// - ends with ';' a line break is required.
prev_needs_space = match line.chars().next_back() {
Some('(') | Some('{') => self.config.bracket_spacing,
Some(',') | Some(';') => true,
_ => false,
};
}
return size;
}
Expand Down
5 changes: 2 additions & 3 deletions crates/fmt/src/state/sol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1246,9 +1246,8 @@ impl<'ast> State<'_, 'ast> {
self.call_stack.add_precall(lhs_size);

let is_simple_rhs = matches!(rhs.kind, ast::ExprKind::Lit(..) | ast::ExprKind::Ident(..));
let is_chain = is_call_chain(&rhs.kind, false);

if (is_chain && overflows && fits_alone) || is_simple_rhs {
if (overflows && fits_alone) || is_simple_rhs {
self.s.ibox(self.ind)
} else {
self.s.ibox(0)
Expand All @@ -1267,7 +1266,7 @@ impl<'ast> State<'_, 'ast> {
self.print_expr(rhs);
self.end();
}
_ if (is_chain && overflows && fits_alone) || (is_simple_rhs && overflows) => {
_ if overflows && (fits_alone || is_simple_rhs) => {
self.print_sep(Separator::Space);
self.print_expr(rhs);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/fmt/testdata/OperatorExpressions/120.fmt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ function test_nested() {
"string mismatch"
);

state.zeroForOne = IERC20(Currency.unwrap(state.poolKey1.currency0))
== IERC20(Currency.unwrap(state.poolKey0.curerncy1));
state.zeroForOne =
IERC20(Currency.unwrap(state.poolKey1.currency0)) == IERC20(Currency.unwrap(state.poolKey0.curerncy1));

coreAddresses.evc == address(0) && coreAddresses.protocolConfig == address(0)
&& coreAddresses.sequenceRegistry == address(0) && coreAddresses.balanceTracker == address(0)
Expand Down
6 changes: 6 additions & 0 deletions crates/fmt/testdata/ReprosCalls/110.fmt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,11 @@ contract Orchestrator {
amount(),
0 /* nonce */
);

// https://github.com/foundry-rs/foundry/issues/11835
feeGrowthInside0X128 =
self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
feeGrowthInside0X128 =
self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
}
}
4 changes: 4 additions & 0 deletions crates/fmt/testdata/ReprosCalls/120.fmt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,9 @@ contract Orchestrator {
amount(),
0 /* nonce */
);

// https://github.com/foundry-rs/foundry/issues/11835
feeGrowthInside0X128 = self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
feeGrowthInside0X128 = self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
}
}
6 changes: 6 additions & 0 deletions crates/fmt/testdata/ReprosCalls/80.fmt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,11 @@ contract Orchestrator {
amount(),
0 /* nonce */
);

// https://github.com/foundry-rs/foundry/issues/11835
feeGrowthInside0X128 = self.feeGrowthGlobal0X128
- lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
feeGrowthInside0X128 = self.feeGrowthGlobal0X128
- lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
}
}
6 changes: 6 additions & 0 deletions crates/fmt/testdata/ReprosCalls/original.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,11 @@ contract Orchestrator {
ISignatureTransfer.PermitTransferFrom memory permit = defaultERC20PermitTransfer(
address(fromToken()), amount(), 0 /* nonce */
);

// https://github.com/foundry-rs/foundry/issues/11835
feeGrowthInside0X128 =
self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
feeGrowthInside0X128 = self.feeGrowthGlobal0X128
- lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
}
}
29 changes: 29 additions & 0 deletions crates/forge/tests/cli/fmt_integration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use foundry_test_utils::util::ExtTester;

/// Test `forge fmt` immutability.
/// TODO: make sure original fmt is not changed after projects format and rev available.
/// TODO: enable win test after <https://github.com/foundry-rs/foundry/issues/11841> fixed.
macro_rules! fmt_test {
($name:ident, $org:expr, $repo:expr, $commit:expr) => {
#[test]
fn $name() {
let (_, mut cmd) = ExtTester::new($org, $repo, $commit).setup_forge_prj(false);
cmd.arg("fmt").assert_success();
cmd.arg("--check").assert_success();
}
};
}

fmt_test!(fmt_ithaca_account, "ithacaxyz", "account", "213c04ee1808784c18609607d85feba7730538fd");

fmt_test!(fmt_univ4_core, "Uniswap", "v4-core", "59d3ecf53afa9264a16bba0e38f4c5d2231f80bc");

fmt_test!(
fmt_evk_periphery,
"euler-xyz",
"evk-periphery",
"e41f2b9b7ed677ca03ff7bd7221a4e2fdd55504f"
);

#[cfg(not(windows))]
fmt_test!(fmt_0x_settler, "0xProject", "0x-settler", "a388c8251ab6c4bedce1641b31027d7b1136daef");
6 changes: 3 additions & 3 deletions crates/forge/tests/cli/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ Compiler run successful!
async fn uni_v4_core_sync_foundry_lock() {
let (prj, mut cmd) =
ExtTester::new("Uniswap", "v4-core", "e50237c43811bd9b526eff40f26772152a42daba")
.setup_forge_prj();
.setup_forge_prj(true);

assert!(!prj.root().join(FOUNDRY_LOCK).exists());

Expand Down Expand Up @@ -504,7 +504,7 @@ async fn oz_contracts_sync_foundry_lock() {
"openzeppelin-contracts",
"840c974028316f3c8172c1b8e5ed67ad95e255ca",
)
.setup_forge_prj();
.setup_forge_prj(true);

assert!(!prj.root().join(FOUNDRY_LOCK).exists());

Expand Down Expand Up @@ -561,7 +561,7 @@ async fn correctly_sync_dep_with_multiple_version() {
"sync-lockfile-multi-version-dep",
"1ca47e73a168e54f8f7761862dbd0c603856c5c8",
)
.setup_forge_prj();
.setup_forge_prj(true);

assert!(!prj.root().join(FOUNDRY_LOCK).exists());

Expand Down
1 change: 1 addition & 0 deletions crates/forge/tests/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ mod version;

mod ext_integration;
mod fmt;
mod fmt_integration;
mod test_optimizer;
15 changes: 10 additions & 5 deletions crates/test-utils/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl ExtTester {
self
}

pub fn setup_forge_prj(&self) -> (TestProject, TestCommand) {
pub fn setup_forge_prj(&self, recursive: bool) -> (TestProject, TestCommand) {
let (prj, mut test_cmd) = setup_forge(self.name, self.style.clone());

// Export vyper and forge in test command - workaround for snekmate venom tests.
Expand All @@ -170,7 +170,7 @@ impl ExtTester {
// Clone the external repository.
let repo_url = format!("https://github.com/{}/{}.git", self.org, self.name);
let root = prj.root().to_str().unwrap();
clone_remote(&repo_url, root);
clone_remote(&repo_url, root, recursive);

// Checkout the revision.
if self.rev.is_empty() {
Expand Down Expand Up @@ -224,7 +224,7 @@ impl ExtTester {
return;
}

let (prj, mut test_cmd) = self.setup_forge_prj();
let (prj, mut test_cmd) = self.setup_forge_prj(true);

// Run installation command.
self.run_install_commands(prj.root().to_str().unwrap());
Expand Down Expand Up @@ -423,9 +423,14 @@ pub fn get_vyper() -> Vyper {
}

/// Clones a remote repository into the specified directory. Panics if the command fails.
pub fn clone_remote(repo_url: &str, target_dir: &str) {
pub fn clone_remote(repo_url: &str, target_dir: &str, recursive: bool) {
let mut cmd = Command::new("git");
cmd.args(["clone", "--recursive", "--shallow-submodules"]);
cmd.args(["clone"]);
if recursive {
cmd.args(["--recursive", "--shallow-submodules"]);
} else {
cmd.args(["--depth=1", "--no-checkout", "--filter=blob:none", "--no-recurse-submodules"]);
}
cmd.args([repo_url, target_dir]);
test_debug!("{cmd:?}");
let status = cmd.status().unwrap();
Expand Down
Loading