1use crate::solang_ext::pt::*;
4
5pub trait Visitor {
10 type Error: std::error::Error;
11
12 fn visit_source(&mut self, _loc: Loc) -> Result<(), Self::Error> {
13 Ok(())
14 }
15
16 fn visit_source_unit(&mut self, _source_unit: &mut SourceUnit) -> Result<(), Self::Error> {
17 Ok(())
18 }
19
20 fn visit_contract(&mut self, _contract: &mut ContractDefinition) -> Result<(), Self::Error> {
21 Ok(())
22 }
23
24 fn visit_annotation(&mut self, annotation: &mut Annotation) -> Result<(), Self::Error> {
25 self.visit_source(annotation.loc)
26 }
27
28 fn visit_pragma(
29 &mut self,
30 loc: Loc,
31 _ident: &mut Option<Identifier>,
32 _str: &mut Option<StringLiteral>,
33 ) -> Result<(), Self::Error> {
34 self.visit_source(loc)
35 }
36
37 fn visit_import_plain(
38 &mut self,
39 _loc: Loc,
40 _import: &mut ImportPath,
41 ) -> Result<(), Self::Error> {
42 Ok(())
43 }
44
45 fn visit_import_global(
46 &mut self,
47 _loc: Loc,
48 _global: &mut ImportPath,
49 _alias: &mut Identifier,
50 ) -> Result<(), Self::Error> {
51 Ok(())
52 }
53
54 fn visit_import_renames(
55 &mut self,
56 _loc: Loc,
57 _imports: &mut [(Identifier, Option<Identifier>)],
58 _from: &mut ImportPath,
59 ) -> Result<(), Self::Error> {
60 Ok(())
61 }
62
63 fn visit_enum(&mut self, _enum: &mut EnumDefinition) -> Result<(), Self::Error> {
64 Ok(())
65 }
66
67 fn visit_assembly(
68 &mut self,
69 loc: Loc,
70 _dialect: &mut Option<StringLiteral>,
71 _block: &mut YulBlock,
72 _flags: &mut Option<Vec<StringLiteral>>,
73 ) -> Result<(), Self::Error> {
74 self.visit_source(loc)
75 }
76
77 fn visit_block(
78 &mut self,
79 loc: Loc,
80 _unchecked: bool,
81 _statements: &mut Vec<Statement>,
82 ) -> Result<(), Self::Error> {
83 self.visit_source(loc)
84 }
85
86 fn visit_args(&mut self, loc: Loc, _args: &mut Vec<NamedArgument>) -> Result<(), Self::Error> {
87 self.visit_source(loc)
88 }
89
90 fn visit_expr(&mut self, loc: Loc, _expr: &mut Expression) -> Result<(), Self::Error> {
93 self.visit_source(loc)
94 }
95
96 fn visit_ident(&mut self, loc: Loc, _ident: &mut Identifier) -> Result<(), Self::Error> {
97 self.visit_source(loc)
98 }
99
100 fn visit_ident_path(&mut self, idents: &mut IdentifierPath) -> Result<(), Self::Error> {
101 self.visit_source(idents.loc)
102 }
103
104 fn visit_emit(&mut self, loc: Loc, _event: &mut Expression) -> Result<(), Self::Error> {
105 self.visit_source(loc)?;
106 self.visit_stray_semicolon()?;
107
108 Ok(())
109 }
110
111 fn visit_var_definition(&mut self, var: &mut VariableDefinition) -> Result<(), Self::Error> {
112 self.visit_source(var.loc)?;
113 self.visit_stray_semicolon()?;
114
115 Ok(())
116 }
117
118 fn visit_var_definition_stmt(
119 &mut self,
120 loc: Loc,
121 _declaration: &mut VariableDeclaration,
122 _expr: &mut Option<Expression>,
123 ) -> Result<(), Self::Error> {
124 self.visit_source(loc)?;
125 self.visit_stray_semicolon()
126 }
127
128 fn visit_var_declaration(&mut self, var: &mut VariableDeclaration) -> Result<(), Self::Error> {
129 self.visit_source(var.loc)
130 }
131
132 fn visit_return(
133 &mut self,
134 loc: Loc,
135 _expr: &mut Option<Expression>,
136 ) -> Result<(), Self::Error> {
137 self.visit_source(loc)?;
138 self.visit_stray_semicolon()?;
139
140 Ok(())
141 }
142
143 fn visit_revert(
144 &mut self,
145 loc: Loc,
146 _error: &mut Option<IdentifierPath>,
147 _args: &mut Vec<Expression>,
148 ) -> Result<(), Self::Error> {
149 self.visit_source(loc)?;
150 self.visit_stray_semicolon()?;
151
152 Ok(())
153 }
154
155 fn visit_revert_named_args(
156 &mut self,
157 loc: Loc,
158 _error: &mut Option<IdentifierPath>,
159 _args: &mut Vec<NamedArgument>,
160 ) -> Result<(), Self::Error> {
161 self.visit_source(loc)?;
162 self.visit_stray_semicolon()?;
163
164 Ok(())
165 }
166
167 fn visit_break(&mut self, loc: Loc, _semicolon: bool) -> Result<(), Self::Error> {
168 self.visit_source(loc)
169 }
170
171 fn visit_continue(&mut self, loc: Loc, _semicolon: bool) -> Result<(), Self::Error> {
172 self.visit_source(loc)
173 }
174
175 #[expect(clippy::type_complexity)]
176 fn visit_try(
177 &mut self,
178 loc: Loc,
179 _expr: &mut Expression,
180 _returns: &mut Option<(Vec<(Loc, Option<Parameter>)>, Box<Statement>)>,
181 _clauses: &mut Vec<CatchClause>,
182 ) -> Result<(), Self::Error> {
183 self.visit_source(loc)
184 }
185
186 fn visit_if(
187 &mut self,
188 loc: Loc,
189 _cond: &mut Expression,
190 _if_branch: &mut Box<Statement>,
191 _else_branch: &mut Option<Box<Statement>>,
192 _is_first_stmt: bool,
193 ) -> Result<(), Self::Error> {
194 self.visit_source(loc)
195 }
196
197 fn visit_do_while(
198 &mut self,
199 loc: Loc,
200 _body: &mut Statement,
201 _cond: &mut Expression,
202 ) -> Result<(), Self::Error> {
203 self.visit_source(loc)
204 }
205
206 fn visit_while(
207 &mut self,
208 loc: Loc,
209 _cond: &mut Expression,
210 _body: &mut Statement,
211 ) -> Result<(), Self::Error> {
212 self.visit_source(loc)
213 }
214
215 fn visit_for(
216 &mut self,
217 loc: Loc,
218 _init: &mut Option<Box<Statement>>,
219 _cond: &mut Option<Box<Expression>>,
220 _update: &mut Option<Box<Expression>>,
221 _body: &mut Option<Box<Statement>>,
222 ) -> Result<(), Self::Error> {
223 self.visit_source(loc)
224 }
225
226 fn visit_function(&mut self, func: &mut FunctionDefinition) -> Result<(), Self::Error> {
227 self.visit_source(func.loc())?;
228 if func.body.is_none() {
229 self.visit_stray_semicolon()?;
230 }
231
232 Ok(())
233 }
234
235 fn visit_function_attribute(
236 &mut self,
237 attribute: &mut FunctionAttribute,
238 ) -> Result<(), Self::Error> {
239 self.visit_source(attribute.loc())?;
240 Ok(())
241 }
242
243 fn visit_var_attribute(
244 &mut self,
245 attribute: &mut VariableAttribute,
246 ) -> Result<(), Self::Error> {
247 self.visit_source(attribute.loc())?;
248 Ok(())
249 }
250
251 fn visit_base(&mut self, base: &mut Base) -> Result<(), Self::Error> {
252 self.visit_source(base.loc)
253 }
254
255 fn visit_parameter(&mut self, parameter: &mut Parameter) -> Result<(), Self::Error> {
256 self.visit_source(parameter.loc)
257 }
258
259 fn visit_struct(&mut self, structure: &mut StructDefinition) -> Result<(), Self::Error> {
260 self.visit_source(structure.loc)?;
261
262 Ok(())
263 }
264
265 fn visit_event(&mut self, event: &mut EventDefinition) -> Result<(), Self::Error> {
266 self.visit_source(event.loc)?;
267 self.visit_stray_semicolon()?;
268
269 Ok(())
270 }
271
272 fn visit_event_parameter(&mut self, param: &mut EventParameter) -> Result<(), Self::Error> {
273 self.visit_source(param.loc)
274 }
275
276 fn visit_error(&mut self, error: &mut ErrorDefinition) -> Result<(), Self::Error> {
277 self.visit_source(error.loc)?;
278 self.visit_stray_semicolon()?;
279
280 Ok(())
281 }
282
283 fn visit_error_parameter(&mut self, param: &mut ErrorParameter) -> Result<(), Self::Error> {
284 self.visit_source(param.loc)
285 }
286
287 fn visit_type_definition(&mut self, def: &mut TypeDefinition) -> Result<(), Self::Error> {
288 self.visit_source(def.loc)
289 }
290
291 fn visit_stray_semicolon(&mut self) -> Result<(), Self::Error> {
292 Ok(())
293 }
294
295 fn visit_opening_paren(&mut self) -> Result<(), Self::Error> {
296 Ok(())
297 }
298
299 fn visit_closing_paren(&mut self) -> Result<(), Self::Error> {
300 Ok(())
301 }
302
303 fn visit_newline(&mut self) -> Result<(), Self::Error> {
304 Ok(())
305 }
306
307 fn visit_using(&mut self, using: &mut Using) -> Result<(), Self::Error> {
308 self.visit_source(using.loc)?;
309 self.visit_stray_semicolon()?;
310
311 Ok(())
312 }
313
314 fn visit_yul_block(
315 &mut self,
316 loc: Loc,
317 _stmts: &mut Vec<YulStatement>,
318 _attempt_single_line: bool,
319 ) -> Result<(), Self::Error> {
320 self.visit_source(loc)
321 }
322
323 fn visit_yul_expr(&mut self, expr: &mut YulExpression) -> Result<(), Self::Error> {
324 self.visit_source(expr.loc())
325 }
326
327 fn visit_yul_assignment<T>(
328 &mut self,
329 loc: Loc,
330 _exprs: &mut Vec<T>,
331 _expr: &mut Option<&mut YulExpression>,
332 ) -> Result<(), Self::Error>
333 where
334 T: Visitable + CodeLocation,
335 {
336 self.visit_source(loc)
337 }
338
339 fn visit_yul_for(&mut self, stmt: &mut YulFor) -> Result<(), Self::Error> {
340 self.visit_source(stmt.loc)
341 }
342
343 fn visit_yul_function_call(&mut self, stmt: &mut YulFunctionCall) -> Result<(), Self::Error> {
344 self.visit_source(stmt.loc)
345 }
346
347 fn visit_yul_fun_def(&mut self, stmt: &mut YulFunctionDefinition) -> Result<(), Self::Error> {
348 self.visit_source(stmt.loc)
349 }
350
351 fn visit_yul_if(
352 &mut self,
353 loc: Loc,
354 _expr: &mut YulExpression,
355 _block: &mut YulBlock,
356 ) -> Result<(), Self::Error> {
357 self.visit_source(loc)
358 }
359
360 fn visit_yul_leave(&mut self, loc: Loc) -> Result<(), Self::Error> {
361 self.visit_source(loc)
362 }
363
364 fn visit_yul_switch(&mut self, stmt: &mut YulSwitch) -> Result<(), Self::Error> {
365 self.visit_source(stmt.loc)
366 }
367
368 fn visit_yul_var_declaration(
369 &mut self,
370 loc: Loc,
371 _idents: &mut Vec<YulTypedIdentifier>,
372 _expr: &mut Option<YulExpression>,
373 ) -> Result<(), Self::Error> {
374 self.visit_source(loc)
375 }
376
377 fn visit_yul_typed_ident(&mut self, ident: &mut YulTypedIdentifier) -> Result<(), Self::Error> {
378 self.visit_source(ident.loc)
379 }
380
381 fn visit_parser_error(&mut self, loc: Loc) -> Result<(), Self::Error> {
382 self.visit_source(loc)
383 }
384}
385
386pub trait Visitable {
395 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
396 where
397 V: Visitor;
398}
399
400impl<T> Visitable for &mut T
401where
402 T: Visitable,
403{
404 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
405 where
406 V: Visitor,
407 {
408 T::visit(self, v)
409 }
410}
411
412impl<T> Visitable for Option<T>
413where
414 T: Visitable,
415{
416 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
417 where
418 V: Visitor,
419 {
420 if let Some(inner) = self.as_mut() {
421 inner.visit(v)
422 } else {
423 Ok(())
424 }
425 }
426}
427
428impl<T> Visitable for Box<T>
429where
430 T: Visitable,
431{
432 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
433 where
434 V: Visitor,
435 {
436 T::visit(self, v)
437 }
438}
439
440impl<T> Visitable for Vec<T>
441where
442 T: Visitable,
443{
444 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
445 where
446 V: Visitor,
447 {
448 for item in self.iter_mut() {
449 item.visit(v)?;
450 }
451 Ok(())
452 }
453}
454
455impl Visitable for SourceUnitPart {
456 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
457 where
458 V: Visitor,
459 {
460 match self {
461 Self::ContractDefinition(contract) => v.visit_contract(contract),
462 Self::PragmaDirective(loc, ident, str) => v.visit_pragma(*loc, ident, str),
463 Self::ImportDirective(import) => import.visit(v),
464 Self::EnumDefinition(enumeration) => v.visit_enum(enumeration),
465 Self::StructDefinition(structure) => v.visit_struct(structure),
466 Self::EventDefinition(event) => v.visit_event(event),
467 Self::ErrorDefinition(error) => v.visit_error(error),
468 Self::FunctionDefinition(function) => v.visit_function(function),
469 Self::VariableDefinition(variable) => v.visit_var_definition(variable),
470 Self::TypeDefinition(def) => v.visit_type_definition(def),
471 Self::StraySemicolon(_) => v.visit_stray_semicolon(),
472 Self::Using(using) => v.visit_using(using),
473 Self::Annotation(annotation) => v.visit_annotation(annotation),
474 }
475 }
476}
477
478impl Visitable for Import {
479 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
480 where
481 V: Visitor,
482 {
483 match self {
484 Self::Plain(import, loc) => v.visit_import_plain(*loc, import),
485 Self::GlobalSymbol(global, import_as, loc) => {
486 v.visit_import_global(*loc, global, import_as)
487 }
488 Self::Rename(from, imports, loc) => v.visit_import_renames(*loc, imports, from),
489 }
490 }
491}
492
493impl Visitable for ContractPart {
494 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
495 where
496 V: Visitor,
497 {
498 match self {
499 Self::StructDefinition(structure) => v.visit_struct(structure),
500 Self::EventDefinition(event) => v.visit_event(event),
501 Self::ErrorDefinition(error) => v.visit_error(error),
502 Self::EnumDefinition(enumeration) => v.visit_enum(enumeration),
503 Self::VariableDefinition(variable) => v.visit_var_definition(variable),
504 Self::FunctionDefinition(function) => v.visit_function(function),
505 Self::TypeDefinition(def) => v.visit_type_definition(def),
506 Self::StraySemicolon(_) => v.visit_stray_semicolon(),
507 Self::Using(using) => v.visit_using(using),
508 Self::Annotation(annotation) => v.visit_annotation(annotation),
509 }
510 }
511}
512
513impl Visitable for Statement {
514 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
515 where
516 V: Visitor,
517 {
518 match self {
519 Self::Block { loc, unchecked, statements } => {
520 v.visit_block(*loc, *unchecked, statements)
521 }
522 Self::Assembly { loc, dialect, block, flags } => {
523 v.visit_assembly(*loc, dialect, block, flags)
524 }
525 Self::Args(loc, args) => v.visit_args(*loc, args),
526 Self::If(loc, cond, if_branch, else_branch) => {
527 v.visit_if(*loc, cond, if_branch, else_branch, true)
528 }
529 Self::While(loc, cond, body) => v.visit_while(*loc, cond, body),
530 Self::Expression(loc, expr) => {
531 v.visit_expr(*loc, expr)?;
532 v.visit_stray_semicolon()
533 }
534 Self::VariableDefinition(loc, declaration, expr) => {
535 v.visit_var_definition_stmt(*loc, declaration, expr)
536 }
537 Self::For(loc, init, cond, update, body) => v.visit_for(*loc, init, cond, update, body),
538 Self::DoWhile(loc, body, cond) => v.visit_do_while(*loc, body, cond),
539 Self::Continue(loc) => v.visit_continue(*loc, true),
540 Self::Break(loc) => v.visit_break(*loc, true),
541 Self::Return(loc, expr) => v.visit_return(*loc, expr),
542 Self::Revert(loc, error, args) => v.visit_revert(*loc, error, args),
543 Self::RevertNamedArgs(loc, error, args) => v.visit_revert_named_args(*loc, error, args),
544 Self::Emit(loc, event) => v.visit_emit(*loc, event),
545 Self::Try(loc, expr, returns, clauses) => v.visit_try(*loc, expr, returns, clauses),
546 Self::Error(loc) => v.visit_parser_error(*loc),
547 }
548 }
549}
550
551impl Visitable for Loc {
552 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
553 where
554 V: Visitor,
555 {
556 v.visit_source(*self)
557 }
558}
559
560impl Visitable for Expression {
561 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
562 where
563 V: Visitor,
564 {
565 v.visit_expr(self.loc(), self)
566 }
567}
568
569impl Visitable for Identifier {
570 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
571 where
572 V: Visitor,
573 {
574 v.visit_ident(self.loc, self)
575 }
576}
577
578impl Visitable for VariableDeclaration {
579 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
580 where
581 V: Visitor,
582 {
583 v.visit_var_declaration(self)
584 }
585}
586
587impl Visitable for YulBlock {
588 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
589 where
590 V: Visitor,
591 {
592 v.visit_yul_block(self.loc, self.statements.as_mut(), false)
593 }
594}
595
596impl Visitable for YulStatement {
597 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
598 where
599 V: Visitor,
600 {
601 match self {
602 Self::Assign(loc, exprs, expr) => v.visit_yul_assignment(*loc, exprs, &mut Some(expr)),
603 Self::Block(block) => v.visit_yul_block(block.loc, block.statements.as_mut(), false),
604 Self::Break(loc) => v.visit_break(*loc, false),
605 Self::Continue(loc) => v.visit_continue(*loc, false),
606 Self::For(stmt) => v.visit_yul_for(stmt),
607 Self::FunctionCall(stmt) => v.visit_yul_function_call(stmt),
608 Self::FunctionDefinition(stmt) => v.visit_yul_fun_def(stmt),
609 Self::If(loc, expr, block) => v.visit_yul_if(*loc, expr, block),
610 Self::Leave(loc) => v.visit_yul_leave(*loc),
611 Self::Switch(stmt) => v.visit_yul_switch(stmt),
612 Self::VariableDeclaration(loc, idents, expr) => {
613 v.visit_yul_var_declaration(*loc, idents, expr)
614 }
615 Self::Error(loc) => v.visit_parser_error(*loc),
616 }
617 }
618}
619
620macro_rules! impl_visitable {
621 ($type:ty, $func:ident) => {
622 impl Visitable for $type {
623 fn visit<V>(&mut self, v: &mut V) -> Result<(), V::Error>
624 where
625 V: Visitor,
626 {
627 v.$func(self)
628 }
629 }
630 };
631}
632
633impl_visitable!(SourceUnit, visit_source_unit);
634impl_visitable!(FunctionAttribute, visit_function_attribute);
635impl_visitable!(VariableAttribute, visit_var_attribute);
636impl_visitable!(Parameter, visit_parameter);
637impl_visitable!(Base, visit_base);
638impl_visitable!(EventParameter, visit_event_parameter);
639impl_visitable!(ErrorParameter, visit_error_parameter);
640impl_visitable!(IdentifierPath, visit_ident_path);
641impl_visitable!(YulExpression, visit_yul_expr);
642impl_visitable!(YulTypedIdentifier, visit_yul_typed_ident);