revive_solc_json_interface/standard_json/input/
mod.rs

1//! The `solc --standard-json` input.
2
3use std::collections::BTreeMap;
4#[cfg(feature = "resolc")]
5use std::collections::BTreeSet;
6#[cfg(feature = "resolc")]
7use std::path::Path;
8#[cfg(feature = "resolc")]
9use std::path::PathBuf;
10
11#[cfg(all(feature = "parallel", feature = "resolc"))]
12use rayon::iter::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator};
13use serde::Deserialize;
14use serde::Serialize;
15
16#[cfg(feature = "resolc")]
17use crate::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
18#[cfg(feature = "resolc")]
19use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
20#[cfg(feature = "resolc")]
21use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
22#[cfg(feature = "resolc")]
23use crate::SolcStandardJsonInputSettingsLibraries;
24#[cfg(feature = "resolc")]
25use crate::SolcStandardJsonInputSettingsPolkaVM;
26
27use self::language::Language;
28#[cfg(feature = "resolc")]
29use self::settings::warning::Warning;
30use self::settings::Settings;
31use self::source::Source;
32
33pub mod language;
34pub mod settings;
35pub mod source;
36
37/// The `solc --standard-json` input.
38#[derive(Clone, Debug, Serialize, Deserialize)]
39#[serde(rename_all = "camelCase")]
40pub struct Input {
41    /// The input language.
42    pub language: Language,
43    /// The input source code files hashmap.
44    pub sources: BTreeMap<String, Source>,
45    /// The compiler settings.
46    pub settings: Settings,
47    /// The suppressed warnings.
48    #[cfg(feature = "resolc")]
49    #[serde(default, skip_serializing)]
50    pub suppressed_warnings: Vec<Warning>,
51}
52
53#[cfg(feature = "resolc")]
54impl Input {
55    /// A shortcut constructor.
56    ///
57    /// If the `path` is `None`, the input is read from the stdin.
58    pub fn try_from(path: Option<&Path>) -> anyhow::Result<Self> {
59        let input_json = match path {
60            Some(path) => std::fs::read_to_string(path)
61                .map_err(|error| anyhow::anyhow!("Standard JSON file {path:?} reading: {error}")),
62            None => std::io::read_to_string(std::io::stdin())
63                .map_err(|error| anyhow::anyhow!("Standard JSON reading from stdin: {error}")),
64        }?;
65        revive_common::deserialize_from_str::<Self>(input_json.as_str())
66            .map_err(|error| anyhow::anyhow!("Standard JSON parsing: {error}"))
67    }
68
69    /// A shortcut constructor from paths.
70    pub fn try_from_solidity_paths(
71        evm_version: Option<revive_common::EVMVersion>,
72        paths: &[PathBuf],
73        libraries: &[String],
74        remappings: BTreeSet<String>,
75        output_selection: SolcStandardJsonInputSettingsSelection,
76        optimizer: SolcStandardJsonInputSettingsOptimizer,
77        metadata: SolcStandardJsonInputSettingsMetadata,
78        suppressed_warnings: Vec<Warning>,
79        polkavm: SolcStandardJsonInputSettingsPolkaVM,
80        llvm_arguments: Vec<String>,
81        detect_missing_libraries: bool,
82    ) -> anyhow::Result<Self> {
83        let mut paths: BTreeSet<PathBuf> = paths.iter().cloned().collect();
84        let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?;
85        for library_file in libraries.as_inner().keys() {
86            paths.insert(PathBuf::from(library_file));
87        }
88
89        #[cfg(feature = "parallel")]
90        let iter = paths.into_par_iter(); // Parallel iterator
91        #[cfg(not(feature = "parallel"))]
92        let iter = paths.into_iter(); // Sequential iterator
93
94        let sources = iter
95            .map(|path| {
96                let source = Source::try_read(path.as_path())?;
97                Ok((path.to_string_lossy().to_string(), source))
98            })
99            .collect::<anyhow::Result<BTreeMap<String, Source>>>()?;
100
101        Self::try_from_solidity_sources(
102            evm_version,
103            sources,
104            libraries,
105            remappings,
106            output_selection,
107            optimizer,
108            metadata,
109            suppressed_warnings,
110            polkavm,
111            llvm_arguments,
112            detect_missing_libraries,
113        )
114    }
115
116    /// A shortcut constructor from source code.
117    /// Only for the integration test purposes.
118    pub fn try_from_solidity_sources(
119        evm_version: Option<revive_common::EVMVersion>,
120        sources: BTreeMap<String, Source>,
121        libraries: SolcStandardJsonInputSettingsLibraries,
122        remappings: BTreeSet<String>,
123        output_selection: SolcStandardJsonInputSettingsSelection,
124        optimizer: SolcStandardJsonInputSettingsOptimizer,
125        metadata: SolcStandardJsonInputSettingsMetadata,
126        suppressed_warnings: Vec<Warning>,
127        polkavm: SolcStandardJsonInputSettingsPolkaVM,
128        llvm_arguments: Vec<String>,
129        detect_missing_libraries: bool,
130    ) -> anyhow::Result<Self> {
131        Ok(Self {
132            language: Language::Solidity,
133            sources,
134            settings: Settings::new(
135                evm_version,
136                libraries,
137                remappings,
138                output_selection,
139                optimizer,
140                metadata,
141                polkavm,
142                suppressed_warnings.clone(),
143                llvm_arguments,
144                detect_missing_libraries,
145            ),
146            suppressed_warnings,
147        })
148    }
149
150    /// A shortcut constructor from paths to Yul source files.
151    pub fn from_yul_paths(
152        paths: &[PathBuf],
153        libraries: SolcStandardJsonInputSettingsLibraries,
154        optimizer: SolcStandardJsonInputSettingsOptimizer,
155        llvm_options: Vec<String>,
156    ) -> Self {
157        let sources = paths
158            .iter()
159            .map(|path| {
160                (
161                    path.to_string_lossy().to_string(),
162                    Source::from(path.as_path()),
163                )
164            })
165            .collect();
166        Self::from_yul_sources(sources, libraries, optimizer, llvm_options)
167    }
168
169    /// A shortcut constructor from Yul source code.
170    pub fn from_yul_sources(
171        sources: BTreeMap<String, Source>,
172        libraries: SolcStandardJsonInputSettingsLibraries,
173        optimizer: SolcStandardJsonInputSettingsOptimizer,
174        llvm_arguments: Vec<String>,
175    ) -> Self {
176        let output_selection = SolcStandardJsonInputSettingsSelection::new_yul_validation();
177
178        Self {
179            language: Language::Yul,
180            sources,
181            settings: Settings::new(
182                None,
183                libraries,
184                Default::default(),
185                output_selection,
186                optimizer,
187                Default::default(),
188                Default::default(),
189                vec![],
190                llvm_arguments,
191                false,
192            ),
193            suppressed_warnings: vec![],
194        }
195    }
196
197    /// Extends the output selection with another one.
198    pub fn extend_selection(&mut self, selection: SolcStandardJsonInputSettingsSelection) {
199        self.settings.extend_selection(selection);
200    }
201
202    /// Tries to resolve all sources.
203    pub fn resolve_sources(&mut self) {
204        #[cfg(feature = "parallel")]
205        let iter = self.sources.par_iter_mut();
206        #[cfg(not(feature = "parallel"))]
207        let iter = self.sources.iter_mut();
208
209        iter.for_each(|(_path, source)| {
210            let _ = source.try_resolve();
211        });
212    }
213}