feat(solc): include source file ast in artifact (#1081)
* refactor: extend artifactsoutput interface * add source file to trait * fix: make it compile again
This commit is contained in:
parent
919a570237
commit
2689981782
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
CompactContractBytecodeCow, CompactEvm, DevDoc, Ewasm, GasEstimates, LosslessAbi, Metadata,
|
CompactContractBytecodeCow, CompactEvm, DevDoc, Ewasm, GasEstimates, LosslessAbi, Metadata,
|
||||||
Offsets, Settings, StorageLayout, UserDoc,
|
Offsets, Settings, StorageLayout, UserDoc,
|
||||||
},
|
},
|
||||||
ArtifactOutput, SolcConfig, SolcError,
|
ArtifactOutput, SolcConfig, SolcError, SourceFile,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{borrow::Cow, collections::BTreeMap, fs, path::Path};
|
use std::{borrow::Cow, collections::BTreeMap, fs, path::Path};
|
||||||
|
@ -47,6 +47,8 @@ pub struct ConfigurableContractArtifact {
|
||||||
pub ir_optimized: Option<String>,
|
pub ir_optimized: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub ewasm: Option<Ewasm>,
|
pub ewasm: Option<Ewasm>,
|
||||||
|
#[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
|
||||||
|
pub ast: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigurableContractArtifact {
|
impl ConfigurableContractArtifact {
|
||||||
|
@ -190,7 +192,13 @@ impl ArtifactOutput for ConfigurableArtifacts {
|
||||||
self.additional_files.write_extras(contract, file)
|
self.additional_files.write_extras(contract, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contract_to_artifact(&self, _file: &str, _name: &str, contract: Contract) -> Self::Artifact {
|
fn contract_to_artifact(
|
||||||
|
&self,
|
||||||
|
_file: &str,
|
||||||
|
_name: &str,
|
||||||
|
contract: Contract,
|
||||||
|
source_file: Option<&SourceFile>,
|
||||||
|
) -> Self::Artifact {
|
||||||
let mut artifact_userdoc = None;
|
let mut artifact_userdoc = None;
|
||||||
let mut artifact_devdoc = None;
|
let mut artifact_devdoc = None;
|
||||||
let mut artifact_metadata = None;
|
let mut artifact_metadata = None;
|
||||||
|
@ -276,6 +284,7 @@ impl ArtifactOutput for ConfigurableArtifacts {
|
||||||
ir: artifact_ir,
|
ir: artifact_ir,
|
||||||
ir_optimized: artifact_ir_optimized,
|
ir_optimized: artifact_ir_optimized,
|
||||||
ewasm: artifact_ewasm,
|
ewasm: artifact_ewasm,
|
||||||
|
ast: source_file.map(|s| s.ast.clone()).unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ mod configurable;
|
||||||
use crate::artifacts::{
|
use crate::artifacts::{
|
||||||
contract::{CompactContract, CompactContractBytecode, Contract},
|
contract::{CompactContract, CompactContractBytecode, Contract},
|
||||||
BytecodeObject, CompactBytecode, CompactContractBytecodeCow, CompactDeployedBytecode,
|
BytecodeObject, CompactBytecode, CompactContractBytecodeCow, CompactDeployedBytecode,
|
||||||
|
SourceFile,
|
||||||
};
|
};
|
||||||
pub use configurable::*;
|
pub use configurable::*;
|
||||||
|
|
||||||
|
@ -437,9 +438,10 @@ pub trait ArtifactOutput {
|
||||||
fn on_output(
|
fn on_output(
|
||||||
&self,
|
&self,
|
||||||
contracts: &VersionedContracts,
|
contracts: &VersionedContracts,
|
||||||
|
sources: &BTreeMap<String, SourceFile>,
|
||||||
layout: &ProjectPathsConfig,
|
layout: &ProjectPathsConfig,
|
||||||
) -> Result<Artifacts<Self::Artifact>> {
|
) -> Result<Artifacts<Self::Artifact>> {
|
||||||
let mut artifacts = self.output_to_artifacts(contracts);
|
let mut artifacts = self.output_to_artifacts(contracts, sources);
|
||||||
artifacts.join_all(&layout.artifacts);
|
artifacts.join_all(&layout.artifacts);
|
||||||
artifacts.write_all()?;
|
artifacts.write_all()?;
|
||||||
|
|
||||||
|
@ -581,16 +583,28 @@ pub trait ArtifactOutput {
|
||||||
/// Convert a contract to the artifact type
|
/// Convert a contract to the artifact type
|
||||||
///
|
///
|
||||||
/// This is the core conversion function that takes care of converting a `Contract` into the
|
/// This is the core conversion function that takes care of converting a `Contract` into the
|
||||||
/// associated `Artifact` type
|
/// associated `Artifact` type.
|
||||||
fn contract_to_artifact(&self, _file: &str, _name: &str, contract: Contract) -> Self::Artifact;
|
/// The `SourceFile` is also provided
|
||||||
|
fn contract_to_artifact(
|
||||||
|
&self,
|
||||||
|
_file: &str,
|
||||||
|
_name: &str,
|
||||||
|
contract: Contract,
|
||||||
|
source_file: Option<&SourceFile>,
|
||||||
|
) -> Self::Artifact;
|
||||||
|
|
||||||
/// Convert the compiler output into a set of artifacts
|
/// Convert the compiler output into a set of artifacts
|
||||||
///
|
///
|
||||||
/// **Note:** This does only convert, but _NOT_ write the artifacts to disk, See
|
/// **Note:** This does only convert, but _NOT_ write the artifacts to disk, See
|
||||||
/// [`Self::on_output()`]
|
/// [`Self::on_output()`]
|
||||||
fn output_to_artifacts(&self, contracts: &VersionedContracts) -> Artifacts<Self::Artifact> {
|
fn output_to_artifacts(
|
||||||
|
&self,
|
||||||
|
contracts: &VersionedContracts,
|
||||||
|
sources: &BTreeMap<String, SourceFile>,
|
||||||
|
) -> Artifacts<Self::Artifact> {
|
||||||
let mut artifacts = ArtifactsMap::new();
|
let mut artifacts = ArtifactsMap::new();
|
||||||
for (file, contracts) in contracts.as_ref().iter() {
|
for (file, contracts) in contracts.as_ref().iter() {
|
||||||
|
let source_file = sources.get(file);
|
||||||
let mut entries = BTreeMap::new();
|
let mut entries = BTreeMap::new();
|
||||||
for (name, versioned_contracts) in contracts {
|
for (name, versioned_contracts) in contracts {
|
||||||
let mut contracts = Vec::with_capacity(versioned_contracts.len());
|
let mut contracts = Vec::with_capacity(versioned_contracts.len());
|
||||||
|
@ -601,7 +615,13 @@ pub trait ArtifactOutput {
|
||||||
} else {
|
} else {
|
||||||
Self::output_file(file, name)
|
Self::output_file(file, name)
|
||||||
};
|
};
|
||||||
let artifact = self.contract_to_artifact(file, name, contract.contract.clone());
|
|
||||||
|
let artifact = self.contract_to_artifact(
|
||||||
|
file,
|
||||||
|
name,
|
||||||
|
contract.contract.clone(),
|
||||||
|
source_file,
|
||||||
|
);
|
||||||
|
|
||||||
contracts.push(ArtifactFile {
|
contracts.push(ArtifactFile {
|
||||||
artifact,
|
artifact,
|
||||||
|
@ -636,7 +656,13 @@ pub struct MinimalCombinedArtifacts {
|
||||||
impl ArtifactOutput for MinimalCombinedArtifacts {
|
impl ArtifactOutput for MinimalCombinedArtifacts {
|
||||||
type Artifact = CompactContractBytecode;
|
type Artifact = CompactContractBytecode;
|
||||||
|
|
||||||
fn contract_to_artifact(&self, _file: &str, _name: &str, contract: Contract) -> Self::Artifact {
|
fn contract_to_artifact(
|
||||||
|
&self,
|
||||||
|
_file: &str,
|
||||||
|
_name: &str,
|
||||||
|
contract: Contract,
|
||||||
|
_source_file: Option<&SourceFile>,
|
||||||
|
) -> Self::Artifact {
|
||||||
Self::Artifact::from(contract)
|
Self::Artifact::from(contract)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,9 +680,10 @@ impl ArtifactOutput for MinimalCombinedArtifactsHardhatFallback {
|
||||||
fn on_output(
|
fn on_output(
|
||||||
&self,
|
&self,
|
||||||
output: &VersionedContracts,
|
output: &VersionedContracts,
|
||||||
|
sources: &BTreeMap<String, SourceFile>,
|
||||||
layout: &ProjectPathsConfig,
|
layout: &ProjectPathsConfig,
|
||||||
) -> Result<Artifacts<Self::Artifact>> {
|
) -> Result<Artifacts<Self::Artifact>> {
|
||||||
MinimalCombinedArtifacts::default().on_output(output, layout)
|
MinimalCombinedArtifacts::default().on_output(output, sources, layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_cached_artifact(path: impl AsRef<Path>) -> Result<Self::Artifact> {
|
fn read_cached_artifact(path: impl AsRef<Path>) -> Result<Self::Artifact> {
|
||||||
|
@ -673,8 +700,14 @@ impl ArtifactOutput for MinimalCombinedArtifactsHardhatFallback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contract_to_artifact(&self, file: &str, name: &str, contract: Contract) -> Self::Artifact {
|
fn contract_to_artifact(
|
||||||
MinimalCombinedArtifacts::default().contract_to_artifact(file, name, contract)
|
&self,
|
||||||
|
file: &str,
|
||||||
|
name: &str,
|
||||||
|
contract: Contract,
|
||||||
|
source_file: Option<&SourceFile>,
|
||||||
|
) -> Self::Artifact {
|
||||||
|
MinimalCombinedArtifacts::default().contract_to_artifact(file, name, contract, source_file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,15 +266,22 @@ impl<'a, T: ArtifactOutput> CompiledState<'a, T> {
|
||||||
|
|
||||||
// write all artifacts via the handler but only if the build succeeded
|
// write all artifacts via the handler but only if the build succeeded
|
||||||
let compiled_artifacts = if cache.project().no_artifacts {
|
let compiled_artifacts = if cache.project().no_artifacts {
|
||||||
cache.project().artifacts_handler().output_to_artifacts(&output.contracts)
|
|
||||||
} else if output.has_error() {
|
|
||||||
tracing::trace!("skip writing cache file due to solc errors: {:?}", output.errors);
|
|
||||||
cache.project().artifacts_handler().output_to_artifacts(&output.contracts)
|
|
||||||
} else {
|
|
||||||
cache
|
cache
|
||||||
.project()
|
.project()
|
||||||
.artifacts_handler()
|
.artifacts_handler()
|
||||||
.on_output(&output.contracts, &cache.project().paths)?
|
.output_to_artifacts(&output.contracts, &output.sources)
|
||||||
|
} else if output.has_error() {
|
||||||
|
tracing::trace!("skip writing cache file due to solc errors: {:?}", output.errors);
|
||||||
|
cache
|
||||||
|
.project()
|
||||||
|
.artifacts_handler()
|
||||||
|
.output_to_artifacts(&output.contracts, &output.sources)
|
||||||
|
} else {
|
||||||
|
cache.project().artifacts_handler().on_output(
|
||||||
|
&output.contracts,
|
||||||
|
&output.sources,
|
||||||
|
&cache.project().paths,
|
||||||
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ArtifactsState { output, cache, compiled_artifacts })
|
Ok(ArtifactsState { output, cache, compiled_artifacts })
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
contract::{CompactContract, CompactContractBytecode, Contract, ContractBytecode},
|
contract::{CompactContract, CompactContractBytecode, Contract, ContractBytecode},
|
||||||
CompactContractBytecodeCow, LosslessAbi, Offsets,
|
CompactContractBytecodeCow, LosslessAbi, Offsets,
|
||||||
},
|
},
|
||||||
ArtifactOutput,
|
ArtifactOutput, SourceFile,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{borrow::Cow, collections::btree_map::BTreeMap};
|
use std::{borrow::Cow, collections::btree_map::BTreeMap};
|
||||||
|
@ -97,7 +97,13 @@ pub struct HardhatArtifacts {
|
||||||
impl ArtifactOutput for HardhatArtifacts {
|
impl ArtifactOutput for HardhatArtifacts {
|
||||||
type Artifact = HardhatArtifact;
|
type Artifact = HardhatArtifact;
|
||||||
|
|
||||||
fn contract_to_artifact(&self, file: &str, name: &str, contract: Contract) -> Self::Artifact {
|
fn contract_to_artifact(
|
||||||
|
&self,
|
||||||
|
file: &str,
|
||||||
|
name: &str,
|
||||||
|
contract: Contract,
|
||||||
|
_source_file: Option<&SourceFile>,
|
||||||
|
) -> Self::Artifact {
|
||||||
let (bytecode, link_references, deployed_bytecode, deployed_link_references) =
|
let (bytecode, link_references, deployed_bytecode, deployed_link_references) =
|
||||||
if let Some(evm) = contract.evm {
|
if let Some(evm) = contract.evm {
|
||||||
let (deployed_bytecode, deployed_link_references) =
|
let (deployed_bytecode, deployed_link_references) =
|
||||||
|
|
|
@ -24,7 +24,7 @@ mod config;
|
||||||
pub use config::{AllowedLibPaths, PathStyle, ProjectPathsConfig, SolcConfig};
|
pub use config::{AllowedLibPaths, PathStyle, ProjectPathsConfig, SolcConfig};
|
||||||
|
|
||||||
pub mod remappings;
|
pub mod remappings;
|
||||||
use crate::artifacts::Source;
|
use crate::artifacts::{Source, SourceFile};
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod filter;
|
mod filter;
|
||||||
|
@ -677,9 +677,10 @@ impl<T: ArtifactOutput> ArtifactOutput for Project<T> {
|
||||||
fn on_output(
|
fn on_output(
|
||||||
&self,
|
&self,
|
||||||
contracts: &VersionedContracts,
|
contracts: &VersionedContracts,
|
||||||
|
sources: &BTreeMap<String, SourceFile>,
|
||||||
layout: &ProjectPathsConfig,
|
layout: &ProjectPathsConfig,
|
||||||
) -> Result<Artifacts<Self::Artifact>> {
|
) -> Result<Artifacts<Self::Artifact>> {
|
||||||
self.artifacts_handler().on_output(contracts, layout)
|
self.artifacts_handler().on_output(contracts, sources, layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_contract_extras(&self, contract: &Contract, file: &Path) -> Result<()> {
|
fn write_contract_extras(&self, contract: &Contract, file: &Path) -> Result<()> {
|
||||||
|
@ -738,12 +739,22 @@ impl<T: ArtifactOutput> ArtifactOutput for Project<T> {
|
||||||
T::read_cached_artifacts(files)
|
T::read_cached_artifacts(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contract_to_artifact(&self, file: &str, name: &str, contract: Contract) -> Self::Artifact {
|
fn contract_to_artifact(
|
||||||
self.artifacts_handler().contract_to_artifact(file, name, contract)
|
&self,
|
||||||
|
file: &str,
|
||||||
|
name: &str,
|
||||||
|
contract: Contract,
|
||||||
|
source_file: Option<&SourceFile>,
|
||||||
|
) -> Self::Artifact {
|
||||||
|
self.artifacts_handler().contract_to_artifact(file, name, contract, source_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_to_artifacts(&self, contracts: &VersionedContracts) -> Artifacts<Self::Artifact> {
|
fn output_to_artifacts(
|
||||||
self.artifacts_handler().output_to_artifacts(contracts)
|
&self,
|
||||||
|
contracts: &VersionedContracts,
|
||||||
|
sources: &BTreeMap<String, SourceFile>,
|
||||||
|
) -> Artifacts<Self::Artifact> {
|
||||||
|
self.artifacts_handler().output_to_artifacts(contracts, sources)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue