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) => {
594 self.walk_expression(v, &node.expression)
595 }
596 PatternLike::TSNonNullExpression(node) => {
597 self.walk_expression(v, &node.expression)
598 }
599 PatternLike::TSTypeAssertion(node) => self.walk_expression(v, &node.expression),
600 PatternLike::TypeCastExpression(node) => self.walk_expression(v, &node.expression),
601 }
602 }
603
604 fn walk_for_in_of_left<'ast>(&mut self, v: &mut impl Visitor<'ast>, left: &'ast ForInOfLeft) {
607 match left {
608 ForInOfLeft::VariableDeclaration(decl) => self.walk_variable_declaration(v, decl),
609 ForInOfLeft::Pattern(pat) => self.walk_pattern(v, pat),
610 }
611 }
612
613 fn walk_variable_declaration<'ast>(
614 &mut self,
615 v: &mut impl Visitor<'ast>,
616 decl: &'ast VariableDeclaration,
617 ) {
618 for declarator in &decl.declarations {
619 v.enter_variable_declarator(declarator, &self.scope_stack);
620 self.walk_pattern(v, &declarator.id);
621 if let Some(init) = &declarator.init {
622 self.walk_expression(v, init);
623 }
624 v.leave_variable_declarator(declarator, &self.scope_stack);
625 }
626 }
627
628 fn walk_function_declaration_inner<'ast>(
629 &mut self,
630 v: &mut impl Visitor<'ast>,
631 node: &'ast FunctionDeclaration,
632 ) {
633 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
634 v.enter_function_declaration(node, &self.scope_stack);
635 if v.traverse_function_bodies() {
636 for param in &node.params {
637 self.walk_pattern(v, param);
638 }
639 self.walk_block_statement(v, &node.body);
640 }
641 v.leave_function_declaration(node, &self.scope_stack);
642 if pushed {
643 self.scope_stack.pop();
644 }
645 }
646
647 fn walk_object_expression_property<'ast>(
648 &mut self,
649 v: &mut impl Visitor<'ast>,
650 prop: &'ast ObjectExpressionProperty,
651 ) {
652 match prop {
653 ObjectExpressionProperty::ObjectProperty(p) => {
654 if p.computed {
655 self.walk_expression(v, &p.key);
656 }
657 self.walk_expression(v, &p.value);
658 }
659 ObjectExpressionProperty::ObjectMethod(node) => {
660 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
661 v.enter_object_method(node, &self.scope_stack);
662 if v.traverse_function_bodies() {
663 if node.computed {
664 self.walk_expression(v, &node.key);
665 }
666 for param in &node.params {
667 self.walk_pattern(v, param);
668 }
669 self.walk_block_statement(v, &node.body);
670 }
671 v.leave_object_method(node, &self.scope_stack);
672 if pushed {
673 self.scope_stack.pop();
674 }
675 }
676 ObjectExpressionProperty::SpreadElement(p) => {
677 self.walk_expression(v, &p.argument);
678 }
679 }
680 }
681
682 fn walk_declaration<'ast>(&mut self, v: &mut impl Visitor<'ast>, decl: &'ast Declaration) {
683 match decl {
684 Declaration::FunctionDeclaration(node) => {
685 self.walk_function_declaration_inner(v, node);
686 }
687 Declaration::VariableDeclaration(node) => {
688 self.walk_variable_declaration(v, node);
689 }
690 _ => {}
692 }
693 }
694
695 fn walk_export_default_decl<'ast>(
696 &mut self,
697 v: &mut impl Visitor<'ast>,
698 decl: &'ast ExportDefaultDecl,
699 ) {
700 match decl {
701 ExportDefaultDecl::FunctionDeclaration(node) => {
702 self.walk_function_declaration_inner(v, node);
703 }
704 ExportDefaultDecl::ClassDeclaration(node) => {
705 v.enter_class_declaration(node, &self.scope_stack);
707 }
708 ExportDefaultDecl::EnumDeclaration(_) => {
709 }
711 ExportDefaultDecl::Expression(expr) => {
712 self.walk_expression(v, expr);
713 }
714 }
715 }
716
717 fn walk_jsx_element<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast JSXElement) {
718 v.enter_jsx_opening_element(&node.opening_element, &self.scope_stack);
719 self.walk_jsx_element_name(v, &node.opening_element.name);
720 v.leave_jsx_opening_element(&node.opening_element, &self.scope_stack);
721 for attr in &node.opening_element.attributes {
722 match attr {
723 JSXAttributeItem::JSXAttribute(a) => {
724 if let Some(value) = &a.value {
725 match value {
726 JSXAttributeValue::JSXExpressionContainer(c) => {
727 self.walk_jsx_expr_container(v, c);
728 }
729 JSXAttributeValue::JSXElement(el) => {
730 self.walk_jsx_element(v, el);
731 }
732 JSXAttributeValue::JSXFragment(f) => {
733 self.walk_jsx_fragment(v, f);
734 }
735 JSXAttributeValue::StringLiteral(_) => {}
736 }
737 }
738 }
739 JSXAttributeItem::JSXSpreadAttribute(a) => {
740 self.walk_expression(v, &a.argument);
741 }
742 }
743 }
744 for child in &node.children {
745 self.walk_jsx_child(v, child);
746 }
747 }
748
749 fn walk_jsx_fragment<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast JSXFragment) {
750 for child in &node.children {
751 self.walk_jsx_child(v, child);
752 }
753 }
754
755 fn walk_jsx_child<'ast>(&mut self, v: &mut impl Visitor<'ast>, child: &'ast JSXChild) {
756 match child {
757 JSXChild::JSXElement(el) => self.walk_jsx_element(v, el),
758 JSXChild::JSXFragment(f) => self.walk_jsx_fragment(v, f),
759 JSXChild::JSXExpressionContainer(c) => self.walk_jsx_expr_container(v, c),
760 JSXChild::JSXSpreadChild(s) => self.walk_expression(v, &s.expression),
761 JSXChild::JSXText(_) => {}
762 }
763 }
764
765 fn walk_jsx_expr_container<'ast>(
766 &mut self,
767 v: &mut impl Visitor<'ast>,
768 node: &'ast JSXExpressionContainer,
769 ) {
770 match &node.expression {
771 JSXExpressionContainerExpr::Expression(expr) => self.walk_expression(v, expr),
772 JSXExpressionContainerExpr::JSXEmptyExpression(_) => {}
773 }
774 }
775
776 fn walk_jsx_element_name<'ast>(
777 &mut self,
778 v: &mut impl Visitor<'ast>,
779 name: &'ast JSXElementName,
780 ) {
781 match name {
782 JSXElementName::JSXIdentifier(id) => {
783 v.enter_jsx_identifier(id, &self.scope_stack);
784 }
785 JSXElementName::JSXMemberExpression(expr) => {
786 self.walk_jsx_member_expression(v, expr);
787 }
788 JSXElementName::JSXNamespacedName(_) => {}
789 }
790 }
791
792 fn walk_jsx_member_expression<'ast>(
793 &mut self,
794 v: &mut impl Visitor<'ast>,
795 expr: &'ast JSXMemberExpression,
796 ) {
797 match &*expr.object {
798 JSXMemberExprObject::JSXIdentifier(id) => {
799 v.enter_jsx_identifier(id, &self.scope_stack);
800 }
801 JSXMemberExprObject::JSXMemberExpression(inner) => {
802 self.walk_jsx_member_expression(v, inner);
803 }
804 }
805 v.enter_jsx_identifier(&expr.property, &self.scope_stack);
806 }
807}
808
809#[derive(Debug, Clone, Copy, PartialEq, Eq)]
815pub enum VisitResult {
816 Continue,
818 Stop,
820}
821
822impl VisitResult {
823 pub fn is_stop(self) -> bool {
824 self == VisitResult::Stop
825 }
826}
827
828pub trait MutVisitor {
835 fn visit_statement(&mut self, _stmt: &mut Statement) -> VisitResult {
837 VisitResult::Continue
838 }
839
840 fn visit_expression(&mut self, _expr: &mut Expression) -> VisitResult {
842 VisitResult::Continue
843 }
844
845 fn visit_identifier(&mut self, _node: &mut Identifier) -> VisitResult {
847 VisitResult::Continue
848 }
849}
850
851pub fn walk_program_mut(v: &mut impl MutVisitor, program: &mut Program) -> VisitResult {
853 for stmt in program.body.iter_mut() {
854 if walk_statement_mut(v, stmt).is_stop() {
855 return VisitResult::Stop;
856 }
857 }
858 VisitResult::Continue
859}
860
861pub fn walk_statement_mut(v: &mut impl MutVisitor, stmt: &mut Statement) -> VisitResult {
863 if v.visit_statement(stmt).is_stop() {
864 return VisitResult::Stop;
865 }
866 match stmt {
867 Statement::BlockStatement(node) => {
868 for s in node.body.iter_mut() {
869 if walk_statement_mut(v, s).is_stop() {
870 return VisitResult::Stop;
871 }
872 }
873 }
874 Statement::ReturnStatement(node) => {
875 if let Some(ref mut arg) = node.argument {
876 if walk_expression_mut(v, arg).is_stop() {
877 return VisitResult::Stop;
878 }
879 }
880 }
881 Statement::ExpressionStatement(node) => {
882 if walk_expression_mut(v, &mut node.expression).is_stop() {
883 return VisitResult::Stop;
884 }
885 }
886 Statement::IfStatement(node) => {
887 if walk_expression_mut(v, &mut node.test).is_stop() {
888 return VisitResult::Stop;
889 }
890 if walk_statement_mut(v, &mut node.consequent).is_stop() {
891 return VisitResult::Stop;
892 }
893 if let Some(ref mut alt) = node.alternate {
894 if walk_statement_mut(v, alt).is_stop() {
895 return VisitResult::Stop;
896 }
897 }
898 }
899 Statement::ForStatement(node) => {
900 if let Some(ref mut init) = node.init {
901 match init.as_mut() {
902 ForInit::VariableDeclaration(decl) => {
903 if walk_variable_declaration_mut(v, decl).is_stop() {
904 return VisitResult::Stop;
905 }
906 }
907 ForInit::Expression(expr) => {
908 if walk_expression_mut(v, expr).is_stop() {
909 return VisitResult::Stop;
910 }
911 }
912 }
913 }
914 if let Some(ref mut test) = node.test {
915 if walk_expression_mut(v, test).is_stop() {
916 return VisitResult::Stop;
917 }
918 }
919 if let Some(ref mut update) = node.update {
920 if walk_expression_mut(v, update).is_stop() {
921 return VisitResult::Stop;
922 }
923 }
924 if walk_statement_mut(v, &mut node.body).is_stop() {
925 return VisitResult::Stop;
926 }
927 }
928 Statement::WhileStatement(node) => {
929 if walk_expression_mut(v, &mut node.test).is_stop() {
930 return VisitResult::Stop;
931 }
932 if walk_statement_mut(v, &mut node.body).is_stop() {
933 return VisitResult::Stop;
934 }
935 }
936 Statement::DoWhileStatement(node) => {
937 if walk_statement_mut(v, &mut node.body).is_stop() {
938 return VisitResult::Stop;
939 }
940 if walk_expression_mut(v, &mut node.test).is_stop() {
941 return VisitResult::Stop;
942 }
943 }
944 Statement::ForInStatement(node) => {
945 if walk_expression_mut(v, &mut node.right).is_stop() {
946 return VisitResult::Stop;
947 }
948 if walk_statement_mut(v, &mut node.body).is_stop() {
949 return VisitResult::Stop;
950 }
951 }
952 Statement::ForOfStatement(node) => {
953 if walk_expression_mut(v, &mut node.right).is_stop() {
954 return VisitResult::Stop;
955 }
956 if walk_statement_mut(v, &mut node.body).is_stop() {
957 return VisitResult::Stop;
958 }
959 }
960 Statement::SwitchStatement(node) => {
961 if walk_expression_mut(v, &mut node.discriminant).is_stop() {
962 return VisitResult::Stop;
963 }
964 for case in node.cases.iter_mut() {
965 if let Some(ref mut test) = case.test {
966 if walk_expression_mut(v, test).is_stop() {
967 return VisitResult::Stop;
968 }
969 }
970 for s in case.consequent.iter_mut() {
971 if walk_statement_mut(v, s).is_stop() {
972 return VisitResult::Stop;
973 }
974 }
975 }
976 }
977 Statement::ThrowStatement(node) => {
978 if walk_expression_mut(v, &mut node.argument).is_stop() {
979 return VisitResult::Stop;
980 }
981 }
982 Statement::TryStatement(node) => {
983 for s in node.block.body.iter_mut() {
984 if walk_statement_mut(v, s).is_stop() {
985 return VisitResult::Stop;
986 }
987 }
988 if let Some(ref mut handler) = node.handler {
989 for s in handler.body.body.iter_mut() {
990 if walk_statement_mut(v, s).is_stop() {
991 return VisitResult::Stop;
992 }
993 }
994 }
995 if let Some(ref mut finalizer) = node.finalizer {
996 for s in finalizer.body.iter_mut() {
997 if walk_statement_mut(v, s).is_stop() {
998 return VisitResult::Stop;
999 }
1000 }
1001 }
1002 }
1003 Statement::LabeledStatement(node) => {
1004 if walk_statement_mut(v, &mut node.body).is_stop() {
1005 return VisitResult::Stop;
1006 }
1007 }
1008 Statement::VariableDeclaration(node) => {
1009 if walk_variable_declaration_mut(v, node).is_stop() {
1010 return VisitResult::Stop;
1011 }
1012 }
1013 Statement::FunctionDeclaration(node) => {
1014 for s in node.body.body.iter_mut() {
1015 if walk_statement_mut(v, s).is_stop() {
1016 return VisitResult::Stop;
1017 }
1018 }
1019 }
1020 Statement::ClassDeclaration(node) => {
1021 if let Some(ref mut sc) = node.super_class {
1022 if walk_expression_mut(v, sc).is_stop() {
1023 return VisitResult::Stop;
1024 }
1025 }
1026 }
1027 Statement::WithStatement(node) => {
1028 if walk_expression_mut(v, &mut node.object).is_stop() {
1029 return VisitResult::Stop;
1030 }
1031 if walk_statement_mut(v, &mut node.body).is_stop() {
1032 return VisitResult::Stop;
1033 }
1034 }
1035 Statement::ExportNamedDeclaration(node) => {
1036 if let Some(ref mut decl) = node.declaration {
1037 if walk_declaration_mut(v, decl).is_stop() {
1038 return VisitResult::Stop;
1039 }
1040 }
1041 }
1042 Statement::ExportDefaultDeclaration(node) => {
1043 if walk_export_default_decl_mut(v, &mut node.declaration).is_stop() {
1044 return VisitResult::Stop;
1045 }
1046 }
1047 Statement::BreakStatement(_)
1049 | Statement::ContinueStatement(_)
1050 | Statement::EmptyStatement(_)
1051 | Statement::DebuggerStatement(_)
1052 | Statement::ImportDeclaration(_)
1053 | Statement::ExportAllDeclaration(_)
1054 | Statement::TSTypeAliasDeclaration(_)
1055 | Statement::TSInterfaceDeclaration(_)
1056 | Statement::TSEnumDeclaration(_)
1057 | Statement::TSModuleDeclaration(_)
1058 | Statement::TSDeclareFunction(_)
1059 | Statement::TypeAlias(_)
1060 | Statement::OpaqueType(_)
1061 | Statement::InterfaceDeclaration(_)
1062 | Statement::DeclareVariable(_)
1063 | Statement::DeclareFunction(_)
1064 | Statement::DeclareClass(_)
1065 | Statement::DeclareModule(_)
1066 | Statement::DeclareModuleExports(_)
1067 | Statement::DeclareExportDeclaration(_)
1068 | Statement::DeclareExportAllDeclaration(_)
1069 | Statement::DeclareInterface(_)
1070 | Statement::DeclareTypeAlias(_)
1071 | Statement::DeclareOpaqueType(_)
1072 | Statement::EnumDeclaration(_)
1073 | Statement::Unknown(_) => {}
1075 }
1076 VisitResult::Continue
1077}
1078
1079pub fn walk_expression_mut(v: &mut impl MutVisitor, expr: &mut Expression) -> VisitResult {
1081 if v.visit_expression(expr).is_stop() {
1082 return VisitResult::Stop;
1083 }
1084 match expr {
1085 Expression::Identifier(node) => {
1086 if v.visit_identifier(node).is_stop() {
1087 return VisitResult::Stop;
1088 }
1089 }
1090 Expression::CallExpression(node) => {
1091 if walk_expression_mut(v, &mut node.callee).is_stop() {
1092 return VisitResult::Stop;
1093 }
1094 for arg in node.arguments.iter_mut() {
1095 if walk_expression_mut(v, arg).is_stop() {
1096 return VisitResult::Stop;
1097 }
1098 }
1099 }
1100 Expression::MemberExpression(node) => {
1101 if walk_expression_mut(v, &mut node.object).is_stop() {
1102 return VisitResult::Stop;
1103 }
1104 if node.computed {
1105 if walk_expression_mut(v, &mut node.property).is_stop() {
1106 return VisitResult::Stop;
1107 }
1108 }
1109 }
1110 Expression::OptionalCallExpression(node) => {
1111 if walk_expression_mut(v, &mut node.callee).is_stop() {
1112 return VisitResult::Stop;
1113 }
1114 for arg in node.arguments.iter_mut() {
1115 if walk_expression_mut(v, arg).is_stop() {
1116 return VisitResult::Stop;
1117 }
1118 }
1119 }
1120 Expression::OptionalMemberExpression(node) => {
1121 if walk_expression_mut(v, &mut node.object).is_stop() {
1122 return VisitResult::Stop;
1123 }
1124 if node.computed {
1125 if walk_expression_mut(v, &mut node.property).is_stop() {
1126 return VisitResult::Stop;
1127 }
1128 }
1129 }
1130 Expression::BinaryExpression(node) => {
1131 if walk_expression_mut(v, &mut node.left).is_stop() {
1132 return VisitResult::Stop;
1133 }
1134 if walk_expression_mut(v, &mut node.right).is_stop() {
1135 return VisitResult::Stop;
1136 }
1137 }
1138 Expression::LogicalExpression(node) => {
1139 if walk_expression_mut(v, &mut node.left).is_stop() {
1140 return VisitResult::Stop;
1141 }
1142 if walk_expression_mut(v, &mut node.right).is_stop() {
1143 return VisitResult::Stop;
1144 }
1145 }
1146 Expression::UnaryExpression(node) => {
1147 if walk_expression_mut(v, &mut node.argument).is_stop() {
1148 return VisitResult::Stop;
1149 }
1150 }
1151 Expression::UpdateExpression(node) => {
1152 if walk_expression_mut(v, &mut node.argument).is_stop() {
1153 return VisitResult::Stop;
1154 }
1155 }
1156 Expression::ConditionalExpression(node) => {
1157 if walk_expression_mut(v, &mut node.test).is_stop() {
1158 return VisitResult::Stop;
1159 }
1160 if walk_expression_mut(v, &mut node.consequent).is_stop() {
1161 return VisitResult::Stop;
1162 }
1163 if walk_expression_mut(v, &mut node.alternate).is_stop() {
1164 return VisitResult::Stop;
1165 }
1166 }
1167 Expression::AssignmentExpression(node) => {
1168 if walk_expression_mut(v, &mut node.right).is_stop() {
1169 return VisitResult::Stop;
1170 }
1171 }
1172 Expression::SequenceExpression(node) => {
1173 for e in node.expressions.iter_mut() {
1174 if walk_expression_mut(v, e).is_stop() {
1175 return VisitResult::Stop;
1176 }
1177 }
1178 }
1179 Expression::ArrowFunctionExpression(node) => match node.body.as_mut() {
1180 ArrowFunctionBody::BlockStatement(block) => {
1181 for s in block.body.iter_mut() {
1182 if walk_statement_mut(v, s).is_stop() {
1183 return VisitResult::Stop;
1184 }
1185 }
1186 }
1187 ArrowFunctionBody::Expression(e) => {
1188 if walk_expression_mut(v, e).is_stop() {
1189 return VisitResult::Stop;
1190 }
1191 }
1192 },
1193 Expression::FunctionExpression(node) => {
1194 for s in node.body.body.iter_mut() {
1195 if walk_statement_mut(v, s).is_stop() {
1196 return VisitResult::Stop;
1197 }
1198 }
1199 }
1200 Expression::ObjectExpression(node) => {
1201 for prop in node.properties.iter_mut() {
1202 match prop {
1203 ObjectExpressionProperty::ObjectProperty(p) => {
1204 if p.computed {
1205 if walk_expression_mut(v, &mut p.key).is_stop() {
1206 return VisitResult::Stop;
1207 }
1208 }
1209 if walk_expression_mut(v, &mut p.value).is_stop() {
1210 return VisitResult::Stop;
1211 }
1212 }
1213 ObjectExpressionProperty::ObjectMethod(m) => {
1214 for s in m.body.body.iter_mut() {
1215 if walk_statement_mut(v, s).is_stop() {
1216 return VisitResult::Stop;
1217 }
1218 }
1219 }
1220 ObjectExpressionProperty::SpreadElement(s) => {
1221 if walk_expression_mut(v, &mut s.argument).is_stop() {
1222 return VisitResult::Stop;
1223 }
1224 }
1225 }
1226 }
1227 }
1228 Expression::ArrayExpression(node) => {
1229 for elem in node.elements.iter_mut().flatten() {
1230 if walk_expression_mut(v, elem).is_stop() {
1231 return VisitResult::Stop;
1232 }
1233 }
1234 }
1235 Expression::NewExpression(node) => {
1236 if walk_expression_mut(v, &mut node.callee).is_stop() {
1237 return VisitResult::Stop;
1238 }
1239 for arg in node.arguments.iter_mut() {
1240 if walk_expression_mut(v, arg).is_stop() {
1241 return VisitResult::Stop;
1242 }
1243 }
1244 }
1245 Expression::TemplateLiteral(node) => {
1246 for e in node.expressions.iter_mut() {
1247 if walk_expression_mut(v, e).is_stop() {
1248 return VisitResult::Stop;
1249 }
1250 }
1251 }
1252 Expression::TaggedTemplateExpression(node) => {
1253 if walk_expression_mut(v, &mut node.tag).is_stop() {
1254 return VisitResult::Stop;
1255 }
1256 for e in node.quasi.expressions.iter_mut() {
1257 if walk_expression_mut(v, e).is_stop() {
1258 return VisitResult::Stop;
1259 }
1260 }
1261 }
1262 Expression::AwaitExpression(node) => {
1263 if walk_expression_mut(v, &mut node.argument).is_stop() {
1264 return VisitResult::Stop;
1265 }
1266 }
1267 Expression::YieldExpression(node) => {
1268 if let Some(ref mut arg) = node.argument {
1269 if walk_expression_mut(v, arg).is_stop() {
1270 return VisitResult::Stop;
1271 }
1272 }
1273 }
1274 Expression::SpreadElement(node) => {
1275 if walk_expression_mut(v, &mut node.argument).is_stop() {
1276 return VisitResult::Stop;
1277 }
1278 }
1279 Expression::ParenthesizedExpression(node) => {
1280 if walk_expression_mut(v, &mut node.expression).is_stop() {
1281 return VisitResult::Stop;
1282 }
1283 }
1284 Expression::AssignmentPattern(node) => {
1285 if walk_expression_mut(v, &mut node.right).is_stop() {
1286 return VisitResult::Stop;
1287 }
1288 }
1289 Expression::ClassExpression(node) => {
1290 if let Some(ref mut sc) = node.super_class {
1291 if walk_expression_mut(v, sc).is_stop() {
1292 return VisitResult::Stop;
1293 }
1294 }
1295 }
1296 Expression::JSXElement(node) => {
1297 if walk_jsx_mut(v, &mut node.opening_element.attributes, &mut node.children).is_stop() {
1298 return VisitResult::Stop;
1299 }
1300 }
1301 Expression::JSXFragment(node) => {
1302 if walk_jsx_children_mut(v, &mut node.children).is_stop() {
1303 return VisitResult::Stop;
1304 }
1305 }
1306 Expression::TSAsExpression(node) => {
1308 if walk_expression_mut(v, &mut node.expression).is_stop() {
1309 return VisitResult::Stop;
1310 }
1311 }
1312 Expression::TSSatisfiesExpression(node) => {
1313 if walk_expression_mut(v, &mut node.expression).is_stop() {
1314 return VisitResult::Stop;
1315 }
1316 }
1317 Expression::TSNonNullExpression(node) => {
1318 if walk_expression_mut(v, &mut node.expression).is_stop() {
1319 return VisitResult::Stop;
1320 }
1321 }
1322 Expression::TSTypeAssertion(node) => {
1323 if walk_expression_mut(v, &mut node.expression).is_stop() {
1324 return VisitResult::Stop;
1325 }
1326 }
1327 Expression::TSInstantiationExpression(node) => {
1328 if walk_expression_mut(v, &mut node.expression).is_stop() {
1329 return VisitResult::Stop;
1330 }
1331 }
1332 Expression::TypeCastExpression(node) => {
1333 if walk_expression_mut(v, &mut node.expression).is_stop() {
1334 return VisitResult::Stop;
1335 }
1336 }
1337 Expression::StringLiteral(_)
1339 | Expression::NumericLiteral(_)
1340 | Expression::BooleanLiteral(_)
1341 | Expression::NullLiteral(_)
1342 | Expression::BigIntLiteral(_)
1343 | Expression::RegExpLiteral(_)
1344 | Expression::MetaProperty(_)
1345 | Expression::PrivateName(_)
1346 | Expression::Super(_)
1347 | Expression::Import(_)
1348 | Expression::ThisExpression(_) => {}
1349 }
1350 VisitResult::Continue
1351}
1352
1353fn walk_jsx_mut(
1354 v: &mut impl MutVisitor,
1355 attrs: &mut [crate::jsx::JSXAttributeItem],
1356 children: &mut [crate::jsx::JSXChild],
1357) -> VisitResult {
1358 for attr in attrs.iter_mut() {
1359 match attr {
1360 crate::jsx::JSXAttributeItem::JSXAttribute(a) => {
1361 if let Some(ref mut val) = a.value {
1362 match val {
1363 crate::jsx::JSXAttributeValue::JSXExpressionContainer(c) => {
1364 if let crate::jsx::JSXExpressionContainerExpr::Expression(ref mut e) =
1365 c.expression
1366 {
1367 if walk_expression_mut(v, e).is_stop() {
1368 return VisitResult::Stop;
1369 }
1370 }
1371 }
1372 _ => {}
1373 }
1374 }
1375 }
1376 crate::jsx::JSXAttributeItem::JSXSpreadAttribute(s) => {
1377 if walk_expression_mut(v, &mut s.argument).is_stop() {
1378 return VisitResult::Stop;
1379 }
1380 }
1381 }
1382 }
1383 walk_jsx_children_mut(v, children)
1384}
1385
1386fn walk_jsx_children_mut(
1387 v: &mut impl MutVisitor,
1388 children: &mut [crate::jsx::JSXChild],
1389) -> VisitResult {
1390 for child in children.iter_mut() {
1391 match child {
1392 crate::jsx::JSXChild::JSXElement(el) => {
1393 if walk_jsx_mut(v, &mut el.opening_element.attributes, &mut el.children).is_stop() {
1394 return VisitResult::Stop;
1395 }
1396 }
1397 crate::jsx::JSXChild::JSXFragment(f) => {
1398 if walk_jsx_children_mut(v, &mut f.children).is_stop() {
1399 return VisitResult::Stop;
1400 }
1401 }
1402 crate::jsx::JSXChild::JSXExpressionContainer(c) => {
1403 if let crate::jsx::JSXExpressionContainerExpr::Expression(ref mut e) = c.expression
1404 {
1405 if walk_expression_mut(v, e).is_stop() {
1406 return VisitResult::Stop;
1407 }
1408 }
1409 }
1410 crate::jsx::JSXChild::JSXSpreadChild(s) => {
1411 if walk_expression_mut(v, &mut s.expression).is_stop() {
1412 return VisitResult::Stop;
1413 }
1414 }
1415 _ => {}
1416 }
1417 }
1418 VisitResult::Continue
1419}
1420
1421fn walk_variable_declaration_mut(
1424 v: &mut impl MutVisitor,
1425 decl: &mut VariableDeclaration,
1426) -> VisitResult {
1427 for declarator in decl.declarations.iter_mut() {
1428 if let Some(ref mut init) = declarator.init {
1429 if walk_expression_mut(v, init).is_stop() {
1430 return VisitResult::Stop;
1431 }
1432 }
1433 }
1434 VisitResult::Continue
1435}
1436
1437fn walk_declaration_mut(v: &mut impl MutVisitor, decl: &mut Declaration) -> VisitResult {
1438 match decl {
1439 Declaration::FunctionDeclaration(node) => {
1440 for s in node.body.body.iter_mut() {
1441 if walk_statement_mut(v, s).is_stop() {
1442 return VisitResult::Stop;
1443 }
1444 }
1445 }
1446 Declaration::VariableDeclaration(node) => {
1447 if walk_variable_declaration_mut(v, node).is_stop() {
1448 return VisitResult::Stop;
1449 }
1450 }
1451 Declaration::ClassDeclaration(node) => {
1452 if let Some(ref mut sc) = node.super_class {
1453 if walk_expression_mut(v, sc).is_stop() {
1454 return VisitResult::Stop;
1455 }
1456 }
1457 }
1458 _ => {}
1459 }
1460 VisitResult::Continue
1461}
1462
1463fn walk_export_default_decl_mut(
1464 v: &mut impl MutVisitor,
1465 decl: &mut ExportDefaultDecl,
1466) -> VisitResult {
1467 match decl {
1468 ExportDefaultDecl::FunctionDeclaration(node) => {
1469 for s in node.body.body.iter_mut() {
1470 if walk_statement_mut(v, s).is_stop() {
1471 return VisitResult::Stop;
1472 }
1473 }
1474 }
1475 ExportDefaultDecl::Expression(expr) => {
1476 if walk_expression_mut(v, expr).is_stop() {
1477 return VisitResult::Stop;
1478 }
1479 }
1480 ExportDefaultDecl::ClassDeclaration(node) => {
1481 if let Some(ref mut sc) = node.super_class {
1482 if walk_expression_mut(v, sc).is_stop() {
1483 return VisitResult::Stop;
1484 }
1485 }
1486 }
1487 ExportDefaultDecl::EnumDeclaration(_) => {
1488 }
1490 }
1491 VisitResult::Continue
1492}