1use crate::Program;
8use crate::declarations::*;
9use crate::expressions::*;
10use crate::jsx::*;
11use crate::patterns::*;
12use crate::scope::ScopeId;
13use crate::scope::ScopeInfo;
14use crate::statements::*;
15
16pub trait Visitor<'ast> {
25 fn traverse_function_bodies(&self) -> bool {
32 true
33 }
34
35 fn enter_function_declaration(
36 &mut self,
37 _node: &'ast FunctionDeclaration,
38 _scope_stack: &[ScopeId],
39 ) {
40 }
41 fn leave_function_declaration(
42 &mut self,
43 _node: &'ast FunctionDeclaration,
44 _scope_stack: &[ScopeId],
45 ) {
46 }
47 fn enter_function_expression(
48 &mut self,
49 _node: &'ast FunctionExpression,
50 _scope_stack: &[ScopeId],
51 ) {
52 }
53 fn leave_function_expression(
54 &mut self,
55 _node: &'ast FunctionExpression,
56 _scope_stack: &[ScopeId],
57 ) {
58 }
59 fn enter_arrow_function_expression(
60 &mut self,
61 _node: &'ast ArrowFunctionExpression,
62 _scope_stack: &[ScopeId],
63 ) {
64 }
65 fn leave_arrow_function_expression(
66 &mut self,
67 _node: &'ast ArrowFunctionExpression,
68 _scope_stack: &[ScopeId],
69 ) {
70 }
71 fn enter_class_declaration(
72 &mut self,
73 _node: &'ast crate::statements::ClassDeclaration,
74 _scope_stack: &[ScopeId],
75 ) {
76 }
77 fn enter_class_expression(&mut self, _node: &'ast ClassExpression, _scope_stack: &[ScopeId]) {}
78 fn enter_object_method(&mut self, _node: &'ast ObjectMethod, _scope_stack: &[ScopeId]) {}
79 fn leave_object_method(&mut self, _node: &'ast ObjectMethod, _scope_stack: &[ScopeId]) {}
80 fn enter_assignment_expression(
81 &mut self,
82 _node: &'ast AssignmentExpression,
83 _scope_stack: &[ScopeId],
84 ) {
85 }
86 fn enter_update_expression(&mut self, _node: &'ast UpdateExpression, _scope_stack: &[ScopeId]) {
87 }
88 fn enter_identifier(&mut self, _node: &'ast Identifier, _scope_stack: &[ScopeId]) {}
89 fn enter_jsx_identifier(&mut self, _node: &'ast JSXIdentifier, _scope_stack: &[ScopeId]) {}
90 fn enter_jsx_opening_element(
91 &mut self,
92 _node: &'ast JSXOpeningElement,
93 _scope_stack: &[ScopeId],
94 ) {
95 }
96 fn leave_jsx_opening_element(
97 &mut self,
98 _node: &'ast JSXOpeningElement,
99 _scope_stack: &[ScopeId],
100 ) {
101 }
102
103 fn enter_variable_declarator(
104 &mut self,
105 _node: &'ast VariableDeclarator,
106 _scope_stack: &[ScopeId],
107 ) {
108 }
109 fn leave_variable_declarator(
110 &mut self,
111 _node: &'ast VariableDeclarator,
112 _scope_stack: &[ScopeId],
113 ) {
114 }
115
116 fn enter_call_expression(&mut self, _node: &'ast CallExpression, _scope_stack: &[ScopeId]) {}
117 fn leave_call_expression(&mut self, _node: &'ast CallExpression, _scope_stack: &[ScopeId]) {}
118
119 fn enter_loop_expression(&mut self) {}
124 fn leave_loop_expression(&mut self) {}
125}
126
127pub struct AstWalker<'a> {
129 scope_info: &'a ScopeInfo,
130 scope_stack: Vec<ScopeId>,
131 loop_expression_depth: usize,
137}
138
139impl<'a> AstWalker<'a> {
140 pub fn new(scope_info: &'a ScopeInfo) -> Self {
141 AstWalker {
142 scope_info,
143 scope_stack: Vec::new(),
144 loop_expression_depth: 0,
145 }
146 }
147
148 pub fn with_initial_scope(scope_info: &'a ScopeInfo, initial_scope: ScopeId) -> Self {
150 AstWalker {
151 scope_info,
152 scope_stack: vec![initial_scope],
153 loop_expression_depth: 0,
154 }
155 }
156
157 pub fn scope_stack(&self) -> &[ScopeId] {
158 &self.scope_stack
159 }
160
161 pub fn loop_expression_depth(&self) -> usize {
166 self.loop_expression_depth
167 }
168
169 fn try_push_scope(&mut self, _start: Option<u32>, node_id: Option<u32>) -> bool {
171 let scope = self.scope_info.resolve_scope_for_node(node_id);
172 if let Some(scope_id) = scope {
173 self.scope_stack.push(scope_id);
174 return true;
175 }
176 false
177 }
178
179 pub fn walk_program<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast Program) {
182 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
183 for stmt in &node.body {
184 self.walk_statement(v, stmt);
185 }
186 if pushed {
187 self.scope_stack.pop();
188 }
189 }
190
191 pub fn walk_block_statement<'ast>(
192 &mut self,
193 v: &mut impl Visitor<'ast>,
194 node: &'ast BlockStatement,
195 ) {
196 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
197 for stmt in &node.body {
198 self.walk_statement(v, stmt);
199 }
200 if pushed {
201 self.scope_stack.pop();
202 }
203 }
204
205 pub fn walk_statement<'ast>(&mut self, v: &mut impl Visitor<'ast>, stmt: &'ast Statement) {
206 match stmt {
207 Statement::BlockStatement(node) => self.walk_block_statement(v, node),
208 Statement::ReturnStatement(node) => {
209 if let Some(arg) = &node.argument {
210 self.walk_expression(v, arg);
211 }
212 }
213 Statement::ExpressionStatement(node) => {
214 self.walk_expression(v, &node.expression);
215 }
216 Statement::IfStatement(node) => {
217 self.walk_expression(v, &node.test);
218 self.walk_statement(v, &node.consequent);
219 if let Some(alt) = &node.alternate {
220 self.walk_statement(v, alt);
221 }
222 }
223 Statement::ForStatement(node) => {
224 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
225 if let Some(init) = &node.init {
226 match init.as_ref() {
227 ForInit::VariableDeclaration(decl) => {
228 self.walk_variable_declaration(v, decl)
229 }
230 ForInit::Expression(expr) => self.walk_expression(v, expr),
231 }
232 }
233 if let Some(test) = &node.test {
234 self.walk_expression(v, test);
235 }
236 if let Some(update) = &node.update {
237 self.walk_expression(v, update);
238 }
239 self.walk_statement(v, &node.body);
240 if pushed {
241 self.scope_stack.pop();
242 }
243 }
244 Statement::WhileStatement(node) => {
245 self.loop_expression_depth += 1;
246 v.enter_loop_expression();
247 self.walk_expression(v, &node.test);
248 v.leave_loop_expression();
249 self.loop_expression_depth -= 1;
250 self.walk_statement(v, &node.body);
251 }
252 Statement::DoWhileStatement(node) => {
253 self.walk_statement(v, &node.body);
254 self.loop_expression_depth += 1;
255 v.enter_loop_expression();
256 self.walk_expression(v, &node.test);
257 v.leave_loop_expression();
258 self.loop_expression_depth -= 1;
259 }
260 Statement::ForInStatement(node) => {
261 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
262 self.walk_for_in_of_left(v, &node.left);
263 self.loop_expression_depth += 1;
264 v.enter_loop_expression();
265 self.walk_expression(v, &node.right);
266 v.leave_loop_expression();
267 self.loop_expression_depth -= 1;
268 self.walk_statement(v, &node.body);
269 if pushed {
270 self.scope_stack.pop();
271 }
272 }
273 Statement::ForOfStatement(node) => {
274 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
275 self.walk_for_in_of_left(v, &node.left);
276 self.loop_expression_depth += 1;
277 v.enter_loop_expression();
278 self.walk_expression(v, &node.right);
279 v.leave_loop_expression();
280 self.loop_expression_depth -= 1;
281 self.walk_statement(v, &node.body);
282 if pushed {
283 self.scope_stack.pop();
284 }
285 }
286 Statement::SwitchStatement(node) => {
287 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
288 self.walk_expression(v, &node.discriminant);
289 for case in &node.cases {
290 if let Some(test) = &case.test {
291 self.walk_expression(v, test);
292 }
293 for consequent in &case.consequent {
294 self.walk_statement(v, consequent);
295 }
296 }
297 if pushed {
298 self.scope_stack.pop();
299 }
300 }
301 Statement::ThrowStatement(node) => {
302 self.walk_expression(v, &node.argument);
303 }
304 Statement::TryStatement(node) => {
305 self.walk_block_statement(v, &node.block);
306 if let Some(handler) = &node.handler {
307 let pushed = self.try_push_scope(handler.base.start, handler.base.node_id);
308 if let Some(param) = &handler.param {
309 self.walk_pattern(v, param);
310 }
311 self.walk_block_statement(v, &handler.body);
312 if pushed {
313 self.scope_stack.pop();
314 }
315 }
316 if let Some(finalizer) = &node.finalizer {
317 self.walk_block_statement(v, finalizer);
318 }
319 }
320 Statement::LabeledStatement(node) => {
321 self.walk_statement(v, &node.body);
322 }
323 Statement::VariableDeclaration(node) => {
324 self.walk_variable_declaration(v, node);
325 }
326 Statement::FunctionDeclaration(node) => {
327 self.walk_function_declaration_inner(v, node);
328 }
329 Statement::ClassDeclaration(node) => {
330 v.enter_class_declaration(node, &self.scope_stack);
333 }
334 Statement::WithStatement(node) => {
335 self.walk_expression(v, &node.object);
336 self.walk_statement(v, &node.body);
337 }
338 Statement::ExportNamedDeclaration(node) => {
339 if let Some(decl) = &node.declaration {
340 self.walk_declaration(v, decl);
341 }
342 }
343 Statement::ExportDefaultDeclaration(node) => {
344 self.walk_export_default_decl(v, &node.declaration);
345 }
346 Statement::BreakStatement(_)
348 | Statement::ContinueStatement(_)
349 | Statement::EmptyStatement(_)
350 | Statement::DebuggerStatement(_)
351 | Statement::ImportDeclaration(_)
352 | Statement::ExportAllDeclaration(_)
353 | Statement::TSTypeAliasDeclaration(_)
354 | Statement::TSInterfaceDeclaration(_)
355 | Statement::TSEnumDeclaration(_)
356 | Statement::TSModuleDeclaration(_)
357 | Statement::TSDeclareFunction(_)
358 | Statement::TypeAlias(_)
359 | Statement::OpaqueType(_)
360 | Statement::InterfaceDeclaration(_)
361 | Statement::DeclareVariable(_)
362 | Statement::DeclareFunction(_)
363 | Statement::DeclareClass(_)
364 | Statement::DeclareModule(_)
365 | Statement::DeclareModuleExports(_)
366 | Statement::DeclareExportDeclaration(_)
367 | Statement::DeclareExportAllDeclaration(_)
368 | Statement::DeclareInterface(_)
369 | Statement::DeclareTypeAlias(_)
370 | Statement::DeclareOpaqueType(_)
371 | Statement::EnumDeclaration(_)
372 | Statement::Unknown(_) => {}
374 }
375 }
376
377 pub fn walk_expression<'ast>(&mut self, v: &mut impl Visitor<'ast>, expr: &'ast Expression) {
378 match expr {
379 Expression::Identifier(node) => {
380 v.enter_identifier(node, &self.scope_stack);
381 }
382 Expression::CallExpression(node) => {
383 v.enter_call_expression(node, &self.scope_stack);
384 self.walk_expression(v, &node.callee);
385 for arg in &node.arguments {
386 self.walk_expression(v, arg);
387 }
388 v.leave_call_expression(node, &self.scope_stack);
389 }
390 Expression::MemberExpression(node) => {
391 self.walk_expression(v, &node.object);
392 if node.computed {
393 self.walk_expression(v, &node.property);
394 }
395 }
396 Expression::OptionalCallExpression(node) => {
397 self.walk_expression(v, &node.callee);
398 for arg in &node.arguments {
399 self.walk_expression(v, arg);
400 }
401 }
402 Expression::OptionalMemberExpression(node) => {
403 self.walk_expression(v, &node.object);
404 if node.computed {
405 self.walk_expression(v, &node.property);
406 }
407 }
408 Expression::BinaryExpression(node) => {
409 self.walk_expression(v, &node.left);
410 self.walk_expression(v, &node.right);
411 }
412 Expression::LogicalExpression(node) => {
413 self.walk_expression(v, &node.left);
414 self.walk_expression(v, &node.right);
415 }
416 Expression::UnaryExpression(node) => {
417 self.walk_expression(v, &node.argument);
418 }
419 Expression::UpdateExpression(node) => {
420 v.enter_update_expression(node, &self.scope_stack);
421 self.walk_expression(v, &node.argument);
422 }
423 Expression::ConditionalExpression(node) => {
424 self.walk_expression(v, &node.test);
425 self.walk_expression(v, &node.consequent);
426 self.walk_expression(v, &node.alternate);
427 }
428 Expression::AssignmentExpression(node) => {
429 v.enter_assignment_expression(node, &self.scope_stack);
430 self.walk_pattern(v, &node.left);
431 self.walk_expression(v, &node.right);
432 }
433 Expression::SequenceExpression(node) => {
434 for expr in &node.expressions {
435 self.walk_expression(v, expr);
436 }
437 }
438 Expression::ArrowFunctionExpression(node) => {
439 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
440 v.enter_arrow_function_expression(node, &self.scope_stack);
441 if v.traverse_function_bodies() {
442 for param in &node.params {
443 self.walk_pattern(v, param);
444 }
445 match node.body.as_ref() {
446 ArrowFunctionBody::BlockStatement(block) => {
447 self.walk_block_statement(v, block);
448 }
449 ArrowFunctionBody::Expression(expr) => {
450 self.walk_expression(v, expr);
451 }
452 }
453 }
454 v.leave_arrow_function_expression(node, &self.scope_stack);
455 if pushed {
456 self.scope_stack.pop();
457 }
458 }
459 Expression::FunctionExpression(node) => {
460 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
461 v.enter_function_expression(node, &self.scope_stack);
462 if v.traverse_function_bodies() {
463 for param in &node.params {
464 self.walk_pattern(v, param);
465 }
466 self.walk_block_statement(v, &node.body);
467 }
468 v.leave_function_expression(node, &self.scope_stack);
469 if pushed {
470 self.scope_stack.pop();
471 }
472 }
473 Expression::ObjectExpression(node) => {
474 for prop in &node.properties {
475 self.walk_object_expression_property(v, prop);
476 }
477 }
478 Expression::ArrayExpression(node) => {
479 for element in &node.elements {
480 if let Some(el) = element {
481 self.walk_expression(v, el);
482 }
483 }
484 }
485 Expression::NewExpression(node) => {
486 self.walk_expression(v, &node.callee);
487 for arg in &node.arguments {
488 self.walk_expression(v, arg);
489 }
490 }
491 Expression::TemplateLiteral(node) => {
492 for expr in &node.expressions {
493 self.walk_expression(v, expr);
494 }
495 }
496 Expression::TaggedTemplateExpression(node) => {
497 self.walk_expression(v, &node.tag);
498 for expr in &node.quasi.expressions {
499 self.walk_expression(v, expr);
500 }
501 }
502 Expression::AwaitExpression(node) => {
503 self.walk_expression(v, &node.argument);
504 }
505 Expression::YieldExpression(node) => {
506 if let Some(arg) = &node.argument {
507 self.walk_expression(v, arg);
508 }
509 }
510 Expression::SpreadElement(node) => {
511 self.walk_expression(v, &node.argument);
512 }
513 Expression::ParenthesizedExpression(node) => {
514 self.walk_expression(v, &node.expression);
515 }
516 Expression::AssignmentPattern(node) => {
517 self.walk_pattern(v, &node.left);
518 self.walk_expression(v, &node.right);
519 }
520 Expression::ClassExpression(node) => {
521 v.enter_class_expression(node, &self.scope_stack);
524 }
525 Expression::JSXElement(node) => self.walk_jsx_element(v, node),
527 Expression::JSXFragment(node) => self.walk_jsx_fragment(v, node),
528 Expression::TSAsExpression(node) => self.walk_expression(v, &node.expression),
530 Expression::TSSatisfiesExpression(node) => self.walk_expression(v, &node.expression),
531 Expression::TSNonNullExpression(node) => self.walk_expression(v, &node.expression),
532 Expression::TSTypeAssertion(node) => self.walk_expression(v, &node.expression),
533 Expression::TSInstantiationExpression(node) => {
534 self.walk_expression(v, &node.expression)
535 }
536 Expression::TypeCastExpression(node) => self.walk_expression(v, &node.expression),
537 Expression::StringLiteral(_)
539 | Expression::NumericLiteral(_)
540 | Expression::BooleanLiteral(_)
541 | Expression::NullLiteral(_)
542 | Expression::BigIntLiteral(_)
543 | Expression::RegExpLiteral(_)
544 | Expression::MetaProperty(_)
545 | Expression::PrivateName(_)
546 | Expression::Super(_)
547 | Expression::Import(_)
548 | Expression::ThisExpression(_) => {}
549 }
550 }
551
552 pub fn walk_pattern<'ast>(&mut self, v: &mut impl Visitor<'ast>, pat: &'ast PatternLike) {
553 match pat {
554 PatternLike::Identifier(node) => {
555 v.enter_identifier(node, &self.scope_stack);
556 }
557 PatternLike::ObjectPattern(node) => {
558 for prop in &node.properties {
559 match prop {
560 ObjectPatternProperty::ObjectProperty(p) => {
561 if p.computed {
562 self.walk_expression(v, &p.key);
563 }
564 self.walk_pattern(v, &p.value);
565 }
566 ObjectPatternProperty::RestElement(p) => {
567 self.walk_pattern(v, &p.argument);
568 }
569 }
570 }
571 }
572 PatternLike::ArrayPattern(node) => {
573 for element in &node.elements {
574 if let Some(el) = element {
575 self.walk_pattern(v, el);
576 }
577 }
578 }
579 PatternLike::AssignmentPattern(node) => {
580 self.walk_pattern(v, &node.left);
581 self.walk_expression(v, &node.right);
582 }
583 PatternLike::RestElement(node) => {
584 self.walk_pattern(v, &node.argument);
585 }
586 PatternLike::MemberExpression(node) => {
587 self.walk_expression(v, &node.object);
588 if node.computed {
589 self.walk_expression(v, &node.property);
590 }
591 }
592 PatternLike::TSAsExpression(node) => self.walk_expression(v, &node.expression),
593 PatternLike::TSSatisfiesExpression(node) => self.walk_expression(v, &node.expression),
594 PatternLike::TSNonNullExpression(node) => self.walk_expression(v, &node.expression),
595 PatternLike::TSTypeAssertion(node) => self.walk_expression(v, &node.expression),
596 PatternLike::TypeCastExpression(node) => self.walk_expression(v, &node.expression),
597 }
598 }
599
600 fn walk_for_in_of_left<'ast>(&mut self, v: &mut impl Visitor<'ast>, left: &'ast ForInOfLeft) {
603 match left {
604 ForInOfLeft::VariableDeclaration(decl) => self.walk_variable_declaration(v, decl),
605 ForInOfLeft::Pattern(pat) => self.walk_pattern(v, pat),
606 }
607 }
608
609 fn walk_variable_declaration<'ast>(
610 &mut self,
611 v: &mut impl Visitor<'ast>,
612 decl: &'ast VariableDeclaration,
613 ) {
614 for declarator in &decl.declarations {
615 v.enter_variable_declarator(declarator, &self.scope_stack);
616 self.walk_pattern(v, &declarator.id);
617 if let Some(init) = &declarator.init {
618 self.walk_expression(v, init);
619 }
620 v.leave_variable_declarator(declarator, &self.scope_stack);
621 }
622 }
623
624 fn walk_function_declaration_inner<'ast>(
625 &mut self,
626 v: &mut impl Visitor<'ast>,
627 node: &'ast FunctionDeclaration,
628 ) {
629 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
630 v.enter_function_declaration(node, &self.scope_stack);
631 if v.traverse_function_bodies() {
632 for param in &node.params {
633 self.walk_pattern(v, param);
634 }
635 self.walk_block_statement(v, &node.body);
636 }
637 v.leave_function_declaration(node, &self.scope_stack);
638 if pushed {
639 self.scope_stack.pop();
640 }
641 }
642
643 fn walk_object_expression_property<'ast>(
644 &mut self,
645 v: &mut impl Visitor<'ast>,
646 prop: &'ast ObjectExpressionProperty,
647 ) {
648 match prop {
649 ObjectExpressionProperty::ObjectProperty(p) => {
650 if p.computed {
651 self.walk_expression(v, &p.key);
652 }
653 self.walk_expression(v, &p.value);
654 }
655 ObjectExpressionProperty::ObjectMethod(node) => {
656 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
657 v.enter_object_method(node, &self.scope_stack);
658 if v.traverse_function_bodies() {
659 if node.computed {
660 self.walk_expression(v, &node.key);
661 }
662 for param in &node.params {
663 self.walk_pattern(v, param);
664 }
665 self.walk_block_statement(v, &node.body);
666 }
667 v.leave_object_method(node, &self.scope_stack);
668 if pushed {
669 self.scope_stack.pop();
670 }
671 }
672 ObjectExpressionProperty::SpreadElement(p) => {
673 self.walk_expression(v, &p.argument);
674 }
675 }
676 }
677
678 fn walk_declaration<'ast>(&mut self, v: &mut impl Visitor<'ast>, decl: &'ast Declaration) {
679 match decl {
680 Declaration::FunctionDeclaration(node) => {
681 self.walk_function_declaration_inner(v, node);
682 }
683 Declaration::VariableDeclaration(node) => {
684 self.walk_variable_declaration(v, node);
685 }
686 _ => {}
688 }
689 }
690
691 fn walk_export_default_decl<'ast>(
692 &mut self,
693 v: &mut impl Visitor<'ast>,
694 decl: &'ast ExportDefaultDecl,
695 ) {
696 match decl {
697 ExportDefaultDecl::FunctionDeclaration(node) => {
698 self.walk_function_declaration_inner(v, node);
699 }
700 ExportDefaultDecl::ClassDeclaration(node) => {
701 v.enter_class_declaration(node, &self.scope_stack);
703 }
704 ExportDefaultDecl::EnumDeclaration(_) => {
705 }
707 ExportDefaultDecl::Expression(expr) => {
708 self.walk_expression(v, expr);
709 }
710 }
711 }
712
713 fn walk_jsx_element<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast JSXElement) {
714 v.enter_jsx_opening_element(&node.opening_element, &self.scope_stack);
715 self.walk_jsx_element_name(v, &node.opening_element.name);
716 v.leave_jsx_opening_element(&node.opening_element, &self.scope_stack);
717 for attr in &node.opening_element.attributes {
718 match attr {
719 JSXAttributeItem::JSXAttribute(a) => {
720 if let Some(value) = &a.value {
721 match value {
722 JSXAttributeValue::JSXExpressionContainer(c) => {
723 self.walk_jsx_expr_container(v, c);
724 }
725 JSXAttributeValue::JSXElement(el) => {
726 self.walk_jsx_element(v, el);
727 }
728 JSXAttributeValue::JSXFragment(f) => {
729 self.walk_jsx_fragment(v, f);
730 }
731 JSXAttributeValue::StringLiteral(_) => {}
732 }
733 }
734 }
735 JSXAttributeItem::JSXSpreadAttribute(a) => {
736 self.walk_expression(v, &a.argument);
737 }
738 }
739 }
740 for child in &node.children {
741 self.walk_jsx_child(v, child);
742 }
743 }
744
745 fn walk_jsx_fragment<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast JSXFragment) {
746 for child in &node.children {
747 self.walk_jsx_child(v, child);
748 }
749 }
750
751 fn walk_jsx_child<'ast>(&mut self, v: &mut impl Visitor<'ast>, child: &'ast JSXChild) {
752 match child {
753 JSXChild::JSXElement(el) => self.walk_jsx_element(v, el),
754 JSXChild::JSXFragment(f) => self.walk_jsx_fragment(v, f),
755 JSXChild::JSXExpressionContainer(c) => self.walk_jsx_expr_container(v, c),
756 JSXChild::JSXSpreadChild(s) => self.walk_expression(v, &s.expression),
757 JSXChild::JSXText(_) => {}
758 }
759 }
760
761 fn walk_jsx_expr_container<'ast>(
762 &mut self,
763 v: &mut impl Visitor<'ast>,
764 node: &'ast JSXExpressionContainer,
765 ) {
766 match &node.expression {
767 JSXExpressionContainerExpr::Expression(expr) => self.walk_expression(v, expr),
768 JSXExpressionContainerExpr::JSXEmptyExpression(_) => {}
769 }
770 }
771
772 fn walk_jsx_element_name<'ast>(
773 &mut self,
774 v: &mut impl Visitor<'ast>,
775 name: &'ast JSXElementName,
776 ) {
777 match name {
778 JSXElementName::JSXIdentifier(id) => {
779 v.enter_jsx_identifier(id, &self.scope_stack);
780 }
781 JSXElementName::JSXMemberExpression(expr) => {
782 self.walk_jsx_member_expression(v, expr);
783 }
784 JSXElementName::JSXNamespacedName(_) => {}
785 }
786 }
787
788 fn walk_jsx_member_expression<'ast>(
789 &mut self,
790 v: &mut impl Visitor<'ast>,
791 expr: &'ast JSXMemberExpression,
792 ) {
793 match &*expr.object {
794 JSXMemberExprObject::JSXIdentifier(id) => {
795 v.enter_jsx_identifier(id, &self.scope_stack);
796 }
797 JSXMemberExprObject::JSXMemberExpression(inner) => {
798 self.walk_jsx_member_expression(v, inner);
799 }
800 }
801 v.enter_jsx_identifier(&expr.property, &self.scope_stack);
802 }
803}
804
805#[derive(Debug, Clone, Copy, PartialEq, Eq)]
811pub enum VisitResult {
812 Continue,
814 Stop,
816}
817
818impl VisitResult {
819 pub fn is_stop(self) -> bool {
820 self == VisitResult::Stop
821 }
822}
823
824pub trait MutVisitor {
831 fn visit_statement(&mut self, _stmt: &mut Statement) -> VisitResult {
833 VisitResult::Continue
834 }
835
836 fn visit_expression(&mut self, _expr: &mut Expression) -> VisitResult {
838 VisitResult::Continue
839 }
840
841 fn visit_identifier(&mut self, _node: &mut Identifier) -> VisitResult {
843 VisitResult::Continue
844 }
845}
846
847pub fn walk_program_mut(v: &mut impl MutVisitor, program: &mut Program) -> VisitResult {
849 for stmt in program.body.iter_mut() {
850 if walk_statement_mut(v, stmt).is_stop() {
851 return VisitResult::Stop;
852 }
853 }
854 VisitResult::Continue
855}
856
857pub fn walk_statement_mut(v: &mut impl MutVisitor, stmt: &mut Statement) -> VisitResult {
859 if v.visit_statement(stmt).is_stop() {
860 return VisitResult::Stop;
861 }
862 match stmt {
863 Statement::BlockStatement(node) => {
864 for s in node.body.iter_mut() {
865 if walk_statement_mut(v, s).is_stop() {
866 return VisitResult::Stop;
867 }
868 }
869 }
870 Statement::ReturnStatement(node) => {
871 if let Some(ref mut arg) = node.argument {
872 if walk_expression_mut(v, arg).is_stop() {
873 return VisitResult::Stop;
874 }
875 }
876 }
877 Statement::ExpressionStatement(node) => {
878 if walk_expression_mut(v, &mut node.expression).is_stop() {
879 return VisitResult::Stop;
880 }
881 }
882 Statement::IfStatement(node) => {
883 if walk_expression_mut(v, &mut node.test).is_stop() {
884 return VisitResult::Stop;
885 }
886 if walk_statement_mut(v, &mut node.consequent).is_stop() {
887 return VisitResult::Stop;
888 }
889 if let Some(ref mut alt) = node.alternate {
890 if walk_statement_mut(v, alt).is_stop() {
891 return VisitResult::Stop;
892 }
893 }
894 }
895 Statement::ForStatement(node) => {
896 if let Some(ref mut init) = node.init {
897 match init.as_mut() {
898 ForInit::VariableDeclaration(decl) => {
899 if walk_variable_declaration_mut(v, decl).is_stop() {
900 return VisitResult::Stop;
901 }
902 }
903 ForInit::Expression(expr) => {
904 if walk_expression_mut(v, expr).is_stop() {
905 return VisitResult::Stop;
906 }
907 }
908 }
909 }
910 if let Some(ref mut test) = node.test {
911 if walk_expression_mut(v, test).is_stop() {
912 return VisitResult::Stop;
913 }
914 }
915 if let Some(ref mut update) = node.update {
916 if walk_expression_mut(v, update).is_stop() {
917 return VisitResult::Stop;
918 }
919 }
920 if walk_statement_mut(v, &mut node.body).is_stop() {
921 return VisitResult::Stop;
922 }
923 }
924 Statement::WhileStatement(node) => {
925 if walk_expression_mut(v, &mut node.test).is_stop() {
926 return VisitResult::Stop;
927 }
928 if walk_statement_mut(v, &mut node.body).is_stop() {
929 return VisitResult::Stop;
930 }
931 }
932 Statement::DoWhileStatement(node) => {
933 if walk_statement_mut(v, &mut node.body).is_stop() {
934 return VisitResult::Stop;
935 }
936 if walk_expression_mut(v, &mut node.test).is_stop() {
937 return VisitResult::Stop;
938 }
939 }
940 Statement::ForInStatement(node) => {
941 if walk_expression_mut(v, &mut node.right).is_stop() {
942 return VisitResult::Stop;
943 }
944 if walk_statement_mut(v, &mut node.body).is_stop() {
945 return VisitResult::Stop;
946 }
947 }
948 Statement::ForOfStatement(node) => {
949 if walk_expression_mut(v, &mut node.right).is_stop() {
950 return VisitResult::Stop;
951 }
952 if walk_statement_mut(v, &mut node.body).is_stop() {
953 return VisitResult::Stop;
954 }
955 }
956 Statement::SwitchStatement(node) => {
957 if walk_expression_mut(v, &mut node.discriminant).is_stop() {
958 return VisitResult::Stop;
959 }
960 for case in node.cases.iter_mut() {
961 if let Some(ref mut test) = case.test {
962 if walk_expression_mut(v, test).is_stop() {
963 return VisitResult::Stop;
964 }
965 }
966 for s in case.consequent.iter_mut() {
967 if walk_statement_mut(v, s).is_stop() {
968 return VisitResult::Stop;
969 }
970 }
971 }
972 }
973 Statement::ThrowStatement(node) => {
974 if walk_expression_mut(v, &mut node.argument).is_stop() {
975 return VisitResult::Stop;
976 }
977 }
978 Statement::TryStatement(node) => {
979 for s in node.block.body.iter_mut() {
980 if walk_statement_mut(v, s).is_stop() {
981 return VisitResult::Stop;
982 }
983 }
984 if let Some(ref mut handler) = node.handler {
985 for s in handler.body.body.iter_mut() {
986 if walk_statement_mut(v, s).is_stop() {
987 return VisitResult::Stop;
988 }
989 }
990 }
991 if let Some(ref mut finalizer) = node.finalizer {
992 for s in finalizer.body.iter_mut() {
993 if walk_statement_mut(v, s).is_stop() {
994 return VisitResult::Stop;
995 }
996 }
997 }
998 }
999 Statement::LabeledStatement(node) => {
1000 if walk_statement_mut(v, &mut node.body).is_stop() {
1001 return VisitResult::Stop;
1002 }
1003 }
1004 Statement::VariableDeclaration(node) => {
1005 if walk_variable_declaration_mut(v, node).is_stop() {
1006 return VisitResult::Stop;
1007 }
1008 }
1009 Statement::FunctionDeclaration(node) => {
1010 for s in node.body.body.iter_mut() {
1011 if walk_statement_mut(v, s).is_stop() {
1012 return VisitResult::Stop;
1013 }
1014 }
1015 }
1016 Statement::ClassDeclaration(node) => {
1017 if let Some(ref mut sc) = node.super_class {
1018 if walk_expression_mut(v, sc).is_stop() {
1019 return VisitResult::Stop;
1020 }
1021 }
1022 }
1023 Statement::WithStatement(node) => {
1024 if walk_expression_mut(v, &mut node.object).is_stop() {
1025 return VisitResult::Stop;
1026 }
1027 if walk_statement_mut(v, &mut node.body).is_stop() {
1028 return VisitResult::Stop;
1029 }
1030 }
1031 Statement::ExportNamedDeclaration(node) => {
1032 if let Some(ref mut decl) = node.declaration {
1033 if walk_declaration_mut(v, decl).is_stop() {
1034 return VisitResult::Stop;
1035 }
1036 }
1037 }
1038 Statement::ExportDefaultDeclaration(node) => {
1039 if walk_export_default_decl_mut(v, &mut node.declaration).is_stop() {
1040 return VisitResult::Stop;
1041 }
1042 }
1043 Statement::BreakStatement(_)
1045 | Statement::ContinueStatement(_)
1046 | Statement::EmptyStatement(_)
1047 | Statement::DebuggerStatement(_)
1048 | Statement::ImportDeclaration(_)
1049 | Statement::ExportAllDeclaration(_)
1050 | Statement::TSTypeAliasDeclaration(_)
1051 | Statement::TSInterfaceDeclaration(_)
1052 | Statement::TSEnumDeclaration(_)
1053 | Statement::TSModuleDeclaration(_)
1054 | Statement::TSDeclareFunction(_)
1055 | Statement::TypeAlias(_)
1056 | Statement::OpaqueType(_)
1057 | Statement::InterfaceDeclaration(_)
1058 | Statement::DeclareVariable(_)
1059 | Statement::DeclareFunction(_)
1060 | Statement::DeclareClass(_)
1061 | Statement::DeclareModule(_)
1062 | Statement::DeclareModuleExports(_)
1063 | Statement::DeclareExportDeclaration(_)
1064 | Statement::DeclareExportAllDeclaration(_)
1065 | Statement::DeclareInterface(_)
1066 | Statement::DeclareTypeAlias(_)
1067 | Statement::DeclareOpaqueType(_)
1068 | Statement::EnumDeclaration(_)
1069 | Statement::Unknown(_) => {}
1071 }
1072 VisitResult::Continue
1073}
1074
1075pub fn walk_expression_mut(v: &mut impl MutVisitor, expr: &mut Expression) -> VisitResult {
1077 if v.visit_expression(expr).is_stop() {
1078 return VisitResult::Stop;
1079 }
1080 match expr {
1081 Expression::Identifier(node) => {
1082 if v.visit_identifier(node).is_stop() {
1083 return VisitResult::Stop;
1084 }
1085 }
1086 Expression::CallExpression(node) => {
1087 if walk_expression_mut(v, &mut node.callee).is_stop() {
1088 return VisitResult::Stop;
1089 }
1090 for arg in node.arguments.iter_mut() {
1091 if walk_expression_mut(v, arg).is_stop() {
1092 return VisitResult::Stop;
1093 }
1094 }
1095 }
1096 Expression::MemberExpression(node) => {
1097 if walk_expression_mut(v, &mut node.object).is_stop() {
1098 return VisitResult::Stop;
1099 }
1100 if node.computed {
1101 if walk_expression_mut(v, &mut node.property).is_stop() {
1102 return VisitResult::Stop;
1103 }
1104 }
1105 }
1106 Expression::OptionalCallExpression(node) => {
1107 if walk_expression_mut(v, &mut node.callee).is_stop() {
1108 return VisitResult::Stop;
1109 }
1110 for arg in node.arguments.iter_mut() {
1111 if walk_expression_mut(v, arg).is_stop() {
1112 return VisitResult::Stop;
1113 }
1114 }
1115 }
1116 Expression::OptionalMemberExpression(node) => {
1117 if walk_expression_mut(v, &mut node.object).is_stop() {
1118 return VisitResult::Stop;
1119 }
1120 if node.computed {
1121 if walk_expression_mut(v, &mut node.property).is_stop() {
1122 return VisitResult::Stop;
1123 }
1124 }
1125 }
1126 Expression::BinaryExpression(node) => {
1127 if walk_expression_mut(v, &mut node.left).is_stop() {
1128 return VisitResult::Stop;
1129 }
1130 if walk_expression_mut(v, &mut node.right).is_stop() {
1131 return VisitResult::Stop;
1132 }
1133 }
1134 Expression::LogicalExpression(node) => {
1135 if walk_expression_mut(v, &mut node.left).is_stop() {
1136 return VisitResult::Stop;
1137 }
1138 if walk_expression_mut(v, &mut node.right).is_stop() {
1139 return VisitResult::Stop;
1140 }
1141 }
1142 Expression::UnaryExpression(node) => {
1143 if walk_expression_mut(v, &mut node.argument).is_stop() {
1144 return VisitResult::Stop;
1145 }
1146 }
1147 Expression::UpdateExpression(node) => {
1148 if walk_expression_mut(v, &mut node.argument).is_stop() {
1149 return VisitResult::Stop;
1150 }
1151 }
1152 Expression::ConditionalExpression(node) => {
1153 if walk_expression_mut(v, &mut node.test).is_stop() {
1154 return VisitResult::Stop;
1155 }
1156 if walk_expression_mut(v, &mut node.consequent).is_stop() {
1157 return VisitResult::Stop;
1158 }
1159 if walk_expression_mut(v, &mut node.alternate).is_stop() {
1160 return VisitResult::Stop;
1161 }
1162 }
1163 Expression::AssignmentExpression(node) => {
1164 if walk_expression_mut(v, &mut node.right).is_stop() {
1165 return VisitResult::Stop;
1166 }
1167 }
1168 Expression::SequenceExpression(node) => {
1169 for e in node.expressions.iter_mut() {
1170 if walk_expression_mut(v, e).is_stop() {
1171 return VisitResult::Stop;
1172 }
1173 }
1174 }
1175 Expression::ArrowFunctionExpression(node) => match node.body.as_mut() {
1176 ArrowFunctionBody::BlockStatement(block) => {
1177 for s in block.body.iter_mut() {
1178 if walk_statement_mut(v, s).is_stop() {
1179 return VisitResult::Stop;
1180 }
1181 }
1182 }
1183 ArrowFunctionBody::Expression(e) => {
1184 if walk_expression_mut(v, e).is_stop() {
1185 return VisitResult::Stop;
1186 }
1187 }
1188 },
1189 Expression::FunctionExpression(node) => {
1190 for s in node.body.body.iter_mut() {
1191 if walk_statement_mut(v, s).is_stop() {
1192 return VisitResult::Stop;
1193 }
1194 }
1195 }
1196 Expression::ObjectExpression(node) => {
1197 for prop in node.properties.iter_mut() {
1198 match prop {
1199 ObjectExpressionProperty::ObjectProperty(p) => {
1200 if p.computed {
1201 if walk_expression_mut(v, &mut p.key).is_stop() {
1202 return VisitResult::Stop;
1203 }
1204 }
1205 if walk_expression_mut(v, &mut p.value).is_stop() {
1206 return VisitResult::Stop;
1207 }
1208 }
1209 ObjectExpressionProperty::ObjectMethod(m) => {
1210 for s in m.body.body.iter_mut() {
1211 if walk_statement_mut(v, s).is_stop() {
1212 return VisitResult::Stop;
1213 }
1214 }
1215 }
1216 ObjectExpressionProperty::SpreadElement(s) => {
1217 if walk_expression_mut(v, &mut s.argument).is_stop() {
1218 return VisitResult::Stop;
1219 }
1220 }
1221 }
1222 }
1223 }
1224 Expression::ArrayExpression(node) => {
1225 for elem in node.elements.iter_mut().flatten() {
1226 if walk_expression_mut(v, elem).is_stop() {
1227 return VisitResult::Stop;
1228 }
1229 }
1230 }
1231 Expression::NewExpression(node) => {
1232 if walk_expression_mut(v, &mut node.callee).is_stop() {
1233 return VisitResult::Stop;
1234 }
1235 for arg in node.arguments.iter_mut() {
1236 if walk_expression_mut(v, arg).is_stop() {
1237 return VisitResult::Stop;
1238 }
1239 }
1240 }
1241 Expression::TemplateLiteral(node) => {
1242 for e in node.expressions.iter_mut() {
1243 if walk_expression_mut(v, e).is_stop() {
1244 return VisitResult::Stop;
1245 }
1246 }
1247 }
1248 Expression::TaggedTemplateExpression(node) => {
1249 if walk_expression_mut(v, &mut node.tag).is_stop() {
1250 return VisitResult::Stop;
1251 }
1252 for e in node.quasi.expressions.iter_mut() {
1253 if walk_expression_mut(v, e).is_stop() {
1254 return VisitResult::Stop;
1255 }
1256 }
1257 }
1258 Expression::AwaitExpression(node) => {
1259 if walk_expression_mut(v, &mut node.argument).is_stop() {
1260 return VisitResult::Stop;
1261 }
1262 }
1263 Expression::YieldExpression(node) => {
1264 if let Some(ref mut arg) = node.argument {
1265 if walk_expression_mut(v, arg).is_stop() {
1266 return VisitResult::Stop;
1267 }
1268 }
1269 }
1270 Expression::SpreadElement(node) => {
1271 if walk_expression_mut(v, &mut node.argument).is_stop() {
1272 return VisitResult::Stop;
1273 }
1274 }
1275 Expression::ParenthesizedExpression(node) => {
1276 if walk_expression_mut(v, &mut node.expression).is_stop() {
1277 return VisitResult::Stop;
1278 }
1279 }
1280 Expression::AssignmentPattern(node) => {
1281 if walk_expression_mut(v, &mut node.right).is_stop() {
1282 return VisitResult::Stop;
1283 }
1284 }
1285 Expression::ClassExpression(node) => {
1286 if let Some(ref mut sc) = node.super_class {
1287 if walk_expression_mut(v, sc).is_stop() {
1288 return VisitResult::Stop;
1289 }
1290 }
1291 }
1292 Expression::JSXElement(node) => {
1293 if walk_jsx_mut(v, &mut node.opening_element.attributes, &mut node.children).is_stop() {
1294 return VisitResult::Stop;
1295 }
1296 }
1297 Expression::JSXFragment(node) => {
1298 if walk_jsx_children_mut(v, &mut node.children).is_stop() {
1299 return VisitResult::Stop;
1300 }
1301 }
1302 Expression::TSAsExpression(node) => {
1304 if walk_expression_mut(v, &mut node.expression).is_stop() {
1305 return VisitResult::Stop;
1306 }
1307 }
1308 Expression::TSSatisfiesExpression(node) => {
1309 if walk_expression_mut(v, &mut node.expression).is_stop() {
1310 return VisitResult::Stop;
1311 }
1312 }
1313 Expression::TSNonNullExpression(node) => {
1314 if walk_expression_mut(v, &mut node.expression).is_stop() {
1315 return VisitResult::Stop;
1316 }
1317 }
1318 Expression::TSTypeAssertion(node) => {
1319 if walk_expression_mut(v, &mut node.expression).is_stop() {
1320 return VisitResult::Stop;
1321 }
1322 }
1323 Expression::TSInstantiationExpression(node) => {
1324 if walk_expression_mut(v, &mut node.expression).is_stop() {
1325 return VisitResult::Stop;
1326 }
1327 }
1328 Expression::TypeCastExpression(node) => {
1329 if walk_expression_mut(v, &mut node.expression).is_stop() {
1330 return VisitResult::Stop;
1331 }
1332 }
1333 Expression::StringLiteral(_)
1335 | Expression::NumericLiteral(_)
1336 | Expression::BooleanLiteral(_)
1337 | Expression::NullLiteral(_)
1338 | Expression::BigIntLiteral(_)
1339 | Expression::RegExpLiteral(_)
1340 | Expression::MetaProperty(_)
1341 | Expression::PrivateName(_)
1342 | Expression::Super(_)
1343 | Expression::Import(_)
1344 | Expression::ThisExpression(_) => {}
1345 }
1346 VisitResult::Continue
1347}
1348
1349fn walk_jsx_mut(
1350 v: &mut impl MutVisitor,
1351 attrs: &mut [crate::jsx::JSXAttributeItem],
1352 children: &mut [crate::jsx::JSXChild],
1353) -> VisitResult {
1354 for attr in attrs.iter_mut() {
1355 match attr {
1356 crate::jsx::JSXAttributeItem::JSXAttribute(a) => {
1357 if let Some(ref mut val) = a.value {
1358 match val {
1359 crate::jsx::JSXAttributeValue::JSXExpressionContainer(c) => {
1360 if let crate::jsx::JSXExpressionContainerExpr::Expression(ref mut e) =
1361 c.expression
1362 {
1363 if walk_expression_mut(v, e).is_stop() {
1364 return VisitResult::Stop;
1365 }
1366 }
1367 }
1368 _ => {}
1369 }
1370 }
1371 }
1372 crate::jsx::JSXAttributeItem::JSXSpreadAttribute(s) => {
1373 if walk_expression_mut(v, &mut s.argument).is_stop() {
1374 return VisitResult::Stop;
1375 }
1376 }
1377 }
1378 }
1379 walk_jsx_children_mut(v, children)
1380}
1381
1382fn walk_jsx_children_mut(
1383 v: &mut impl MutVisitor,
1384 children: &mut [crate::jsx::JSXChild],
1385) -> VisitResult {
1386 for child in children.iter_mut() {
1387 match child {
1388 crate::jsx::JSXChild::JSXElement(el) => {
1389 if walk_jsx_mut(v, &mut el.opening_element.attributes, &mut el.children).is_stop() {
1390 return VisitResult::Stop;
1391 }
1392 }
1393 crate::jsx::JSXChild::JSXFragment(f) => {
1394 if walk_jsx_children_mut(v, &mut f.children).is_stop() {
1395 return VisitResult::Stop;
1396 }
1397 }
1398 crate::jsx::JSXChild::JSXExpressionContainer(c) => {
1399 if let crate::jsx::JSXExpressionContainerExpr::Expression(ref mut e) = c.expression
1400 {
1401 if walk_expression_mut(v, e).is_stop() {
1402 return VisitResult::Stop;
1403 }
1404 }
1405 }
1406 crate::jsx::JSXChild::JSXSpreadChild(s) => {
1407 if walk_expression_mut(v, &mut s.expression).is_stop() {
1408 return VisitResult::Stop;
1409 }
1410 }
1411 _ => {}
1412 }
1413 }
1414 VisitResult::Continue
1415}
1416
1417fn walk_variable_declaration_mut(
1420 v: &mut impl MutVisitor,
1421 decl: &mut VariableDeclaration,
1422) -> VisitResult {
1423 for declarator in decl.declarations.iter_mut() {
1424 if let Some(ref mut init) = declarator.init {
1425 if walk_expression_mut(v, init).is_stop() {
1426 return VisitResult::Stop;
1427 }
1428 }
1429 }
1430 VisitResult::Continue
1431}
1432
1433fn walk_declaration_mut(v: &mut impl MutVisitor, decl: &mut Declaration) -> VisitResult {
1434 match decl {
1435 Declaration::FunctionDeclaration(node) => {
1436 for s in node.body.body.iter_mut() {
1437 if walk_statement_mut(v, s).is_stop() {
1438 return VisitResult::Stop;
1439 }
1440 }
1441 }
1442 Declaration::VariableDeclaration(node) => {
1443 if walk_variable_declaration_mut(v, node).is_stop() {
1444 return VisitResult::Stop;
1445 }
1446 }
1447 Declaration::ClassDeclaration(node) => {
1448 if let Some(ref mut sc) = node.super_class {
1449 if walk_expression_mut(v, sc).is_stop() {
1450 return VisitResult::Stop;
1451 }
1452 }
1453 }
1454 _ => {}
1455 }
1456 VisitResult::Continue
1457}
1458
1459fn walk_export_default_decl_mut(
1460 v: &mut impl MutVisitor,
1461 decl: &mut ExportDefaultDecl,
1462) -> VisitResult {
1463 match decl {
1464 ExportDefaultDecl::FunctionDeclaration(node) => {
1465 for s in node.body.body.iter_mut() {
1466 if walk_statement_mut(v, s).is_stop() {
1467 return VisitResult::Stop;
1468 }
1469 }
1470 }
1471 ExportDefaultDecl::Expression(expr) => {
1472 if walk_expression_mut(v, expr).is_stop() {
1473 return VisitResult::Stop;
1474 }
1475 }
1476 ExportDefaultDecl::ClassDeclaration(node) => {
1477 if let Some(ref mut sc) = node.super_class {
1478 if walk_expression_mut(v, sc).is_stop() {
1479 return VisitResult::Stop;
1480 }
1481 }
1482 }
1483 ExportDefaultDecl::EnumDeclaration(_) => {
1484 }
1486 }
1487 VisitResult::Continue
1488}