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