From 3c1de6424044b0d73251b69b6858cf7082fef9ed Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 4 Jul 2022 20:53:49 +0200 Subject: [PATCH] refactor(solc): unify find/remove api (#1449) * refactor(solc): unify find/remove api * fix: update docs --- ethers-solc/src/artifact_output/mod.rs | 49 +++++- ethers-solc/src/artifacts/contract.rs | 2 +- ethers-solc/src/compile/output/contracts.rs | 39 ++++- ethers-solc/src/compile/output/mod.rs | 180 +++++++++++++++++--- ethers-solc/tests/project.rs | 168 +++++++++--------- examples/contract_human_readable.rs | 2 +- 6 files changed, 324 insertions(+), 116 deletions(-) diff --git a/ethers-solc/src/artifact_output/mod.rs b/ethers-solc/src/artifact_output/mod.rs index 616e6cdb..05e56922 100644 --- a/ethers-solc/src/artifact_output/mod.rs +++ b/ethers-solc/src/artifact_output/mod.rs @@ -19,8 +19,10 @@ use std::{ borrow::Cow, collections::{btree_map::BTreeMap, HashSet}, fmt, fs, io, + ops::Deref, path::{Path, PathBuf}, }; + mod configurable; pub use configurable::*; @@ -64,7 +66,7 @@ impl ArtifactId { } /// Represents an artifact file representing a [`crate::Contract`] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ArtifactFile { /// The Artifact that was written pub artifact: T, @@ -102,7 +104,7 @@ impl ArtifactFile { pub(crate) type ArtifactsMap = FileToContractsMap>>; /// Represents a set of Artifacts -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Artifacts(pub ArtifactsMap); impl From> for Artifacts { @@ -149,6 +151,14 @@ impl AsMut> for Artifacts { } } +impl Deref for Artifacts { + type Target = ArtifactsMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl Artifacts { /// Writes all artifacts into the given `artifacts_root` folder pub fn write_all(&self) -> Result<()> { @@ -264,18 +274,49 @@ impl Artifacts { } /// Finds the first artifact `T` with a matching contract name - pub fn find(&self, contract_name: impl AsRef) -> Option<&T> { + pub fn find_first(&self, contract_name: impl AsRef) -> Option<&T> { let contract_name = contract_name.as_ref(); self.0.iter().find_map(|(_file, contracts)| { contracts.get(contract_name).and_then(|c| c.get(0).map(|a| &a.artifact)) }) } + /// Finds the artifact with matching path and name + pub fn find(&self, path: impl AsRef, contract: impl AsRef) -> Option<&T> { + let contract_path = path.as_ref(); + let contract_name = contract.as_ref(); + self.0.iter().filter(|(path, _)| path.as_str() == contract_path).find_map( + |(_file, contracts)| { + contracts.get(contract_name).and_then(|c| c.get(0).map(|a| &a.artifact)) + }, + ) + } + + /// Removes the artifact with matching file and name + pub fn remove(&mut self, path: impl AsRef, contract: impl AsRef) -> Option { + let contract_path = path.as_ref(); + let contract_name = contract.as_ref(); + self.0.iter_mut().filter(|(path, _)| path.as_str() == contract_path).find_map( + |(_file, contracts)| { + let mut artifact = None; + if let Some((c, mut artifacts)) = contracts.remove_entry(contract_name) { + if !artifacts.is_empty() { + artifact = Some(artifacts.remove(0).artifact); + } + if !artifacts.is_empty() { + contracts.insert(c, artifacts); + } + } + artifact + }, + ) + } + /// Removes the first artifact `T` with a matching contract name /// /// *Note:* if there are multiple artifacts (contract compiled with different solc) then this /// returns the first artifact in that set - pub fn remove(&mut self, contract_name: impl AsRef) -> Option { + pub fn remove_first(&mut self, contract_name: impl AsRef) -> Option { let contract_name = contract_name.as_ref(); self.0.iter_mut().find_map(|(_file, contracts)| { let mut artifact = None; diff --git a/ethers-solc/src/artifacts/contract.rs b/ethers-solc/src/artifacts/contract.rs index bd4e6a5d..d0a51fe2 100644 --- a/ethers-solc/src/artifacts/contract.rs +++ b/ethers-solc/src/artifacts/contract.rs @@ -498,7 +498,7 @@ impl<'a> CompactContractRef<'a> { /// use ethers_solc::artifacts::*; /// # fn demo(project: Project) { /// let output = project.compile().unwrap().output(); - /// let contract = output.find("Greeter").unwrap(); + /// let contract = output.find_first("Greeter").unwrap(); /// let contract = contract.unwrap(); /// # } /// ``` diff --git a/ethers-solc/src/compile/output/contracts.rs b/ethers-solc/src/compile/output/contracts.rs index f8de71b2..e81cd3a2 100644 --- a/ethers-solc/src/compile/output/contracts.rs +++ b/ethers-solc/src/compile/output/contracts.rs @@ -4,7 +4,7 @@ use crate::artifacts::{ }; use semver::Version; use serde::{Deserialize, Serialize}; -use std::{collections::BTreeMap, path::Path}; +use std::{collections::BTreeMap, ops::Deref, path::Path}; /// file -> [(contract name -> Contract + solc version)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] @@ -34,16 +34,41 @@ impl VersionedContracts { /// use ethers_solc::artifacts::*; /// # fn demo(project: Project) { /// let output = project.compile().unwrap().output(); - /// let contract = output.find("Greeter").unwrap(); + /// let contract = output.find_first("Greeter").unwrap(); /// # } /// ``` - pub fn find(&self, contract: impl AsRef) -> Option { + pub fn find_first(&self, contract: impl AsRef) -> Option { let contract_name = contract.as_ref(); self.contracts().find_map(|(name, contract)| { (name == contract_name).then(|| CompactContractRef::from(contract)) }) } + /// Finds the contract with matching path and name + /// + /// # Example + /// + /// ``` + /// use ethers_solc::Project; + /// use ethers_solc::artifacts::*; + /// # fn demo(project: Project) { + /// let output = project.compile().unwrap().output(); + /// let contract = output.contracts.find("src/Greeter.sol", "Greeter").unwrap(); + /// # } + /// ``` + pub fn find( + &self, + path: impl AsRef, + contract: impl AsRef, + ) -> Option { + let contract_path = path.as_ref(); + let contract_name = contract.as_ref(); + self.contracts_with_files().find_map(|(path, name, contract)| { + (path == contract_path && name == contract_name) + .then(|| CompactContractRef::from(contract)) + }) + } + /// Removes the _first_ contract with the given name from the set /// /// # Example @@ -231,6 +256,14 @@ impl AsMut>> for VersionedContracts { } } +impl Deref for VersionedContracts { + type Target = FileToContractsMap>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl IntoIterator for VersionedContracts { type Item = (String, BTreeMap>); type IntoIter = diff --git a/ethers-solc/src/compile/output/mod.rs b/ethers-solc/src/compile/output/mod.rs index bcb5e1e8..298a0680 100644 --- a/ethers-solc/src/compile/output/mod.rs +++ b/ethers-solc/src/compile/output/mod.rs @@ -53,6 +53,28 @@ impl ProjectCompileOutput { cached_artifacts.into_artifacts::().chain(compiled_artifacts.into_artifacts::()) } + /// This returns a chained iterator of both cached and recompiled contract artifacts that yields + /// the contract name and the corresponding artifact + /// + /// # Example + /// + /// ```no_run + /// use std::collections::btree_map::BTreeMap; + /// use ethers_solc::ConfigurableContractArtifact; + /// use ethers_solc::Project; + /// + /// let project = Project::builder().build().unwrap(); + /// let artifacts: BTreeMap = project.compile().unwrap().artifacts().collect(); + /// ``` + pub fn artifacts(&self) -> impl Iterator { + self.cached_artifacts + .artifact_files() + .chain(self.compiled_artifacts.artifact_files()) + .filter_map(|artifact| { + T::contract_name(&artifact.file).map(|name| (name, &artifact.artifact)) + }) + } + /// All artifacts together with their contract file and name as tuple `(file, contract /// name, artifact)` /// @@ -151,15 +173,6 @@ impl ProjectCompileOutput { self.compiler_output.has_warning(&self.ignored_error_codes) } - /// Finds the first contract with the given name and removes it from the set - pub fn remove(&mut self, contract_name: impl AsRef) -> Option { - let contract_name = contract_name.as_ref(); - if let artifact @ Some(_) = self.compiled_artifacts.remove(contract_name) { - return artifact - } - self.cached_artifacts.remove(contract_name) - } - /// Returns the set of `Artifacts` that were cached and got reused during /// [`crate::Project::compile()`] pub fn cached_artifacts(&self) -> &Artifacts { @@ -188,19 +201,140 @@ impl ProjectCompileOutput { } contracts } -} -impl ProjectCompileOutput -where - T::Artifact: Clone, -{ - /// Finds the first contract with the given name - pub fn find(&self, contract_name: impl AsRef) -> Option<&T::Artifact> { - let contract_name = contract_name.as_ref(); - if let artifact @ Some(_) = self.compiled_artifacts.find(contract_name) { + /// Removes the contract with matching path and name using the `:` pattern + /// where `path` is optional. + /// + /// If the `path` segment is `None`, then the first matching `Contract` is returned, see + /// [Self::remove_first] + /// + /// # Example + /// + /// + /// ``` + /// use ethers_solc::Project; + /// use ethers_solc::artifacts::*; + /// use ethers_solc::info::ContractInfo; + /// + /// # fn demo(project: Project) { + /// let output = project.compile().unwrap(); + /// let info = ContractInfo::new("src/Greeter.sol:Greeter"); + /// let contract = output.find_contract(&info).unwrap(); + /// # } + /// ``` + pub fn find_contract<'a>(&self, info: impl Into>) -> Option<&T::Artifact> { + let ContractInfoRef { path, name } = info.into(); + if let Some(path) = path { + self.find(path, name) + } else { + self.find_first(name) + } + } + + /// Finds the artifact with matching path and name + /// + /// # Example + /// + /// ``` + /// use ethers_solc::Project; + /// use ethers_solc::artifacts::*; + /// # fn demo(project: Project) { + /// let output = project.compile().unwrap(); + /// let contract = output.find("src/Greeter.sol", "Greeter").unwrap(); + /// # } + /// ``` + pub fn find(&self, path: impl AsRef, contract: impl AsRef) -> Option<&T::Artifact> { + let contract_path = path.as_ref(); + let contract_name = contract.as_ref(); + if let artifact @ Some(_) = self.compiled_artifacts.find(contract_path, contract_name) { return artifact } - self.cached_artifacts.find(contract_name) + self.cached_artifacts.find(contract_path, contract_name) + } + + /// Finds the first contract with the given name + pub fn find_first(&self, contract_name: impl AsRef) -> Option<&T::Artifact> { + let contract_name = contract_name.as_ref(); + if let artifact @ Some(_) = self.compiled_artifacts.find_first(contract_name) { + return artifact + } + self.cached_artifacts.find_first(contract_name) + } + + /// Finds the artifact with matching path and name + /// + /// # Example + /// + /// ``` + /// use ethers_solc::Project; + /// use ethers_solc::artifacts::*; + /// # fn demo(project: Project) { + /// let output = project.compile().unwrap(); + /// let contract = output.find("src/Greeter.sol", "Greeter").unwrap(); + /// # } + /// ``` + pub fn remove( + &mut self, + path: impl AsRef, + contract: impl AsRef, + ) -> Option { + let contract_path = path.as_ref(); + let contract_name = contract.as_ref(); + if let artifact @ Some(_) = self.compiled_artifacts.remove(contract_path, contract_name) { + return artifact + } + self.cached_artifacts.remove(contract_path, contract_name) + } + + /// Removes the _first_ contract with the given name from the set + /// + /// # Example + /// + /// ``` + /// use ethers_solc::Project; + /// use ethers_solc::artifacts::*; + /// # fn demo(project: Project) { + /// let mut output = project.compile().unwrap(); + /// let contract = output.remove_first("Greeter").unwrap(); + /// # } + /// ``` + pub fn remove_first(&mut self, contract_name: impl AsRef) -> Option { + let contract_name = contract_name.as_ref(); + if let artifact @ Some(_) = self.compiled_artifacts.remove_first(contract_name) { + return artifact + } + self.cached_artifacts.remove_first(contract_name) + } + + /// Removes the contract with matching path and name using the `:` pattern + /// where `path` is optional. + /// + /// If the `path` segment is `None`, then the first matching `Contract` is returned, see + /// [Self::remove_first] + /// + /// + /// # Example + /// + /// ``` + /// use ethers_solc::Project; + /// use ethers_solc::artifacts::*; + /// use ethers_solc::info::ContractInfo; + /// # fn demo(project: Project) { + /// let mut output = project.compile().unwrap(); + /// let info = ContractInfo::new("src/Greeter.sol:Greeter"); + /// let contract = output.remove_contract(&info).unwrap(); + /// # } + /// ``` + pub fn remove_contract<'a>( + &mut self, + info: impl Into>, + ) -> Option { + let ContractInfoRef { path, name } = info.into(); + if let Some(path) = path { + self.remove(path, name) + } else { + self.remove_first(name) + } } } @@ -340,11 +474,11 @@ impl AggregatedCompilerOutput { /// use ethers_solc::artifacts::*; /// # fn demo(project: Project) { /// let output = project.compile().unwrap().output(); - /// let contract = output.find("Greeter").unwrap(); + /// let contract = output.find_first("Greeter").unwrap(); /// # } /// ``` - pub fn find(&self, contract: impl AsRef) -> Option { - self.contracts.find(contract) + pub fn find_first(&self, contract: impl AsRef) -> Option { + self.contracts.find_first(contract) } /// Removes the _first_ contract with the given name from the set @@ -548,7 +682,7 @@ impl<'a> OutputDiagnostics<'a> { return true } - self.compiler_output.find(&contract_path).map_or(false, |contract| { + self.compiler_output.find_first(&contract_path).map_or(false, |contract| { contract.abi.map_or(false, |abi| abi.functions.contains_key("IS_TEST")) }) } diff --git a/ethers-solc/tests/project.rs b/ethers-solc/tests/project.rs index f126f5c3..1093036b 100644 --- a/ethers-solc/tests/project.rs +++ b/ethers-solc/tests/project.rs @@ -55,21 +55,21 @@ fn can_compile_hardhat_sample() { let project = TempProject::::new(paths).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Greeter").is_some()); - assert!(compiled.find("console").is_some()); + assert!(compiled.find_first("Greeter").is_some()); + assert!(compiled.find_first("console").is_some()); assert!(!compiled.has_compiler_errors()); // nothing to compile let compiled = project.compile().unwrap(); - assert!(compiled.find("Greeter").is_some()); - assert!(compiled.find("console").is_some()); + assert!(compiled.find_first("Greeter").is_some()); + assert!(compiled.find_first("console").is_some()); assert!(compiled.is_unchanged()); // delete artifacts std::fs::remove_dir_all(&project.paths().artifacts).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Greeter").is_some()); - assert!(compiled.find("console").is_some()); + assert!(compiled.find_first("Greeter").is_some()); + assert!(compiled.find_first("console").is_some()); assert!(!compiled.is_unchanged()); } @@ -80,12 +80,12 @@ fn can_compile_dapp_sample() { let project = TempProject::::new(paths).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); + assert!(compiled.find_first("Dapp").is_some()); assert!(!compiled.has_compiler_errors()); // nothing to compile let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); + assert!(compiled.find_first("Dapp").is_some()); assert!(compiled.is_unchanged()); let cache = SolFilesCache::read(project.cache_path()).unwrap(); @@ -93,7 +93,7 @@ fn can_compile_dapp_sample() { // delete artifacts std::fs::remove_dir_all(&project.paths().artifacts).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); + assert!(compiled.find_first("Dapp").is_some()); assert!(!compiled.is_unchanged()); let updated_cache = SolFilesCache::read(project.cache_path()).unwrap(); @@ -107,14 +107,14 @@ fn can_compile_yul_sample() { let project = TempProject::::new(paths).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); - assert!(compiled.find("SimpleStore").is_some()); + assert!(compiled.find_first("Dapp").is_some()); + assert!(compiled.find_first("SimpleStore").is_some()); assert!(!compiled.has_compiler_errors()); // nothing to compile let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); - assert!(compiled.find("SimpleStore").is_some()); + assert!(compiled.find_first("Dapp").is_some()); + assert!(compiled.find_first("SimpleStore").is_some()); assert!(compiled.is_unchanged()); let cache = SolFilesCache::read(project.cache_path()).unwrap(); @@ -122,8 +122,8 @@ fn can_compile_yul_sample() { // delete artifacts std::fs::remove_dir_all(&project.paths().artifacts).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); - assert!(compiled.find("SimpleStore").is_some()); + assert!(compiled.find_first("Dapp").is_some()); + assert!(compiled.find_first("SimpleStore").is_some()); assert!(!compiled.is_unchanged()); let updated_cache = SolFilesCache::read(project.cache_path()).unwrap(); @@ -149,7 +149,7 @@ fn can_compile_configured() { let settings = handler.settings(); let project = TempProject::with_artifacts(paths, handler).unwrap().with_settings(settings); let compiled = project.compile().unwrap(); - let artifact = compiled.find("Dapp").unwrap(); + let artifact = compiled.find_first("Dapp").unwrap(); assert!(artifact.metadata.is_some()); assert!(artifact.raw_metadata.is_some()); assert!(artifact.ir.is_some()); @@ -195,13 +195,13 @@ fn can_compile_dapp_detect_changes_in_libs() { assert_eq!(graph.files().clone(), HashMap::from([(src, 0), (lib, 1),])); let compiled = project.compile().unwrap(); - assert!(compiled.find("Foo").is_some()); - assert!(compiled.find("Bar").is_some()); + assert!(compiled.find_first("Foo").is_some()); + assert!(compiled.find_first("Bar").is_some()); assert!(!compiled.has_compiler_errors()); // nothing to compile let compiled = project.compile().unwrap(); - assert!(compiled.find("Foo").is_some()); + assert!(compiled.find_first("Foo").is_some()); assert!(compiled.is_unchanged()); let cache = SolFilesCache::read(&project.paths().cache).unwrap(); @@ -224,8 +224,8 @@ fn can_compile_dapp_detect_changes_in_libs() { assert_eq!(graph.files().len(), 2); let compiled = project.compile().unwrap(); - assert!(compiled.find("Foo").is_some()); - assert!(compiled.find("Bar").is_some()); + assert!(compiled.find_first("Foo").is_some()); + assert!(compiled.find_first("Bar").is_some()); // ensure change is detected assert!(!compiled.is_unchanged()); } @@ -269,14 +269,14 @@ fn can_compile_dapp_detect_changes_in_sources() { let compiled = project.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("DssSpellTest").is_some()); - assert!(compiled.find("DssSpellTestBase").is_some()); + assert!(compiled.find_first("DssSpellTest").is_some()); + assert!(compiled.find_first("DssSpellTestBase").is_some()); // nothing to compile let compiled = project.compile().unwrap(); assert!(compiled.is_unchanged()); - assert!(compiled.find("DssSpellTest").is_some()); - assert!(compiled.find("DssSpellTestBase").is_some()); + assert!(compiled.find_first("DssSpellTest").is_some()); + assert!(compiled.find_first("DssSpellTestBase").is_some()); let cache = SolFilesCache::read(&project.paths().cache).unwrap(); assert_eq!(cache.files.len(), 2); @@ -303,8 +303,8 @@ fn can_compile_dapp_detect_changes_in_sources() { assert_eq!(graph.files().len(), 2); let compiled = project.compile().unwrap(); - assert!(compiled.find("DssSpellTest").is_some()); - assert!(compiled.find("DssSpellTestBase").is_some()); + assert!(compiled.find_first("DssSpellTest").is_some()); + assert!(compiled.find_first("DssSpellTestBase").is_some()); // ensure change is detected assert!(!compiled.is_unchanged()); @@ -377,26 +377,26 @@ fn can_compile_dapp_sample_with_cache() { // first compile let project = Project::builder().paths(paths).build().unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); + assert!(compiled.find_first("Dapp").is_some()); assert!(!compiled.has_compiler_errors()); // cache is used when nothing to compile let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); + assert!(compiled.find_first("Dapp").is_some()); assert!(compiled.is_unchanged()); // deleted artifacts cause recompile even with cache std::fs::remove_dir_all(&project.artifacts_path()).unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); + assert!(compiled.find_first("Dapp").is_some()); assert!(!compiled.is_unchanged()); // new file is compiled even with partial cache std::fs::copy(cache_testdata_dir.join("NewContract.sol"), root.join("src/NewContract.sol")) .unwrap(); let compiled = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_some()); - assert!(compiled.find("NewContract").is_some()); + assert!(compiled.find_first("Dapp").is_some()); + assert!(compiled.find_first("NewContract").is_some()); assert!(!compiled.is_unchanged()); assert_eq!( compiled.into_artifacts().map(|(artifact_id, _)| artifact_id.name).collect::>(), @@ -424,7 +424,7 @@ fn can_compile_dapp_sample_with_cache() { // deleted artifact is not taken from the cache std::fs::remove_file(&project.paths.sources.join("Dapp.sol")).unwrap(); let compiled: ProjectCompileOutput<_> = project.compile().unwrap(); - assert!(compiled.find("Dapp").is_none()); + assert!(compiled.find_first("Dapp").is_none()); } fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { @@ -1022,7 +1022,7 @@ fn can_compile_single_files() { let compiled = tmp.project().compile_file(f.clone()).unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("Foo").is_some()); + assert!(compiled.find_first("Foo").is_some()); let bar = tmp .add_contract( @@ -1037,8 +1037,8 @@ fn can_compile_single_files() { let compiled = tmp.project().compile_files(vec![f, bar]).unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("Foo").is_some()); - assert!(compiled.find("Bar").is_some()); + assert!(compiled.find_first("Foo").is_some()); + assert!(compiled.find_first("Bar").is_some()); } #[test] @@ -1066,7 +1066,7 @@ contract LinkTest { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - let contract = compiled.find("LinkTest").unwrap(); + let contract = compiled.find_first("LinkTest").unwrap(); let bytecode = &contract.bytecode.as_ref().unwrap().object; assert!(bytecode.is_unlinked()); let s = bytecode.as_str().unwrap(); @@ -1111,8 +1111,8 @@ library MyLib { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("MyLib").is_some()); - let contract = compiled.find("LinkTest").unwrap(); + assert!(compiled.find_first("MyLib").is_some()); + let contract = compiled.find_first("LinkTest").unwrap(); let bytecode = &contract.bytecode.as_ref().unwrap().object; assert!(bytecode.is_unlinked()); @@ -1126,8 +1126,8 @@ library MyLib { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("MyLib").is_some()); - let contract = compiled.find("LinkTest").unwrap(); + assert!(compiled.find_first("MyLib").is_some()); + let contract = compiled.find_first("LinkTest").unwrap(); let bytecode = &contract.bytecode.as_ref().unwrap().object; assert!(!bytecode.is_unlinked()); @@ -1138,8 +1138,8 @@ library MyLib { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("MyLib").is_some()); - let contract = compiled.find("LinkTest").unwrap(); + assert!(compiled.find_first("MyLib").is_some()); + let contract = compiled.find_first("LinkTest").unwrap(); let bytecode = &contract.bytecode.as_ref().unwrap().object; assert!(!bytecode.is_unlinked()); } @@ -1183,8 +1183,8 @@ library MyLib { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("MyLib").is_some()); - let contract = compiled.find("LinkTest").unwrap(); + assert!(compiled.find_first("MyLib").is_some()); + let contract = compiled.find_first("LinkTest").unwrap(); let bytecode = &contract.bytecode.as_ref().unwrap().object; assert!(bytecode.is_unlinked()); @@ -1195,8 +1195,8 @@ library MyLib { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("MyLib").is_some()); - let contract = compiled.find("LinkTest").unwrap(); + assert!(compiled.find_first("MyLib").is_some()); + let contract = compiled.find_first("LinkTest").unwrap(); let bytecode = &contract.bytecode.as_ref().unwrap().object; assert!(!bytecode.is_unlinked()); } @@ -1223,12 +1223,12 @@ fn can_recompile_with_changes() { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("A").is_some()); - assert!(compiled.find("B").is_some()); + assert!(compiled.find_first("A").is_some()); + assert!(compiled.find_first("B").is_some()); let compiled = tmp.compile().unwrap(); - assert!(compiled.find("A").is_some()); - assert!(compiled.find("B").is_some()); + assert!(compiled.find_first("A").is_some()); + assert!(compiled.find_first("B").is_some()); assert!(compiled.is_unchanged()); // modify A.sol @@ -1236,8 +1236,8 @@ fn can_recompile_with_changes() { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); assert!(!compiled.is_unchanged()); - assert!(compiled.find("A").is_some()); - assert!(compiled.find("B").is_some()); + assert!(compiled.find_first("A").is_some()); + assert!(compiled.find_first("B").is_some()); } #[test] @@ -1272,18 +1272,18 @@ fn can_recompile_with_lowercase_names() { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("DeployProxy").is_some()); - assert!(compiled.find("UpgradeProxy").is_some()); - assert!(compiled.find("ProxyAdmin").is_some()); + assert!(compiled.find_first("DeployProxy").is_some()); + assert!(compiled.find_first("UpgradeProxy").is_some()); + assert!(compiled.find_first("ProxyAdmin").is_some()); let artifacts = tmp.artifacts_snapshot().unwrap(); assert_eq!(artifacts.artifacts.as_ref().len(), 3); artifacts.assert_artifacts_essentials_present(); let compiled = tmp.compile().unwrap(); - assert!(compiled.find("DeployProxy").is_some()); - assert!(compiled.find("UpgradeProxy").is_some()); - assert!(compiled.find("ProxyAdmin").is_some()); + assert!(compiled.find_first("DeployProxy").is_some()); + assert!(compiled.find_first("UpgradeProxy").is_some()); + assert!(compiled.find_first("ProxyAdmin").is_some()); assert!(compiled.is_unchanged()); // modify upgradeProxy.sol @@ -1291,9 +1291,9 @@ fn can_recompile_with_lowercase_names() { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); assert!(!compiled.is_unchanged()); - assert!(compiled.find("DeployProxy").is_some()); - assert!(compiled.find("UpgradeProxy").is_some()); - assert!(compiled.find("ProxyAdmin").is_some()); + assert!(compiled.find_first("DeployProxy").is_some()); + assert!(compiled.find_first("UpgradeProxy").is_some()); + assert!(compiled.find_first("ProxyAdmin").is_some()); let artifacts = tmp.artifacts_snapshot().unwrap(); assert_eq!(artifacts.artifacts.as_ref().len(), 3); @@ -1331,12 +1331,12 @@ fn can_recompile_unchanged_with_empty_files() { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("A").is_some()); - assert!(compiled.find("C").is_some()); + assert!(compiled.find_first("A").is_some()); + assert!(compiled.find_first("C").is_some()); let compiled = tmp.compile().unwrap(); - assert!(compiled.find("A").is_some()); - assert!(compiled.find("C").is_some()); + assert!(compiled.find_first("A").is_some()); + assert!(compiled.find_first("C").is_some()); assert!(compiled.is_unchanged()); // modify C.sol @@ -1344,8 +1344,8 @@ fn can_recompile_unchanged_with_empty_files() { 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()); + assert!(compiled.find_first("A").is_some()); + assert!(compiled.find_first("C").is_some()); } #[test] @@ -1380,8 +1380,8 @@ contract Contract { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("Contract").is_some()); - assert!(compiled.find("top_level").is_some()); + assert!(compiled.find_first("Contract").is_some()); + assert!(compiled.find_first("top_level").is_some()); let mut artifacts = tmp.artifacts_snapshot().unwrap(); assert_eq!(artifacts.artifacts.as_ref().len(), 2); @@ -1536,11 +1536,11 @@ fn can_compile_sparse_with_link_references() { let mut output = compiled.clone().output(); - assert!(compiled.find("ATest").is_some()); - assert!(compiled.find("MyLib").is_some()); - let lib = compiled.remove("MyLib").unwrap(); + assert!(compiled.find_first("ATest").is_some()); + assert!(compiled.find_first("MyLib").is_some()); + let lib = compiled.remove_first("MyLib").unwrap(); assert!(lib.bytecode.is_some()); - let lib = compiled.remove("MyLib"); + let lib = compiled.remove_first("MyLib"); assert!(lib.is_none()); let mut dup = output.clone(); @@ -1578,7 +1578,7 @@ fn can_sanitize_bytecode_hash() { let compiled = tmp.compile().unwrap(); assert!(!compiled.has_compiler_errors()); - assert!(compiled.find("A").is_some()); + assert!(compiled.find_first("A").is_some()); } #[test] @@ -1614,7 +1614,7 @@ fn can_compile_model_checker_sample() { }); let compiled = project.compile().unwrap(); - assert!(compiled.find("Assert").is_some()); + assert!(compiled.find_first("Assert").is_some()); assert!(!compiled.has_compiler_errors()); assert!(compiled.has_compiler_warnings()); } @@ -1735,8 +1735,8 @@ fn can_parse_notice() { let mut compiled = project.compile().unwrap(); assert!(!compiled.has_compiler_errors()); assert!(!compiled.is_unchanged()); - assert!(compiled.find("Contract").is_some()); - let userdoc = compiled.remove("Contract").unwrap().userdoc; + assert!(compiled.find_first("Contract").is_some()); + let userdoc = compiled.remove_first("Contract").unwrap().userdoc; assert_eq!( userdoc, @@ -1759,8 +1759,8 @@ fn can_parse_notice() { let mut compiled = project.compile().unwrap(); assert!(!compiled.has_compiler_errors()); assert!(!compiled.is_unchanged()); - assert!(compiled.find("Contract").is_some()); - let userdoc = compiled.remove("Contract").unwrap().userdoc; + assert!(compiled.find_first("Contract").is_some()); + let userdoc = compiled.remove_first("Contract").unwrap().userdoc; assert_eq!( userdoc, @@ -1830,8 +1830,8 @@ contract NotERC20 is INotERC20 { assert!(!compiled.has_compiler_errors()); assert!(!compiled.is_unchanged()); - assert!(compiled.find("INotERC20").is_some()); - let contract = compiled.remove("INotERC20").unwrap(); + assert!(compiled.find_first("INotERC20").is_some()); + let contract = compiled.remove_first("INotERC20").unwrap(); assert_eq!( contract.userdoc, Some(UserDoc { @@ -1901,8 +1901,8 @@ contract NotERC20 is INotERC20 { }) ); - assert!(compiled.find("NotERC20").is_some()); - let contract = compiled.remove("NotERC20").unwrap(); + assert!(compiled.find_first("NotERC20").is_some()); + let contract = compiled.remove_first("NotERC20").unwrap(); assert_eq!( contract.userdoc, Some(UserDoc { diff --git a/examples/contract_human_readable.rs b/examples/contract_human_readable.rs index a1de69f2..33ddc2d2 100644 --- a/examples/contract_human_readable.rs +++ b/examples/contract_human_readable.rs @@ -30,7 +30,7 @@ async fn main() -> Result<()> { let project = Project::builder().paths(paths).ephemeral().no_artifacts().build().unwrap(); // compile the project and get the artifacts let output = project.compile().unwrap(); - let contract = output.find("SimpleStorage").expect("could not find contract").clone(); + let contract = output.find_first("SimpleStorage").expect("could not find contract").clone(); let (abi, bytecode, _) = contract.into_parts(); // 2. instantiate our wallet & anvil