revive_solc_json_interface/standard_json/input/settings/selection/
mod.rs

1//! The `solc --standard-json` output selection.
2
3pub mod file;
4
5use std::collections::BTreeMap;
6
7use serde::Deserialize;
8use serde::Serialize;
9
10use self::file::flag::Flag;
11use self::file::File as FileSelection;
12
13/// The `solc --standard-json` per-file output selection.
14#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq)]
15pub struct PerFileSelection {
16    /// Individual file selection configuration, required for foundry.
17    #[serde(skip_serializing_if = "BTreeMap::is_empty", flatten)]
18    pub files: BTreeMap<String, FileSelection>,
19}
20
21impl PerFileSelection {
22    /// Extends the output selection with another one.
23    pub fn extend(&mut self, other: Self) {
24        for (entry, file) in other.files {
25            self.files
26                .entry(entry)
27                .and_modify(|v| {
28                    v.extend(file.clone());
29                })
30                .or_insert(file);
31        }
32    }
33
34    /// Returns flags that are going to be automatically added by the compiler,
35    /// but were not explicitly requested by the user.
36    ///
37    /// Afterwards, the flags are used to prune JSON output before returning it.
38    pub fn selection_to_prune(&self) -> Self {
39        let files = self
40            .files
41            .iter()
42            .map(|(k, v)| (k.to_owned(), v.selection_to_prune()))
43            .collect();
44        Self { files }
45    }
46
47    /// Returns whether `path` contains the `flag` or `None` if there is no selection for `path`.
48    pub fn contains(&self, path: &String, flag: &Flag) -> Option<bool> {
49        if let Some(file) = self.files.get(path) {
50            return Some(file.contains(flag));
51        };
52        None
53    }
54
55    /// Returns whether this is the empty per file selection.
56    pub fn is_empty(&self) -> bool {
57        self.files.is_empty()
58    }
59}
60
61/// The `solc --standard-json` output selection.
62#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq)]
63pub struct Selection {
64    /// Only the 'all' wildcard is available for robustness reasons.
65    #[serde(default, rename = "*", skip_serializing_if = "FileSelection::is_empty")]
66    /// Individual file selection configuration, required for foundry.
67    pub all: FileSelection,
68    #[serde(skip_serializing_if = "PerFileSelection::is_empty", flatten)]
69    files: PerFileSelection,
70}
71
72impl Selection {
73    /// Creates the selection with arbitrary flags.
74    pub fn new(flags: Vec<Flag>) -> Self {
75        Self {
76            all: FileSelection::new(flags),
77            files: Default::default(),
78        }
79    }
80
81    /// Creates the selection required by our compilation process.
82    pub fn new_required() -> Self {
83        Self::new(vec![
84            Flag::AST,
85            Flag::MethodIdentifiers,
86            Flag::Metadata,
87            Flag::Yul,
88        ])
89    }
90
91    /// Creates the selection required for test compilation (includes EVM bytecode).
92    pub fn new_required_for_tests() -> Self {
93        Self {
94            all: FileSelection::new_required_for_tests(),
95            files: Default::default(),
96        }
97    }
98
99    /// Creates the selection required by Yul validation process.
100    pub fn new_yul_validation() -> Self {
101        Self::new(vec![Flag::EVM])
102    }
103
104    /// Extends the output selection with another one.
105    pub fn extend(&mut self, other: Self) -> &mut Self {
106        self.all.extend(other.all);
107        self.files.extend(other.files);
108        self
109    }
110
111    /// Returns flags that are going to be automatically added by the compiler,
112    /// but were not explicitly requested by the user.
113    ///
114    /// Afterwards, the flags are used to prune JSON output before returning it.
115    pub fn selection_to_prune(&self) -> Self {
116        Self {
117            all: self.all.selection_to_prune(),
118            files: self.files.selection_to_prune(),
119        }
120    }
121
122    /// Whether the flag is requested.
123    pub fn contains(&self, path: &String, flag: &Flag) -> bool {
124        self.files
125            .contains(path, flag)
126            .unwrap_or(self.all.contains(flag))
127    }
128}