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    /// Removes unneeded selections.
61    pub fn retain(&mut self) {
62        for file in self.files.values_mut() {
63            file.per_contract.retain(Flag::is_required_for_codegen);
64            file.per_file.retain(Flag::is_required_for_codegen);
65        }
66    }
67}
68
69/// The `solc --standard-json` output selection.
70#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq)]
71pub struct Selection {
72    /// Only the 'all' wildcard is available for robustness reasons.
73    #[serde(default, rename = "*", skip_serializing_if = "FileSelection::is_empty")]
74    /// Individual file selection configuration, required for foundry.
75    pub all: FileSelection,
76    #[serde(skip_serializing_if = "PerFileSelection::is_empty", flatten)]
77    files: PerFileSelection,
78}
79
80impl Selection {
81    /// Creates the selection with arbitrary flags.
82    pub fn new(flags: Vec<Flag>) -> Self {
83        Self {
84            all: FileSelection::new(flags),
85            files: Default::default(),
86        }
87    }
88
89    /// Creates the selection required by our compilation process.
90    pub fn new_required() -> Self {
91        Self::new(vec![
92            Flag::AST,
93            Flag::MethodIdentifiers,
94            Flag::Metadata,
95            Flag::Yul,
96        ])
97    }
98
99    /// Creates the selection required for test compilation (includes EVM bytecode).
100    pub fn new_required_for_tests() -> Self {
101        Self {
102            all: FileSelection::new_required_for_tests(),
103            files: Default::default(),
104        }
105    }
106
107    /// Creates the selection required by Yul validation process.
108    pub fn new_yul_validation() -> Self {
109        Self::new(vec![Flag::EVM])
110    }
111
112    /// Extends the output selection with another one.
113    pub fn extend(&mut self, other: Self) -> &mut Self {
114        self.all.extend(other.all);
115        self.files.extend(other.files);
116        self
117    }
118
119    /// Returns flags that are going to be automatically added by the compiler,
120    /// but were not explicitly requested by the user.
121    ///
122    /// Afterwards, the flags are used to prune JSON output before returning it.
123    pub fn selection_to_prune(&self) -> Self {
124        Self {
125            all: self.all.selection_to_prune(),
126            files: self.files.selection_to_prune(),
127        }
128    }
129
130    /// Whether the flag is requested.
131    pub fn contains(&self, path: &String, flag: &Flag) -> bool {
132        self.files
133            .contains(path, flag)
134            .unwrap_or(self.all.contains(flag))
135    }
136
137    /// Removes unneeded selections.
138    pub fn retain(&mut self) {
139        self.all.per_file.retain(Flag::is_required_for_codegen);
140        self.all.per_contract.retain(Flag::is_required_for_codegen);
141        self.files.retain();
142    }
143}