Files
revive/crates/solc-json-interface/src/standard_json/input/mod.rs
T
xermicus 79aaca1a85 std json: do not request EVM bytecode (#410)
These compiler outputs are irrelevant for the `resolc` compilation
pipeline. It can also break the compilation pipeline. For example, solc
may reject the code without via-ir or fail during the EVM codegen phase
with stack too deep errors - which is not relevant to us.

---------

Signed-off-by: xermicus <cyrill@parity.io>
2025-11-13 10:32:32 +01:00

219 lines
7.4 KiB
Rust

//! The `solc --standard-json` input.
use std::collections::BTreeMap;
#[cfg(feature = "resolc")]
use std::collections::BTreeSet;
#[cfg(feature = "resolc")]
use std::path::Path;
#[cfg(feature = "resolc")]
use std::path::PathBuf;
#[cfg(all(feature = "parallel", feature = "resolc"))]
use rayon::iter::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator};
use serde::Deserialize;
use serde::Serialize;
#[cfg(feature = "resolc")]
use crate::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
#[cfg(feature = "resolc")]
use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
#[cfg(feature = "resolc")]
use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
#[cfg(feature = "resolc")]
use crate::SolcStandardJsonInputSettingsLibraries;
#[cfg(feature = "resolc")]
use crate::SolcStandardJsonInputSettingsPolkaVM;
use self::language::Language;
#[cfg(feature = "resolc")]
use self::settings::warning::Warning;
use self::settings::Settings;
use self::source::Source;
pub mod language;
pub mod settings;
pub mod source;
/// The `solc --standard-json` input.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Input {
/// The input language.
pub language: Language,
/// The input source code files hashmap.
pub sources: BTreeMap<String, Source>,
/// The compiler settings.
pub settings: Settings,
/// The suppressed warnings.
#[cfg(feature = "resolc")]
#[serde(default, skip_serializing)]
pub suppressed_warnings: Vec<Warning>,
}
#[cfg(feature = "resolc")]
impl Input {
/// A shortcut constructor.
///
/// If the `path` is `None`, the input is read from the stdin.
pub fn try_from(path: Option<&Path>) -> anyhow::Result<Self> {
let input_json = match path {
Some(path) => std::fs::read_to_string(path)
.map_err(|error| anyhow::anyhow!("Standard JSON file {path:?} reading: {error}")),
None => std::io::read_to_string(std::io::stdin())
.map_err(|error| anyhow::anyhow!("Standard JSON reading from stdin: {error}")),
}?;
revive_common::deserialize_from_str::<Self>(input_json.as_str())
.map_err(|error| anyhow::anyhow!("Standard JSON parsing: {error}"))
}
/// A shortcut constructor from paths.
pub fn try_from_solidity_paths(
evm_version: Option<revive_common::EVMVersion>,
paths: &[PathBuf],
libraries: &[String],
remappings: BTreeSet<String>,
output_selection: SolcStandardJsonInputSettingsSelection,
optimizer: SolcStandardJsonInputSettingsOptimizer,
metadata: SolcStandardJsonInputSettingsMetadata,
suppressed_warnings: Vec<Warning>,
polkavm: SolcStandardJsonInputSettingsPolkaVM,
llvm_arguments: Vec<String>,
detect_missing_libraries: bool,
) -> anyhow::Result<Self> {
let mut paths: BTreeSet<PathBuf> = paths.iter().cloned().collect();
let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?;
for library_file in libraries.as_inner().keys() {
paths.insert(PathBuf::from(library_file));
}
#[cfg(feature = "parallel")]
let iter = paths.into_par_iter(); // Parallel iterator
#[cfg(not(feature = "parallel"))]
let iter = paths.into_iter(); // Sequential iterator
let sources = iter
.map(|path| {
let source = Source::try_read(path.as_path())?;
Ok((path.to_string_lossy().to_string(), source))
})
.collect::<anyhow::Result<BTreeMap<String, Source>>>()?;
Self::try_from_solidity_sources(
evm_version,
sources,
libraries,
remappings,
output_selection,
optimizer,
metadata,
suppressed_warnings,
polkavm,
llvm_arguments,
detect_missing_libraries,
)
}
/// A shortcut constructor from source code.
/// Only for the integration test purposes.
pub fn try_from_solidity_sources(
evm_version: Option<revive_common::EVMVersion>,
sources: BTreeMap<String, Source>,
libraries: SolcStandardJsonInputSettingsLibraries,
remappings: BTreeSet<String>,
output_selection: SolcStandardJsonInputSettingsSelection,
optimizer: SolcStandardJsonInputSettingsOptimizer,
metadata: SolcStandardJsonInputSettingsMetadata,
suppressed_warnings: Vec<Warning>,
polkavm: SolcStandardJsonInputSettingsPolkaVM,
llvm_arguments: Vec<String>,
detect_missing_libraries: bool,
) -> anyhow::Result<Self> {
Ok(Self {
language: Language::Solidity,
sources,
settings: Settings::new(
evm_version,
libraries,
remappings,
output_selection,
optimizer,
metadata,
polkavm,
suppressed_warnings.clone(),
llvm_arguments,
detect_missing_libraries,
),
suppressed_warnings,
})
}
/// A shortcut constructor from paths to Yul source files.
pub fn from_yul_paths(
paths: &[PathBuf],
libraries: SolcStandardJsonInputSettingsLibraries,
optimizer: SolcStandardJsonInputSettingsOptimizer,
llvm_options: Vec<String>,
) -> Self {
let sources = paths
.iter()
.map(|path| {
(
path.to_string_lossy().to_string(),
Source::from(path.as_path()),
)
})
.collect();
Self::from_yul_sources(sources, libraries, optimizer, llvm_options)
}
/// A shortcut constructor from Yul source code.
pub fn from_yul_sources(
sources: BTreeMap<String, Source>,
libraries: SolcStandardJsonInputSettingsLibraries,
optimizer: SolcStandardJsonInputSettingsOptimizer,
llvm_arguments: Vec<String>,
) -> Self {
let output_selection = SolcStandardJsonInputSettingsSelection::new_yul_validation();
Self {
language: Language::Yul,
sources,
settings: Settings::new(
None,
libraries,
Default::default(),
output_selection,
optimizer,
Default::default(),
Default::default(),
vec![],
llvm_arguments,
false,
),
suppressed_warnings: vec![],
}
}
/// Extends the output selection with another one.
pub fn extend_selection(&mut self, selection: SolcStandardJsonInputSettingsSelection) {
self.settings.extend_selection(selection);
}
/// Tries to resolve all sources.
pub fn resolve_sources(&mut self) {
#[cfg(feature = "parallel")]
let iter = self.sources.par_iter_mut();
#[cfg(not(feature = "parallel"))]
let iter = self.sources.iter_mut();
iter.for_each(|(_path, source)| {
let _ = source.try_resolve();
});
}
/// Removes unneded output selections.
pub fn retain_output_selection(&mut self) {
self.settings.retain_output_selection();
}
}