darklua_core/process/
visitors.rs

1use crate::nodes::*;
2use crate::process::NodeProcessor;
3
4use std::marker::PhantomData;
5
6/// A trait that defines method that iterates on nodes and process them using a NodeProcessor.
7pub trait NodeVisitor<T: NodeProcessor> {
8    fn visit_block(block: &mut Block, processor: &mut T) {
9        processor.process_block(block);
10
11        block
12            .iter_mut_statements()
13            .for_each(|statement| Self::visit_statement(statement, processor));
14
15        if let Some(last_statement) = block.mutate_last_statement() {
16            Self::visit_last_statement(last_statement, processor);
17        };
18    }
19
20    fn visit_statement(statement: &mut Statement, processor: &mut T) {
21        processor.process_statement(statement);
22
23        match statement {
24            Statement::Assign(statement) => Self::visit_assign_statement(statement, processor),
25            Statement::Do(statement) => Self::visit_do_statement(statement, processor),
26            Statement::Call(statement) => Self::visit_function_call(statement, processor),
27            Statement::CompoundAssign(statement) => {
28                Self::visit_compound_assign(statement, processor)
29            }
30            Statement::Function(statement) => Self::visit_function_statement(statement, processor),
31            Statement::GenericFor(statement) => Self::visit_generic_for(statement, processor),
32            Statement::If(statement) => Self::visit_if_statement(statement, processor),
33            Statement::LocalAssign(statement) => Self::visit_local_assign(statement, processor),
34            Statement::LocalFunction(statement) => Self::visit_local_function(statement, processor),
35            Statement::NumericFor(statement) => Self::visit_numeric_for(statement, processor),
36            Statement::Repeat(statement) => Self::visit_repeat_statement(statement, processor),
37            Statement::While(statement) => Self::visit_while_statement(statement, processor),
38            Statement::TypeDeclaration(statement) => {
39                Self::visit_type_declaration(statement, processor)
40            }
41        };
42    }
43
44    fn visit_last_statement(last_statement: &mut LastStatement, processor: &mut T) {
45        processor.process_last_statement(last_statement);
46
47        if let LastStatement::Return(expressions) = last_statement {
48            expressions
49                .iter_mut_expressions()
50                .for_each(|expression| Self::visit_expression(expression, processor));
51        };
52    }
53
54    fn visit_expression(expression: &mut Expression, processor: &mut T) {
55        processor.process_expression(expression);
56
57        match expression {
58            Expression::Binary(expression) => {
59                Self::visit_binary_expression(expression, processor);
60            }
61            Expression::Call(expression) => Self::visit_function_call(expression, processor),
62            Expression::Field(field) => Self::visit_field_expression(field, processor),
63            Expression::Function(function) => Self::visit_function_expression(function, processor),
64            Expression::Identifier(identifier) => Self::visit_identifier(identifier, processor),
65            Expression::If(if_expression) => Self::visit_if_expression(if_expression, processor),
66            Expression::Index(index) => Self::visit_index_expression(index, processor),
67            Expression::Number(number) => Self::visit_number_expression(number, processor),
68            Expression::Parenthese(expression) => {
69                Self::visit_parenthese_expression(expression, processor);
70            }
71            Expression::String(string) => {
72                Self::visit_string_expression(string, processor);
73            }
74            Expression::InterpolatedString(interpolated_string) => {
75                Self::visit_interpolated_string_expression(interpolated_string, processor);
76            }
77            Expression::Table(table) => Self::visit_table(table, processor),
78            Expression::Unary(unary) => {
79                Self::visit_unary_expression(unary, processor);
80            }
81            Expression::TypeCast(type_cast) => {
82                Self::visit_type_cast_expression(type_cast, processor);
83            }
84            Expression::False(_)
85            | Expression::Nil(_)
86            | Expression::True(_)
87            | Expression::VariableArguments(_) => {}
88        }
89    }
90
91    fn visit_binary_expression(binary: &mut BinaryExpression, processor: &mut T) {
92        processor.process_binary_expression(binary);
93        Self::visit_expression(binary.mutate_left(), processor);
94        Self::visit_expression(binary.mutate_right(), processor);
95    }
96
97    fn visit_number_expression(number: &mut NumberExpression, processor: &mut T) {
98        processor.process_number_expression(number);
99    }
100
101    fn visit_parenthese_expression(parenthese: &mut ParentheseExpression, processor: &mut T) {
102        processor.process_parenthese_expression(parenthese);
103        Self::visit_expression(parenthese.mutate_inner_expression(), processor)
104    }
105
106    fn visit_string_expression(string: &mut StringExpression, processor: &mut T) {
107        processor.process_string_expression(string);
108    }
109
110    fn visit_interpolated_string_expression(
111        interpolated_string: &mut InterpolatedStringExpression,
112        processor: &mut T,
113    ) {
114        processor.process_interpolated_string_expression(interpolated_string);
115
116        for segment in interpolated_string.iter_mut_segments() {
117            match segment {
118                InterpolationSegment::String(_) => {}
119                InterpolationSegment::Value(value) => {
120                    Self::visit_expression(value.mutate_expression(), processor)
121                }
122            }
123        }
124    }
125
126    fn visit_unary_expression(unary: &mut UnaryExpression, processor: &mut T) {
127        processor.process_unary_expression(unary);
128        Self::visit_expression(unary.mutate_expression(), processor);
129    }
130
131    fn visit_type_cast_expression(type_cast: &mut TypeCastExpression, processor: &mut T) {
132        processor.process_type_cast_expression(type_cast);
133
134        Self::visit_expression(type_cast.mutate_expression(), processor);
135        Self::visit_type(type_cast.mutate_type(), processor);
136    }
137
138    fn visit_function_expression(function: &mut FunctionExpression, processor: &mut T) {
139        processor.process_function_expression(function);
140
141        processor.process_scope(function.mutate_block(), None);
142
143        Self::visit_block(function.mutate_block(), processor);
144
145        for r#type in function
146            .iter_mut_parameters()
147            .filter_map(TypedIdentifier::mutate_type)
148        {
149            Self::visit_type(r#type, processor);
150        }
151
152        if let Some(variadic_type) = function.mutate_variadic_type() {
153            Self::visit_function_variadic_type(variadic_type, processor);
154        }
155
156        if let Some(return_type) = function.mutate_return_type() {
157            Self::visit_function_return_type(return_type, processor);
158        }
159    }
160
161    fn visit_assign_statement(statement: &mut AssignStatement, processor: &mut T) {
162        processor.process_assign_statement(statement);
163
164        statement
165            .mutate_variables()
166            .iter_mut()
167            .for_each(|variable| Self::visit_variable(variable, processor));
168
169        statement
170            .iter_mut_values()
171            .for_each(|expression| Self::visit_expression(expression, processor));
172    }
173
174    fn visit_do_statement(statement: &mut DoStatement, processor: &mut T) {
175        processor.process_do_statement(statement);
176        processor.process_scope(statement.mutate_block(), None);
177        Self::visit_block(statement.mutate_block(), processor);
178    }
179
180    fn visit_compound_assign(statement: &mut CompoundAssignStatement, processor: &mut T) {
181        processor.process_compound_assign_statement(statement);
182        Self::visit_variable(statement.mutate_variable(), processor);
183        Self::visit_expression(statement.mutate_value(), processor);
184    }
185
186    fn visit_function_statement(statement: &mut FunctionStatement, processor: &mut T) {
187        processor.process_function_statement(statement);
188
189        Self::visit_identifier(
190            statement.mutate_function_name().mutate_identifier(),
191            processor,
192        );
193
194        processor.process_scope(statement.mutate_block(), None);
195        Self::visit_block(statement.mutate_block(), processor);
196
197        for r#type in statement
198            .iter_mut_parameters()
199            .filter_map(TypedIdentifier::mutate_type)
200        {
201            Self::visit_type(r#type, processor);
202        }
203
204        if let Some(variadic_type) = statement.mutate_variadic_type() {
205            Self::visit_function_variadic_type(variadic_type, processor);
206        }
207
208        if let Some(return_type) = statement.mutate_return_type() {
209            Self::visit_function_return_type(return_type, processor);
210        }
211    }
212
213    fn visit_generic_for(statement: &mut GenericForStatement, processor: &mut T) {
214        processor.process_generic_for_statement(statement);
215
216        statement
217            .iter_mut_expressions()
218            .for_each(|expression| Self::visit_expression(expression, processor));
219
220        processor.process_scope(statement.mutate_block(), None);
221        Self::visit_block(statement.mutate_block(), processor);
222
223        for r#type in statement
224            .iter_mut_identifiers()
225            .filter_map(TypedIdentifier::mutate_type)
226        {
227            Self::visit_type(r#type, processor);
228        }
229    }
230
231    fn visit_if_statement(statement: &mut IfStatement, processor: &mut T) {
232        processor.process_if_statement(statement);
233
234        statement.mutate_branches().iter_mut().for_each(|branch| {
235            Self::visit_expression(branch.mutate_condition(), processor);
236            processor.process_scope(branch.mutate_block(), None);
237            Self::visit_block(branch.mutate_block(), processor);
238        });
239
240        if let Some(block) = statement.mutate_else_block() {
241            processor.process_scope(block, None);
242            Self::visit_block(block, processor);
243        }
244    }
245
246    fn visit_local_assign(statement: &mut LocalAssignStatement, processor: &mut T) {
247        processor.process_local_assign_statement(statement);
248
249        statement
250            .iter_mut_values()
251            .for_each(|value| Self::visit_expression(value, processor));
252
253        for r#type in statement
254            .iter_mut_variables()
255            .filter_map(TypedIdentifier::mutate_type)
256        {
257            Self::visit_type(r#type, processor);
258        }
259    }
260
261    fn visit_local_function(statement: &mut LocalFunctionStatement, processor: &mut T) {
262        processor.process_local_function_statement(statement);
263        processor.process_scope(statement.mutate_block(), None);
264        Self::visit_block(statement.mutate_block(), processor);
265
266        for r#type in statement
267            .iter_mut_parameters()
268            .filter_map(TypedIdentifier::mutate_type)
269        {
270            Self::visit_type(r#type, processor);
271        }
272
273        if let Some(variadic_type) = statement.mutate_variadic_type() {
274            Self::visit_function_variadic_type(variadic_type, processor);
275        }
276
277        if let Some(return_type) = statement.mutate_return_type() {
278            Self::visit_function_return_type(return_type, processor);
279        }
280    }
281
282    fn visit_function_variadic_type(variadic_type: &mut FunctionVariadicType, processor: &mut T) {
283        match variadic_type {
284            FunctionVariadicType::Type(r#type) => {
285                Self::visit_type(r#type, processor);
286            }
287            FunctionVariadicType::GenericTypePack(generic) => {
288                Self::visit_generic_type_pack(generic, processor);
289            }
290        }
291    }
292
293    fn visit_generic_type_pack(generic: &mut GenericTypePack, processor: &mut T) {
294        processor.process_generic_type_pack(generic);
295    }
296
297    fn visit_numeric_for(statement: &mut NumericForStatement, processor: &mut T) {
298        processor.process_numeric_for_statement(statement);
299
300        Self::visit_expression(statement.mutate_start(), processor);
301        Self::visit_expression(statement.mutate_end(), processor);
302
303        if let Some(step) = statement.mutate_step() {
304            Self::visit_expression(step, processor);
305        };
306
307        processor.process_scope(statement.mutate_block(), None);
308        Self::visit_block(statement.mutate_block(), processor);
309
310        if let Some(r#type) = statement.mutate_identifier().mutate_type() {
311            Self::visit_type(r#type, processor);
312        }
313    }
314
315    fn visit_repeat_statement(statement: &mut RepeatStatement, processor: &mut T) {
316        processor.process_repeat_statement(statement);
317
318        let (block, condition) = statement.mutate_block_and_condition();
319        processor.process_scope(block, Some(condition));
320
321        Self::visit_expression(statement.mutate_condition(), processor);
322        Self::visit_block(statement.mutate_block(), processor);
323    }
324
325    fn visit_while_statement(statement: &mut WhileStatement, processor: &mut T) {
326        processor.process_while_statement(statement);
327
328        Self::visit_expression(statement.mutate_condition(), processor);
329
330        processor.process_scope(statement.mutate_block(), None);
331        Self::visit_block(statement.mutate_block(), processor);
332    }
333
334    fn visit_type_declaration(statement: &mut TypeDeclarationStatement, processor: &mut T) {
335        processor.process_type_declaration(statement);
336
337        if let Some(generic_parameters) = statement.mutate_generic_parameters() {
338            for parameter in generic_parameters {
339                match parameter {
340                    GenericParameterMutRef::TypeVariable(_) => {}
341                    GenericParameterMutRef::TypeVariableWithDefault(type_variable) => {
342                        Self::visit_type(type_variable.mutate_default_type(), processor);
343                    }
344                    GenericParameterMutRef::GenericTypePack(generic_type_pack) => {
345                        Self::visit_generic_type_pack(generic_type_pack, processor);
346                    }
347                    GenericParameterMutRef::GenericTypePackWithDefault(
348                        generic_type_pack_with_default,
349                    ) => {
350                        Self::visit_generic_type_pack(
351                            generic_type_pack_with_default.mutate_generic_type_pack(),
352                            processor,
353                        );
354
355                        match generic_type_pack_with_default.mutate_default_type() {
356                            GenericTypePackDefault::TypePack(type_pack) => {
357                                Self::visit_type_pack(type_pack, processor);
358                            }
359                            GenericTypePackDefault::VariadicTypePack(variadic_type_pack) => {
360                                Self::visit_variadic_type_pack(variadic_type_pack, processor);
361                            }
362                            GenericTypePackDefault::GenericTypePack(generic_type_pack) => {
363                                Self::visit_generic_type_pack(generic_type_pack, processor);
364                            }
365                        }
366                    }
367                }
368            }
369        }
370
371        Self::visit_type(statement.mutate_type(), processor);
372    }
373
374    fn visit_variable(variable: &mut Variable, processor: &mut T) {
375        processor.process_variable(variable);
376
377        match variable {
378            Variable::Identifier(identifier) => Self::visit_identifier(identifier, processor),
379            Variable::Field(field) => Self::visit_field_expression(field, processor),
380            Variable::Index(index) => Self::visit_index_expression(index, processor),
381        }
382    }
383
384    fn visit_identifier(identifier: &mut Identifier, processor: &mut T) {
385        processor.process_variable_expression(identifier);
386    }
387
388    fn visit_if_expression(if_expression: &mut IfExpression, processor: &mut T) {
389        processor.process_if_expression(if_expression);
390
391        Self::visit_expression(if_expression.mutate_condition(), processor);
392        Self::visit_expression(if_expression.mutate_result(), processor);
393
394        for branch in if_expression.iter_mut_branches() {
395            Self::visit_expression(branch.mutate_condition(), processor);
396            Self::visit_expression(branch.mutate_result(), processor);
397        }
398
399        Self::visit_expression(if_expression.mutate_else_result(), processor);
400    }
401
402    fn visit_field_expression(field: &mut FieldExpression, processor: &mut T) {
403        processor.process_field_expression(field);
404
405        Self::visit_prefix_expression(field.mutate_prefix(), processor);
406    }
407
408    fn visit_index_expression(index: &mut IndexExpression, processor: &mut T) {
409        processor.process_index_expression(index);
410
411        Self::visit_prefix_expression(index.mutate_prefix(), processor);
412        Self::visit_expression(index.mutate_index(), processor);
413    }
414
415    fn visit_function_call(call: &mut FunctionCall, processor: &mut T) {
416        processor.process_function_call(call);
417
418        Self::visit_prefix_expression(call.mutate_prefix(), processor);
419        Self::visit_arguments(call.mutate_arguments(), processor);
420    }
421
422    fn visit_arguments(arguments: &mut Arguments, processor: &mut T) {
423        match arguments {
424            Arguments::String(string) => Self::visit_string_expression(string, processor),
425            Arguments::Table(table) => Self::visit_table(table, processor),
426            Arguments::Tuple(expressions) => expressions
427                .iter_mut_values()
428                .for_each(|expression| Self::visit_expression(expression, processor)),
429        }
430    }
431
432    fn visit_table(table: &mut TableExpression, processor: &mut T) {
433        processor.process_table_expression(table);
434
435        table.iter_mut_entries().for_each(|entry| match entry {
436            TableEntry::Field(entry) => Self::visit_expression(entry.mutate_value(), processor),
437            TableEntry::Index(entry) => {
438                Self::visit_expression(entry.mutate_key(), processor);
439                Self::visit_expression(entry.mutate_value(), processor);
440            }
441            TableEntry::Value(value) => Self::visit_expression(value, processor),
442        });
443    }
444
445    fn visit_prefix_expression(prefix: &mut Prefix, processor: &mut T) {
446        processor.process_prefix_expression(prefix);
447
448        match prefix {
449            Prefix::Call(call) => Self::visit_function_call(call, processor),
450            Prefix::Field(field) => Self::visit_field_expression(field, processor),
451            Prefix::Identifier(identifier) => Self::visit_identifier(identifier, processor),
452            Prefix::Index(index) => Self::visit_index_expression(index, processor),
453            Prefix::Parenthese(expression) => {
454                Self::visit_parenthese_expression(expression, processor)
455            }
456        };
457    }
458
459    fn visit_type(r#type: &mut Type, processor: &mut T) {
460        processor.process_type(r#type);
461
462        match r#type {
463            Type::Name(type_name) => Self::visit_type_name(type_name, processor),
464            Type::Field(type_field) => Self::visit_type_field(type_field, processor),
465            Type::Array(array) => Self::visit_array_type(array, processor),
466            Type::Table(table) => Self::visit_table_type(table, processor),
467            Type::TypeOf(expression_type) => {
468                Self::visit_expression_type(expression_type, processor)
469            }
470            Type::Parenthese(parenthese) => Self::visit_parenthese_type(parenthese, processor),
471            Type::Function(function) => Self::visit_function_type(function, processor),
472            Type::Optional(optional) => Self::visit_optional_type(optional, processor),
473            Type::Intersection(intersection) => {
474                Self::visit_intersection_type(intersection, processor)
475            }
476            Type::Union(union) => Self::visit_union_type(union, processor),
477            Type::String(string) => Self::visit_string_type(string, processor),
478            Type::True(_) | Type::False(_) | Type::Nil(_) => {}
479        }
480    }
481
482    fn visit_type_name(type_name: &mut TypeName, processor: &mut T) {
483        processor.process_type_name(type_name);
484
485        if let Some(type_parameters) = type_name.mutate_type_parameters() {
486            for type_parameter in type_parameters {
487                match type_parameter {
488                    TypeParameter::Type(next_type) => {
489                        Self::visit_type(next_type, processor);
490                    }
491                    TypeParameter::TypePack(type_pack) => {
492                        Self::visit_type_pack(type_pack, processor);
493                    }
494                    TypeParameter::VariadicTypePack(variadic_type_pack) => {
495                        Self::visit_variadic_type_pack(variadic_type_pack, processor);
496                    }
497                    TypeParameter::GenericTypePack(generic_type_pack) => {
498                        Self::visit_generic_type_pack(generic_type_pack, processor);
499                    }
500                }
501            }
502        }
503    }
504
505    fn visit_type_field(type_field: &mut TypeField, processor: &mut T) {
506        processor.process_type_field(type_field);
507        Self::visit_type_name(type_field.mutate_type_name(), processor);
508    }
509
510    fn visit_array_type(array: &mut ArrayType, processor: &mut T) {
511        processor.process_array_type(array);
512        Self::visit_type(array.mutate_element_type(), processor);
513    }
514
515    fn visit_table_type(table: &mut TableType, processor: &mut T) {
516        processor.process_table_type(table);
517
518        for entry in table.iter_mut_entries() {
519            match entry {
520                TableEntryType::Property(property) => {
521                    Self::visit_type(property.mutate_type(), processor);
522                }
523                TableEntryType::Literal(property) => {
524                    Self::visit_string_type(property.mutate_string(), processor);
525                    Self::visit_type(property.mutate_type(), processor);
526                }
527                TableEntryType::Indexer(indexer) => {
528                    Self::visit_type(indexer.mutate_key_type(), processor);
529                    Self::visit_type(indexer.mutate_value_type(), processor);
530                }
531            }
532        }
533    }
534
535    fn visit_expression_type(expression_type: &mut ExpressionType, processor: &mut T) {
536        processor.process_expression_type(expression_type);
537        Self::visit_expression(expression_type.mutate_expression(), processor);
538    }
539
540    fn visit_parenthese_type(parenthese: &mut ParentheseType, processor: &mut T) {
541        processor.process_parenthese_type(parenthese);
542        Self::visit_type(parenthese.mutate_inner_type(), processor);
543    }
544
545    fn visit_function_type(function: &mut FunctionType, processor: &mut T) {
546        processor.process_function_type(function);
547
548        for argument in function.iter_mut_arguments() {
549            Self::visit_type(argument.mutate_type(), processor);
550        }
551
552        if let Some(variadic_type) = function.mutate_variadic_argument_type() {
553            Self::visit_variadic_argument_type(variadic_type, processor);
554        }
555
556        Self::visit_function_return_type(function.mutate_return_type(), processor);
557    }
558
559    fn visit_optional_type(optional: &mut OptionalType, processor: &mut T) {
560        processor.process_optional_type(optional);
561        Self::visit_type(optional.mutate_inner_type(), processor);
562    }
563
564    fn visit_intersection_type(intersection: &mut IntersectionType, processor: &mut T) {
565        processor.process_intersection_type(intersection);
566
567        for r#type in intersection.iter_mut_types() {
568            Self::visit_type(r#type, processor);
569        }
570    }
571
572    fn visit_union_type(union: &mut UnionType, processor: &mut T) {
573        processor.process_union_type(union);
574
575        for r#type in union.iter_mut_types() {
576            Self::visit_type(r#type, processor);
577        }
578    }
579
580    fn visit_string_type(string: &mut StringType, processor: &mut T) {
581        processor.process_string_type(string);
582    }
583
584    fn visit_type_pack(type_pack: &mut TypePack, processor: &mut T) {
585        processor.process_type_pack(type_pack);
586
587        for next_type in type_pack.into_iter() {
588            Self::visit_type(next_type, processor)
589        }
590        if let Some(variadic_type) = type_pack.mutate_variadic_type() {
591            Self::visit_variadic_argument_type(variadic_type, processor);
592        }
593    }
594
595    fn visit_variadic_type_pack(variadic_type_pack: &mut VariadicTypePack, processor: &mut T) {
596        processor.process_variadic_type_pack(variadic_type_pack);
597        Self::visit_type(variadic_type_pack.mutate_type(), processor);
598    }
599
600    fn visit_variadic_argument_type(variadic_type: &mut VariadicArgumentType, processor: &mut T) {
601        match variadic_type {
602            VariadicArgumentType::VariadicTypePack(variadic_type_pack) => {
603                Self::visit_variadic_type_pack(variadic_type_pack, processor);
604            }
605            VariadicArgumentType::GenericTypePack(generic_type_pack) => {
606                Self::visit_generic_type_pack(generic_type_pack, processor);
607            }
608        }
609    }
610
611    fn visit_function_return_type(
612        function_return_type: &mut FunctionReturnType,
613        processor: &mut T,
614    ) {
615        match function_return_type {
616            FunctionReturnType::Type(next_type) => {
617                Self::visit_type(next_type, processor);
618            }
619            FunctionReturnType::TypePack(type_pack) => Self::visit_type_pack(type_pack, processor),
620            FunctionReturnType::VariadicTypePack(variadic_type_pack) => {
621                Self::visit_variadic_type_pack(variadic_type_pack, processor);
622            }
623            FunctionReturnType::GenericTypePack(generic_type_pack) => {
624                Self::visit_generic_type_pack(generic_type_pack, processor);
625            }
626        }
627    }
628}
629
630/// The default node visitor.
631pub struct DefaultVisitor<T> {
632    _phantom: PhantomData<T>,
633}
634
635impl<T: NodeProcessor> NodeVisitor<T> for DefaultVisitor<T> {}
636
637#[cfg(test)]
638mod test {
639    use super::*;
640    use crate::process::NodeCounter;
641
642    #[test]
643    fn visit_do_statement() {
644        let mut counter = NodeCounter::new();
645        let mut block = Block::default().with_statement(DoStatement::default());
646
647        DefaultVisitor::visit_block(&mut block, &mut counter);
648
649        assert_eq!(counter.block_count, 2);
650        assert_eq!(counter.do_count, 1);
651    }
652
653    #[test]
654    fn visit_numeric_for_statement() {
655        let mut counter = NodeCounter::new();
656        let mut block = Block::default().with_statement(NumericForStatement::new(
657            "i".to_owned(),
658            Expression::from(true),
659            Expression::from(true),
660            None,
661            Block::default(),
662        ));
663
664        DefaultVisitor::visit_block(&mut block, &mut counter);
665
666        assert_eq!(counter.block_count, 2);
667        assert_eq!(counter.expression_count, 2);
668        assert_eq!(counter.numeric_for_count, 1);
669    }
670
671    #[test]
672    fn visit_generic_for_statement() {
673        let mut counter = NodeCounter::new();
674        let mut block = Block::default().with_statement(GenericForStatement::new(
675            vec!["k".into()],
676            vec![Expression::from(true)],
677            Block::default(),
678        ));
679
680        DefaultVisitor::visit_block(&mut block, &mut counter);
681
682        assert_eq!(counter.block_count, 2);
683        assert_eq!(counter.expression_count, 1);
684        assert_eq!(counter.generic_for_count, 1);
685    }
686
687    #[test]
688    fn visit_repeat_statement() {
689        let mut counter = NodeCounter::new();
690        let mut block =
691            Block::default().with_statement(RepeatStatement::new(Block::default(), true));
692
693        DefaultVisitor::visit_block(&mut block, &mut counter);
694
695        assert_eq!(counter.block_count, 2);
696        assert_eq!(counter.expression_count, 1);
697        assert_eq!(counter.repeat_count, 1);
698    }
699
700    #[test]
701    fn visit_while_statement() {
702        let mut counter = NodeCounter::new();
703        let mut block =
704            Block::default().with_statement(WhileStatement::new(Block::default(), true));
705
706        DefaultVisitor::visit_block(&mut block, &mut counter);
707
708        assert_eq!(counter.block_count, 2);
709        assert_eq!(counter.expression_count, 1);
710        assert_eq!(counter.while_count, 1);
711    }
712
713    #[test]
714    fn visit_if_statement() {
715        let mut counter = NodeCounter::new();
716        let mut block =
717            Block::default().with_statement(IfStatement::create(true, Block::default()));
718
719        DefaultVisitor::visit_block(&mut block, &mut counter);
720
721        assert_eq!(counter.block_count, 2);
722        assert_eq!(counter.expression_count, 1);
723        assert_eq!(counter.if_count, 1);
724    }
725
726    #[test]
727    fn visit_if_statement_with_else() {
728        let mut counter = NodeCounter::new();
729        let if_statement =
730            IfStatement::create(true, Block::default()).with_else_block(Block::default());
731
732        let mut block = Block::default().with_statement(if_statement);
733
734        DefaultVisitor::visit_block(&mut block, &mut counter);
735
736        assert_eq!(counter.block_count, 3);
737        assert_eq!(counter.expression_count, 1);
738        assert_eq!(counter.if_count, 1);
739    }
740
741    #[test]
742    fn visit_if_statement_with_elseif_and_else() {
743        let mut counter = NodeCounter::new();
744        let if_statement = IfStatement::create(true, Block::default())
745            .with_new_branch(false, Block::default())
746            .with_else_block(Block::default());
747
748        let mut block = Block::default().with_statement(if_statement);
749
750        DefaultVisitor::visit_block(&mut block, &mut counter);
751
752        assert_eq!(counter.block_count, 4);
753        assert_eq!(counter.expression_count, 2);
754        assert_eq!(counter.if_count, 1);
755    }
756
757    #[test]
758    fn visit_compound_assign_statement() {
759        let mut counter = NodeCounter::new();
760        let statement =
761            CompoundAssignStatement::new(CompoundOperator::Plus, Variable::new("var"), 1_f64);
762
763        let mut block = statement.into();
764
765        DefaultVisitor::visit_block(&mut block, &mut counter);
766
767        assert_eq!(counter.compound_assign, 1);
768        assert_eq!(counter.expression_count, 1);
769        assert_eq!(counter.variable_count, 1);
770    }
771
772    #[test]
773    fn visit_interpolated_string() {
774        let mut counter = NodeCounter::new();
775        let statement = LocalAssignStatement::from_variable("value")
776            .with_value(InterpolatedStringExpression::empty().with_segment(Expression::from(true)));
777
778        let mut block = statement.into();
779
780        DefaultVisitor::visit_block(&mut block, &mut counter);
781
782        assert_eq!(counter.interpolated_string_count, 1);
783        assert_eq!(counter.expression_count, 2);
784    }
785}