From 9a84423b6c66f4bb0e2cc94c5ef1d01d5410705b Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 1 Oct 2024 16:44:39 +0400 Subject: [PATCH 1/4] feat: better extra_args handling --- crates/compilers/src/compilers/mod.rs | 20 +++++++----- .../compilers/src/compilers/solc/compiler.rs | 31 +++++++++++++++---- crates/compilers/src/compilers/solc/mod.rs | 2 +- crates/compilers/src/compilers/vyper/mod.rs | 2 +- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/crates/compilers/src/compilers/mod.rs b/crates/compilers/src/compilers/mod.rs index 8c0ec244..f2a60a01 100644 --- a/crates/compilers/src/compilers/mod.rs +++ b/crates/compilers/src/compilers/mod.rs @@ -278,19 +278,23 @@ pub trait Compiler: Send + Sync + Clone { pub(crate) fn cache_version( path: PathBuf, + args: &Vec, f: impl FnOnce(&Path) -> Result, ) -> Result { - static VERSION_CACHE: OnceLock>> = OnceLock::new(); + static VERSION_CACHE: OnceLock, Version>>>> = + OnceLock::new(); let mut lock = VERSION_CACHE .get_or_init(|| Mutex::new(HashMap::new())) .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - Ok(match lock.entry(path) { - std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(), - std::collections::hash_map::Entry::Vacant(entry) => { - let value = f(entry.key())?; - entry.insert(value) - } + + if let Some(version) = lock.get(&path).and_then(|versions| versions.get(args)) { + return Ok(version.clone()); } - .clone()) + + let version = f(&path)?; + + lock.entry(path).or_default().insert(args.clone(), version.clone()); + + Ok(version) } diff --git a/crates/compilers/src/compilers/solc/compiler.rs b/crates/compilers/src/compilers/solc/compiler.rs index b95b8e4f..1a21e371 100644 --- a/crates/compilers/src/compilers/solc/compiler.rs +++ b/crates/compilers/src/compilers/solc/compiler.rs @@ -90,10 +90,28 @@ impl Solc { /// Returns error if `solc` is not found in the system or if the version cannot be retrieved. pub fn new(path: impl Into) -> Result { let path = path.into(); - let version = Self::version(path.clone())?; + let version = Self::version(path.clone(), &Vec::new())?; Ok(Self::new_with_version(path, version)) } + /// A new instance which points to `solc` with additional cli arguments. Invokes `solc + /// --version` to determine the version. + /// + /// Returns error if `solc` is not found in the system or if the version cannot be retrieved. + pub fn new_with_args( + path: impl Into, + extra_args: impl IntoIterator>, + ) -> Result { + let args = extra_args.into_iter().map(Into::into).collect(); + let path = path.into(); + let version = Self::version(path.clone(), &args)?; + + let mut solc = Self::new_with_version(path, version); + solc.extra_args = args; + + Ok(solc) + } + /// A new instance which points to `solc` with the given version pub fn new_with_version(path: impl Into, version: Version) -> Self { Self { @@ -428,10 +446,11 @@ impl Solc { /// Invokes `solc --version` and parses the output as a SemVer [`Version`]. #[instrument(level = "debug", skip_all)] - pub fn version(solc: impl Into) -> Result { - crate::cache_version(solc.into(), |solc| { + pub fn version(solc: impl Into, args: &Vec) -> Result { + crate::cache_version(solc.into(), args, |solc| { let mut cmd = Command::new(solc); - cmd.arg("--version") + cmd.args(args) + .arg("--version") .stdin(Stdio::piped()) .stderr(Stdio::piped()) .stdout(Stdio::piped()); @@ -454,6 +473,7 @@ impl Solc { pub fn configure_cmd(&self) -> Command { let mut cmd = Command::new(&self.solc); cmd.stdin(Stdio::piped()).stderr(Stdio::piped()).stdout(Stdio::piped()); + cmd.args(&self.extra_args); if !self.allow_paths.is_empty() { cmd.arg("--allow-paths"); @@ -478,7 +498,6 @@ impl Solc { cmd.current_dir(base_path); } - cmd.args(&self.extra_args); cmd.arg("--standard-json"); cmd @@ -624,7 +643,7 @@ mod tests { #[test] fn solc_version_works() { - Solc::version(solc().solc).unwrap(); + Solc::version(solc().solc, &Vec::new()).unwrap(); } #[test] diff --git a/crates/compilers/src/compilers/solc/mod.rs b/crates/compilers/src/compilers/solc/mod.rs index 2e33a52c..0bdb6f42 100644 --- a/crates/compilers/src/compilers/solc/mod.rs +++ b/crates/compilers/src/compilers/solc/mod.rs @@ -55,7 +55,7 @@ impl Compiler for SolcCompiler { solc.base_path.clone_from(&input.cli_settings.base_path); solc.allow_paths.clone_from(&input.cli_settings.allow_paths); solc.include_paths.clone_from(&input.cli_settings.include_paths); - solc.extra_args.clone_from(&input.cli_settings.extra_args); + solc.extra_args.extend_from_slice(&input.cli_settings.extra_args); let solc_output = solc.compile(&input.input)?; diff --git a/crates/compilers/src/compilers/vyper/mod.rs b/crates/compilers/src/compilers/vyper/mod.rs index 9912173f..9b2984c7 100644 --- a/crates/compilers/src/compilers/vyper/mod.rs +++ b/crates/compilers/src/compilers/vyper/mod.rs @@ -166,7 +166,7 @@ impl Vyper { /// Invokes `vyper --version` and parses the output as a SemVer [`Version`]. #[instrument(level = "debug", skip_all)] pub fn version(vyper: impl Into) -> Result { - crate::cache_version(vyper.into(), |vyper| { + crate::cache_version(vyper.into(), &Vec::new(), |vyper| { let mut cmd = Command::new(vyper); cmd.arg("--version") .stdin(Stdio::piped()) From 8a2d332c60b05fed1c4b28e773917393d3528867 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 1 Oct 2024 17:05:33 +0400 Subject: [PATCH 2/4] clippy allow --- crates/compilers/src/compilers/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/compilers/src/compilers/mod.rs b/crates/compilers/src/compilers/mod.rs index f2a60a01..3159a297 100644 --- a/crates/compilers/src/compilers/mod.rs +++ b/crates/compilers/src/compilers/mod.rs @@ -281,6 +281,7 @@ pub(crate) fn cache_version( args: &Vec, f: impl FnOnce(&Path) -> Result, ) -> Result { + #[allow(clippy::complexity)] static VERSION_CACHE: OnceLock, Version>>>> = OnceLock::new(); let mut lock = VERSION_CACHE From 4e0a4697a52aaba0d7e3d6f4249b1e3c2e9f5122 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 1 Oct 2024 18:14:30 +0400 Subject: [PATCH 3/4] keep Solc::version --- crates/compilers/src/compilers/mod.rs | 4 ++-- crates/compilers/src/compilers/solc/compiler.rs | 16 +++++++++++----- crates/compilers/src/compilers/vyper/mod.rs | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/compilers/src/compilers/mod.rs b/crates/compilers/src/compilers/mod.rs index 3159a297..506ea7ca 100644 --- a/crates/compilers/src/compilers/mod.rs +++ b/crates/compilers/src/compilers/mod.rs @@ -278,7 +278,7 @@ pub trait Compiler: Send + Sync + Clone { pub(crate) fn cache_version( path: PathBuf, - args: &Vec, + args: &[String], f: impl FnOnce(&Path) -> Result, ) -> Result { #[allow(clippy::complexity)] @@ -295,7 +295,7 @@ pub(crate) fn cache_version( let version = f(&path)?; - lock.entry(path).or_default().insert(args.clone(), version.clone()); + lock.entry(path).or_default().insert(args.to_vec(), version.clone()); Ok(version) } diff --git a/crates/compilers/src/compilers/solc/compiler.rs b/crates/compilers/src/compilers/solc/compiler.rs index 1a21e371..e4c7d660 100644 --- a/crates/compilers/src/compilers/solc/compiler.rs +++ b/crates/compilers/src/compilers/solc/compiler.rs @@ -90,7 +90,7 @@ impl Solc { /// Returns error if `solc` is not found in the system or if the version cannot be retrieved. pub fn new(path: impl Into) -> Result { let path = path.into(); - let version = Self::version(path.clone(), &Vec::new())?; + let version = Self::version(path.clone())?; Ok(Self::new_with_version(path, version)) } @@ -102,9 +102,9 @@ impl Solc { path: impl Into, extra_args: impl IntoIterator>, ) -> Result { - let args = extra_args.into_iter().map(Into::into).collect(); + let args = extra_args.into_iter().map(Into::into).collect::>(); let path = path.into(); - let version = Self::version(path.clone(), &args)?; + let version = Self::version_with_args(path.clone(), &args)?; let mut solc = Self::new_with_version(path, version); solc.extra_args = args; @@ -446,7 +446,13 @@ impl Solc { /// Invokes `solc --version` and parses the output as a SemVer [`Version`]. #[instrument(level = "debug", skip_all)] - pub fn version(solc: impl Into, args: &Vec) -> Result { + pub fn version(solc: impl Into) -> Result { + Self::version_with_args(solc, &Vec::new()) + } + + /// Invokes `solc --version` and parses the output as a SemVer [`Version`]. + #[instrument(level = "debug", skip_all)] + pub fn version_with_args(solc: impl Into, args: &[String]) -> Result { crate::cache_version(solc.into(), args, |solc| { let mut cmd = Command::new(solc); cmd.args(args) @@ -643,7 +649,7 @@ mod tests { #[test] fn solc_version_works() { - Solc::version(solc().solc, &Vec::new()).unwrap(); + Solc::version(solc().solc).unwrap(); } #[test] diff --git a/crates/compilers/src/compilers/vyper/mod.rs b/crates/compilers/src/compilers/vyper/mod.rs index 9b2984c7..fa64c3ed 100644 --- a/crates/compilers/src/compilers/vyper/mod.rs +++ b/crates/compilers/src/compilers/vyper/mod.rs @@ -166,7 +166,7 @@ impl Vyper { /// Invokes `vyper --version` and parses the output as a SemVer [`Version`]. #[instrument(level = "debug", skip_all)] pub fn version(vyper: impl Into) -> Result { - crate::cache_version(vyper.into(), &Vec::new(), |vyper| { + crate::cache_version(vyper.into(), &[], |vyper| { let mut cmd = Command::new(vyper); cmd.arg("--version") .stdin(Stdio::piped()) From b549f65f9336f539958b8b825b2e0a600b7d3186 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 1 Oct 2024 18:16:36 +0400 Subject: [PATCH 4/4] rm Vec::new() --- crates/compilers/src/compilers/solc/compiler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/compilers/src/compilers/solc/compiler.rs b/crates/compilers/src/compilers/solc/compiler.rs index e4c7d660..aefcc629 100644 --- a/crates/compilers/src/compilers/solc/compiler.rs +++ b/crates/compilers/src/compilers/solc/compiler.rs @@ -447,7 +447,7 @@ impl Solc { /// Invokes `solc --version` and parses the output as a SemVer [`Version`]. #[instrument(level = "debug", skip_all)] pub fn version(solc: impl Into) -> Result { - Self::version_with_args(solc, &Vec::new()) + Self::version_with_args(solc, &[]) } /// Invokes `solc --version` and parses the output as a SemVer [`Version`].