Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
feat(solc): add remove_contract util function
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse committed Jun 30, 2022
1 parent 73d3d3f commit 092df55
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
35 changes: 34 additions & 1 deletion ethers-solc/src/compile/output/info.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Commonly used identifiers for contracts in the compiled output
use std::{convert::TryFrom, fmt, str::FromStr};
use std::{borrow::Cow, convert::TryFrom, fmt, str::FromStr};

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{0}")]
Expand Down Expand Up @@ -77,6 +77,39 @@ impl From<FullContractInfo> for ContractInfo {
}
}

/// The reference type for `ContractInfo`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ContractInfoRef<'a> {
pub path: Option<Cow<'a, str>>,
pub name: Cow<'a, str>,
}

impl<'a> From<ContractInfo> for ContractInfoRef<'a> {
fn from(info: ContractInfo) -> Self {
ContractInfoRef { path: info.path.map(Into::into), name: info.name.into() }
}
}

impl<'a> From<&'a ContractInfo> for ContractInfoRef<'a> {
fn from(info: &'a ContractInfo) -> Self {
ContractInfoRef {
path: info.path.as_deref().map(Into::into),
name: info.name.as_str().into(),
}
}
}
impl<'a> From<FullContractInfo> for ContractInfoRef<'a> {
fn from(info: FullContractInfo) -> Self {
ContractInfoRef { path: Some(info.path.into()), name: info.name.into() }
}
}

impl<'a> From<&'a FullContractInfo> for ContractInfoRef<'a> {
fn from(info: &'a FullContractInfo) -> Self {
ContractInfoRef { path: Some(info.path.as_str().into()), name: info.name.as_str().into() }
}
}

/// Represents the common contract argument pattern `<path>:<contractname>`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct FullContractInfo {
Expand Down
33 changes: 33 additions & 0 deletions ethers-solc/src/compile/output/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
Error,
},
buildinfo::RawBuildInfo,
info::ContractInfoRef,
sources::{VersionedSourceFile, VersionedSourceFiles},
ArtifactId, ArtifactOutput, Artifacts, CompilerOutput, ConfigurableArtifacts, SolcIoError,
};
Expand Down Expand Up @@ -378,6 +379,38 @@ impl AggregatedCompilerOutput {
self.contracts.remove(path, contract)
}

/// 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().output();
/// 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<Contract> {
let ContractInfoRef { path, name } = info.into();
if let Some(path) = path {
self.remove(path, name)
} else {
self.remove_first(name)
}
}

/// Iterate over all contracts and their names
pub fn contracts_iter(&self) -> impl Iterator<Item = (&String, &Contract)> {
self.contracts.contracts()
Expand Down
12 changes: 10 additions & 2 deletions ethers-solc/tests/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use ethers_solc::{
},
buildinfo::BuildInfo,
cache::{SolFilesCache, SOLIDITY_FILES_CACHE_FILENAME},
info::ContractInfo,
project_util::*,
remappings::Remapping,
CompilerInput, ConfigurableArtifacts, ExtraOutputValues, Graph, Project, ProjectCompileOutput,
Expand Down Expand Up @@ -1546,9 +1547,16 @@ fn can_compile_sparse_with_link_references() {
let lib = dup.remove_first("MyLib");
assert!(lib.is_none());

let lib = output.remove(my_lib_path.to_string_lossy(), "MyLib");
dup = output.clone();
let lib = dup.remove(my_lib_path.to_string_lossy(), "MyLib");
assert!(lib.is_some());
let lib = output.remove(my_lib_path.to_string_lossy(), "MyLib");
let lib = dup.remove(my_lib_path.to_string_lossy(), "MyLib");
assert!(lib.is_none());

let info = ContractInfo::new(format!("{}:{}", my_lib_path.to_string_lossy(), "MyLib"));
let lib = output.remove_contract(&info);
assert!(lib.is_some());
let lib = output.remove_contract(&info);
assert!(lib.is_none());
}

Expand Down

0 comments on commit 092df55

Please sign in to comment.