Skip to main content

solidity_language_server/solc_ast/
expressions.rs

1//! Expression AST node types.
2//!
3//! Corresponds to the expression hierarchy rooted at `Expression` in the
4//! official solc AST (`AST.h`).
5
6use serde::{Deserialize, Serialize};
7
8use super::{FunctionCallKind, LiteralKind, NodeID, TypeDescriptions, TypeName};
9
10/// The union of all expression node types.
11///
12/// Discriminated by `nodeType` in the JSON.
13#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
14#[serde(tag = "nodeType")]
15pub enum Expression {
16    Assignment(Assignment),
17    BinaryOperation(BinaryOperation),
18    Conditional(Conditional),
19    ElementaryTypeNameExpression(ElementaryTypeNameExpression),
20    FunctionCall(FunctionCall),
21    FunctionCallOptions(FunctionCallOptions),
22    Identifier(Identifier),
23    IndexAccess(IndexAccess),
24    IndexRangeAccess(IndexRangeAccess),
25    Literal(Literal),
26    MemberAccess(MemberAccess),
27    NewExpression(NewExpression),
28    TupleExpression(TupleExpression),
29    UnaryOperation(UnaryOperation),
30}
31
32// ── Individual expression types ────────────────────────────────────────────
33
34/// An assignment expression (`a = b`, `a += b`, etc.).
35#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
36#[serde(rename_all = "camelCase")]
37pub struct Assignment {
38    pub id: NodeID,
39    pub src: String,
40    pub operator: String,
41    pub left_hand_side: Box<Expression>,
42    pub right_hand_side: Box<Expression>,
43    #[serde(default)]
44    pub type_descriptions: TypeDescriptions,
45    #[serde(default)]
46    pub is_constant: Option<bool>,
47    #[serde(default)]
48    pub is_l_value: Option<bool>,
49    #[serde(default)]
50    pub is_pure: Option<bool>,
51    #[serde(default)]
52    pub l_value_requested: Option<bool>,
53}
54
55/// A binary operation (`a + b`, `a == b`, etc.).
56#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
57#[serde(rename_all = "camelCase")]
58pub struct BinaryOperation {
59    pub id: NodeID,
60    pub src: String,
61    pub operator: String,
62    pub left_expression: Box<Expression>,
63    pub right_expression: Box<Expression>,
64    #[serde(default)]
65    pub common_type: Option<TypeDescriptions>,
66    /// Reference to user-defined operator function, if any.
67    #[serde(default)]
68    pub function: Option<NodeID>,
69    #[serde(default)]
70    pub type_descriptions: TypeDescriptions,
71    #[serde(default)]
72    pub is_constant: Option<bool>,
73    #[serde(default)]
74    pub is_l_value: Option<bool>,
75    #[serde(default)]
76    pub is_pure: Option<bool>,
77    #[serde(default)]
78    pub l_value_requested: Option<bool>,
79}
80
81/// A ternary conditional (`cond ? a : b`).
82#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
83#[serde(rename_all = "camelCase")]
84pub struct Conditional {
85    pub id: NodeID,
86    pub src: String,
87    pub condition: Box<Expression>,
88    pub true_expression: Box<Expression>,
89    pub false_expression: Box<Expression>,
90    #[serde(default)]
91    pub type_descriptions: TypeDescriptions,
92    #[serde(default)]
93    pub is_constant: Option<bool>,
94    #[serde(default)]
95    pub is_l_value: Option<bool>,
96    #[serde(default)]
97    pub is_pure: Option<bool>,
98    #[serde(default)]
99    pub l_value_requested: Option<bool>,
100}
101
102/// An `ElementaryTypeNameExpression` — using a type as a value (e.g. `uint256` in a cast).
103#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
104#[serde(rename_all = "camelCase")]
105pub struct ElementaryTypeNameExpression {
106    pub id: NodeID,
107    pub src: String,
108    /// The type name node. In the JSON this can be either a string or an
109    /// `ElementaryTypeName` object depending on solc version.
110    pub type_name: serde_json::Value,
111    #[serde(default)]
112    pub type_descriptions: TypeDescriptions,
113    #[serde(default)]
114    pub argument_types: Option<serde_json::Value>,
115    #[serde(default)]
116    pub is_constant: Option<bool>,
117    #[serde(default)]
118    pub is_l_value: Option<bool>,
119    #[serde(default)]
120    pub is_pure: Option<bool>,
121    #[serde(default)]
122    pub l_value_requested: Option<bool>,
123}
124
125/// A function call expression.
126#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
127#[serde(rename_all = "camelCase")]
128pub struct FunctionCall {
129    pub id: NodeID,
130    pub src: String,
131    pub expression: Box<Expression>,
132    #[serde(default)]
133    pub arguments: Vec<Expression>,
134    #[serde(default)]
135    pub names: Vec<String>,
136    #[serde(default)]
137    pub name_locations: Vec<String>,
138    #[serde(default)]
139    pub kind: Option<FunctionCallKind>,
140    #[serde(default)]
141    pub try_call: Option<bool>,
142    #[serde(default)]
143    pub type_descriptions: TypeDescriptions,
144    #[serde(default)]
145    pub is_constant: Option<bool>,
146    #[serde(default)]
147    pub is_l_value: Option<bool>,
148    #[serde(default)]
149    pub is_pure: Option<bool>,
150    #[serde(default)]
151    pub l_value_requested: Option<bool>,
152}
153
154/// Function call options (`addr.call{value: 1}(data)`).
155#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
156#[serde(rename_all = "camelCase")]
157pub struct FunctionCallOptions {
158    pub id: NodeID,
159    pub src: String,
160    pub expression: Box<Expression>,
161    #[serde(default)]
162    pub names: Vec<String>,
163    #[serde(default)]
164    pub options: Vec<Expression>,
165    #[serde(default)]
166    pub type_descriptions: TypeDescriptions,
167    #[serde(default)]
168    pub is_constant: Option<bool>,
169    #[serde(default)]
170    pub is_l_value: Option<bool>,
171    #[serde(default)]
172    pub is_pure: Option<bool>,
173    #[serde(default)]
174    pub l_value_requested: Option<bool>,
175}
176
177/// An identifier reference.
178#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
179#[serde(rename_all = "camelCase")]
180pub struct Identifier {
181    pub id: NodeID,
182    pub src: String,
183    pub name: String,
184    pub referenced_declaration: Option<NodeID>,
185    #[serde(default)]
186    pub overloaded_declarations: Vec<NodeID>,
187    #[serde(default)]
188    pub type_descriptions: TypeDescriptions,
189    #[serde(default)]
190    pub argument_types: Option<serde_json::Value>,
191}
192
193/// An index access (`arr[i]`).
194#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
195#[serde(rename_all = "camelCase")]
196pub struct IndexAccess {
197    pub id: NodeID,
198    pub src: String,
199    pub base_expression: Box<Expression>,
200    pub index_expression: Option<Box<Expression>>,
201    #[serde(default)]
202    pub type_descriptions: TypeDescriptions,
203    #[serde(default)]
204    pub is_constant: Option<bool>,
205    #[serde(default)]
206    pub is_l_value: Option<bool>,
207    #[serde(default)]
208    pub is_pure: Option<bool>,
209    #[serde(default)]
210    pub l_value_requested: Option<bool>,
211}
212
213/// An index range access (`arr[start:end]`).
214#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
215#[serde(rename_all = "camelCase")]
216pub struct IndexRangeAccess {
217    pub id: NodeID,
218    pub src: String,
219    pub base_expression: Box<Expression>,
220    pub start_expression: Option<Box<Expression>>,
221    pub end_expression: Option<Box<Expression>>,
222    #[serde(default)]
223    pub type_descriptions: TypeDescriptions,
224    #[serde(default)]
225    pub is_constant: Option<bool>,
226    #[serde(default)]
227    pub is_l_value: Option<bool>,
228    #[serde(default)]
229    pub is_pure: Option<bool>,
230    #[serde(default)]
231    pub l_value_requested: Option<bool>,
232}
233
234/// A literal value (`42`, `"hello"`, `true`, `hex"dead"`, etc.).
235#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
236#[serde(rename_all = "camelCase")]
237pub struct Literal {
238    pub id: NodeID,
239    pub src: String,
240    pub kind: LiteralKind,
241    #[serde(default)]
242    pub value: Option<String>,
243    #[serde(default)]
244    pub hex_value: Option<String>,
245    #[serde(default)]
246    pub subdenomination: Option<String>,
247    #[serde(default)]
248    pub type_descriptions: TypeDescriptions,
249    #[serde(default)]
250    pub is_constant: Option<bool>,
251    #[serde(default)]
252    pub is_l_value: Option<bool>,
253    #[serde(default)]
254    pub is_pure: Option<bool>,
255    #[serde(default)]
256    pub l_value_requested: Option<bool>,
257}
258
259/// A member access (`expr.member`).
260#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
261#[serde(rename_all = "camelCase")]
262pub struct MemberAccess {
263    pub id: NodeID,
264    pub src: String,
265    pub member_name: String,
266    #[serde(default)]
267    pub member_location: Option<String>,
268    pub expression: Box<Expression>,
269    pub referenced_declaration: Option<NodeID>,
270    #[serde(default)]
271    pub type_descriptions: TypeDescriptions,
272    #[serde(default)]
273    pub argument_types: Option<serde_json::Value>,
274    #[serde(default)]
275    pub is_constant: Option<bool>,
276    #[serde(default)]
277    pub is_l_value: Option<bool>,
278    #[serde(default)]
279    pub is_pure: Option<bool>,
280    #[serde(default)]
281    pub l_value_requested: Option<bool>,
282}
283
284/// A `new` expression (`new MyContract()`).
285#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
286#[serde(rename_all = "camelCase")]
287pub struct NewExpression {
288    pub id: NodeID,
289    pub src: String,
290    pub type_name: Box<TypeName>,
291    #[serde(default)]
292    pub type_descriptions: TypeDescriptions,
293    #[serde(default)]
294    pub is_constant: Option<bool>,
295    #[serde(default)]
296    pub is_l_value: Option<bool>,
297    #[serde(default)]
298    pub is_pure: Option<bool>,
299    #[serde(default)]
300    pub l_value_requested: Option<bool>,
301}
302
303/// A tuple expression or inline array (`(a, b)` or `[a, b]`).
304#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
305#[serde(rename_all = "camelCase")]
306pub struct TupleExpression {
307    pub id: NodeID,
308    pub src: String,
309    /// Components may be `null` for omitted elements in destructuring.
310    #[serde(default)]
311    pub components: Vec<Option<Expression>>,
312    #[serde(default)]
313    pub is_inline_array: Option<bool>,
314    #[serde(default)]
315    pub type_descriptions: TypeDescriptions,
316    #[serde(default)]
317    pub is_constant: Option<bool>,
318    #[serde(default)]
319    pub is_l_value: Option<bool>,
320    #[serde(default)]
321    pub is_pure: Option<bool>,
322    #[serde(default)]
323    pub l_value_requested: Option<bool>,
324}
325
326/// A unary operation (`!a`, `++a`, `delete x`, etc.).
327#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
328#[serde(rename_all = "camelCase")]
329pub struct UnaryOperation {
330    pub id: NodeID,
331    pub src: String,
332    pub operator: String,
333    pub prefix: bool,
334    pub sub_expression: Box<Expression>,
335    /// Reference to user-defined operator function, if any.
336    #[serde(default)]
337    pub function: Option<NodeID>,
338    #[serde(default)]
339    pub type_descriptions: TypeDescriptions,
340    #[serde(default)]
341    pub is_constant: Option<bool>,
342    #[serde(default)]
343    pub is_l_value: Option<bool>,
344    #[serde(default)]
345    pub is_pure: Option<bool>,
346    #[serde(default)]
347    pub l_value_requested: Option<bool>,
348}