Artifact ids (#882)
* Added ArtifactId * Added ArtifactId impl and updated into_artifacts to return id * Formatting * Fixed warning * Added versioned slug method to ArtifactId * Added Ord/Eq derives to ArtifactId * Fixed broken tests and doc tests * Added failing test for versioned link references * chore: ignore linkrefs test - to be fixed in followup * test(solc): remove artifact json Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
parent
ce8c671218
commit
d8e5e536cc
|
@ -68,7 +68,7 @@ harness = false
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "project"
|
name = "project"
|
||||||
path = "tests/project.rs"
|
path = "tests/project.rs"
|
||||||
required-features = ["project-util"]
|
required-features = ["async", "svm", "project-util"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rustls"]
|
default = ["rustls"]
|
||||||
|
|
|
@ -18,6 +18,36 @@ use std::{
|
||||||
mod configurable;
|
mod configurable;
|
||||||
pub use configurable::*;
|
pub use configurable::*;
|
||||||
|
|
||||||
|
/// Represents unique artifact metadata for identifying artifacts on output
|
||||||
|
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||||
|
pub struct ArtifactId {
|
||||||
|
/// `artifact` cache path
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub name: String,
|
||||||
|
/// Original source file path
|
||||||
|
pub source: PathBuf,
|
||||||
|
/// `solc` version that produced this artifact
|
||||||
|
pub version: Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArtifactId {
|
||||||
|
/// Returns a <filename>:<name> slug that identifies an artifact
|
||||||
|
pub fn slug(&self) -> String {
|
||||||
|
format!("{}.json:{}", self.path.file_stem().unwrap().to_string_lossy(), self.name)
|
||||||
|
}
|
||||||
|
/// Returns a <filename><version>:<name> slug that identifies an artifact
|
||||||
|
pub fn slug_versioned(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"{}.{}.{}.{}.json:{}",
|
||||||
|
self.path.file_stem().unwrap().to_string_lossy(),
|
||||||
|
self.version.major,
|
||||||
|
self.version.minor,
|
||||||
|
self.version.patch,
|
||||||
|
self.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents an artifact file representing a [`crate::Contract`]
|
/// Represents an artifact file representing a [`crate::Contract`]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ArtifactFile<T> {
|
pub struct ArtifactFile<T> {
|
||||||
|
@ -162,17 +192,19 @@ impl<T> Artifacts<T> {
|
||||||
/// Returns an iterator over _all_ artifacts and `<file name:contract name>`
|
/// Returns an iterator over _all_ artifacts and `<file name:contract name>`
|
||||||
pub fn into_artifacts<O: ArtifactOutput<Artifact = T>>(
|
pub fn into_artifacts<O: ArtifactOutput<Artifact = T>>(
|
||||||
self,
|
self,
|
||||||
) -> impl Iterator<Item = (String, T)> {
|
) -> impl Iterator<Item = (ArtifactId, T)> {
|
||||||
self.0.into_values().flat_map(|contract_artifacts| {
|
self.0.into_iter().flat_map(|(file, contract_artifacts)| {
|
||||||
contract_artifacts.into_iter().flat_map(|(_contract_name, artifacts)| {
|
contract_artifacts.into_iter().flat_map(move |(_contract_name, artifacts)| {
|
||||||
artifacts.into_iter().filter_map(|artifact| {
|
let source = PathBuf::from(file.clone());
|
||||||
|
artifacts.into_iter().filter_map(move |artifact| {
|
||||||
O::contract_name(&artifact.file).map(|name| {
|
O::contract_name(&artifact.file).map(|name| {
|
||||||
(
|
(
|
||||||
format!(
|
ArtifactId {
|
||||||
"{}:{}",
|
path: PathBuf::from(&artifact.file),
|
||||||
artifact.file.file_name().unwrap().to_string_lossy(),
|
name,
|
||||||
name
|
source: source.clone(),
|
||||||
),
|
version: artifact.version,
|
||||||
|
},
|
||||||
artifact.artifact,
|
artifact.artifact,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
CompactContractBytecode, CompactContractRef, Contract, Error, SourceFile, SourceFiles,
|
CompactContractBytecode, CompactContractRef, Contract, Error, SourceFile, SourceFiles,
|
||||||
},
|
},
|
||||||
contracts::{VersionedContract, VersionedContracts},
|
contracts::{VersionedContract, VersionedContracts},
|
||||||
ArtifactOutput, Artifacts, CompilerOutput, ConfigurableArtifacts,
|
ArtifactId, ArtifactOutput, Artifacts, CompilerOutput, ConfigurableArtifacts,
|
||||||
};
|
};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use std::{collections::BTreeMap, fmt, path::Path};
|
use std::{collections::BTreeMap, fmt, path::Path};
|
||||||
|
@ -36,12 +36,12 @@ impl<T: ArtifactOutput> ProjectCompileOutput<T> {
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use std::collections::btree_map::BTreeMap;
|
/// use std::collections::btree_map::BTreeMap;
|
||||||
/// use ethers_solc::ConfigurableContractArtifact;
|
/// use ethers_solc::ConfigurableContractArtifact;
|
||||||
/// use ethers_solc::Project;
|
/// use ethers_solc::{ArtifactId, Project};
|
||||||
///
|
///
|
||||||
/// let project = Project::builder().build().unwrap();
|
/// let project = Project::builder().build().unwrap();
|
||||||
/// let contracts: BTreeMap<String, ConfigurableContractArtifact> = project.compile().unwrap().into_artifacts().collect();
|
/// let contracts: BTreeMap<ArtifactId, ConfigurableContractArtifact> = project.compile().unwrap().into_artifacts().collect();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn into_artifacts(self) -> impl Iterator<Item = (String, T::Artifact)> {
|
pub fn into_artifacts(self) -> impl Iterator<Item = (ArtifactId, T::Artifact)> {
|
||||||
let Self { cached_artifacts, compiled_artifacts, .. } = self;
|
let Self { cached_artifacts, compiled_artifacts, .. } = self;
|
||||||
cached_artifacts.into_artifacts::<T>().chain(compiled_artifacts.into_artifacts::<T>())
|
cached_artifacts.into_artifacts::<T>().chain(compiled_artifacts.into_artifacts::<T>())
|
||||||
}
|
}
|
||||||
|
@ -183,15 +183,16 @@ impl ProjectCompileOutput<ConfigurableArtifacts> {
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use std::collections::btree_map::BTreeMap;
|
/// use std::collections::btree_map::BTreeMap;
|
||||||
/// use ethers_solc::artifacts::CompactContractBytecode;
|
/// use ethers_solc::artifacts::CompactContractBytecode;
|
||||||
/// use ethers_solc::Project;
|
/// use ethers_solc::{ArtifactId, Project};
|
||||||
///
|
///
|
||||||
/// let project = Project::builder().build().unwrap();
|
/// let project = Project::builder().build().unwrap();
|
||||||
/// let contracts: BTreeMap<String, CompactContractBytecode> = project.compile().unwrap().into_contract_bytecodes().collect();
|
/// let contracts: BTreeMap<ArtifactId, CompactContractBytecode> = project.compile().unwrap().into_contract_bytecodes().collect();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn into_contract_bytecodes(
|
pub fn into_contract_bytecodes(
|
||||||
self,
|
self,
|
||||||
) -> impl Iterator<Item = (String, CompactContractBytecode)> {
|
) -> impl Iterator<Item = (ArtifactId, CompactContractBytecode)> {
|
||||||
self.into_artifacts().map(|(name, artifact)| (name, artifact.into_contract_bytecode()))
|
self.into_artifacts()
|
||||||
|
.map(|(artifact_id, artifact)| (artifact_id, artifact.into_contract_bytecode()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: UNLICENSED
|
||||||
|
pragma solidity >0.4.0;
|
||||||
|
|
||||||
|
contract Lib {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: UNLICENSED
|
||||||
|
pragma solidity <=0.8.10;
|
||||||
|
|
||||||
|
import "../lib/Lib.sol";
|
||||||
|
|
||||||
|
contract FooV1 {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: UNLICENSED
|
||||||
|
pragma solidity 0.8.11;
|
||||||
|
|
||||||
|
import "../lib/Lib.sol";
|
||||||
|
|
||||||
|
contract FooV2 {}
|
|
@ -23,6 +23,24 @@ fn init_tracing() {
|
||||||
.init();
|
.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn can_get_versioned_linkrefs() {
|
||||||
|
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/test-versioned-linkrefs");
|
||||||
|
let paths = ProjectPathsConfig::builder()
|
||||||
|
.sources(root.join("src"))
|
||||||
|
.lib(root.join("lib"))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let project = Project::builder().paths(paths).ephemeral().no_artifacts().build().unwrap();
|
||||||
|
|
||||||
|
let compiled = project.compile().unwrap();
|
||||||
|
assert!(!compiled.has_compiler_errors());
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_compile_hardhat_sample() {
|
fn can_compile_hardhat_sample() {
|
||||||
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/hardhat-sample");
|
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/hardhat-sample");
|
||||||
|
@ -304,12 +322,12 @@ fn can_compile_dapp_sample_with_cache() {
|
||||||
assert!(compiled.find("NewContract").is_some());
|
assert!(compiled.find("NewContract").is_some());
|
||||||
assert!(!compiled.is_unchanged());
|
assert!(!compiled.is_unchanged());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compiled.into_artifacts().map(|(name, _)| name).collect::<HashSet<_>>(),
|
compiled.into_artifacts().map(|(artifact_id, _)| artifact_id.name).collect::<HashSet<_>>(),
|
||||||
HashSet::from([
|
HashSet::from([
|
||||||
"Dapp.json:Dapp".to_string(),
|
"Dapp".to_string(),
|
||||||
"DappTest.json:DappTest".to_string(),
|
"DappTest".to_string(),
|
||||||
"DSTest.json:DSTest".to_string(),
|
"DSTest".to_string(),
|
||||||
"NewContract.json:NewContract".to_string(),
|
"NewContract".to_string(),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -317,12 +335,12 @@ fn can_compile_dapp_sample_with_cache() {
|
||||||
std::fs::copy(cache_testdata_dir.join("Dapp.sol"), root.join("src/Dapp.sol")).unwrap();
|
std::fs::copy(cache_testdata_dir.join("Dapp.sol"), root.join("src/Dapp.sol")).unwrap();
|
||||||
let compiled = project.compile().unwrap();
|
let compiled = project.compile().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compiled.into_artifacts().map(|(name, _)| name).collect::<HashSet<_>>(),
|
compiled.into_artifacts().map(|(artifact_id, _)| artifact_id.name).collect::<HashSet<_>>(),
|
||||||
HashSet::from([
|
HashSet::from([
|
||||||
"DappTest.json:DappTest".to_string(),
|
"DappTest".to_string(),
|
||||||
"NewContract.json:NewContract".to_string(),
|
"NewContract".to_string(),
|
||||||
"DSTest.json:DSTest".to_string(),
|
"DSTest".to_string(),
|
||||||
"Dapp.json:Dapp".to_string(),
|
"Dapp".to_string(),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue