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