foundry_compilers_artifacts_solc/ast/
lowfidelity.rs1use crate::serde_helpers;
4use serde::{de::DeserializeOwned, Deserialize, Serialize};
5use std::{collections::BTreeMap, fmt, fmt::Write, str::FromStr};
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Ast {
10 #[serde(rename = "absolutePath")]
11 pub absolute_path: String,
12 pub id: usize,
13 #[serde(default, rename = "exportedSymbols")]
14 pub exported_symbols: BTreeMap<String, Vec<usize>>,
15 #[serde(rename = "nodeType")]
16 pub node_type: NodeType,
17 #[serde(with = "serde_helpers::display_from_str")]
18 pub src: SourceLocation,
19 #[serde(default)]
20 pub nodes: Vec<Node>,
21
22 #[serde(flatten)]
24 pub other: BTreeMap<String, serde_json::Value>,
25}
26
27#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
28pub struct Node {
29 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub id: Option<usize>,
32
33 #[serde(rename = "nodeType")]
35 pub node_type: NodeType,
36
37 #[serde(with = "serde_helpers::display_from_str")]
39 pub src: SourceLocation,
40
41 #[serde(default)]
43 pub nodes: Vec<Node>,
44
45 #[serde(default, skip_serializing_if = "Option::is_none")]
47 pub body: Option<Box<Node>>,
48
49 #[serde(flatten)]
51 pub other: BTreeMap<String, serde_json::Value>,
52}
53
54impl Node {
55 pub fn attribute<D: DeserializeOwned>(&self, key: &str) -> Option<D> {
57 self.other.get(key).and_then(|v| serde_json::from_value(v.clone()).ok())
59 }
60}
61
62#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
66pub struct SourceLocation {
67 pub start: usize,
68 pub length: Option<usize>,
69 pub index: Option<usize>,
70}
71
72impl FromStr for SourceLocation {
73 type Err = String;
74
75 fn from_str(s: &str) -> Result<Self, Self::Err> {
76 let invalid_location = move || format!("{s} invalid source location");
77
78 let mut split = s.split(':');
79 let start = split
80 .next()
81 .ok_or_else(invalid_location)?
82 .parse::<usize>()
83 .map_err(|_| invalid_location())?;
84 let length = split
85 .next()
86 .ok_or_else(invalid_location)?
87 .parse::<isize>()
88 .map_err(|_| invalid_location())?;
89 let index = split
90 .next()
91 .ok_or_else(invalid_location)?
92 .parse::<isize>()
93 .map_err(|_| invalid_location())?;
94
95 let length = if length < 0 { None } else { Some(length as usize) };
96 let index = if index < 0 { None } else { Some(index as usize) };
97
98 Ok(Self { start, length, index })
99 }
100}
101
102impl fmt::Display for SourceLocation {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 self.start.fmt(f)?;
105 f.write_char(':')?;
106 if let Some(length) = self.length {
107 length.fmt(f)?;
108 } else {
109 f.write_str("-1")?;
110 }
111 f.write_char(':')?;
112 if let Some(index) = self.index {
113 index.fmt(f)?;
114 } else {
115 f.write_str("-1")?;
116 }
117 Ok(())
118 }
119}
120
121#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
122pub enum NodeType {
123 Assignment,
125 BinaryOperation,
126 Conditional,
127 ElementaryTypeNameExpression,
128 FunctionCall,
129 FunctionCallOptions,
130 Identifier,
131 IndexAccess,
132 IndexRangeAccess,
133 Literal,
134 MemberAccess,
135 NewExpression,
136 TupleExpression,
137 UnaryOperation,
138
139 Block,
141 Break,
142 Continue,
143 DoWhileStatement,
144 EmitStatement,
145 ExpressionStatement,
146 ForStatement,
147 IfStatement,
148 InlineAssembly,
149 PlaceholderStatement,
150 Return,
151 RevertStatement,
152 TryStatement,
153 UncheckedBlock,
154 VariableDeclarationStatement,
155 VariableDeclaration,
156 WhileStatement,
157
158 YulAssignment,
160 YulBlock,
161 YulBreak,
162 YulCase,
163 YulContinue,
164 YulExpressionStatement,
165 YulLeave,
166 YulForLoop,
167 YulFunctionDefinition,
168 YulIf,
169 YulSwitch,
170 YulVariableDeclaration,
171
172 YulFunctionCall,
174 YulIdentifier,
175 YulLiteral,
176
177 YulLiteralValue,
179 YulHexValue,
180 YulTypedName,
181
182 ContractDefinition,
184 FunctionDefinition,
185 EventDefinition,
186 ErrorDefinition,
187 ModifierDefinition,
188 StructDefinition,
189 EnumDefinition,
190 UserDefinedValueTypeDefinition,
191
192 PragmaDirective,
194 ImportDirective,
195 UsingForDirective,
196
197 SourceUnit,
199 InheritanceSpecifier,
200 ElementaryTypeName,
201 FunctionTypeName,
202 ParameterList,
203 TryCatchClause,
204 ModifierInvocation,
205 UserDefinedTypeName,
206 ArrayTypeName,
207 Mapping,
208
209 Other(String),
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn can_parse_ast() {
219 let ast = include_str!("../../../../../test-data/ast/ast-erc4626.json");
220 let _ast: Ast = serde_json::from_str(ast).unwrap();
221 }
222}