1use crate::ast::ArrayElement;
2use crate::ast::ClassOrObjectMemberKey;
3use crate::ast::ClassOrObjectMemberValue;
4use crate::ast::ExportNames;
5use crate::ast::ForInit;
6use crate::ast::LiteralTemplatePart;
7use crate::ast::Node;
8use crate::ast::ObjectMemberType;
9use crate::ast::Syntax;
10
11pub struct JourneyControls {
14 skip: bool,
15}
16
17impl JourneyControls {
18 pub fn skip(&mut self) {
19 self.skip = true;
20 }
21}
22
23pub trait Visitor {
24 fn on_syntax_down(&mut self, node: &Node, ctl: &mut JourneyControls) {}
25
26 fn on_syntax_up(&mut self, node: &Node) {}
27
28 fn visit_class_or_object_key(&mut self, key: &ClassOrObjectMemberKey) {
29 match key {
30 ClassOrObjectMemberKey::Direct(_) => {}
31 ClassOrObjectMemberKey::Computed(key) => self.visit(key),
32 };
33 }
34
35 fn visit_class_or_object_value(&mut self, value: &ClassOrObjectMemberValue) {
36 match value {
37 ClassOrObjectMemberValue::Getter { function } => self.visit(function),
38 ClassOrObjectMemberValue::Method { function, .. } => {
39 self.visit(function);
40 }
41 ClassOrObjectMemberValue::Property { initializer } => {
42 if let Some(initializer) = initializer {
43 self.visit(initializer);
44 };
45 }
46 ClassOrObjectMemberValue::Setter { function } => {
47 self.visit(function);
48 }
49 }
50 }
51
52 fn visit(&mut self, n: &Node) {
53 let mut ctl = JourneyControls { skip: false };
54 self.on_syntax_down(n, &mut ctl);
55 if ctl.skip {
56 return;
57 };
58
59 match n.stx.as_ref() {
60 Syntax::TopLevel { body } => {
61 for stmt in body {
62 self.visit(stmt);
63 }
64 }
65 Syntax::FunctionExpr { name, function, .. } => {
66 if let Some(name) = name {
67 self.visit(name);
68 };
69 self.visit(function);
70 }
71 Syntax::IdentifierPattern { .. }
72 | Syntax::IdentifierExpr { .. }
73 | Syntax::ClassOrFunctionName { .. } => {}
74 Syntax::ArrayPattern { elements, rest } => {
75 for elem in elements {
76 if let Some(elem) = elem {
77 self.visit(&elem.target);
78 };
79 }
80 if let Some(rest) = rest {
81 self.visit(rest);
82 };
83 }
84 Syntax::ArrowFunctionExpr { function, .. } => {
85 self.visit(function);
86 }
87 Syntax::BinaryExpr {
88 left,
89 right,
90 operator,
91 ..
92 } => {
93 if operator.is_assignment()
94 && match left.stx.as_ref() {
95 Syntax::ArrayPattern { .. }
96 | Syntax::ObjectPattern { .. }
97 | Syntax::IdentifierPattern { .. } => true,
98 _ => false,
99 }
100 {
101 self.visit(right);
102 self.visit(left);
103 } else {
104 self.visit(left);
105 self.visit(right);
106 };
107 }
108 Syntax::BlockStmt { body } => {
109 for stmt in body {
110 self.visit(stmt);
111 }
112 }
113 Syntax::BreakStmt { .. } => {}
114 Syntax::CallExpr {
115 callee, arguments, ..
116 } => {
117 for arg in arguments {
118 self.visit(arg);
119 }
120 self.visit(callee);
121 }
122 Syntax::CatchBlock { parameter, body } => {
123 if let Some(param) = parameter {
124 self.visit(param);
125 }
126 for stmt in body {
127 self.visit(stmt);
128 }
129 }
130 Syntax::ClassDecl {
131 name,
132 extends,
133 members,
134 ..
135 } => {
136 if let Some(name) = name {
137 self.visit(name);
138 }
139 if let Some(extends) = extends {
140 self.visit(extends);
141 };
142 for member in members {
143 self.visit(member);
144 }
145 }
146 Syntax::ClassExpr {
147 name,
148 extends,
149 members,
150 ..
151 } => {
152 if let Some(name) = name {
153 self.visit(name);
154 }
155 if let Some(extends) = extends {
156 self.visit(extends);
157 };
158 for member in members {
159 self.visit(member);
160 }
161 }
162 Syntax::ClassMember { key, value, .. } => {
163 self.visit_class_or_object_key(key);
164 self.visit_class_or_object_value(value);
165 }
166 Syntax::ComputedMemberExpr { object, member, .. } => {
167 self.visit(object);
168 self.visit(member);
169 }
170 Syntax::ConditionalExpr {
171 test,
172 consequent,
173 alternate,
174 ..
175 } => {
176 self.visit(test);
177 self.visit(consequent);
178 self.visit(alternate);
179 }
180 Syntax::ContinueStmt { .. } => {}
181 Syntax::DebuggerStmt {} => {}
182 Syntax::DoWhileStmt { condition, body } => {
183 self.visit(body);
184 self.visit(condition);
185 }
186 Syntax::EmptyStmt {} => {}
187 Syntax::ExportDefaultExprStmt { expression } => self.visit(expression),
188 Syntax::ExportListStmt { names, .. } => match names {
189 ExportNames::All(alias) => {
190 if let Some(alias) = alias {
191 self.visit(alias);
192 }
193 }
194 ExportNames::Specific(imports) => {
195 for imp in imports {
196 self.visit(&imp.alias);
197 }
198 }
199 },
200 Syntax::ExpressionStmt { expression } => {
201 self.visit(expression);
202 }
203 Syntax::ForBody { body } => {
204 for stmt in body {
205 self.visit(stmt);
206 }
207 }
208 Syntax::ForStmt {
209 body,
210 condition,
211 init,
212 post,
213 } => {
214 match init {
215 ForInit::None => {}
216 ForInit::Expression(expr) => self.visit(expr),
217 ForInit::Declaration(decl) => self.visit(decl),
218 };
219 if let Some(condition) = condition {
220 self.visit(condition);
221 };
222 self.visit(body);
223 if let Some(post) = post {
224 self.visit(post);
225 };
226 }
227 Syntax::ForInStmt { pat, rhs, body, .. } => {
228 self.visit(pat);
229 self.visit(rhs);
230 self.visit(body);
231 }
232 Syntax::ForOfStmt { pat, rhs, body, .. } => {
233 self.visit(pat);
234 self.visit(rhs);
235 self.visit(body);
236 }
237 Syntax::Function {
238 parameters, body, ..
239 } => {
240 for param in parameters {
241 self.visit(param);
242 }
243 self.visit(body);
244 }
245 Syntax::FunctionBody { body } => {
246 for stmt in body {
247 self.visit(stmt);
248 }
249 }
250 Syntax::FunctionDecl { name, function, .. } => {
251 if let Some(name) = name {
252 self.visit(name);
253 }
254 self.visit(function);
255 }
256 Syntax::IfStmt {
257 test,
258 consequent,
259 alternate,
260 } => {
261 self.visit(test);
262 self.visit(consequent);
263 if let Some(alternate) = alternate {
264 self.visit(alternate);
265 };
266 }
267 Syntax::ImportExpr { module } => self.visit(module),
268 Syntax::ImportMeta {} => {}
269 Syntax::ImportStmt { default, names, .. } => {
270 if let Some(default) = default {
271 self.visit(default);
272 };
273 for name in names {
274 match name {
275 ExportNames::All(alias) => {
276 if let Some(alias) = alias {
277 self.visit(alias);
278 }
279 }
280 ExportNames::Specific(names) => {
281 for name in names {
282 self.visit(&name.alias);
283 }
284 }
285 }
286 }
287 }
288 Syntax::JsxAttribute { name, value } => {
289 self.visit(name);
290 if let Some(value) = value {
291 self.visit(value);
292 };
293 }
294 Syntax::JsxElement {
295 attributes,
296 children,
297 name,
298 } => {
299 if let Some(name) = name {
300 self.visit(name);
301 }
302 for attr in attributes {
303 self.visit(attr);
304 }
305 for child in children {
306 self.visit(child);
307 }
308 }
309 Syntax::JsxExpressionContainer { value } => {
310 self.visit(value);
311 }
312 Syntax::JsxMemberExpression { base, .. } => {
313 self.visit(base);
314 }
315 Syntax::JsxName { .. } => {}
316 Syntax::JsxSpreadAttribute { value } => {
317 self.visit(value);
318 }
319 Syntax::JsxText { .. } => {}
320 Syntax::LiteralArrayExpr { elements } => {
321 for elem in elements {
322 match elem {
323 ArrayElement::Single(elem) => self.visit(elem),
324 ArrayElement::Rest(elem) => self.visit(elem),
325 ArrayElement::Empty => {}
326 }
327 }
328 }
329 Syntax::LiteralBigIntExpr { .. } => {}
330 Syntax::LiteralBooleanExpr { .. } => {}
331 Syntax::LiteralNull {} => {}
332 Syntax::LiteralNumberExpr { .. } => {}
333 Syntax::LiteralObjectExpr { members } => {
334 for member in members {
335 self.visit(member);
336 }
337 }
338 Syntax::LiteralRegexExpr { .. } => {}
339 Syntax::LiteralStringExpr { .. } => {}
340 Syntax::LiteralTemplateExpr { parts } => {
341 for part in parts {
342 match part {
343 LiteralTemplatePart::Substitution(expr) => self.visit(expr),
344 LiteralTemplatePart::String(_) => {}
345 }
346 }
347 }
348 Syntax::ObjectPattern { properties, rest } => {
349 for prop in properties {
350 self.visit(prop);
351 }
352 if let Some(rest) = rest {
353 self.visit(rest);
354 }
355 }
356 Syntax::ObjectPatternProperty {
357 key,
358 target,
359 default_value,
360 ..
361 } => {
362 match key {
363 ClassOrObjectMemberKey::Direct(..) => {}
364 ClassOrObjectMemberKey::Computed(key) => self.visit(key),
365 };
366 self.visit(target);
367 if let Some(value) = default_value {
368 self.visit(value);
369 }
370 }
371 Syntax::ParamDecl {
372 pattern,
373 default_value,
374 ..
375 } => {
376 self.visit(pattern);
377 if let Some(value) = default_value {
378 self.visit(value);
379 }
380 }
381 Syntax::ReturnStmt { value } => {
382 if let Some(value) = value {
383 self.visit(value);
384 }
385 }
386 Syntax::SwitchBranch { case, body } => {
387 if let Some(value) = case {
388 self.visit(value);
389 }
390 for stmt in body {
391 self.visit(stmt);
392 }
393 }
394 Syntax::SwitchStmt { test, branches } => {
395 self.visit(test);
396 for branch in branches {
397 self.visit(branch);
398 }
399 }
400 Syntax::TaggedTemplateExpr { function, parts } => {
401 self.visit(function);
402 for part in parts {
403 match part {
404 LiteralTemplatePart::Substitution(expr) => self.visit(expr),
405 LiteralTemplatePart::String(_) => {}
406 }
407 }
408 }
409 Syntax::ThisExpr {} => {}
410 Syntax::ThrowStmt { value } => {
411 self.visit(value);
412 }
413 Syntax::TryStmt {
414 wrapped,
415 catch,
416 finally,
417 } => {
418 self.visit(wrapped);
419 if let Some(catch) = catch {
420 self.visit(catch);
421 }
422 if let Some(finally) = finally {
423 self.visit(finally);
424 }
425 }
426 Syntax::UnaryExpr { argument, .. } => {
427 self.visit(argument);
428 }
429 Syntax::UnaryPostfixExpr { argument, .. } => {
430 self.visit(argument);
431 }
432 Syntax::VarDecl { declarators, .. } => {
433 for decl in declarators {
434 self.visit(&decl.pattern);
435 if let Some(init) = &decl.initializer {
436 self.visit(init);
437 }
438 }
439 }
440 Syntax::WhileStmt { condition, body } => {
441 self.visit(condition);
442 self.visit(body);
443 }
444 Syntax::ObjectMember { typ } => {
445 match typ {
446 ObjectMemberType::Valued { key, value } => {
447 self.visit_class_or_object_key(key);
448 self.visit_class_or_object_value(value);
449 }
450 ObjectMemberType::Shorthand { .. } => {}
451 ObjectMemberType::Rest { value } => {
452 self.visit(value);
453 }
454 };
455 }
456 Syntax::MemberExpr { left, .. } => {
457 self.visit(left);
458 }
459 Syntax::LabelStmt { statement, .. } => {
460 self.visit(statement);
461 }
462 Syntax::CallArg { value, .. } => {
463 self.visit(value);
464 }
465 Syntax::SuperExpr {} => {}
466 };
467
468 self.on_syntax_up(n);
469 }
470}
471
472pub trait VisitorMut {
473 fn on_syntax_down(&mut self, node: &mut Node, ctl: &mut JourneyControls) {}
474
475 fn on_syntax_up(&mut self, node: &mut Node) {}
476
477 fn visit_class_or_object_key(&mut self, key: &mut ClassOrObjectMemberKey) {
478 match key {
479 ClassOrObjectMemberKey::Direct(_) => {}
480 ClassOrObjectMemberKey::Computed(key) => self.visit(key),
481 };
482 }
483
484 fn visit_class_or_object_value(&mut self, value: &mut ClassOrObjectMemberValue) {
485 match value {
486 ClassOrObjectMemberValue::Getter { function } => self.visit(function),
487 ClassOrObjectMemberValue::Method { function, .. } => {
488 self.visit(function);
489 }
490 ClassOrObjectMemberValue::Property { initializer } => {
491 if let Some(initializer) = initializer {
492 self.visit(initializer);
493 };
494 }
495 ClassOrObjectMemberValue::Setter { function } => {
496 self.visit(function);
497 }
498 }
499 }
500
501 fn visit(&mut self, n: &mut Node) {
502 let mut cur_stx_type = core::mem::discriminant(n.stx.as_ref());
503 loop {
504 let mut ctl = JourneyControls { skip: false };
505 self.on_syntax_down(n, &mut ctl);
506 if ctl.skip {
507 return;
508 };
509 let new_stx_type = core::mem::discriminant(n.stx.as_ref());
510 if cur_stx_type == new_stx_type {
511 break;
512 };
513 cur_stx_type = new_stx_type;
514 }
515
516 match n.stx.as_mut() {
517 Syntax::TopLevel { body } => {
518 for stmt in body {
519 self.visit(stmt);
520 }
521 }
522 Syntax::FunctionExpr { name, function, .. } => {
523 if let Some(name) = name {
524 self.visit(name);
525 };
526 self.visit(function);
527 }
528 Syntax::IdentifierPattern { .. }
529 | Syntax::IdentifierExpr { .. }
530 | Syntax::ClassOrFunctionName { .. } => {}
531 Syntax::ArrayPattern { elements, rest } => {
532 for elem in elements {
533 if let Some(elem) = elem {
534 self.visit(&mut elem.target);
535 };
536 }
537 if let Some(rest) = rest {
538 self.visit(rest);
539 };
540 }
541 Syntax::ArrowFunctionExpr { function, .. } => {
542 self.visit(function);
543 }
544 Syntax::BinaryExpr {
545 left,
546 right,
547 operator,
548 ..
549 } => {
550 if operator.is_assignment()
551 && match left.stx.as_ref() {
552 Syntax::ArrayPattern { .. }
553 | Syntax::ObjectPattern { .. }
554 | Syntax::IdentifierPattern { .. } => true,
555 _ => false,
556 }
557 {
558 self.visit(right);
559 self.visit(left);
560 } else {
561 self.visit(left);
562 self.visit(right);
563 };
564 }
565 Syntax::BlockStmt { body } => {
566 for stmt in body {
567 self.visit(stmt);
568 }
569 }
570 Syntax::BreakStmt { .. } => {}
571 Syntax::CallExpr {
572 callee, arguments, ..
573 } => {
574 for arg in arguments {
575 self.visit(arg);
576 }
577 self.visit(callee);
578 }
579 Syntax::CatchBlock { parameter, body } => {
580 if let Some(param) = parameter {
581 self.visit(param);
582 }
583 for stmt in body {
584 self.visit(stmt);
585 }
586 }
587 Syntax::ClassDecl {
588 name,
589 extends,
590 members,
591 ..
592 } => {
593 if let Some(name) = name {
594 self.visit(name);
595 }
596 if let Some(extends) = extends {
597 self.visit(extends);
598 };
599 for member in members {
600 self.visit(member);
601 }
602 }
603 Syntax::ClassExpr {
604 name,
605 extends,
606 members,
607 ..
608 } => {
609 if let Some(name) = name {
610 self.visit(name);
611 }
612 if let Some(extends) = extends {
613 self.visit(extends);
614 };
615 for member in members {
616 self.visit(member);
617 }
618 }
619 Syntax::ClassMember { key, value, .. } => {
620 self.visit_class_or_object_key(key);
621 self.visit_class_or_object_value(value);
622 }
623 Syntax::ComputedMemberExpr { object, member, .. } => {
624 self.visit(object);
625 self.visit(member);
626 }
627 Syntax::ConditionalExpr {
628 test,
629 consequent,
630 alternate,
631 ..
632 } => {
633 self.visit(test);
634 self.visit(consequent);
635 self.visit(alternate);
636 }
637 Syntax::ContinueStmt { .. } => {}
638 Syntax::DebuggerStmt {} => {}
639 Syntax::DoWhileStmt { condition, body } => {
640 self.visit(body);
641 self.visit(condition);
642 }
643 Syntax::EmptyStmt {} => {}
644 Syntax::ExportDefaultExprStmt { expression } => self.visit(expression),
645 Syntax::ExportListStmt { names, .. } => match names {
646 ExportNames::All(alias) => {
647 if let Some(alias) = alias {
648 self.visit(alias);
649 }
650 }
651 ExportNames::Specific(imports) => {
652 for imp in imports {
653 self.visit(&mut imp.alias);
654 }
655 }
656 },
657 Syntax::ExpressionStmt { expression } => {
658 self.visit(expression);
659 }
660 Syntax::ForBody { body } => {
661 for stmt in body {
662 self.visit(stmt);
663 }
664 }
665 Syntax::ForStmt {
666 body,
667 condition,
668 init,
669 post,
670 } => {
671 match init {
672 ForInit::None => {}
673 ForInit::Expression(expr) => self.visit(expr),
674 ForInit::Declaration(decl) => self.visit(decl),
675 };
676 if let Some(condition) = condition {
677 self.visit(condition);
678 };
679 self.visit(body);
680 if let Some(post) = post {
681 self.visit(post);
682 };
683 }
684 Syntax::ForInStmt { pat, rhs, body, .. } => {
685 self.visit(pat);
686 self.visit(rhs);
687 self.visit(body);
688 }
689 Syntax::ForOfStmt { pat, rhs, body, .. } => {
690 self.visit(pat);
691 self.visit(rhs);
692 self.visit(body);
693 }
694 Syntax::Function {
695 parameters, body, ..
696 } => {
697 for param in parameters {
698 self.visit(param);
699 }
700 self.visit(body);
701 }
702 Syntax::FunctionBody { body } => {
703 for stmt in body {
704 self.visit(stmt);
705 }
706 }
707 Syntax::FunctionDecl { name, function, .. } => {
708 if let Some(name) = name {
709 self.visit(name);
710 }
711 self.visit(function);
712 }
713 Syntax::IfStmt {
714 test,
715 consequent,
716 alternate,
717 } => {
718 self.visit(test);
719 self.visit(consequent);
720 if let Some(alternate) = alternate {
721 self.visit(alternate);
722 };
723 }
724 Syntax::ImportExpr { module } => self.visit(module),
725 Syntax::ImportMeta {} => {}
726 Syntax::ImportStmt { default, names, .. } => {
727 if let Some(default) = default {
728 self.visit(default);
729 };
730 for name in names {
731 match name {
732 ExportNames::All(alias) => {
733 if let Some(alias) = alias {
734 self.visit(alias);
735 }
736 }
737 ExportNames::Specific(names) => {
738 for name in names {
739 self.visit(&mut name.alias);
740 }
741 }
742 }
743 }
744 }
745 Syntax::JsxAttribute { name, value } => {
746 self.visit(name);
747 if let Some(value) = value {
748 self.visit(value);
749 };
750 }
751 Syntax::JsxElement {
752 attributes,
753 children,
754 name,
755 } => {
756 if let Some(name) = name {
757 self.visit(name);
758 }
759 for attr in attributes {
760 self.visit(attr);
761 }
762 for child in children {
763 self.visit(child);
764 }
765 }
766 Syntax::JsxExpressionContainer { value } => {
767 self.visit(value);
768 }
769 Syntax::JsxMemberExpression { base, .. } => {
770 self.visit(base);
771 }
772 Syntax::JsxName { .. } => {}
773 Syntax::JsxSpreadAttribute { value } => {
774 self.visit(value);
775 }
776 Syntax::JsxText { .. } => {}
777 Syntax::LiteralArrayExpr { elements } => {
778 for elem in elements {
779 match elem {
780 ArrayElement::Single(elem) => self.visit(elem),
781 ArrayElement::Rest(elem) => self.visit(elem),
782 ArrayElement::Empty => {}
783 }
784 }
785 }
786 Syntax::LiteralBigIntExpr { .. } => {}
787 Syntax::LiteralBooleanExpr { .. } => {}
788 Syntax::LiteralNull {} => {}
789 Syntax::LiteralNumberExpr { .. } => {}
790 Syntax::LiteralObjectExpr { members } => {
791 for member in members {
792 self.visit(member);
793 }
794 }
795 Syntax::LiteralRegexExpr { .. } => {}
796 Syntax::LiteralStringExpr { .. } => {}
797 Syntax::LiteralTemplateExpr { parts } => {
798 for part in parts {
799 match part {
800 LiteralTemplatePart::Substitution(expr) => self.visit(expr),
801 LiteralTemplatePart::String(_) => {}
802 }
803 }
804 }
805 Syntax::ObjectPattern { properties, rest } => {
806 for prop in properties {
807 self.visit(prop);
808 }
809 if let Some(rest) = rest {
810 self.visit(rest);
811 }
812 }
813 Syntax::ObjectPatternProperty {
814 key,
815 target,
816 default_value,
817 ..
818 } => {
819 match key {
820 ClassOrObjectMemberKey::Direct(..) => {}
821 ClassOrObjectMemberKey::Computed(key) => self.visit(key),
822 };
823 self.visit(target);
824 if let Some(value) = default_value {
825 self.visit(value);
826 }
827 }
828 Syntax::ParamDecl {
829 pattern,
830 default_value,
831 ..
832 } => {
833 self.visit(pattern);
834 if let Some(value) = default_value {
835 self.visit(value);
836 }
837 }
838 Syntax::ReturnStmt { value } => {
839 if let Some(value) = value {
840 self.visit(value);
841 }
842 }
843 Syntax::SwitchBranch { case, body } => {
844 if let Some(value) = case {
845 self.visit(value);
846 }
847 for stmt in body {
848 self.visit(stmt);
849 }
850 }
851 Syntax::SwitchStmt { test, branches } => {
852 self.visit(test);
853 for branch in branches {
854 self.visit(branch);
855 }
856 }
857 Syntax::TaggedTemplateExpr { function, parts } => {
858 self.visit(function);
859 for part in parts {
860 match part {
861 LiteralTemplatePart::Substitution(expr) => self.visit(expr),
862 LiteralTemplatePart::String(_) => {}
863 }
864 }
865 }
866 Syntax::ThisExpr {} => {}
867 Syntax::ThrowStmt { value } => {
868 self.visit(value);
869 }
870 Syntax::TryStmt {
871 wrapped,
872 catch,
873 finally,
874 } => {
875 self.visit(wrapped);
876 if let Some(catch) = catch {
877 self.visit(catch);
878 }
879 if let Some(finally) = finally {
880 self.visit(finally);
881 }
882 }
883 Syntax::UnaryExpr { argument, .. } => {
884 self.visit(argument);
885 }
886 Syntax::UnaryPostfixExpr { argument, .. } => {
887 self.visit(argument);
888 }
889 Syntax::VarDecl { declarators, .. } => {
890 for decl in declarators {
891 self.visit(&mut decl.pattern);
892 if let Some(init) = &mut decl.initializer {
893 self.visit(init);
894 }
895 }
896 }
897 Syntax::WhileStmt { condition, body } => {
898 self.visit(condition);
899 self.visit(body);
900 }
901 Syntax::ObjectMember { typ } => {
902 match typ {
903 ObjectMemberType::Valued { key, value } => {
904 self.visit_class_or_object_key(key);
905 self.visit_class_or_object_value(value);
906 }
907 ObjectMemberType::Shorthand { .. } => {}
908 ObjectMemberType::Rest { value } => {
909 self.visit(value);
910 }
911 };
912 }
913 Syntax::MemberExpr { left, .. } => {
914 self.visit(left);
915 }
916 Syntax::LabelStmt { statement, .. } => {
917 self.visit(statement);
918 }
919 Syntax::CallArg { value, .. } => {
920 self.visit(value);
921 }
922 Syntax::SuperExpr {} => {}
923 };
924
925 loop {
926 self.on_syntax_up(n);
927 let new_stx_type = core::mem::discriminant(n.stx.as_ref());
928 if cur_stx_type == new_stx_type {
929 break;
930 };
931 cur_stx_type = new_stx_type;
932 }
933 }
934}