parse_js/
visit.rs

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
11/// Nodes must be visited in execution order. This is helpful for many uses.
12
13pub 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}