From eacb549329b82abe54c264a4c0048b1e123bd6df Mon Sep 17 00:00:00 2001 From: Joaquin Gonzalez Date: Sat, 11 May 2024 19:00:26 -0300 Subject: [PATCH 01/16] feat(forge): add solc subcommand and utilities --- crates/forge/bin/cmd/mod.rs | 1 + crates/forge/bin/cmd/solc.rs | 55 ++++++++++++++++++++++++++++++++++++ crates/forge/bin/main.rs | 1 + crates/forge/bin/opts.rs | 8 +++++- 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 crates/forge/bin/cmd/solc.rs diff --git a/crates/forge/bin/cmd/mod.rs b/crates/forge/bin/cmd/mod.rs index c8d1dbb0e006..576c43c43d09 100644 --- a/crates/forge/bin/cmd/mod.rs +++ b/crates/forge/bin/cmd/mod.rs @@ -59,6 +59,7 @@ pub mod remappings; pub mod remove; pub mod selectors; pub mod snapshot; +pub mod solc; pub mod test; pub mod tree; pub mod update; diff --git a/crates/forge/bin/cmd/solc.rs b/crates/forge/bin/cmd/solc.rs new file mode 100644 index 000000000000..144587edf8d3 --- /dev/null +++ b/crates/forge/bin/cmd/solc.rs @@ -0,0 +1,55 @@ +use clap::{Parser, ValueHint}; +use eyre::Result; +use foundry_compilers::{compilers::solc::SolcVersionManager, Graph}; +use foundry_config::Config; +use std::path::PathBuf; + +/// CLI arguments for `forge solc`. +#[derive(Clone, Debug, Parser)] +pub enum SolcSubcommands { + /// Retrieves the resolved version(s) of the solidity compiler (solc) within the project. + #[command(visible_alias = "vr")] + VersionResolving { + /// The root directory + #[arg(value_hint = ValueHint::DirPath, default_value = ".", value_name = "PATH")] + root: PathBuf, + }, +} + +impl SolcSubcommands { + pub async fn run(self) -> Result<()> { + match &self { + SolcSubcommands::VersionResolving { root } => { + self.handle_version_resolving(&root).await + } + } + } + + async fn handle_version_resolving(&self, root: &PathBuf) -> Result<()> { + let config = Config::load_with_root(root); + let project = config.project()?; + + let graph = Graph::resolve(&project.paths)?; + + let version_manager = SolcVersionManager::default(); + let (versions, _) = graph.into_sources_by_version(project.offline, &version_manager)?; + + let sources_by_version = versions.get(&version_manager)?; + + for (_, version, sources) in sources_by_version { + println!("{}", version); + for (path_file, _) in sources.iter() { + println!( + "├── {}", + path_file + .strip_prefix(&project.paths.root) + .unwrap_or(path_file) + .to_path_buf() + .display() + ); + } + println!(""); + } + Ok(()) + } +} diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index 8db9036e186b..685aaf133486 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -111,6 +111,7 @@ fn main() -> Result<()> { GenerateSubcommands::Test(cmd) => cmd.run(), }, ForgeSubcommand::VerifyBytecode(cmd) => utils::block_on(cmd.run()), + ForgeSubcommand::Solc { command } => utils::block_on(command.run()), } } diff --git a/crates/forge/bin/opts.rs b/crates/forge/bin/opts.rs index 6ca78da0f44e..df17e8923a95 100644 --- a/crates/forge/bin/opts.rs +++ b/crates/forge/bin/opts.rs @@ -2,7 +2,7 @@ use crate::cmd::{ bind::BindArgs, build::BuildArgs, cache::CacheArgs, clone::CloneArgs, config, coverage, create::CreateArgs, debug::DebugArgs, doc::DocArgs, flatten, fmt::FmtArgs, geiger, generate, init::InitArgs, inspect, install::InstallArgs, remappings::RemappingArgs, remove::RemoveArgs, - selectors::SelectorsSubcommands, snapshot, test, tree, update, + selectors::SelectorsSubcommands, snapshot, solc::SolcSubcommands, test, tree, update, }; use clap::{Parser, Subcommand, ValueHint}; use forge_script::ScriptArgs; @@ -161,6 +161,12 @@ pub enum ForgeSubcommand { /// Verify the deployed bytecode against its source. #[clap(visible_alias = "vb")] VerifyBytecode(VerifyBytecodeArgs), + + /// Function solc utilities + Solc { + #[command(subcommand)] + command: SolcSubcommands, + }, } #[cfg(test)] From 09bb812cb5349f4d20e55dc6799d2b0c7a71e2d9 Mon Sep 17 00:00:00 2001 From: Joaquin Gonzalez Date: Sat, 11 May 2024 20:50:05 -0300 Subject: [PATCH 02/16] style: improve formatting in solc.rs file --- crates/forge/bin/cmd/solc.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/forge/bin/cmd/solc.rs b/crates/forge/bin/cmd/solc.rs index 144587edf8d3..295cf2e4e856 100644 --- a/crates/forge/bin/cmd/solc.rs +++ b/crates/forge/bin/cmd/solc.rs @@ -19,9 +19,7 @@ pub enum SolcSubcommands { impl SolcSubcommands { pub async fn run(self) -> Result<()> { match &self { - SolcSubcommands::VersionResolving { root } => { - self.handle_version_resolving(&root).await - } + SolcSubcommands::VersionResolving { root } => self.handle_version_resolving(root).await, } } @@ -37,7 +35,7 @@ impl SolcSubcommands { let sources_by_version = versions.get(&version_manager)?; for (_, version, sources) in sources_by_version { - println!("{}", version); + println!("{}:", version); for (path_file, _) in sources.iter() { println!( "├── {}", @@ -48,7 +46,6 @@ impl SolcSubcommands { .display() ); } - println!(""); } Ok(()) } From db2864b6e89e14247cba6b78ea5f34992b8f6585 Mon Sep 17 00:00:00 2001 From: Joaquin Gonzalez Date: Mon, 15 Jul 2024 11:42:52 -0300 Subject: [PATCH 03/16] fix: merge --- crates/forge/bin/cmd/solc.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/forge/bin/cmd/solc.rs b/crates/forge/bin/cmd/solc.rs index 295cf2e4e856..0b3f429bc333 100644 --- a/crates/forge/bin/cmd/solc.rs +++ b/crates/forge/bin/cmd/solc.rs @@ -30,7 +30,11 @@ impl SolcSubcommands { let graph = Graph::resolve(&project.paths)?; let version_manager = SolcVersionManager::default(); - let (versions, _) = graph.into_sources_by_version(project.offline, &version_manager)?; + let (versions, _) = graph.into_sources_by_version( + project.offline, + &project.locked_versions, + &version_manager, + )?; let sources_by_version = versions.get(&version_manager)?; From 433c0fb1ab89c163ad057c6fd92fe8e1be306a93 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 11:44:58 +0200 Subject: [PATCH 04/16] add json compatible output --- crates/forge/bin/cmd/compiler.rs | 116 ++++++++++++++++++++++++------- crates/forge/bin/main.rs | 2 +- crates/forge/bin/opts.rs | 17 ++--- 3 files changed, 99 insertions(+), 36 deletions(-) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index a169db790cea..0360d438ad5a 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -1,30 +1,54 @@ -use clap::{Parser, ValueHint}; +use clap::{ArgAction, Parser, Subcommand, ValueHint}; use eyre::Result; use foundry_compilers::Graph; use foundry_config::Config; -use std::path::PathBuf; +use std::{collections::BTreeMap, path::PathBuf}; /// CLI arguments for `forge compiler`. -#[derive(Clone, Debug, Parser)] -pub enum CompilerSubcommands { - /// Retrieves the resolved version(s) of the compiler within the project. - #[command(visible_alias = "r")] - Resolve { - /// The root directory - #[arg(value_hint = ValueHint::DirPath, default_value = ".", value_name = "PATH")] - root: PathBuf, - }, +#[derive(Debug, Parser)] +pub struct CompilerArgs { + #[command(subcommand)] + pub sub: CompilerSubcommands, } -impl CompilerSubcommands { +impl CompilerArgs { pub async fn run(self) -> Result<()> { - match &self { - Self::Resolve { root } => self.handle_version_resolving(root).await, + match self.sub { + CompilerSubcommands::Resolve(args) => args.run().await, } } +} +#[derive(Debug, Subcommand)] +pub enum CompilerSubcommands { /// Retrieves the resolved version(s) of the compiler within the project. - async fn handle_version_resolving(&self, root: &PathBuf) -> Result<()> { + Resolve(ResolveArgs), +} + +/// CLI arguments for `forge compiler resolve`. +#[derive(Debug, Parser)] +pub struct ResolveArgs { + /// The root directory + #[arg(value_hint = ValueHint::DirPath, default_value = ".", value_name = "PATH")] + root: PathBuf, + + /// Verbosity of the output. + /// + /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + /// + /// Verbosity levels: + /// - 2: Print sources + #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count, help_heading = "Display options")] + pub verbosity: u8, + + /// Print as JSON. + #[arg(long, short, help_heading = "Display options")] + json: bool, +} + +impl ResolveArgs { + pub async fn run(self) -> Result<()> { + let Self { root, verbosity, json } = self; let config = Config::load_with_root(root); let project = config.project()?; @@ -35,16 +59,58 @@ impl CompilerSubcommands { &project.compiler, )?; - for (language, sources) in sources { - for (version, sources) in sources { - println!("{language} {version}:"); - for (idx, (path_file, _)) in sources.iter().enumerate() { - let path = path_file - .strip_prefix(&project.paths.root) - .unwrap_or(path_file) - .to_path_buf(); - let prefix = if idx == sources.len() - 1 { "└──" } else { "├──" }; - println!("{prefix} {}", path.display()); + if json { + let mut output = BTreeMap::new(); + + for (language, sources) in sources { + let versions: Vec>> = sources + .iter() + .map(|(version, sources)| { + let paths: Vec = sources + .iter() + .map(|(path_file, _)| { + path_file + .strip_prefix(&project.paths.root) + .unwrap_or(path_file) + .to_path_buf() + .display() + .to_string() + }) + .collect(); + + let mut version_map = BTreeMap::new(); + version_map.insert(version.to_string(), paths); + version_map + }) + .collect(); + + // Insert language and its versions into the output map + output.insert(language.to_string(), versions); + } + + println!("{}", serde_json::to_string(&output)?); + } else { + for (language, sources) in sources { + println!("{language}:\n"); + + for (version, sources) in sources { + if verbosity >= 1 { + println!("{version}:"); + for (idx, (path_file, _)) in sources.iter().enumerate() { + let path = path_file + .strip_prefix(&project.paths.root) + .unwrap_or(path_file) + .to_path_buf(); + + if idx == sources.len() - 1 { + println!("└── {}\n", path.display()); + } else { + println!("├── {}", path.display()); + } + } + } else { + println!("- {language} {version}"); + } } } } diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index 895edb9a3803..59bf274d9e01 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -118,7 +118,7 @@ fn main() -> Result<()> { ForgeSubcommand::Generate(cmd) => match cmd.sub { GenerateSubcommands::Test(cmd) => cmd.run(), }, - ForgeSubcommand::Compiler { command } => utils::block_on(command.run()), + ForgeSubcommand::Compiler(cmd) => utils::block_on(cmd.run()), ForgeSubcommand::Soldeer(cmd) => utils::block_on(cmd.run()), ForgeSubcommand::Eip712(cmd) => cmd.run(), ForgeSubcommand::BindJson(cmd) => cmd.run(), diff --git a/crates/forge/bin/opts.rs b/crates/forge/bin/opts.rs index 316fd4cc56e1..d0dfecd3a132 100644 --- a/crates/forge/bin/opts.rs +++ b/crates/forge/bin/opts.rs @@ -1,9 +1,9 @@ use crate::cmd::{ bind::BindArgs, bind_json, build::BuildArgs, cache::CacheArgs, clone::CloneArgs, - compiler::CompilerSubcommands, config, coverage, create::CreateArgs, debug::DebugArgs, - doc::DocArgs, eip712, flatten, fmt::FmtArgs, geiger, generate, init::InitArgs, inspect, - install::InstallArgs, remappings::RemappingArgs, remove::RemoveArgs, - selectors::SelectorsSubcommands, snapshot, soldeer, test, tree, update, + compiler::CompilerArgs, config, coverage, create::CreateArgs, debug::DebugArgs, doc::DocArgs, + eip712, flatten, fmt::FmtArgs, geiger, generate, init::InitArgs, inspect, install::InstallArgs, + remappings::RemappingArgs, remove::RemoveArgs, selectors::SelectorsSubcommands, snapshot, + soldeer, test, tree, update, }; use clap::{Parser, Subcommand, ValueHint}; use forge_script::ScriptArgs; @@ -153,7 +153,7 @@ pub enum ForgeSubcommand { /// Generate documentation for the project. Doc(DocArgs), - /// Function selector utilities + /// Function selector utilities. #[command(visible_alias = "se")] Selectors { #[command(subcommand)] @@ -163,11 +163,8 @@ pub enum ForgeSubcommand { /// Generate scaffold files. Generate(generate::GenerateArgs), - /// Compiler utilities - Compiler { - #[command(subcommand)] - command: CompilerSubcommands, - }, + /// Compiler utilities. + Compiler(CompilerArgs), /// Soldeer dependency manager. Soldeer(soldeer::SoldeerArgs), From abe2456630a000cb8ff3751cbcff4ebe66e965a2 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 12:56:33 +0200 Subject: [PATCH 05/16] add basic tests --- crates/forge/bin/cmd/compiler.rs | 200 ++++++++++++++++++++++++------- 1 file changed, 154 insertions(+), 46 deletions(-) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 0360d438ad5a..ff235d94e2d5 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -2,6 +2,7 @@ use clap::{ArgAction, Parser, Subcommand, ValueHint}; use eyre::Result; use foundry_compilers::Graph; use foundry_config::Config; +use semver::Version; use std::{collections::BTreeMap, path::PathBuf}; /// CLI arguments for `forge compiler`. @@ -21,6 +22,7 @@ impl CompilerArgs { #[derive(Debug, Subcommand)] pub enum CompilerSubcommands { + #[command(visible_alias = "r")] /// Retrieves the resolved version(s) of the compiler within the project. Resolve(ResolveArgs), } @@ -59,62 +61,168 @@ impl ResolveArgs { &project.compiler, )?; - if json { - let mut output = BTreeMap::new(); - - for (language, sources) in sources { - let versions: Vec>> = sources - .iter() - .map(|(version, sources)| { - let paths: Vec = sources - .iter() - .map(|(path_file, _)| { - path_file - .strip_prefix(&project.paths.root) - .unwrap_or(path_file) - .to_path_buf() - .display() - .to_string() - }) - .collect(); - - let mut version_map = BTreeMap::new(); - version_map.insert(version.to_string(), paths); - version_map - }) - .collect(); - - // Insert language and its versions into the output map - output.insert(language.to_string(), versions); - } - - println!("{}", serde_json::to_string(&output)?); - } else { - for (language, sources) in sources { - println!("{language}:\n"); + let mut output = BTreeMap::new(); - for (version, sources) in sources { - if verbosity >= 1 { - println!("{version}:"); - for (idx, (path_file, _)) in sources.iter().enumerate() { - let path = path_file + for (language, sources) in sources { + let mut versions_with_paths: Vec<(Version, Vec)> = sources + .iter() + .map(|(version, sources)| { + let paths: Vec = sources + .iter() + .map(|(path_file, _)| { + path_file .strip_prefix(&project.paths.root) .unwrap_or(path_file) - .to_path_buf(); + .to_path_buf() + .display() + .to_string() + }) + .collect(); + + (version.clone(), paths) + }) + .collect(); - if idx == sources.len() - 1 { - println!("└── {}\n", path.display()); - } else { - println!("├── {}", path.display()); - } + // Sort the versions based on semantic versioning. + versions_with_paths.sort_by(|(v1, _), (v2, _)| v1.cmp(v2)); + + let sorted_versions: BTreeMap> = versions_with_paths + .into_iter() + .map(|(version, paths)| (version.to_string(), paths)) + .collect(); + + output.insert(language.to_string(), sorted_versions); + } + + if json { + println!("{}", serde_json::to_string(&output)?); + return Ok(()); + } + + for (language, versions) in &output { + if verbosity < 1 { + println!("{language}:"); + } else { + println!("{language}:\n"); + } + + for (version, paths) in versions { + if verbosity >= 1 { + println!("{version}:"); + for (idx, path) in paths.iter().enumerate() { + if idx == paths.len() - 1 { + println!("└── {path}\n"); + } else { + println!("├── {path}"); } - } else { - println!("- {language} {version}"); } + } else { + println!("- {version}"); } } + + if verbosity < 1 { + println!(); + } } Ok(()) } } + +#[cfg(test)] +mod tests { + use foundry_test_utils::{forgetest_init, snapbox::IntoData, str}; + + forgetest_init!(can_resolve_path, |prj, cmd| { + cmd.args(["compiler", "resolve", prj.root().to_str().unwrap()]).assert_success().stdout_eq( + str![[r#" +Solidity: +- 0.8.27 + + +"#]], + ); + }); + + forgetest_init!(can_list_resolved_compiler_versions, |prj, cmd| { + cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" +Solidity: +- 0.8.27 + + +"#]]); + }); + + forgetest_init!(can_list_resolved_compiler_versions_verbose, |prj, cmd| { + cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" +Solidity: + +0.8.27: +├── lib/forge-std/src/Base.sol +├── lib/forge-std/src/Script.sol +├── lib/forge-std/src/StdAssertions.sol +├── lib/forge-std/src/StdChains.sol +├── lib/forge-std/src/StdCheats.sol +├── lib/forge-std/src/StdError.sol +├── lib/forge-std/src/StdInvariant.sol +├── lib/forge-std/src/StdJson.sol +├── lib/forge-std/src/StdMath.sol +├── lib/forge-std/src/StdStorage.sol +├── lib/forge-std/src/StdStyle.sol +├── lib/forge-std/src/StdToml.sol +├── lib/forge-std/src/StdUtils.sol +├── lib/forge-std/src/Test.sol +├── lib/forge-std/src/Vm.sol +├── lib/forge-std/src/console.sol +├── lib/forge-std/src/console2.sol +├── lib/forge-std/src/interfaces/IERC165.sol +├── lib/forge-std/src/interfaces/IERC20.sol +├── lib/forge-std/src/interfaces/IERC721.sol +├── lib/forge-std/src/interfaces/IMulticall3.sol +├── lib/forge-std/src/mocks/MockERC20.sol +├── lib/forge-std/src/mocks/MockERC721.sol +├── lib/forge-std/src/safeconsole.sol +├── script/Counter.s.sol +├── src/Counter.sol +└── test/Counter.t.sol + + +"#]]); + }); + + forgetest_init!(can_list_resolved_compiler_versions_json, |prj, cmd| { + cmd.args(["compiler", "resolve", "--json"]) + .assert_success() + .stdout_eq(str![[r#" +{"Solidity":{"0.8.27":["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]}}"#]].is_jsonlines()); + }); + + const CONTRACT_A: &str = r#" +//SPDX-license-identifier: MIT +pragma solidity 0.8.4; + +contract ContractA {} +"#; + + const CONTRACT_B: &str = r#" +//SPDX-license-identifier: MIT +pragma solidity 0.8.11; + +contract ContractB {} +"#; + + forgetest_init!(can_list_resolved_multiple_compiler_versions, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + + cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" +Solidity: +- 0.8.11 +- 0.8.27 +- 0.8.4 + + +"#]]); + }); +} From 1d6f47a94366bcb9a5736af849a6a93b8fdd707d Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 13:45:13 +0200 Subject: [PATCH 06/16] add basic tests --- crates/forge/bin/cmd/compiler.rs | 64 ++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index ff235d94e2d5..ef4a3c28638a 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -61,7 +61,7 @@ impl ResolveArgs { &project.compiler, )?; - let mut output = BTreeMap::new(); + let mut output: BTreeMap)>> = BTreeMap::new(); for (language, sources) in sources { let mut versions_with_paths: Vec<(Version, Vec)> = sources @@ -83,15 +83,9 @@ impl ResolveArgs { }) .collect(); - // Sort the versions based on semantic versioning. - versions_with_paths.sort_by(|(v1, _), (v2, _)| v1.cmp(v2)); + versions_with_paths.sort_by(|(v1, _), (v2, _)| Version::cmp(v1, v2)); - let sorted_versions: BTreeMap> = versions_with_paths - .into_iter() - .map(|(version, paths)| (version.to_string(), paths)) - .collect(); - - output.insert(language.to_string(), sorted_versions); + output.insert(language.to_string(), versions_with_paths); } if json { @@ -195,7 +189,7 @@ Solidity: cmd.args(["compiler", "resolve", "--json"]) .assert_success() .stdout_eq(str![[r#" -{"Solidity":{"0.8.27":["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]}}"#]].is_jsonlines()); +{"Solidity":[["0.8.27",["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]]]}"#]].is_jsonlines()); }); const CONTRACT_A: &str = r#" @@ -216,11 +210,57 @@ contract ContractB {} prj.add_source("ContractA", CONTRACT_A).unwrap(); prj.add_source("ContractB", CONTRACT_B).unwrap(); - cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" + cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" Solidity: +- 0.8.4 - 0.8.11 - 0.8.27 -- 0.8.4 + + +"#]]); + }); + + forgetest_init!(can_list_resolved_multiple_compiler_versions_verbose, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + + cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" +Solidity: + +0.8.4: +└── src/ContractA.sol + +0.8.11: +└── src/ContractB.sol + +0.8.27: +├── lib/forge-std/src/Base.sol +├── lib/forge-std/src/Script.sol +├── lib/forge-std/src/StdAssertions.sol +├── lib/forge-std/src/StdChains.sol +├── lib/forge-std/src/StdCheats.sol +├── lib/forge-std/src/StdError.sol +├── lib/forge-std/src/StdInvariant.sol +├── lib/forge-std/src/StdJson.sol +├── lib/forge-std/src/StdMath.sol +├── lib/forge-std/src/StdStorage.sol +├── lib/forge-std/src/StdStyle.sol +├── lib/forge-std/src/StdToml.sol +├── lib/forge-std/src/StdUtils.sol +├── lib/forge-std/src/Test.sol +├── lib/forge-std/src/Vm.sol +├── lib/forge-std/src/console.sol +├── lib/forge-std/src/console2.sol +├── lib/forge-std/src/interfaces/IERC165.sol +├── lib/forge-std/src/interfaces/IERC20.sol +├── lib/forge-std/src/interfaces/IERC721.sol +├── lib/forge-std/src/interfaces/IMulticall3.sol +├── lib/forge-std/src/mocks/MockERC20.sol +├── lib/forge-std/src/mocks/MockERC721.sol +├── lib/forge-std/src/safeconsole.sol +├── script/Counter.s.sol +├── src/Counter.sol +└── test/Counter.t.sol "#]]); From 766aaa533b9cca0cab13c1a69e81a6b952f833bf Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 13:45:47 +0200 Subject: [PATCH 07/16] clean up --- crates/forge/bin/cmd/compiler.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index ef4a3c28638a..191e9d80b0f2 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -39,7 +39,7 @@ pub struct ResolveArgs { /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). /// /// Verbosity levels: - /// - 2: Print sources + /// - 2: Print source paths. #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count, help_heading = "Display options")] pub verbosity: u8, @@ -193,14 +193,14 @@ Solidity: }); const CONTRACT_A: &str = r#" -//SPDX-license-identifier: MIT +// SPDX-license-identifier: MIT pragma solidity 0.8.4; contract ContractA {} "#; const CONTRACT_B: &str = r#" -//SPDX-license-identifier: MIT +// SPDX-license-identifier: MIT pragma solidity 0.8.11; contract ContractB {} From 32863e7b19bc07304ad0cac2e2b018fdde295f94 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 14:19:05 +0200 Subject: [PATCH 08/16] finish tests --- Cargo.lock | 15 ++-- Cargo.toml | 3 + crates/forge/bin/cmd/compiler.rs | 116 +++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e597a7a91fd0..c19a129412d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3737,8 +3737,7 @@ dependencies = [ [[package]] name = "foundry-compilers" version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6cc925fc9fdd73f1038c528fef17ddbdd7512311809ace7d1860fe3666dbb5" +source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3775,8 +3774,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d5c999c80c6d702c51522f5b4a805bec5fcae978637f0c337fa5c7a4b43d863" +source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3785,8 +3783,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3747cfeab1fc8299d70ceae0a28b7e2e005324e8eba78ac7d06729d67be5a1ec" +source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3809,8 +3806,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd5c142355bd4822b8a7ec37268cfafe37b2e36835fa8d067b2b9d5a22c7529" +source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3824,8 +3820,7 @@ dependencies = [ [[package]] name = "foundry-compilers-core" version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1291c05a4c8c3b4558eb1b50f53ee1f1b599ff2490d62cdc519ad5ae4b088d6" +source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" dependencies = [ "alloy-primitives", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 322152f87221..f0222e5ab361 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -319,3 +319,6 @@ yansi = { version = "1.0", features = ["detect-tty", "detect-env"] } # alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } + +## foundry +foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "877ab1c" } diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 191e9d80b0f2..038f41b5a27c 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -206,9 +206,44 @@ pragma solidity 0.8.11; contract ContractB {} "#; + const VYPER_INTERFACE: &str = r#" +# pragma version ^0.3.10 + +@external +@view +def number() -> uint256: + return empty(uint256) + +@external +def set_number(new_number: uint256): + pass + +@external +def increment() -> uint256: + return empty(uint256) +"#; + + const VYPER_CONTRACT: &str = r#" +import ICounter +implements: ICounter + +number: public(uint256) + +@external +def set_number(new_number: uint256): + self.number = new_number + +@external +def increment() -> uint256: + self.number += 1 + return self.number +"#; + forgetest_init!(can_list_resolved_multiple_compiler_versions, |prj, cmd| { prj.add_source("ContractA", CONTRACT_A).unwrap(); prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_raw_source("ICounter.vy", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" Solidity: @@ -216,6 +251,9 @@ Solidity: - 0.8.11 - 0.8.27 +Vyper: +- 0.4.0 + "#]]); }); @@ -223,6 +261,8 @@ Solidity: forgetest_init!(can_list_resolved_multiple_compiler_versions_verbose, |prj, cmd| { prj.add_source("ContractA", CONTRACT_A).unwrap(); prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_raw_source("ICounter.vy", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" Solidity: @@ -262,7 +302,83 @@ Solidity: ├── src/Counter.sol └── test/Counter.t.sol +Vyper: + +0.4.0: +├── src/Counter.vy +└── src/ICounter.vy + "#]]); }); + + forgetest_init!(can_list_resolved_multiple_compiler_versions_json, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_raw_source("ICounter.vy", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + // { + // "Solidity":[ + // [ + // "0.8.4", + // [ + // "src/ContractA.sol" + // ] + // ], + // [ + // "0.8.11", + // [ + // "src/ContractB.sol" + // ] + // ], + // [ + // "0.8.27", + // [ + // "lib/forge-std/src/Base.sol", + // "lib/forge-std/src/Script.sol", + // "lib/forge-std/src/StdAssertions.sol", + // "lib/forge-std/src/StdChains.sol", + // "lib/forge-std/src/StdCheats.sol", + // "lib/forge-std/src/StdError.sol", + // "lib/forge-std/src/StdInvariant.sol", + // "lib/forge-std/src/StdJson.sol", + // "lib/forge-std/src/StdMath.sol", + // "lib/forge-std/src/StdStorage.sol", + // "lib/forge-std/src/StdStyle.sol", + // "lib/forge-std/src/StdToml.sol", + // "lib/forge-std/src/StdUtils.sol", + // "lib/forge-std/src/Test.sol", + // "lib/forge-std/src/Vm.sol", + // "lib/forge-std/src/console.sol", + // "lib/forge-std/src/console2.sol", + // "lib/forge-std/src/interfaces/IERC165.sol", + // "lib/forge-std/src/interfaces/IERC20.sol", + // "lib/forge-std/src/interfaces/IERC721.sol", + // "lib/forge-std/src/interfaces/IMulticall3.sol", + // "lib/forge-std/src/mocks/MockERC20.sol", + // "lib/forge-std/src/mocks/MockERC721.sol", + // "lib/forge-std/src/safeconsole.sol", + // "script/Counter.s.sol", + // "src/Counter.sol", + // "test/Counter.t.sol" + // ] + // ] + // ], + // "Vyper":[ + // [ + // "0.4.0", + // [ + // "src/Counter.vy", + // "src/ICounter.vy" + // ] + // ] + // ] + // } + cmd.args(["compiler", "resolve", "--json"]) + .assert_success() + .stdout_eq(str![[r#" +{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vy"]]]} +"#]].is_jsonlines()); + }); } From 724733036ab0eab33f723eb9e2bae8e009d8b186 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 15:07:42 +0200 Subject: [PATCH 09/16] add skip flag --- Cargo.lock | 10 +-- Cargo.toml | 2 +- crates/forge/bin/cmd/compiler.rs | 143 +++++++++++++++---------------- 3 files changed, 75 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c19a129412d7..91ec0943b29c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3737,7 +3737,7 @@ dependencies = [ [[package]] name = "foundry-compilers" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" +source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3774,7 +3774,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" +source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3783,7 +3783,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" +source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3806,7 +3806,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" +source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3820,7 +3820,7 @@ dependencies = [ [[package]] name = "foundry-compilers-core" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=877ab1c#877ab1c3a45efd339d4c3bd6fd7c5942561c477a" +source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" dependencies = [ "alloy-primitives", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index f0222e5ab361..a7bd33b2d27f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -321,4 +321,4 @@ yansi = { version = "1.0", features = ["detect-tty", "detect-env"] } # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } ## foundry -foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "877ab1c" } +foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "71c6ec7" } diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 038f41b5a27c..5ec228a62178 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -31,8 +31,12 @@ pub enum CompilerSubcommands { #[derive(Debug, Parser)] pub struct ResolveArgs { /// The root directory - #[arg(value_hint = ValueHint::DirPath, default_value = ".", value_name = "PATH")] - root: PathBuf, + #[arg(long, short, value_hint = ValueHint::DirPath, value_name = "PATH")] + root: Option, + + /// Skip files that match the given regex pattern. + #[arg(long, short, value_name = "REGEX")] + skip: Option, /// Verbosity of the output. /// @@ -50,8 +54,10 @@ pub struct ResolveArgs { impl ResolveArgs { pub async fn run(self) -> Result<()> { - let Self { root, verbosity, json } = self; - let config = Config::load_with_root(root); + let Self { root, skip, verbosity, json } = self; + + let root = root.unwrap_or_else(|| PathBuf::from(".")); + let config = Config::load_with_root(&root); let project = config.project()?; let graph = Graph::resolve(&project.paths)?; @@ -69,23 +75,37 @@ impl ResolveArgs { .map(|(version, sources)| { let paths: Vec = sources .iter() - .map(|(path_file, _)| { - path_file + .filter_map(|(path_file, _)| { + let path_str = path_file .strip_prefix(&project.paths.root) .unwrap_or(path_file) .to_path_buf() .display() - .to_string() + .to_string(); + + // Skip files that match the given regex pattern. + if let Some(ref regex) = skip { + if regex.is_match(&path_str) { + return None; + } + } + + Some(path_str) }) .collect(); (version.clone(), paths) }) + .filter(|(_, paths)| !paths.is_empty()) .collect(); + // Sort by SemVer version. versions_with_paths.sort_by(|(v1, _), (v2, _)| Version::cmp(v1, v2)); - output.insert(language.to_string(), versions_with_paths); + // Skip language if no paths are found after filtering. + if !versions_with_paths.is_empty() { + output.insert(language.to_string(), versions_with_paths); + } } if json { @@ -129,14 +149,14 @@ mod tests { use foundry_test_utils::{forgetest_init, snapbox::IntoData, str}; forgetest_init!(can_resolve_path, |prj, cmd| { - cmd.args(["compiler", "resolve", prj.root().to_str().unwrap()]).assert_success().stdout_eq( - str![[r#" + cmd.args(["compiler", "resolve", "--root", prj.root().to_str().unwrap()]) + .assert_success() + .stdout_eq(str![[r#" Solidity: - 0.8.27 -"#]], - ); +"#]]); }); forgetest_init!(can_list_resolved_compiler_versions, |prj, cmd| { @@ -242,7 +262,7 @@ def increment() -> uint256: forgetest_init!(can_list_resolved_multiple_compiler_versions, |prj, cmd| { prj.add_source("ContractA", CONTRACT_A).unwrap(); prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vy", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" @@ -258,10 +278,42 @@ Vyper: "#]]); }); + forgetest_init!(can_list_resolved_multiple_compiler_versions_skipped, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve", "--skip", ".sol", "-v"]).assert_success().stdout_eq(str![ + [r#" +Vyper: + +0.4.0: +├── src/Counter.vy +└── src/ICounter.vyi + + +"#] + ]); + }); + + forgetest_init!(can_list_resolved_multiple_compiler_versions_skipped_json, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve", "--skip", "script|test|lib", "--json"]) + .assert_success() + .stdout_eq(str![[r#" +{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["src/Counter.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} +"#]].is_jsonlines()); + }); + forgetest_init!(can_list_resolved_multiple_compiler_versions_verbose, |prj, cmd| { prj.add_source("ContractA", CONTRACT_A).unwrap(); prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vy", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" @@ -306,7 +358,7 @@ Vyper: 0.4.0: ├── src/Counter.vy -└── src/ICounter.vy +└── src/ICounter.vyi "#]]); @@ -315,70 +367,13 @@ Vyper: forgetest_init!(can_list_resolved_multiple_compiler_versions_json, |prj, cmd| { prj.add_source("ContractA", CONTRACT_A).unwrap(); prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vy", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); - // { - // "Solidity":[ - // [ - // "0.8.4", - // [ - // "src/ContractA.sol" - // ] - // ], - // [ - // "0.8.11", - // [ - // "src/ContractB.sol" - // ] - // ], - // [ - // "0.8.27", - // [ - // "lib/forge-std/src/Base.sol", - // "lib/forge-std/src/Script.sol", - // "lib/forge-std/src/StdAssertions.sol", - // "lib/forge-std/src/StdChains.sol", - // "lib/forge-std/src/StdCheats.sol", - // "lib/forge-std/src/StdError.sol", - // "lib/forge-std/src/StdInvariant.sol", - // "lib/forge-std/src/StdJson.sol", - // "lib/forge-std/src/StdMath.sol", - // "lib/forge-std/src/StdStorage.sol", - // "lib/forge-std/src/StdStyle.sol", - // "lib/forge-std/src/StdToml.sol", - // "lib/forge-std/src/StdUtils.sol", - // "lib/forge-std/src/Test.sol", - // "lib/forge-std/src/Vm.sol", - // "lib/forge-std/src/console.sol", - // "lib/forge-std/src/console2.sol", - // "lib/forge-std/src/interfaces/IERC165.sol", - // "lib/forge-std/src/interfaces/IERC20.sol", - // "lib/forge-std/src/interfaces/IERC721.sol", - // "lib/forge-std/src/interfaces/IMulticall3.sol", - // "lib/forge-std/src/mocks/MockERC20.sol", - // "lib/forge-std/src/mocks/MockERC721.sol", - // "lib/forge-std/src/safeconsole.sol", - // "script/Counter.s.sol", - // "src/Counter.sol", - // "test/Counter.t.sol" - // ] - // ] - // ], - // "Vyper":[ - // [ - // "0.4.0", - // [ - // "src/Counter.vy", - // "src/ICounter.vy" - // ] - // ] - // ] - // } cmd.args(["compiler", "resolve", "--json"]) .assert_success() .stdout_eq(str![[r#" -{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vy"]]]} +{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} "#]].is_jsonlines()); }); } From 9ef70a85d858239644fcd612ae5b1cbdd51542be Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 15:36:00 +0200 Subject: [PATCH 10/16] add vyper for unit tests --- .github/workflows/nextest.yml | 4 ++-- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index 8803540806de..610ad6a0f709 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -67,12 +67,12 @@ jobs: with: bun-version: latest - name: Setup Python - if: contains(matrix.name, 'external') + if: contains(matrix.name, 'external') || contains(matrix.name, 'unit') uses: actions/setup-python@v4 with: python-version: 3.11 - name: Install Vyper - if: contains(matrix.name, 'external') + if: contains(matrix.name, 'external') || contains(matrix.name, 'unit') run: pip install vyper~=0.4.0 - name: Forge RPC cache diff --git a/Cargo.lock b/Cargo.lock index 91ec0943b29c..d941dbac8fbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3737,7 +3737,7 @@ dependencies = [ [[package]] name = "foundry-compilers" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" +source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3774,7 +3774,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" +source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3783,7 +3783,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" +source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3806,7 +3806,7 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" +source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3820,7 +3820,7 @@ dependencies = [ [[package]] name = "foundry-compilers-core" version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=71c6ec7#71c6ec7b39e923c5e8ce26bb67bbb0f732b05ad1" +source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" dependencies = [ "alloy-primitives", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index a7bd33b2d27f..7728d4db8583 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -321,4 +321,4 @@ yansi = { version = "1.0", features = ["detect-tty", "detect-env"] } # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } ## foundry -foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "71c6ec7" } +foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "b7005a3" } From f84cabb430bfb31eb6edaa81816a94be771d52d1 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 16:46:50 +0200 Subject: [PATCH 11/16] move tests, pin compiler version, use forgetest! --- crates/forge/bin/cmd/compiler.rs | 234 ----------------------------- crates/forge/tests/cli/compiler.rs | 218 +++++++++++++++++++++++++++ crates/forge/tests/cli/main.rs | 1 + 3 files changed, 219 insertions(+), 234 deletions(-) create mode 100644 crates/forge/tests/cli/compiler.rs diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 5ec228a62178..cdca0a5600e6 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -143,237 +143,3 @@ impl ResolveArgs { Ok(()) } } - -#[cfg(test)] -mod tests { - use foundry_test_utils::{forgetest_init, snapbox::IntoData, str}; - - forgetest_init!(can_resolve_path, |prj, cmd| { - cmd.args(["compiler", "resolve", "--root", prj.root().to_str().unwrap()]) - .assert_success() - .stdout_eq(str![[r#" -Solidity: -- 0.8.27 - - -"#]]); - }); - - forgetest_init!(can_list_resolved_compiler_versions, |prj, cmd| { - cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" -Solidity: -- 0.8.27 - - -"#]]); - }); - - forgetest_init!(can_list_resolved_compiler_versions_verbose, |prj, cmd| { - cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" -Solidity: - -0.8.27: -├── lib/forge-std/src/Base.sol -├── lib/forge-std/src/Script.sol -├── lib/forge-std/src/StdAssertions.sol -├── lib/forge-std/src/StdChains.sol -├── lib/forge-std/src/StdCheats.sol -├── lib/forge-std/src/StdError.sol -├── lib/forge-std/src/StdInvariant.sol -├── lib/forge-std/src/StdJson.sol -├── lib/forge-std/src/StdMath.sol -├── lib/forge-std/src/StdStorage.sol -├── lib/forge-std/src/StdStyle.sol -├── lib/forge-std/src/StdToml.sol -├── lib/forge-std/src/StdUtils.sol -├── lib/forge-std/src/Test.sol -├── lib/forge-std/src/Vm.sol -├── lib/forge-std/src/console.sol -├── lib/forge-std/src/console2.sol -├── lib/forge-std/src/interfaces/IERC165.sol -├── lib/forge-std/src/interfaces/IERC20.sol -├── lib/forge-std/src/interfaces/IERC721.sol -├── lib/forge-std/src/interfaces/IMulticall3.sol -├── lib/forge-std/src/mocks/MockERC20.sol -├── lib/forge-std/src/mocks/MockERC721.sol -├── lib/forge-std/src/safeconsole.sol -├── script/Counter.s.sol -├── src/Counter.sol -└── test/Counter.t.sol - - -"#]]); - }); - - forgetest_init!(can_list_resolved_compiler_versions_json, |prj, cmd| { - cmd.args(["compiler", "resolve", "--json"]) - .assert_success() - .stdout_eq(str![[r#" -{"Solidity":[["0.8.27",["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]]]}"#]].is_jsonlines()); - }); - - const CONTRACT_A: &str = r#" -// SPDX-license-identifier: MIT -pragma solidity 0.8.4; - -contract ContractA {} -"#; - - const CONTRACT_B: &str = r#" -// SPDX-license-identifier: MIT -pragma solidity 0.8.11; - -contract ContractB {} -"#; - - const VYPER_INTERFACE: &str = r#" -# pragma version ^0.3.10 - -@external -@view -def number() -> uint256: - return empty(uint256) - -@external -def set_number(new_number: uint256): - pass - -@external -def increment() -> uint256: - return empty(uint256) -"#; - - const VYPER_CONTRACT: &str = r#" -import ICounter -implements: ICounter - -number: public(uint256) - -@external -def set_number(new_number: uint256): - self.number = new_number - -@external -def increment() -> uint256: - self.number += 1 - return self.number -"#; - - forgetest_init!(can_list_resolved_multiple_compiler_versions, |prj, cmd| { - prj.add_source("ContractA", CONTRACT_A).unwrap(); - prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); - prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); - - cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" -Solidity: -- 0.8.4 -- 0.8.11 -- 0.8.27 - -Vyper: -- 0.4.0 - - -"#]]); - }); - - forgetest_init!(can_list_resolved_multiple_compiler_versions_skipped, |prj, cmd| { - prj.add_source("ContractA", CONTRACT_A).unwrap(); - prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); - prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); - - cmd.args(["compiler", "resolve", "--skip", ".sol", "-v"]).assert_success().stdout_eq(str![ - [r#" -Vyper: - -0.4.0: -├── src/Counter.vy -└── src/ICounter.vyi - - -"#] - ]); - }); - - forgetest_init!(can_list_resolved_multiple_compiler_versions_skipped_json, |prj, cmd| { - prj.add_source("ContractA", CONTRACT_A).unwrap(); - prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); - prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); - - cmd.args(["compiler", "resolve", "--skip", "script|test|lib", "--json"]) - .assert_success() - .stdout_eq(str![[r#" -{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["src/Counter.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} -"#]].is_jsonlines()); - }); - - forgetest_init!(can_list_resolved_multiple_compiler_versions_verbose, |prj, cmd| { - prj.add_source("ContractA", CONTRACT_A).unwrap(); - prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); - prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); - - cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" -Solidity: - -0.8.4: -└── src/ContractA.sol - -0.8.11: -└── src/ContractB.sol - -0.8.27: -├── lib/forge-std/src/Base.sol -├── lib/forge-std/src/Script.sol -├── lib/forge-std/src/StdAssertions.sol -├── lib/forge-std/src/StdChains.sol -├── lib/forge-std/src/StdCheats.sol -├── lib/forge-std/src/StdError.sol -├── lib/forge-std/src/StdInvariant.sol -├── lib/forge-std/src/StdJson.sol -├── lib/forge-std/src/StdMath.sol -├── lib/forge-std/src/StdStorage.sol -├── lib/forge-std/src/StdStyle.sol -├── lib/forge-std/src/StdToml.sol -├── lib/forge-std/src/StdUtils.sol -├── lib/forge-std/src/Test.sol -├── lib/forge-std/src/Vm.sol -├── lib/forge-std/src/console.sol -├── lib/forge-std/src/console2.sol -├── lib/forge-std/src/interfaces/IERC165.sol -├── lib/forge-std/src/interfaces/IERC20.sol -├── lib/forge-std/src/interfaces/IERC721.sol -├── lib/forge-std/src/interfaces/IMulticall3.sol -├── lib/forge-std/src/mocks/MockERC20.sol -├── lib/forge-std/src/mocks/MockERC721.sol -├── lib/forge-std/src/safeconsole.sol -├── script/Counter.s.sol -├── src/Counter.sol -└── test/Counter.t.sol - -Vyper: - -0.4.0: -├── src/Counter.vy -└── src/ICounter.vyi - - -"#]]); - }); - - forgetest_init!(can_list_resolved_multiple_compiler_versions_json, |prj, cmd| { - prj.add_source("ContractA", CONTRACT_A).unwrap(); - prj.add_source("ContractB", CONTRACT_B).unwrap(); - prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); - prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); - - cmd.args(["compiler", "resolve", "--json"]) - .assert_success() - .stdout_eq(str![[r#" -{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["lib/forge-std/src/Base.sol","lib/forge-std/src/Script.sol","lib/forge-std/src/StdAssertions.sol","lib/forge-std/src/StdChains.sol","lib/forge-std/src/StdCheats.sol","lib/forge-std/src/StdError.sol","lib/forge-std/src/StdInvariant.sol","lib/forge-std/src/StdJson.sol","lib/forge-std/src/StdMath.sol","lib/forge-std/src/StdStorage.sol","lib/forge-std/src/StdStyle.sol","lib/forge-std/src/StdToml.sol","lib/forge-std/src/StdUtils.sol","lib/forge-std/src/Test.sol","lib/forge-std/src/Vm.sol","lib/forge-std/src/console.sol","lib/forge-std/src/console2.sol","lib/forge-std/src/interfaces/IERC165.sol","lib/forge-std/src/interfaces/IERC20.sol","lib/forge-std/src/interfaces/IERC721.sol","lib/forge-std/src/interfaces/IMulticall3.sol","lib/forge-std/src/mocks/MockERC20.sol","lib/forge-std/src/mocks/MockERC721.sol","lib/forge-std/src/safeconsole.sol","script/Counter.s.sol","src/Counter.sol","test/Counter.t.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} -"#]].is_jsonlines()); - }); -} diff --git a/crates/forge/tests/cli/compiler.rs b/crates/forge/tests/cli/compiler.rs new file mode 100644 index 000000000000..e2ee5963f1ba --- /dev/null +++ b/crates/forge/tests/cli/compiler.rs @@ -0,0 +1,218 @@ +//! Tests for the `forge compiler` command. + +use foundry_test_utils::snapbox::IntoData; + +const CONTRACT_A: &str = r#" +// SPDX-license-identifier: MIT +pragma solidity 0.8.4; + +contract ContractA {} +"#; + +const CONTRACT_B: &str = r#" +// SPDX-license-identifier: MIT +pragma solidity 0.8.11; + +contract ContractB {} +"#; + +const CONTRACT_C: &str = r#" +// SPDX-license-identifier: MIT +pragma solidity 0.8.27; + +contract ContractC {} +"#; + +const CONTRACT_D: &str = r#" +// SPDX-license-identifier: MIT +pragma solidity 0.8.27; + +contract ContractD {} +"#; + +const VYPER_INTERFACE: &str = r#" +# pragma version 0.4.0 + +@external +@view +def number() -> uint256: + return empty(uint256) + +@external +def set_number(new_number: uint256): + pass + +@external +def increment() -> uint256: + return empty(uint256) +"#; + +const VYPER_CONTRACT: &str = r#" +import ICounter +implements: ICounter + +number: public(uint256) + +@external +def set_number(new_number: uint256): + self.number = new_number + +@external +def increment() -> uint256: + self.number += 1 + return self.number +"#; + +forgetest!(can_resolve_path, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + + cmd.args(["compiler", "resolve", "--root", prj.root().to_str().unwrap()]) + .assert_success() + .stdout_eq(str![[r#" +Solidity: +- 0.8.4 + + +"#]]); +}); + +forgetest!(can_list_resolved_compiler_versions, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + + cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" +Solidity: +- 0.8.4 + + +"#]]); +}); + +forgetest!(can_list_resolved_compiler_versions_verbose, |prj, cmd| { + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + + cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" +Solidity: + +0.8.27: +├── src/ContractC.sol +└── src/ContractD.sol + + +"#]]); +}); + +forgetest!(can_list_resolved_compiler_versions_json, |prj, cmd| { + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + + cmd.args(["compiler", "resolve", "--json"]).assert_success().stdout_eq( + str![[r#" +{"Solidity":[["0.8.27",["src/ContractC.sol","src/ContractD.sol"]]]}"#]] + .is_jsonlines(), + ); +}); + +forgetest!(can_list_resolved_multiple_compiler_versions, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve"]).assert_success().stdout_eq(str![[r#" +Solidity: +- 0.8.4 +- 0.8.11 +- 0.8.27 + +Vyper: +- 0.4.0 + + +"#]]); +}); + +forgetest!(can_list_resolved_multiple_compiler_versions_skipped, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve", "--skip", ".sol", "-v"]).assert_success().stdout_eq(str![[ + r#" +Vyper: + +0.4.0: +├── src/Counter.vy +└── src/ICounter.vyi + + +"# + ]]); +}); + +forgetest!(can_list_resolved_multiple_compiler_versions_skipped_json, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve", "--skip", "Contract(A|B|C)", "--json"]) + .assert_success() + .stdout_eq(str![[r#" +{"Solidity":[["0.8.27",["src/ContractD.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} +"#]].is_jsonlines()); +}); + +forgetest!(can_list_resolved_multiple_compiler_versions_verbose, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve", "-v"]).assert_success().stdout_eq(str![[r#" +Solidity: + +0.8.4: +└── src/ContractA.sol + +0.8.11: +└── src/ContractB.sol + +0.8.27: +├── src/ContractC.sol +└── src/ContractD.sol + +Vyper: + +0.4.0: +├── src/Counter.vy +└── src/ICounter.vyi + + +"#]]); +}); + +forgetest!(can_list_resolved_multiple_compiler_versions_json, |prj, cmd| { + prj.add_source("ContractA", CONTRACT_A).unwrap(); + prj.add_source("ContractB", CONTRACT_B).unwrap(); + prj.add_source("ContractC", CONTRACT_C).unwrap(); + prj.add_source("ContractD", CONTRACT_D).unwrap(); + prj.add_raw_source("ICounter.vyi", VYPER_INTERFACE).unwrap(); + prj.add_raw_source("Counter.vy", VYPER_CONTRACT).unwrap(); + + cmd.args(["compiler", "resolve", "--json"]).assert_success().stdout_eq( + str![[r#" +{"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["src/ContractC.sol","src/ContractD.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} +"#]] + .is_jsonlines(), + ); +}); diff --git a/crates/forge/tests/cli/main.rs b/crates/forge/tests/cli/main.rs index 6ad29ca48a93..a53a26d2ac5a 100644 --- a/crates/forge/tests/cli/main.rs +++ b/crates/forge/tests/cli/main.rs @@ -9,6 +9,7 @@ mod bind_json; mod build; mod cache; mod cmd; +mod compiler; mod config; mod context; mod coverage; From 2d1de84baaada5f0c9424ccece6179ed5bf35311 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Mon, 14 Oct 2024 17:15:07 +0200 Subject: [PATCH 12/16] update CI test location for target Python / Vyper --- .github/workflows/nextest.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index 610ad6a0f709..e71e94c9a250 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -67,12 +67,12 @@ jobs: with: bun-version: latest - name: Setup Python - if: contains(matrix.name, 'external') || contains(matrix.name, 'unit') + if: contains(matrix.name, 'external') || contains(matrix.name, 'integration') uses: actions/setup-python@v4 with: python-version: 3.11 - name: Install Vyper - if: contains(matrix.name, 'external') || contains(matrix.name, 'unit') + if: contains(matrix.name, 'external') || contains(matrix.name, 'integration') run: pip install vyper~=0.4.0 - name: Forge RPC cache From 608214f95526e15289e66f403c61192d3ae35360 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Wed, 16 Oct 2024 10:56:12 +0200 Subject: [PATCH 13/16] update foundry-compilers crate --- Cargo.lock | 25 +++++++++++++++---------- Cargo.toml | 5 +---- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93c1301786c9..e90515c689de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3754,8 +3754,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cabcc146459af3ef3c7d05bfd1cca1450b065aaa0c168d567b3fe25d8530558" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3791,8 +3792,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0217f21ad9c0aa8127fcca23e69bda25101b0849027e3cf949f04252b22810fd" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3800,8 +3802,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35255af997575a4aac46d86259fb43c222edfbcf48230ed929fa7c92ece6277" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3823,8 +3826,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626fdc9a2ba83240d1b5ebbe3d8d50d794f231aa652abf27289119e71f6e774b" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3837,8 +3841,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.11.4" -source = "git+https://github.com/foundry-rs/compilers.git?rev=b7005a3#b7005a35f790db40df32d4aaac8f78d91bdbebe1" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51486ab73194212079801418f6cc66ba05275467c80241a7f05bb7ef0475774a" dependencies = [ "alloy-primitives", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index ccb7f3ec2e56..877037e09716 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -169,7 +169,7 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.7.3", default-features = false } -foundry-compilers = { version = "0.11.4", default-features = false } +foundry-compilers = { version = "0.11.5", default-features = false } foundry-fork-db = "0.4.0" solang-parser = "=0.3.3" @@ -321,6 +321,3 @@ yansi = { version = "1.0", features = ["detect-tty", "detect-env"] } # alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } - -## foundry -foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "b7005a3" } From 65d8d0bccde62b6f26f8bdf154aa87929558fad1 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:51:11 +0200 Subject: [PATCH 14/16] Update crates/forge/bin/cmd/compiler.rs Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- crates/forge/bin/cmd/compiler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index cdca0a5600e6..369041dd6eb0 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -22,8 +22,8 @@ impl CompilerArgs { #[derive(Debug, Subcommand)] pub enum CompilerSubcommands { - #[command(visible_alias = "r")] /// Retrieves the resolved version(s) of the compiler within the project. + #[command(visible_alias = "r")] Resolve(ResolveArgs), } From 4b5a08fd8183ece799eeb5966435709a67ed42a5 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Wed, 16 Oct 2024 11:53:52 +0200 Subject: [PATCH 15/16] `compiler` command is sync, remove conditions on CI for Vyper / Python installs --- .github/workflows/nextest.yml | 2 -- crates/forge/bin/cmd/compiler.rs | 6 +++--- crates/forge/bin/main.rs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index e71e94c9a250..da862c657abf 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -67,12 +67,10 @@ jobs: with: bun-version: latest - name: Setup Python - if: contains(matrix.name, 'external') || contains(matrix.name, 'integration') uses: actions/setup-python@v4 with: python-version: 3.11 - name: Install Vyper - if: contains(matrix.name, 'external') || contains(matrix.name, 'integration') run: pip install vyper~=0.4.0 - name: Forge RPC cache diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 369041dd6eb0..badc053c6c4d 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -13,9 +13,9 @@ pub struct CompilerArgs { } impl CompilerArgs { - pub async fn run(self) -> Result<()> { + pub fn run(self) -> Result<()> { match self.sub { - CompilerSubcommands::Resolve(args) => args.run().await, + CompilerSubcommands::Resolve(args) => args.run(), } } } @@ -53,7 +53,7 @@ pub struct ResolveArgs { } impl ResolveArgs { - pub async fn run(self) -> Result<()> { + pub fn run(self) -> Result<()> { let Self { root, skip, verbosity, json } = self; let root = root.unwrap_or_else(|| PathBuf::from(".")); diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index 59bf274d9e01..925788ef8fda 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -118,7 +118,7 @@ fn main() -> Result<()> { ForgeSubcommand::Generate(cmd) => match cmd.sub { GenerateSubcommands::Test(cmd) => cmd.run(), }, - ForgeSubcommand::Compiler(cmd) => utils::block_on(cmd.run()), + ForgeSubcommand::Compiler(cmd) => cmd.run(), ForgeSubcommand::Soldeer(cmd) => utils::block_on(cmd.run()), ForgeSubcommand::Eip712(cmd) => cmd.run(), ForgeSubcommand::BindJson(cmd) => cmd.run(), From 65a1b2d8d2c4cebbdeeb2623a0ae42a575fd8183 Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Wed, 16 Oct 2024 12:00:12 +0200 Subject: [PATCH 16/16] is_jsonlines -> is_json --- crates/forge/tests/cli/compiler.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/forge/tests/cli/compiler.rs b/crates/forge/tests/cli/compiler.rs index e2ee5963f1ba..665356632320 100644 --- a/crates/forge/tests/cli/compiler.rs +++ b/crates/forge/tests/cli/compiler.rs @@ -109,7 +109,7 @@ forgetest!(can_list_resolved_compiler_versions_json, |prj, cmd| { cmd.args(["compiler", "resolve", "--json"]).assert_success().stdout_eq( str![[r#" {"Solidity":[["0.8.27",["src/ContractC.sol","src/ContractD.sol"]]]}"#]] - .is_jsonlines(), + .is_json(), ); }); @@ -167,7 +167,7 @@ forgetest!(can_list_resolved_multiple_compiler_versions_skipped_json, |prj, cmd| .assert_success() .stdout_eq(str![[r#" {"Solidity":[["0.8.27",["src/ContractD.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} -"#]].is_jsonlines()); +"#]].is_json()); }); forgetest!(can_list_resolved_multiple_compiler_versions_verbose, |prj, cmd| { @@ -213,6 +213,6 @@ forgetest!(can_list_resolved_multiple_compiler_versions_json, |prj, cmd| { str![[r#" {"Solidity":[["0.8.4",["src/ContractA.sol"]],["0.8.11",["src/ContractB.sol"]],["0.8.27",["src/ContractC.sol","src/ContractD.sol"]]],"Vyper":[["0.4.0",["src/Counter.vy","src/ICounter.vyi"]]]} "#]] - .is_jsonlines(), + .is_json(), ); });