Implement basic reporting facility (#18)

* wip

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* save to file after all tasks done

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* error out early if the workdir does not exist

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* the compiler statistics

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* allow compiler statistics per implementation

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* save compiler problems

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* add flag whether to extract compiler errors

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

* whitespace

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>

---------

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
xermicus
2025-05-23 19:15:04 +02:00
committed by GitHub
parent 399f7820cd
commit 10bfaed461
18 changed files with 528 additions and 60 deletions
+47 -17
View File
@@ -8,6 +8,7 @@ use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler};
use revive_dt_config::Arguments;
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
use revive_dt_node_interaction::EthereumNode;
use revive_dt_report::reporter::{CompilationTask, Report, Span};
use revive_solc_json_interface::SolcStandardJsonOutput;
use crate::Platform;
@@ -19,6 +20,7 @@ type Contracts<T> = HashMap<
pub struct State<'a, T: Platform> {
config: &'a Arguments,
span: Span,
contracts: Contracts<T>,
deployed_contracts: HashMap<String, Address>,
}
@@ -27,37 +29,65 @@ impl<'a, T> State<'a, T>
where
T: Platform,
{
pub fn new(config: &'a Arguments) -> Self {
pub fn new(config: &'a Arguments, span: Span) -> Self {
Self {
config,
span,
contracts: Default::default(),
deployed_contracts: Default::default(),
}
}
/// Returns a copy of the current span.
fn span(&self) -> Span {
self.span
}
pub fn build_contracts(&mut self, mode: &SolcMode, metadata: &Metadata) -> anyhow::Result<()> {
let mut span = self.span();
span.next_metadata(
metadata
.file_path
.as_ref()
.expect("metadata should have been read from a file")
.clone(),
);
let Some(version) = mode.last_patch_version(&self.config.solc) else {
anyhow::bail!("unsupported solc version: {:?}", mode.solc_version);
anyhow::bail!("unsupported solc version: {:?}", &mode.solc_version);
};
let sources = metadata.contract_sources()?;
let base_path = metadata.directory()?.display().to_string();
let mut compiler = Compiler::<T::Compiler>::new()
.base_path(metadata.directory()?.display().to_string())
.solc_optimizer(mode.solc_optimize());
let mut compiler = Compiler::<T::Compiler>::new().base_path(base_path.clone());
for (file, _contract) in sources.values() {
for (file, _contract) in metadata.contract_sources()?.values() {
log::debug!("contract source {}", file.display());
compiler = compiler.with_source(file)?;
}
let mut task = CompilationTask {
json_input: compiler.input(),
json_output: None,
mode: mode.clone(),
compiler_version: format!("{}", &version),
error: None,
};
let compiler_path = T::Compiler::get_compiler_executable(self.config, version)?;
let output = compiler
.solc_optimizer(mode.solc_optimize())
.try_build(compiler_path)?;
self.contracts.insert(output.input, output.output);
Ok(())
match compiler.try_build(compiler_path) {
Ok(output) => {
task.json_output = Some(output.output.clone());
task.error = output.error;
self.contracts.insert(output.input, output.output);
Report::compilation(span, T::config_id(), task);
Ok(())
}
Err(error) => {
task.error = Some(error.to_string());
Err(error)
}
}
}
pub fn execute_input(
@@ -102,12 +132,12 @@ where
}
}
pub fn execute(&mut self) -> anyhow::Result<()> {
pub fn execute(&mut self, span: Span) -> anyhow::Result<()> {
for mode in self.metadata.solc_modes() {
let mut leader_state = State::<L>::new(self.config);
let mut leader_state = State::<L>::new(self.config, span);
leader_state.build_contracts(&mode, self.metadata)?;
let mut follower_state = State::<F>::new(self.config);
let mut follower_state = State::<F>::new(self.config, span);
follower_state.build_contracts(&mode, self.metadata)?;
for case in &self.metadata.cases {