refactor(solc): unify find/remove api (#1449)
* refactor(solc): unify find/remove api * fix: update docs
This commit is contained in:
parent
c31eec5008
commit
3c1de64240
|
@ -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<T> {
|
||||
/// The Artifact that was written
|
||||
pub artifact: T,
|
||||
|
@ -102,7 +104,7 @@ impl<T> ArtifactFile<T> {
|
|||
pub(crate) type ArtifactsMap<T> = FileToContractsMap<Vec<ArtifactFile<T>>>;
|
||||
|
||||
/// Represents a set of Artifacts
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Artifacts<T>(pub ArtifactsMap<T>);
|
||||
|
||||
impl<T> From<ArtifactsMap<T>> for Artifacts<T> {
|
||||
|
@ -149,6 +151,14 @@ impl<T> AsMut<ArtifactsMap<T>> for Artifacts<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Artifacts<T> {
|
||||
type Target = ArtifactsMap<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Serialize> Artifacts<T> {
|
||||
/// Writes all artifacts into the given `artifacts_root` folder
|
||||
pub fn write_all(&self) -> Result<()> {
|
||||
|
@ -264,18 +274,49 @@ impl<T> Artifacts<T> {
|
|||
}
|
||||
|
||||
/// Finds the first artifact `T` with a matching contract name
|
||||
pub fn find(&self, contract_name: impl AsRef<str>) -> Option<&T> {
|
||||
pub fn find_first(&self, contract_name: impl AsRef<str>) -> 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<str>, contract: impl AsRef<str>) -> 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<str>, contract: impl AsRef<str>) -> Option<T> {
|
||||
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<str>) -> Option<T> {
|
||||
pub fn remove_first(&mut self, contract_name: impl AsRef<str>) -> Option<T> {
|
||||
let contract_name = contract_name.as_ref();
|
||||
self.0.iter_mut().find_map(|(_file, contracts)| {
|
||||
let mut artifact = None;
|
||||
|
|
|
@ -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();
|
||||
/// # }
|
||||
/// ```
|
||||
|
|
|
@ -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<str>) -> Option<CompactContractRef> {
|
||||
pub fn find_first(&self, contract: impl AsRef<str>) -> Option<CompactContractRef> {
|
||||
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<str>,
|
||||
contract: impl AsRef<str>,
|
||||
) -> Option<CompactContractRef> {
|
||||
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<FileToContractsMap<Vec<VersionedContract>>> for VersionedContracts {
|
|||
}
|
||||
}
|
||||
|
||||
impl Deref for VersionedContracts {
|
||||
type Target = FileToContractsMap<Vec<VersionedContract>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for VersionedContracts {
|
||||
type Item = (String, BTreeMap<String, Vec<VersionedContract>>);
|
||||
type IntoIter =
|
||||
|
|
|
@ -53,6 +53,28 @@ impl<T: ArtifactOutput> ProjectCompileOutput<T> {
|
|||
cached_artifacts.into_artifacts::<T>().chain(compiled_artifacts.into_artifacts::<T>())
|
||||
}
|
||||
|
||||
/// 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<String, &ConfigurableContractArtifact> = project.compile().unwrap().artifacts().collect();
|
||||
/// ```
|
||||
pub fn artifacts(&self) -> impl Iterator<Item = (String, &T::Artifact)> {
|
||||
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<T: ArtifactOutput> ProjectCompileOutput<T> {
|
|||
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<str>) -> Option<T::Artifact> {
|
||||
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<T::Artifact> {
|
||||
|
@ -188,19 +201,140 @@ impl<T: ArtifactOutput> ProjectCompileOutput<T> {
|
|||
}
|
||||
contracts
|
||||
}
|
||||
|
||||
/// Removes the contract with matching path and name using the `<path>:<contractname>` 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<ContractInfoRef<'a>>) -> Option<&T::Artifact> {
|
||||
let ContractInfoRef { path, name } = info.into();
|
||||
if let Some(path) = path {
|
||||
self.find(path, name)
|
||||
} else {
|
||||
self.find_first(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ArtifactOutput> ProjectCompileOutput<T>
|
||||
where
|
||||
T::Artifact: Clone,
|
||||
{
|
||||
/// Finds the first contract with the given name
|
||||
pub fn find(&self, contract_name: impl AsRef<str>) -> Option<&T::Artifact> {
|
||||
let contract_name = contract_name.as_ref();
|
||||
if let artifact @ Some(_) = self.compiled_artifacts.find(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 find(&self, path: impl AsRef<str>, contract: impl AsRef<str>) -> 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<str>) -> 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<str>,
|
||||
contract: impl AsRef<str>,
|
||||
) -> Option<T::Artifact> {
|
||||
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<str>) -> Option<T::Artifact> {
|
||||
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 `<path>:<contractname>` 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<ContractInfoRef<'a>>,
|
||||
) -> Option<T::Artifact> {
|
||||
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<str>) -> Option<CompactContractRef> {
|
||||
self.contracts.find(contract)
|
||||
pub fn find_first(&self, contract: impl AsRef<str>) -> Option<CompactContractRef> {
|
||||
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"))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -55,21 +55,21 @@ fn can_compile_hardhat_sample() {
|
|||
let project = TempProject::<ConfigurableArtifacts>::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::<ConfigurableArtifacts>::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::<ConfigurableArtifacts>::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::<HashSet<_>>(),
|
||||
|
@ -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<Path>, dst: impl AsRef<Path>) -> 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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue