//! 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, /// The compiler settings. pub settings: Settings, /// The suppressed warnings. #[cfg(feature = "resolc")] #[serde(default, skip_serializing)] pub suppressed_warnings: Vec, } #[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 { 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::(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, paths: &[PathBuf], libraries: &[String], remappings: BTreeSet, output_selection: SolcStandardJsonInputSettingsSelection, optimizer: SolcStandardJsonInputSettingsOptimizer, metadata: SolcStandardJsonInputSettingsMetadata, suppressed_warnings: Vec, polkavm: SolcStandardJsonInputSettingsPolkaVM, llvm_arguments: Vec, detect_missing_libraries: bool, ) -> anyhow::Result { let mut paths: BTreeSet = 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::>>()?; 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, sources: BTreeMap, libraries: SolcStandardJsonInputSettingsLibraries, remappings: BTreeSet, output_selection: SolcStandardJsonInputSettingsSelection, optimizer: SolcStandardJsonInputSettingsOptimizer, metadata: SolcStandardJsonInputSettingsMetadata, suppressed_warnings: Vec, polkavm: SolcStandardJsonInputSettingsPolkaVM, llvm_arguments: Vec, detect_missing_libraries: bool, ) -> anyhow::Result { 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, ) -> 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, libraries: SolcStandardJsonInputSettingsLibraries, optimizer: SolcStandardJsonInputSettingsOptimizer, llvm_arguments: Vec, ) -> 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(); } }