From 6b0a1f7911a4d676a1454114b17b3944067e56cd Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sun, 13 Mar 2022 23:36:26 +0100 Subject: [PATCH] fix(solc): skip artifacts check for files without artifacts (#1018) --- ethers-solc/src/cache.rs | 37 +++++++++++++++------------ ethers-solc/tests/project.rs | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/ethers-solc/src/cache.rs b/ethers-solc/src/cache.rs index 9c0edb8e..3a365e2f 100644 --- a/ethers-solc/src/cache.rs +++ b/ethers-solc/src/cache.rs @@ -638,23 +638,28 @@ impl<'a, T: ArtifactOutput> ArtifactsCacheInner<'a, T> { return true } - if !entry.contains_version(version) { - tracing::trace!( - "missing linked artifacts for source file `{}` for version \"{}\"", - file.display(), - version - ); - return true - } - - if entry.artifacts_for_version(version).any(|artifact_path| { - let missing_artifact = !self.cached_artifacts.has_artifact(artifact_path); - if missing_artifact { - tracing::trace!("missing artifact \"{}\"", artifact_path.display()); + // only check artifact's existence if the file generated artifacts. + // e.g. a solidity file consisting only of import statements (like interfaces that + // re-export) do not create artifacts + if !entry.artifacts.is_empty() { + if !entry.contains_version(version) { + tracing::trace!( + "missing linked artifacts for source file `{}` for version \"{}\"", + file.display(), + version + ); + return true + } + + if entry.artifacts_for_version(version).any(|artifact_path| { + let missing_artifact = !self.cached_artifacts.has_artifact(artifact_path); + if missing_artifact { + tracing::trace!("missing artifact \"{}\"", artifact_path.display()); + } + missing_artifact + }) { + return true } - missing_artifact - }) { - return true } // all things match, can be reused return false diff --git a/ethers-solc/tests/project.rs b/ethers-solc/tests/project.rs index c1e7ee28..e2fd432f 100644 --- a/ethers-solc/tests/project.rs +++ b/ethers-solc/tests/project.rs @@ -683,3 +683,51 @@ fn can_recompile_with_changes() { assert!(compiled.find("A").is_some()); assert!(compiled.find("B").is_some()); } + +#[test] +fn can_recompile_unchanged_with_empty_files() { + let tmp = TempProject::dapptools().unwrap(); + + tmp.add_source( + "A", + r#" + pragma solidity ^0.8.10; + import "./B.sol"; + contract A {} + "#, + ) + .unwrap(); + + tmp.add_source( + "B", + r#" + pragma solidity ^0.8.10; + import "./C.sol"; + "#, + ) + .unwrap(); + + let c = r#" + pragma solidity ^0.8.10; + contract C {} + "#; + tmp.add_source("C", c).unwrap(); + + let compiled = tmp.compile().unwrap(); + assert!(!compiled.has_compiler_errors()); + assert!(compiled.find("A").is_some()); + assert!(compiled.find("C").is_some()); + + let compiled = tmp.compile().unwrap(); + assert!(compiled.find("A").is_some()); + assert!(compiled.find("C").is_some()); + assert!(compiled.is_unchanged()); + + // modify C.sol + tmp.add_source("C", format!("{}\n", c)).unwrap(); + let compiled = tmp.compile().unwrap(); + assert!(!compiled.has_compiler_errors()); + assert!(!compiled.is_unchanged()); + assert!(compiled.find("A").is_some()); + assert!(compiled.find("C").is_some()); +}