foundry_compilers_artifacts_solc/ast/
visitor.rs

1use super::*;
2
3pub trait Visitor {
4    fn visit_source_unit(&mut self, _source_unit: &SourceUnit) {}
5    fn visit_import_directive(&mut self, _directive: &ImportDirective) {}
6    fn visit_pragma_directive(&mut self, _directive: &PragmaDirective) {}
7    fn visit_block(&mut self, _block: &Block) {}
8    fn visit_statement(&mut self, _statement: &Statement) {}
9    fn visit_expression(&mut self, _expression: &Expression) {}
10    fn visit_function_call(&mut self, _function_call: &FunctionCall) {}
11    fn visit_user_defined_type_name(&mut self, _type_name: &UserDefinedTypeName) {}
12    fn visit_identifier_path(&mut self, _identifier_path: &IdentifierPath) {}
13    fn visit_type_name(&mut self, _type_name: &TypeName) {}
14    fn visit_parameter_list(&mut self, _parameter_list: &ParameterList) {}
15    fn visit_function_definition(&mut self, _definition: &FunctionDefinition) {}
16    fn visit_enum_definition(&mut self, _definition: &EnumDefinition) {}
17    fn visit_error_definition(&mut self, _definition: &ErrorDefinition) {}
18    fn visit_event_definition(&mut self, _definition: &EventDefinition) {}
19    fn visit_struct_definition(&mut self, _definition: &StructDefinition) {}
20    fn visit_modifier_definition(&mut self, _definition: &ModifierDefinition) {}
21    fn visit_variable_declaration(&mut self, _declaration: &VariableDeclaration) {}
22    fn visit_overrides(&mut self, _specifier: &OverrideSpecifier) {}
23    fn visit_user_defined_value_type(&mut self, _value_type: &UserDefinedValueTypeDefinition) {}
24    fn visit_contract_definition(&mut self, _definition: &ContractDefinition) {}
25    fn visit_using_for(&mut self, _directive: &UsingForDirective) {}
26    fn visit_unary_operation(&mut self, _unary_op: &UnaryOperation) {}
27    fn visit_binary_operation(&mut self, _binary_op: &BinaryOperation) {}
28    fn visit_conditional(&mut self, _conditional: &Conditional) {}
29    fn visit_tuple_expression(&mut self, _tuple_expression: &TupleExpression) {}
30    fn visit_new_expression(&mut self, _new_expression: &NewExpression) {}
31    fn visit_assignment(&mut self, _assignment: &Assignment) {}
32    fn visit_identifier(&mut self, _identifier: &Identifier) {}
33    fn visit_index_access(&mut self, _index_access: &IndexAccess) {}
34    fn visit_index_range_access(&mut self, _index_range_access: &IndexRangeAccess) {}
35    fn visit_while_statement(&mut self, _while_statement: &WhileStatement) {}
36    fn visit_for_statement(&mut self, _for_statement: &ForStatement) {}
37    fn visit_if_statement(&mut self, _if_statement: &IfStatement) {}
38    fn visit_do_while_statement(&mut self, _do_while_statement: &DoWhileStatement) {}
39    fn visit_emit_statement(&mut self, _emit_statement: &EmitStatement) {}
40    fn visit_unchecked_block(&mut self, _unchecked_block: &UncheckedBlock) {}
41    fn visit_try_statement(&mut self, _try_statement: &TryStatement) {}
42    fn visit_revert_statement(&mut self, _revert_statement: &RevertStatement) {}
43    fn visit_member_access(&mut self, _member_access: &MemberAccess) {}
44    fn visit_mapping(&mut self, _mapping: &Mapping) {}
45    fn visit_elementary_type_name(&mut self, _elementary_type_name: &ElementaryTypeName) {}
46    fn visit_literal(&mut self, _literal: &Literal) {}
47    fn visit_function_type_name(&mut self, _function_type_name: &FunctionTypeName) {}
48    fn visit_array_type_name(&mut self, _array_type_name: &ArrayTypeName) {}
49    fn visit_function_call_options(&mut self, _function_call: &FunctionCallOptions) {}
50    fn visit_return(&mut self, _return: &Return) {}
51    fn visit_inheritance_specifier(&mut self, _specifier: &InheritanceSpecifier) {}
52    fn visit_modifier_invocation(&mut self, _invocation: &ModifierInvocation) {}
53    fn visit_inline_assembly(&mut self, _assembly: &InlineAssembly) {}
54    fn visit_external_assembly_reference(&mut self, _ref: &ExternalInlineAssemblyReference) {}
55}
56
57pub trait Walk {
58    fn walk(&self, visitor: &mut dyn Visitor);
59}
60
61macro_rules! impl_walk {
62    // Implement `Walk` for a type, calling the given function.
63    ($ty:ty, | $val:ident, $visitor:ident | $e:expr) => {
64        impl Walk for $ty {
65            fn walk(&self, visitor: &mut dyn Visitor) {
66                let $val = self;
67                let $visitor = visitor;
68                $e
69            }
70        }
71    };
72    ($ty:ty, $func:ident) => {
73        impl_walk!($ty, |obj, visitor| {
74            visitor.$func(obj);
75        });
76    };
77    ($ty:ty, $func:ident, | $val:ident, $visitor:ident | $e:expr) => {
78        impl_walk!($ty, |$val, $visitor| {
79            $visitor.$func($val);
80            $e
81        });
82    };
83}
84
85impl_walk!(SourceUnit, visit_source_unit, |source_unit, visitor| {
86    source_unit.nodes.iter().for_each(|part| {
87        part.walk(visitor);
88    });
89});
90
91impl_walk!(SourceUnitPart, |part, visitor| {
92    match part {
93        SourceUnitPart::ContractDefinition(contract) => {
94            contract.walk(visitor);
95        }
96        SourceUnitPart::UsingForDirective(directive) => {
97            directive.walk(visitor);
98        }
99        SourceUnitPart::ErrorDefinition(error) => {
100            error.walk(visitor);
101        }
102        SourceUnitPart::EventDefinition(event) => {
103            event.walk(visitor);
104        }
105        SourceUnitPart::StructDefinition(struct_) => {
106            struct_.walk(visitor);
107        }
108        SourceUnitPart::VariableDeclaration(declaration) => {
109            declaration.walk(visitor);
110        }
111        SourceUnitPart::FunctionDefinition(function) => {
112            function.walk(visitor);
113        }
114        SourceUnitPart::UserDefinedValueTypeDefinition(value_type) => {
115            value_type.walk(visitor);
116        }
117        SourceUnitPart::ImportDirective(directive) => {
118            directive.walk(visitor);
119        }
120        SourceUnitPart::EnumDefinition(enum_) => {
121            enum_.walk(visitor);
122        }
123        SourceUnitPart::PragmaDirective(directive) => {
124            directive.walk(visitor);
125        }
126    }
127});
128
129impl_walk!(ContractDefinition, visit_contract_definition, |contract, visitor| {
130    contract.base_contracts.iter().for_each(|base_contract| {
131        base_contract.walk(visitor);
132    });
133
134    for part in &contract.nodes {
135        match part {
136            ContractDefinitionPart::FunctionDefinition(function) => {
137                function.walk(visitor);
138            }
139            ContractDefinitionPart::ErrorDefinition(error) => {
140                error.walk(visitor);
141            }
142            ContractDefinitionPart::EventDefinition(event) => {
143                event.walk(visitor);
144            }
145            ContractDefinitionPart::StructDefinition(struct_) => {
146                struct_.walk(visitor);
147            }
148            ContractDefinitionPart::VariableDeclaration(declaration) => {
149                declaration.walk(visitor);
150            }
151            ContractDefinitionPart::ModifierDefinition(modifier) => {
152                modifier.walk(visitor);
153            }
154            ContractDefinitionPart::UserDefinedValueTypeDefinition(definition) => {
155                definition.walk(visitor);
156            }
157            ContractDefinitionPart::UsingForDirective(directive) => {
158                directive.walk(visitor);
159            }
160            ContractDefinitionPart::EnumDefinition(enum_) => {
161                enum_.walk(visitor);
162            }
163        }
164    }
165});
166
167impl_walk!(Expression, visit_expression, |expr, visitor| {
168    match expr {
169        Expression::FunctionCall(expression) => {
170            expression.walk(visitor);
171        }
172        Expression::MemberAccess(member_access) => {
173            member_access.walk(visitor);
174        }
175        Expression::IndexAccess(index_access) => {
176            index_access.walk(visitor);
177        }
178        Expression::UnaryOperation(unary_op) => {
179            unary_op.walk(visitor);
180        }
181        Expression::BinaryOperation(expression) => {
182            expression.walk(visitor);
183        }
184        Expression::Conditional(expression) => {
185            expression.walk(visitor);
186        }
187        Expression::TupleExpression(tuple) => {
188            tuple.walk(visitor);
189        }
190        Expression::NewExpression(expression) => {
191            expression.walk(visitor);
192        }
193        Expression::Assignment(expression) => {
194            expression.walk(visitor);
195        }
196        Expression::Identifier(identifier) => {
197            identifier.walk(visitor);
198        }
199        Expression::FunctionCallOptions(function_call) => {
200            function_call.walk(visitor);
201        }
202        Expression::IndexRangeAccess(range_access) => {
203            range_access.walk(visitor);
204        }
205        Expression::Literal(literal) => {
206            literal.walk(visitor);
207        }
208        Expression::ElementaryTypeNameExpression(type_name) => {
209            type_name.walk(visitor);
210        }
211    }
212});
213
214impl_walk!(Statement, visit_statement, |statement, visitor| {
215    match statement {
216        Statement::Block(block) => {
217            block.walk(visitor);
218        }
219        Statement::WhileStatement(statement) => {
220            statement.walk(visitor);
221        }
222        Statement::ForStatement(statement) => {
223            statement.walk(visitor);
224        }
225        Statement::IfStatement(statement) => {
226            statement.walk(visitor);
227        }
228        Statement::DoWhileStatement(statement) => {
229            statement.walk(visitor);
230        }
231        Statement::EmitStatement(statement) => {
232            statement.walk(visitor);
233        }
234        Statement::VariableDeclarationStatement(statement) => {
235            statement.walk(visitor);
236        }
237        Statement::ExpressionStatement(statement) => {
238            statement.walk(visitor);
239        }
240        Statement::UncheckedBlock(statement) => {
241            statement.walk(visitor);
242        }
243        Statement::TryStatement(statement) => {
244            statement.walk(visitor);
245        }
246        Statement::RevertStatement(statement) => {
247            statement.walk(visitor);
248        }
249        Statement::Return(statement) => {
250            statement.walk(visitor);
251        }
252        Statement::InlineAssembly(assembly) => {
253            assembly.walk(visitor);
254        }
255        Statement::Break(_) | Statement::Continue(_) | Statement::PlaceholderStatement(_) => {}
256    }
257});
258
259impl_walk!(FunctionDefinition, visit_function_definition, |function, visitor| {
260    function.parameters.walk(visitor);
261    function.return_parameters.walk(visitor);
262
263    if let Some(overrides) = &function.overrides {
264        overrides.walk(visitor);
265    }
266
267    if let Some(body) = &function.body {
268        body.walk(visitor);
269    }
270
271    function.modifiers.iter().for_each(|m| m.walk(visitor));
272});
273
274impl_walk!(ErrorDefinition, visit_error_definition, |error, visitor| {
275    error.parameters.walk(visitor);
276});
277
278impl_walk!(EventDefinition, visit_event_definition, |event, visitor| {
279    event.parameters.walk(visitor);
280});
281
282impl_walk!(StructDefinition, visit_struct_definition, |struct_, visitor| {
283    struct_.members.iter().for_each(|member| member.walk(visitor));
284});
285
286impl_walk!(ModifierDefinition, visit_modifier_definition, |modifier, visitor| {
287    if let Some(body) = &modifier.body {
288        body.walk(visitor);
289    }
290    if let Some(override_) = &modifier.overrides {
291        override_.walk(visitor);
292    }
293    modifier.parameters.walk(visitor);
294});
295
296impl_walk!(VariableDeclaration, visit_variable_declaration, |declaration, visitor| {
297    if let Some(value) = &declaration.value {
298        value.walk(visitor);
299    }
300
301    if let Some(type_name) = &declaration.type_name {
302        type_name.walk(visitor);
303    }
304});
305
306impl_walk!(OverrideSpecifier, visit_overrides, |override_, visitor| {
307    override_.overrides.iter().for_each(|type_name| {
308        type_name.walk(visitor);
309    });
310});
311
312impl_walk!(UserDefinedValueTypeDefinition, visit_user_defined_value_type, |value_type, visitor| {
313    value_type.underlying_type.walk(visitor);
314});
315
316impl_walk!(FunctionCallOptions, visit_function_call_options, |function_call, visitor| {
317    function_call.expression.walk(visitor);
318    function_call.options.iter().for_each(|option| {
319        option.walk(visitor);
320    });
321});
322
323impl_walk!(Return, visit_return, |return_, visitor| {
324    if let Some(expr) = return_.expression.as_ref() {
325        expr.walk(visitor);
326    }
327});
328
329impl_walk!(UsingForDirective, visit_using_for, |directive, visitor| {
330    if let Some(type_name) = &directive.type_name {
331        type_name.walk(visitor);
332    }
333    if let Some(library_name) = &directive.library_name {
334        library_name.walk(visitor);
335    }
336    for function in &directive.function_list {
337        function.walk(visitor);
338    }
339});
340
341impl_walk!(UnaryOperation, visit_unary_operation, |unary_op, visitor| {
342    unary_op.sub_expression.walk(visitor);
343});
344
345impl_walk!(BinaryOperation, visit_binary_operation, |binary_op, visitor| {
346    binary_op.lhs.walk(visitor);
347    binary_op.rhs.walk(visitor);
348});
349
350impl_walk!(Conditional, visit_conditional, |conditional, visitor| {
351    conditional.condition.walk(visitor);
352    conditional.true_expression.walk(visitor);
353    conditional.false_expression.walk(visitor);
354});
355
356impl_walk!(TupleExpression, visit_tuple_expression, |tuple_expression, visitor| {
357    tuple_expression.components.iter().filter_map(|component| component.as_ref()).for_each(
358        |component| {
359            component.walk(visitor);
360        },
361    );
362});
363
364impl_walk!(NewExpression, visit_new_expression, |new_expression, visitor| {
365    new_expression.type_name.walk(visitor);
366});
367
368impl_walk!(Assignment, visit_assignment, |assignment, visitor| {
369    assignment.lhs.walk(visitor);
370    assignment.rhs.walk(visitor);
371});
372impl_walk!(IfStatement, visit_if_statement, |if_statement, visitor| {
373    if_statement.condition.walk(visitor);
374    if_statement.true_body.walk(visitor);
375
376    if let Some(false_body) = &if_statement.false_body {
377        false_body.walk(visitor);
378    }
379});
380
381impl_walk!(IndexAccess, visit_index_access, |index_access, visitor| {
382    index_access.base_expression.walk(visitor);
383    if let Some(index_expression) = &index_access.index_expression {
384        index_expression.walk(visitor);
385    }
386});
387
388impl_walk!(IndexRangeAccess, visit_index_range_access, |index_range_access, visitor| {
389    index_range_access.base_expression.walk(visitor);
390    if let Some(start_expression) = &index_range_access.start_expression {
391        start_expression.walk(visitor);
392    }
393    if let Some(end_expression) = &index_range_access.end_expression {
394        end_expression.walk(visitor);
395    }
396});
397
398impl_walk!(WhileStatement, visit_while_statement, |while_statement, visitor| {
399    while_statement.condition.walk(visitor);
400    while_statement.body.walk(visitor);
401});
402
403impl_walk!(ForStatement, visit_for_statement, |for_statement, visitor| {
404    for_statement.body.walk(visitor);
405    if let Some(condition) = &for_statement.condition {
406        condition.walk(visitor);
407    }
408
409    if let Some(loop_expression) = &for_statement.loop_expression {
410        loop_expression.walk(visitor);
411    }
412
413    if let Some(initialization_expr) = &for_statement.initialization_expression {
414        initialization_expr.walk(visitor);
415    }
416});
417
418impl_walk!(DoWhileStatement, visit_do_while_statement, |do_while_statement, visitor| {
419    do_while_statement.body.walk(visitor);
420    do_while_statement.condition.walk(visitor);
421});
422
423impl_walk!(EmitStatement, visit_emit_statement, |emit_statement, visitor| {
424    emit_statement.event_call.walk(visitor);
425});
426
427impl_walk!(VariableDeclarationStatement, |stmt, visitor| {
428    stmt.declarations.iter().filter_map(|d| d.as_ref()).for_each(|declaration| {
429        declaration.walk(visitor);
430    });
431    if let Some(initial_value) = &stmt.initial_value {
432        initial_value.walk(visitor);
433    }
434});
435
436impl_walk!(UncheckedBlock, visit_unchecked_block, |unchecked_block, visitor| {
437    unchecked_block.statements.iter().for_each(|statement| {
438        statement.walk(visitor);
439    });
440});
441
442impl_walk!(TryStatement, visit_try_statement, |try_statement, visitor| {
443    try_statement.clauses.iter().for_each(|clause| {
444        clause.block.walk(visitor);
445
446        if let Some(parameter_list) = &clause.parameters {
447            parameter_list.walk(visitor);
448        }
449    });
450
451    try_statement.external_call.walk(visitor);
452});
453
454impl_walk!(RevertStatement, visit_revert_statement, |revert_statement, visitor| {
455    revert_statement.error_call.walk(visitor);
456});
457
458impl_walk!(MemberAccess, visit_member_access, |member_access, visitor| {
459    member_access.expression.walk(visitor);
460});
461
462impl_walk!(FunctionCall, visit_function_call, |function_call, visitor| {
463    function_call.expression.walk(visitor);
464    function_call.arguments.iter().for_each(|argument| {
465        argument.walk(visitor);
466    });
467});
468
469impl_walk!(Block, visit_block, |block, visitor| {
470    block.statements.iter().for_each(|statement| {
471        statement.walk(visitor);
472    });
473});
474
475impl_walk!(UserDefinedTypeName, visit_user_defined_type_name, |type_name, visitor| {
476    if let Some(path_node) = &type_name.path_node {
477        path_node.walk(visitor);
478    }
479});
480
481impl_walk!(TypeName, visit_type_name, |type_name, visitor| {
482    match type_name {
483        TypeName::ElementaryTypeName(type_name) => {
484            type_name.walk(visitor);
485        }
486        TypeName::UserDefinedTypeName(type_name) => {
487            type_name.walk(visitor);
488        }
489        TypeName::Mapping(mapping) => {
490            mapping.walk(visitor);
491        }
492        TypeName::ArrayTypeName(array) => {
493            array.walk(visitor);
494        }
495        TypeName::FunctionTypeName(function) => {
496            function.walk(visitor);
497        }
498    }
499});
500
501impl_walk!(FunctionTypeName, visit_function_type_name, |function, visitor| {
502    function.parameter_types.walk(visitor);
503    function.return_parameter_types.walk(visitor);
504});
505
506impl_walk!(ParameterList, visit_parameter_list, |parameter_list, visitor| {
507    parameter_list.parameters.iter().for_each(|parameter| {
508        parameter.walk(visitor);
509    });
510});
511
512impl_walk!(Mapping, visit_mapping, |mapping, visitor| {
513    mapping.key_type.walk(visitor);
514    mapping.value_type.walk(visitor);
515});
516
517impl_walk!(ArrayTypeName, visit_array_type_name, |array, visitor| {
518    array.base_type.walk(visitor);
519    if let Some(length) = &array.length {
520        length.walk(visitor);
521    }
522});
523
524impl_walk!(InheritanceSpecifier, visit_inheritance_specifier, |specifier, visitor| {
525    specifier.base_name.walk(visitor);
526    specifier.arguments.iter().for_each(|arg| {
527        arg.walk(visitor);
528    });
529});
530
531impl_walk!(ModifierInvocation, visit_modifier_invocation, |invocation, visitor| {
532    invocation.arguments.iter().for_each(|arg| arg.walk(visitor));
533    invocation.modifier_name.walk(visitor);
534});
535
536impl_walk!(InlineAssembly, visit_inline_assembly, |assembly, visitor| {
537    assembly.external_references.iter().for_each(|reference| {
538        reference.walk(visitor);
539    });
540});
541
542impl_walk!(ExternalInlineAssemblyReference, visit_external_assembly_reference);
543
544impl_walk!(ElementaryTypeName, visit_elementary_type_name);
545impl_walk!(Literal, visit_literal);
546impl_walk!(ImportDirective, visit_import_directive);
547impl_walk!(PragmaDirective, visit_pragma_directive);
548impl_walk!(IdentifierPath, visit_identifier_path);
549impl_walk!(EnumDefinition, visit_enum_definition);
550impl_walk!(Identifier, visit_identifier);
551
552impl_walk!(UserDefinedTypeNameOrIdentifierPath, |type_name, visitor| {
553    match type_name {
554        UserDefinedTypeNameOrIdentifierPath::UserDefinedTypeName(type_name) => {
555            type_name.walk(visitor);
556        }
557        UserDefinedTypeNameOrIdentifierPath::IdentifierPath(identifier_path) => {
558            identifier_path.walk(visitor);
559        }
560    }
561});
562
563impl_walk!(BlockOrStatement, |block_or_statement, visitor| {
564    match block_or_statement {
565        BlockOrStatement::Block(block) => {
566            block.walk(visitor);
567        }
568        BlockOrStatement::Statement(statement) => {
569            statement.walk(visitor);
570        }
571    }
572});
573
574impl_walk!(ExpressionOrVariableDeclarationStatement, |val, visitor| {
575    match val {
576        ExpressionOrVariableDeclarationStatement::ExpressionStatement(expression) => {
577            expression.walk(visitor);
578        }
579        ExpressionOrVariableDeclarationStatement::VariableDeclarationStatement(stmt) => {
580            stmt.walk(visitor);
581        }
582    }
583});
584
585impl_walk!(IdentifierOrIdentifierPath, |val, visitor| {
586    match val {
587        IdentifierOrIdentifierPath::Identifier(ident) => {
588            ident.walk(visitor);
589        }
590        IdentifierOrIdentifierPath::IdentifierPath(path) => {
591            path.walk(visitor);
592        }
593    }
594});
595
596impl_walk!(ExpressionStatement, |expression_statement, visitor| {
597    expression_statement.expression.walk(visitor);
598});
599
600impl_walk!(ElementaryTypeNameExpression, |type_name, visitor| {
601    type_name.type_name.walk(visitor);
602});
603
604impl_walk!(ElementaryOrRawTypeName, |type_name, visitor| {
605    match type_name {
606        ElementaryOrRawTypeName::ElementaryTypeName(type_name) => {
607            type_name.walk(visitor);
608        }
609        ElementaryOrRawTypeName::Raw(_) => {}
610    }
611});
612
613impl_walk!(UsingForFunctionItem, |item, visitor| {
614    match item {
615        UsingForFunctionItem::Function(func) => {
616            func.function.walk(visitor);
617        }
618        UsingForFunctionItem::OverloadedOperator(operator) => {
619            operator.walk(visitor);
620        }
621    }
622});
623
624impl_walk!(OverloadedOperator, |operator, visitor| {
625    operator.definition.walk(visitor);
626});