Skip to content

Commit 122d65a

Browse files
authored
fix(fmt): filter libs when recursing (foundry-rs#12119)
* fix(fmt): account for ternary operators when estimating size * fix(fmt): filter libs when recursing * style: clippy * test: wipe contracts before formatting * test: explicitly test ignore
1 parent ad63319 commit 122d65a

File tree

2 files changed

+51
-8
lines changed

2 files changed

+51
-8
lines changed

crates/forge/src/cmd/fmt.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,51 @@ impl_figment_convert_basic!(FmtArgs);
5151
impl FmtArgs {
5252
pub fn run(self) -> Result<()> {
5353
let config = self.load_config()?;
54+
let cwd = std::env::current_dir()?;
5455

5556
// Expand ignore globs and canonicalize from the get go
5657
let ignored = expand_globs(&config.root, config.fmt.ignore.iter())?
5758
.iter()
58-
.flat_map(foundry_common::fs::canonicalize_path)
59+
.flat_map(fs::canonicalize_path)
5960
.collect::<Vec<_>>();
6061

61-
let cwd = std::env::current_dir()?;
62+
// Expand lib globs separately - we only exclude these during discovery, not explicit paths
63+
let libs = expand_globs(&config.root, config.libs.iter().filter_map(|p| p.to_str()))?
64+
.iter()
65+
.flat_map(fs::canonicalize_path)
66+
.collect::<Vec<_>>();
67+
68+
// Helper to check if a file path is under any ignored or lib directory
69+
let is_under_ignored_dir = |file_path: &Path, include_libs: bool| -> bool {
70+
let check_against_dir = |dir: &PathBuf| {
71+
file_path.starts_with(dir)
72+
|| cwd.join(file_path).starts_with(dir)
73+
|| fs::canonicalize_path(file_path).is_ok_and(|p| p.starts_with(dir))
74+
};
75+
76+
ignored.iter().any(&check_against_dir)
77+
|| (include_libs && libs.iter().any(&check_against_dir))
78+
};
79+
6280
let input = match &self.paths[..] {
6381
[] => {
64-
// Retrieve the project paths, and filter out the ignored ones.
82+
// Retrieve the project paths, and filter out the ignored ones and libs.
6583
let project_paths: Vec<PathBuf> = config
6684
.project_paths::<SolcLanguage>()
6785
.input_files_iter()
68-
.filter(|p| !(ignored.contains(p) || ignored.contains(&cwd.join(p))))
86+
.filter(|p| {
87+
!(ignored.contains(p)
88+
|| ignored.contains(&cwd.join(p))
89+
|| is_under_ignored_dir(p, true))
90+
})
6991
.collect();
7092
Input::Paths(project_paths)
7193
}
7294
[one] if one == Path::new("-") => Input::Stdin,
7395
paths => {
7496
let mut inputs = Vec::with_capacity(paths.len());
7597
for path in paths {
98+
// Check if path is in ignored directories
7699
if !ignored.is_empty()
77100
&& ((path.is_absolute() && ignored.contains(path))
78101
|| ignored.contains(&cwd.join(path)))
@@ -81,11 +104,18 @@ impl FmtArgs {
81104
}
82105

83106
if path.is_dir() {
84-
inputs.extend(foundry_compilers::utils::source_files_iter(
85-
path,
86-
SOLC_EXTENSIONS,
87-
));
107+
// If the input directory is not a lib directory, make sure to ignore libs.
108+
let exclude_libs = !is_under_ignored_dir(path, true);
109+
inputs.extend(
110+
foundry_compilers::utils::source_files_iter(path, SOLC_EXTENSIONS)
111+
.filter(|p| {
112+
!(ignored.contains(p)
113+
|| ignored.contains(&cwd.join(p))
114+
|| is_under_ignored_dir(p, exclude_libs))
115+
}),
116+
);
88117
} else if path.is_sol() {
118+
// Explicit file paths are always included, even if in a lib
89119
inputs.push(path.to_path_buf());
90120
} else {
91121
warn!("Cannot process path {}", path.display());

crates/forge/tests/cli/fmt.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ contract Test {
2424
}
2525
"#;
2626

27+
forgetest_init!(fmt_exclude_libs_in_recursion, |prj, cmd| {
28+
prj.wipe_contracts();
29+
prj.update_config(|config| config.fmt.ignore = vec!["src/ignore/".to_string()]);
30+
31+
prj.add_lib("SomeLib.sol", UNFORMATTED);
32+
prj.add_raw_source("ignore/IgnoredContract.sol", UNFORMATTED);
33+
cmd.args(["fmt", ".", "--check"]);
34+
cmd.assert_success();
35+
36+
cmd.forge_fuse().args(["fmt", "lib/SomeLib.sol", "--check"]);
37+
cmd.assert_failure();
38+
});
39+
2740
// Test that fmt can format a simple contract file
2841
forgetest_init!(fmt_file, |prj, cmd| {
2942
prj.add_raw_source("FmtTest.sol", UNFORMATTED);

0 commit comments

Comments
 (0)