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 }
373 }
374
375 pub fn walk_expression<'ast>(&mut self, v: &mut impl Visitor<'ast>, expr: &'ast Expression) {
376 match expr {
377 Expression::Identifier(node) => {
378 v.enter_identifier(node, &self.scope_stack);
379 }
380 Expression::CallExpression(node) => {
381 v.enter_call_expression(node, &self.scope_stack);
382 self.walk_expression(v, &node.callee);
383 for arg in &node.arguments {
384 self.walk_expression(v, arg);
385 }
386 v.leave_call_expression(node, &self.scope_stack);
387 }
388 Expression::MemberExpression(node) => {
389 self.walk_expression(v, &node.object);
390 if node.computed {
391 self.walk_expression(v, &node.property);
392 }
393 }
394 Expression::OptionalCallExpression(node) => {
395 self.walk_expression(v, &node.callee);
396 for arg in &node.arguments {
397 self.walk_expression(v, arg);
398 }
399 }
400 Expression::OptionalMemberExpression(node) => {
401 self.walk_expression(v, &node.object);
402 if node.computed {
403 self.walk_expression(v, &node.property);
404 }
405 }
406 Expression::BinaryExpression(node) => {
407 self.walk_expression(v, &node.left);
408 self.walk_expression(v, &node.right);
409 }
410 Expression::LogicalExpression(node) => {
411 self.walk_expression(v, &node.left);
412 self.walk_expression(v, &node.right);
413 }
414 Expression::UnaryExpression(node) => {
415 self.walk_expression(v, &node.argument);
416 }
417 Expression::UpdateExpression(node) => {
418 v.enter_update_expression(node, &self.scope_stack);
419 self.walk_expression(v, &node.argument);
420 }
421 Expression::ConditionalExpression(node) => {
422 self.walk_expression(v, &node.test);
423 self.walk_expression(v, &node.consequent);
424 self.walk_expression(v, &node.alternate);
425 }
426 Expression::AssignmentExpression(node) => {
427 v.enter_assignment_expression(node, &self.scope_stack);
428 self.walk_pattern(v, &node.left);
429 self.walk_expression(v, &node.right);
430 }
431 Expression::SequenceExpression(node) => {
432 for expr in &node.expressions {
433 self.walk_expression(v, expr);
434 }
435 }
436 Expression::ArrowFunctionExpression(node) => {
437 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
438 v.enter_arrow_function_expression(node, &self.scope_stack);
439 if v.traverse_function_bodies() {
440 for param in &node.params {
441 self.walk_pattern(v, param);
442 }
443 match node.body.as_ref() {
444 ArrowFunctionBody::BlockStatement(block) => {
445 self.walk_block_statement(v, block);
446 }
447 ArrowFunctionBody::Expression(expr) => {
448 self.walk_expression(v, expr);
449 }
450 }
451 }
452 v.leave_arrow_function_expression(node, &self.scope_stack);
453 if pushed {
454 self.scope_stack.pop();
455 }
456 }
457 Expression::FunctionExpression(node) => {
458 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
459 v.enter_function_expression(node, &self.scope_stack);
460 if v.traverse_function_bodies() {
461 for param in &node.params {
462 self.walk_pattern(v, param);
463 }
464 self.walk_block_statement(v, &node.body);
465 }
466 v.leave_function_expression(node, &self.scope_stack);
467 if pushed {
468 self.scope_stack.pop();
469 }
470 }
471 Expression::ObjectExpression(node) => {
472 for prop in &node.properties {
473 self.walk_object_expression_property(v, prop);
474 }
475 }
476 Expression::ArrayExpression(node) => {
477 for element in &node.elements {
478 if let Some(el) = element {
479 self.walk_expression(v, el);
480 }
481 }
482 }
483 Expression::NewExpression(node) => {
484 self.walk_expression(v, &node.callee);
485 for arg in &node.arguments {
486 self.walk_expression(v, arg);
487 }
488 }
489 Expression::TemplateLiteral(node) => {
490 for expr in &node.expressions {
491 self.walk_expression(v, expr);
492 }
493 }
494 Expression::TaggedTemplateExpression(node) => {
495 self.walk_expression(v, &node.tag);
496 for expr in &node.quasi.expressions {
497 self.walk_expression(v, expr);
498 }
499 }
500 Expression::AwaitExpression(node) => {
501 self.walk_expression(v, &node.argument);
502 }
503 Expression::YieldExpression(node) => {
504 if let Some(arg) = &node.argument {
505 self.walk_expression(v, arg);
506 }
507 }
508 Expression::SpreadElement(node) => {
509 self.walk_expression(v, &node.argument);
510 }
511 Expression::ParenthesizedExpression(node) => {
512 self.walk_expression(v, &node.expression);
513 }
514 Expression::AssignmentPattern(node) => {
515 self.walk_pattern(v, &node.left);
516 self.walk_expression(v, &node.right);
517 }
518 Expression::ClassExpression(node) => {
519 v.enter_class_expression(node, &self.scope_stack);
522 }
523 Expression::JSXElement(node) => self.walk_jsx_element(v, node),
525 Expression::JSXFragment(node) => self.walk_jsx_fragment(v, node),
526 Expression::TSAsExpression(node) => self.walk_expression(v, &node.expression),
528 Expression::TSSatisfiesExpression(node) => self.walk_expression(v, &node.expression),
529 Expression::TSNonNullExpression(node) => self.walk_expression(v, &node.expression),
530 Expression::TSTypeAssertion(node) => self.walk_expression(v, &node.expression),
531 Expression::TSInstantiationExpression(node) => {
532 self.walk_expression(v, &node.expression)
533 }
534 Expression::TypeCastExpression(node) => self.walk_expression(v, &node.expression),
535 Expression::StringLiteral(_)
537 | Expression::NumericLiteral(_)
538 | Expression::BooleanLiteral(_)
539 | Expression::NullLiteral(_)
540 | Expression::BigIntLiteral(_)
541 | Expression::RegExpLiteral(_)
542 | Expression::MetaProperty(_)
543 | Expression::PrivateName(_)
544 | Expression::Super(_)
545 | Expression::Import(_)
546 | Expression::ThisExpression(_) => {}
547 }
548 }
549
550 pub fn walk_pattern<'ast>(&mut self, v: &mut impl Visitor<'ast>, pat: &'ast PatternLike) {
551 match pat {
552 PatternLike::Identifier(node) => {
553 v.enter_identifier(node, &self.scope_stack);
554 }
555 PatternLike::ObjectPattern(node) => {
556 for prop in &node.properties {
557 match prop {
558 ObjectPatternProperty::ObjectProperty(p) => {
559 if p.computed {
560 self.walk_expression(v, &p.key);
561 }
562 self.walk_pattern(v, &p.value);
563 }
564 ObjectPatternProperty::RestElement(p) => {
565 self.walk_pattern(v, &p.argument);
566 }
567 }
568 }
569 }
570 PatternLike::ArrayPattern(node) => {
571 for element in &node.elements {
572 if let Some(el) = element {
573 self.walk_pattern(v, el);
574 }
575 }
576 }
577 PatternLike::AssignmentPattern(node) => {
578 self.walk_pattern(v, &node.left);
579 self.walk_expression(v, &node.right);
580 }
581 PatternLike::RestElement(node) => {
582 self.walk_pattern(v, &node.argument);
583 }
584 PatternLike::MemberExpression(node) => {
585 self.walk_expression(v, &node.object);
586 if node.computed {
587 self.walk_expression(v, &node.property);
588 }
589 }
590 PatternLike::TSAsExpression(node) => self.walk_expression(v, &node.expression),
591 PatternLike::TSSatisfiesExpression(node) => {
592 self.walk_expression(v, &node.expression)
593 }
594 PatternLike::TSNonNullExpression(node) => {
595 self.walk_expression(v, &node.expression)
596 }
597 PatternLike::TSTypeAssertion(node) => self.walk_expression(v, &node.expression),
598 }
599 }
600
601 fn walk_for_in_of_left<'ast>(&mut self, v: &mut impl Visitor<'ast>, left: &'ast ForInOfLeft) {
604 match left {
605 ForInOfLeft::VariableDeclaration(decl) => self.walk_variable_declaration(v, decl),
606 ForInOfLeft::Pattern(pat) => self.walk_pattern(v, pat),
607 }
608 }
609
610 fn walk_variable_declaration<'ast>(
611 &mut self,
612 v: &mut impl Visitor<'ast>,
613 decl: &'ast VariableDeclaration,
614 ) {
615 for declarator in &decl.declarations {
616 v.enter_variable_declarator(declarator, &self.scope_stack);
617 self.walk_pattern(v, &declarator.id);
618 if let Some(init) = &declarator.init {
619 self.walk_expression(v, init);
620 }
621 v.leave_variable_declarator(declarator, &self.scope_stack);
622 }
623 }
624
625 fn walk_function_declaration_inner<'ast>(
626 &mut self,
627 v: &mut impl Visitor<'ast>,
628 node: &'ast FunctionDeclaration,
629 ) {
630 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
631 v.enter_function_declaration(node, &self.scope_stack);
632 if v.traverse_function_bodies() {
633 for param in &node.params {
634 self.walk_pattern(v, param);
635 }
636 self.walk_block_statement(v, &node.body);
637 }
638 v.leave_function_declaration(node, &self.scope_stack);
639 if pushed {
640 self.scope_stack.pop();
641 }
642 }
643
644 fn walk_object_expression_property<'ast>(
645 &mut self,
646 v: &mut impl Visitor<'ast>,
647 prop: &'ast ObjectExpressionProperty,
648 ) {
649 match prop {
650 ObjectExpressionProperty::ObjectProperty(p) => {
651 if p.computed {
652 self.walk_expression(v, &p.key);
653 }
654 self.walk_expression(v, &p.value);
655 }
656 ObjectExpressionProperty::ObjectMethod(node) => {
657 let pushed = self.try_push_scope(node.base.start, node.base.node_id);
658 v.enter_object_method(node, &self.scope_stack);
659 if v.traverse_function_bodies() {
660 if node.computed {
661 self.walk_expression(v, &node.key);
662 }
663 for param in &node.params {
664 self.walk_pattern(v, param);
665 }
666 self.walk_block_statement(v, &node.body);
667 }
668 v.leave_object_method(node, &self.scope_stack);
669 if pushed {
670 self.scope_stack.pop();
671 }
672 }
673 ObjectExpressionProperty::SpreadElement(p) => {
674 self.walk_expression(v, &p.argument);
675 }
676 }
677 }
678
679 fn walk_declaration<'ast>(&mut self, v: &mut impl Visitor<'ast>, decl: &'ast Declaration) {
680 match decl {
681 Declaration::FunctionDeclaration(node) => {
682 self.walk_function_declaration_inner(v, node);
683 }
684 Declaration::VariableDeclaration(node) => {
685 self.walk_variable_declaration(v, node);
686 }
687 _ => {}
689 }
690 }
691
692 fn walk_export_default_decl<'ast>(
693 &mut self,
694 v: &mut impl Visitor<'ast>,
695 decl: &'ast ExportDefaultDecl,
696 ) {
697 match decl {
698 ExportDefaultDecl::FunctionDeclaration(node) => {
699 self.walk_function_declaration_inner(v, node);
700 }
701 ExportDefaultDecl::ClassDeclaration(node) => {
702 v.enter_class_declaration(node, &self.scope_stack);
704 }
705 ExportDefaultDecl::EnumDeclaration(_) => {
706 }
708 ExportDefaultDecl::Expression(expr) => {
709 self.walk_expression(v, expr);
710 }
711 }
712 }
713
714 fn walk_jsx_element<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast JSXElement) {
715 v.enter_jsx_opening_element(&node.opening_element, &self.scope_stack);
716 self.walk_jsx_element_name(v, &node.opening_element.name);
717 v.leave_jsx_opening_element(&node.opening_element, &self.scope_stack);
718 for attr in &node.opening_element.attributes {
719 match attr {
720 JSXAttributeItem::JSXAttribute(a) => {
721 if let Some(value) = &a.value {
722 match value {
723 JSXAttributeValue::JSXExpressionContainer(c) => {
724 self.walk_jsx_expr_container(v, c);
725 }
726 JSXAttributeValue::JSXElement(el) => {
727 self.walk_jsx_element(v, el);
728 }
729 JSXAttributeValue::JSXFragment(f) => {
730 self.walk_jsx_fragment(v, f);
731 }
732 JSXAttributeValue::StringLiteral(_) => {}
733 }
734 }
735 }
736 JSXAttributeItem::JSXSpreadAttribute(a) => {
737 self.walk_expression(v, &a.argument);
738 }
739 }
740 }
741 for child in &node.children {
742 self.walk_jsx_child(v, child);
743 }
744 }
745
746 fn walk_jsx_fragment<'ast>(&mut self, v: &mut impl Visitor<'ast>, node: &'ast JSXFragment) {
747 for child in &node.children {
748 self.walk_jsx_child(v, child);
749 }
750 }
751
752 fn walk_jsx_child<'ast>(&mut self, v: &mut impl Visitor<'ast>, child: &'ast JSXChild) {
753 match child {
754 JSXChild::JSXElement(el) => self.walk_jsx_element(v, el),
755 JSXChild::JSXFragment(f) => self.walk_jsx_fragment(v, f),
756 JSXChild::JSXExpressionContainer(c) => self.walk_jsx_expr_container(v, c),
757 JSXChild::JSXSpreadChild(s) => self.walk_expression(v, &s.expression),
758 JSXChild::JSXText(_) => {}
759 }
760 }
761
762 fn walk_jsx_expr_container<'ast>(
763 &mut self,
764 v: &mut impl Visitor<'ast>,
765 node: &'ast JSXExpressionContainer,
766 ) {
767 match &node.expression {
768 JSXExpressionContainerExpr::Expression(expr) => self.walk_expression(v, expr),
769 JSXExpressionContainerExpr::JSXEmptyExpression(_) => {}
770 }
771 }
772
773 fn walk_jsx_element_name<'ast>(
774 &mut self,
775 v: &mut impl Visitor<'ast>,
776 name: &'ast JSXElementName,
777 ) {
778 match name {
779 JSXElementName::JSXIdentifier(id) => {
780 v.enter_jsx_identifier(id, &self.scope_stack);
781 }
782 JSXElementName::JSXMemberExpression(expr) => {
783 self.walk_jsx_member_expression(v, expr);
784 }
785 JSXElementName::JSXNamespacedName(_) => {}
786 }
787 }
788
789 fn walk_jsx_member_expression<'ast>(
790 &mut self,
791 v: &mut impl Visitor<'ast>,
792 expr: &'ast JSXMemberExpression,
793 ) {
794 match &*expr.object {
795 JSXMemberExprObject::JSXIdentifier(id) => {
796 v.enter_jsx_identifier(id, &self.scope_stack);
797 }
798 JSXMemberExprObject::JSXMemberExpression(inner) => {
799 self.walk_jsx_member_expression(v, inner);
800 }
801 }
802 v.enter_jsx_identifier(&expr.property, &self.scope_stack);
803 }
804}
805
806#[derive(Debug, Clone, Copy, PartialEq, Eq)]
812pub enum VisitResult {
813 Continue,
815 Stop,
817}
818
819impl VisitResult {
820 pub fn is_stop(self) -> bool {
821 self == VisitResult::Stop
822 }
823}
824
825pub trait MutVisitor {
832 fn visit_statement(&mut self, _stmt: &mut Statement) -> VisitResult {
834 VisitResult::Continue
835 }
836
837 fn visit_expression(&mut self, _expr: &mut Expression) -> VisitResult {
839 VisitResult::Continue
840 }
841
842 fn visit_identifier(&mut self, _node: &mut Identifier) -> VisitResult {
844 VisitResult::Continue
845 }
846}
847
848pub fn walk_program_mut(v: &mut impl MutVisitor, program: &mut Program) -> VisitResult {
850 for stmt in program.body.iter_mut() {
851 if walk_statement_mut(v, stmt).is_stop() {
852 return VisitResult::Stop;
853 }
854 }
855 VisitResult::Continue
856}
857
858pub fn walk_statement_mut(v: &mut impl MutVisitor, stmt: &mut Statement) -> VisitResult {
860 if v.visit_statement(stmt).is_stop() {
861 return VisitResult::Stop;
862 }
863 match stmt {
864 Statement::BlockStatement(node) => {
865 for s in node.body.iter_mut() {
866 if walk_statement_mut(v, s).is_stop() {
867 return VisitResult::Stop;
868 }
869 }
870 }
871 Statement::ReturnStatement(node) => {
872 if let Some(ref mut arg) = node.argument {
873 if walk_expression_mut(v, arg).is_stop() {
874 return VisitResult::Stop;
875 }
876 }
877 }
878 Statement::ExpressionStatement(node) => {
879 if walk_expression_mut(v, &mut node.expression).is_stop() {
880 return VisitResult::Stop;
881 }
882 }
883 Statement::IfStatement(node) => {
884 if walk_expression_mut(v, &mut node.test).is_stop() {
885 return VisitResult::Stop;
886 }
887 if walk_statement_mut(v, &mut node.consequent).is_stop() {
888 return VisitResult::Stop;
889 }
890 if let Some(ref mut alt) = node.alternate {
891 if walk_statement_mut(v, alt).is_stop() {
892 return VisitResult::Stop;
893 }
894 }
895 }
896 Statement::ForStatement(node) => {
897 if let Some(ref mut init) = node.init {
898 match init.as_mut() {
899 ForInit::VariableDeclaration(decl) => {
900 if walk_variable_declaration_mut(v, decl).is_stop() {
901 return VisitResult::Stop;
902 }
903 }
904 ForInit::Expression(expr) => {
905 if walk_expression_mut(v, expr).is_stop() {
906 return VisitResult::Stop;
907 }
908 }
909 }
910 }
911 if let Some(ref mut test) = node.test {
912 if walk_expression_mut(v, test).is_stop() {
913 return VisitResult::Stop;
914 }
915 }
916 if let Some(ref mut update) = node.update {
917 if walk_expression_mut(v, update).is_stop() {
918 return VisitResult::Stop;
919 }
920 }
921 if walk_statement_mut(v, &mut node.body).is_stop() {
922 return VisitResult::Stop;
923 }
924 }
925 Statement::WhileStatement(node) => {
926 if walk_expression_mut(v, &mut node.test).is_stop() {
927 return VisitResult::Stop;
928 }
929 if walk_statement_mut(v, &mut node.body).is_stop() {
930 return VisitResult::Stop;
931 }
932 }
933 Statement::DoWhileStatement(node) => {
934 if walk_statement_mut(v, &mut node.body).is_stop() {
935 return VisitResult::Stop;
936 }
937 if walk_expression_mut(v, &mut node.test).is_stop() {
938 return VisitResult::Stop;
939 }
940 }
941 Statement::ForInStatement(node) => {
942 if walk_expression_mut(v, &mut node.right).is_stop() {
943 return VisitResult::Stop;
944 }
945 if walk_statement_mut(v, &mut node.body).is_stop() {
946 return VisitResult::Stop;
947 }
948 }
949 Statement::ForOfStatement(node) => {
950 if walk_expression_mut(v, &mut node.right).is_stop() {
951 return VisitResult::Stop;
952 }
953 if walk_statement_mut(v, &mut node.body).is_stop() {
954 return VisitResult::Stop;
955 }
956 }
957 Statement::SwitchStatement(node) => {
958 if walk_expression_mut(v, &mut node.discriminant).is_stop() {
959 return VisitResult::Stop;
960 }
961 for case in node.cases.iter_mut() {
962 if let Some(ref mut test) = case.test {
963 if walk_expression_mut(v, test).is_stop() {
964 return VisitResult::Stop;
965 }
966 }
967 for s in case.consequent.iter_mut() {
968 if walk_statement_mut(v, s).is_stop() {
969 return VisitResult::Stop;
970 }
971 }
972 }
973 }
974 Statement::ThrowStatement(node) => {
975 if walk_expression_mut(v, &mut node.argument).is_stop() {
976 return VisitResult::Stop;
977 }
978 }
979 Statement::TryStatement(node) => {
980 for s in node.block.body.iter_mut() {
981 if walk_statement_mut(v, s).is_stop() {
982 return VisitResult::Stop;
983 }
984 }
985 if let Some(ref mut handler) = node.handler {
986 for s in handler.body.body.iter_mut() {
987 if walk_statement_mut(v, s).is_stop() {
988 return VisitResult::Stop;
989 }
990 }
991 }
992 if let Some(ref mut finalizer) = node.finalizer {
993 for s in finalizer.body.iter_mut() {
994 if walk_statement_mut(v, s).is_stop() {
995 return VisitResult::Stop;
996 }
997 }
998 }
999 }
1000 Statement::LabeledStatement(node) => {
1001 if walk_statement_mut(v, &mut node.body).is_stop() {
1002 return VisitResult::Stop;
1003 }
1004 }
1005 Statement::VariableDeclaration(node) => {
1006 if walk_variable_declaration_mut(v, node).is_stop() {
1007 return VisitResult::Stop;
1008 }
1009 }
1010 Statement::FunctionDeclaration(node) => {
1011 for s in node.body.body.iter_mut() {
1012 if walk_statement_mut(v, s).is_stop() {
1013 return VisitResult::Stop;
1014 }
1015 }
1016 }
1017 Statement::ClassDeclaration(node) => {
1018 if let Some(ref mut sc) = node.super_class {
1019 if walk_expression_mut(v, sc).is_stop() {
1020 return VisitResult::Stop;
1021 }
1022 }
1023 }
1024 Statement::WithStatement(node) => {
1025 if walk_expression_mut(v, &mut node.object).is_stop() {
1026 return VisitResult::Stop;
1027 }
1028 if walk_statement_mut(v, &mut node.body).is_stop() {
1029 return VisitResult::Stop;
1030 }
1031 }
1032 Statement::ExportNamedDeclaration(node) => {
1033 if let Some(ref mut decl) = node.declaration {
1034 if walk_declaration_mut(v, decl).is_stop() {
1035 return VisitResult::Stop;
1036 }
1037 }
1038 }
1039 Statement::ExportDefaultDeclaration(node) => {
1040 if walk_export_default_decl_mut(v, &mut node.declaration).is_stop() {
1041 return VisitResult::Stop;
1042 }
1043 }
1044 Statement::BreakStatement(_)
1046 | Statement::ContinueStatement(_)
1047 | Statement::EmptyStatement(_)
1048 | Statement::DebuggerStatement(_)
1049 | Statement::ImportDeclaration(_)
1050 | Statement::ExportAllDeclaration(_)
1051 | Statement::TSTypeAliasDeclaration(_)
1052 | Statement::TSInterfaceDeclaration(_)
1053 | Statement::TSEnumDeclaration(_)
1054 | Statement::TSModuleDeclaration(_)
1055 | Statement::TSDeclareFunction(_)
1056 | Statement::TypeAlias(_)
1057 | Statement::OpaqueType(_)
1058 | Statement::InterfaceDeclaration(_)
1059 | Statement::DeclareVariable(_)
1060 | Statement::DeclareFunction(_)
1061 | Statement::DeclareClass(_)
1062 | Statement::DeclareModule(_)
1063 | Statement::DeclareModuleExports(_)
1064 | Statement::DeclareExportDeclaration(_)
1065 | Statement::DeclareExportAllDeclaration(_)
1066 | Statement::DeclareInterface(_)
1067 | Statement::DeclareTypeAlias(_)
1068 | Statement::DeclareOpaqueType(_)
1069 | Statement::EnumDeclaration(_) => {}
1070 }
1071 VisitResult::Continue
1072}
1073
1074pub fn walk_expression_mut(v: &mut impl MutVisitor, expr: &mut Expression) -> VisitResult {
1076 if v.visit_expression(expr).is_stop() {
1077 return VisitResult::Stop;
1078 }
1079 match expr {
1080 Expression::Identifier(node) => {
1081 if v.visit_identifier(node).is_stop() {
1082 return VisitResult::Stop;
1083 }
1084 }
1085 Expression::CallExpression(node) => {
1086 if walk_expression_mut(v, &mut node.callee).is_stop() {
1087 return VisitResult::Stop;
1088 }
1089 for arg in node.arguments.iter_mut() {
1090 if walk_expression_mut(v, arg).is_stop() {
1091 return VisitResult::Stop;
1092 }
1093 }
1094 }
1095 Expression::MemberExpression(node) => {
1096 if walk_expression_mut(v, &mut node.object).is_stop() {
1097 return VisitResult::Stop;
1098 }
1099 if node.computed {
1100 if walk_expression_mut(v, &mut node.property).is_stop() {
1101 return VisitResult::Stop;
1102 }
1103 }
1104 }
1105 Expression::OptionalCallExpression(node) => {
1106 if walk_expression_mut(v, &mut node.callee).is_stop() {
1107 return VisitResult::Stop;
1108 }
1109 for arg in node.arguments.iter_mut() {
1110 if walk_expression_mut(v, arg).is_stop() {
1111 return VisitResult::Stop;
1112 }
1113 }
1114 }
1115 Expression::OptionalMemberExpression(node) => {
1116 if walk_expression_mut(v, &mut node.object).is_stop() {
1117 return VisitResult::Stop;
1118 }
1119 if node.computed {
1120 if walk_expression_mut(v, &mut node.property).is_stop() {
1121 return VisitResult::Stop;
1122 }
1123 }
1124 }
1125 Expression::BinaryExpression(node) => {
1126 if walk_expression_mut(v, &mut node.left).is_stop() {
1127 return VisitResult::Stop;
1128 }
1129 if walk_expression_mut(v, &mut node.right).is_stop() {
1130 return VisitResult::Stop;
1131 }
1132 }
1133 Expression::LogicalExpression(node) => {
1134 if walk_expression_mut(v, &mut node.left).is_stop() {
1135 return VisitResult::Stop;
1136 }
1137 if walk_expression_mut(v, &mut node.right).is_stop() {
1138 return VisitResult::Stop;
1139 }
1140 }
1141 Expression::UnaryExpression(node) => {
1142 if walk_expression_mut(v, &mut node.argument).is_stop() {
1143 return VisitResult::Stop;
1144 }
1145 }
1146 Expression::UpdateExpression(node) => {
1147 if walk_expression_mut(v, &mut node.argument).is_stop() {
1148 return VisitResult::Stop;
1149 }
1150 }
1151 Expression::ConditionalExpression(node) => {
1152 if walk_expression_mut(v, &mut node.test).is_stop() {
1153 return VisitResult::Stop;
1154 }
1155 if walk_expression_mut(v, &mut node.consequent).is_stop() {
1156 return VisitResult::Stop;
1157 }
1158 if walk_expression_mut(v, &mut node.alternate).is_stop() {
1159 return VisitResult::Stop;
1160 }
1161 }
1162 Expression::AssignmentExpression(node) => {
1163 if walk_expression_mut(v, &mut node.right).is_stop() {
1164 return VisitResult::Stop;
1165 }
1166 }
1167 Expression::SequenceExpression(node) => {
1168 for e in node.expressions.iter_mut() {
1169 if walk_expression_mut(v, e).is_stop() {
1170 return VisitResult::Stop;
1171 }
1172 }
1173 }
1174 Expression::ArrowFunctionExpression(node) => match node.body.as_mut() {
1175 ArrowFunctionBody::BlockStatement(block) => {
1176 for s in block.body.iter_mut() {
1177 if walk_statement_mut(v, s).is_stop() {
1178 return VisitResult::Stop;
1179 }
1180 }
1181 }
1182 ArrowFunctionBody::Expression(e) => {
1183 if walk_expression_mut(v, e).is_stop() {
1184 return VisitResult::Stop;
1185 }
1186 }
1187 },
1188 Expression::FunctionExpression(node) => {
1189 for s in node.body.body.iter_mut() {
1190 if walk_statement_mut(v, s).is_stop() {
1191 return VisitResult::Stop;
1192 }
1193 }
1194 }
1195 Expression::ObjectExpression(node) => {
1196 for prop in node.properties.iter_mut() {
1197 match prop {
1198 ObjectExpressionProperty::ObjectProperty(p) => {
1199 if p.computed {
1200 if walk_expression_mut(v, &mut p.key).is_stop() {
1201 return VisitResult::Stop;
1202 }
1203 }
1204 if walk_expression_mut(v, &mut p.value).is_stop() {
1205 return VisitResult::Stop;
1206 }
1207 }
1208 ObjectExpressionProperty::ObjectMethod(m) => {
1209 for s in m.body.body.iter_mut() {
1210 if walk_statement_mut(v, s).is_stop() {
1211 return VisitResult::Stop;
1212 }
1213 }
1214 }
1215 ObjectExpressionProperty::SpreadElement(s) => {
1216 if walk_expression_mut(v, &mut s.argument).is_stop() {
1217 return VisitResult::Stop;
1218 }
1219 }
1220 }
1221 }
1222 }
1223 Expression::ArrayExpression(node) => {
1224 for elem in node.elements.iter_mut().flatten() {
1225 if walk_expression_mut(v, elem).is_stop() {
1226 return VisitResult::Stop;
1227 }
1228 }
1229 }
1230 Expression::NewExpression(node) => {
1231 if walk_expression_mut(v, &mut node.callee).is_stop() {
1232 return VisitResult::Stop;
1233 }
1234 for arg in node.arguments.iter_mut() {
1235 if walk_expression_mut(v, arg).is_stop() {
1236 return VisitResult::Stop;
1237 }
1238 }
1239 }
1240 Expression::TemplateLiteral(node) => {
1241 for e in node.expressions.iter_mut() {
1242 if walk_expression_mut(v, e).is_stop() {
1243 return VisitResult::Stop;
1244 }
1245 }
1246 }
1247 Expression::TaggedTemplateExpression(node) => {
1248 if walk_expression_mut(v, &mut node.tag).is_stop() {
1249 return VisitResult::Stop;
1250 }
1251 for e in node.quasi.expressions.iter_mut() {
1252 if walk_expression_mut(v, e).is_stop() {
1253 return VisitResult::Stop;
1254 }
1255 }
1256 }
1257 Expression::AwaitExpression(node) => {
1258 if walk_expression_mut(v, &mut node.argument).is_stop() {
1259 return VisitResult::Stop;
1260 }
1261 }
1262 Expression::YieldExpression(node) => {
1263 if let Some(ref mut arg) = node.argument {
1264 if walk_expression_mut(v, arg).is_stop() {
1265 return VisitResult::Stop;
1266 }
1267 }
1268 }
1269 Expression::SpreadElement(node) => {
1270 if walk_expression_mut(v, &mut node.argument).is_stop() {
1271 return VisitResult::Stop;
1272 }
1273 }
1274 Expression::ParenthesizedExpression(node) => {
1275 if walk_expression_mut(v, &mut node.expression).is_stop() {
1276 return VisitResult::Stop;
1277 }
1278 }
1279 Expression::AssignmentPattern(node) => {
1280 if walk_expression_mut(v, &mut node.right).is_stop() {
1281 return VisitResult::Stop;
1282 }
1283 }
1284 Expression::ClassExpression(node) => {
1285 if let Some(ref mut sc) = node.super_class {
1286 if walk_expression_mut(v, sc).is_stop() {
1287 return VisitResult::Stop;
1288 }
1289 }
1290 }
1291 Expression::JSXElement(node) => {
1292 if walk_jsx_mut(v, &mut node.opening_element.attributes, &mut node.children).is_stop() {
1293 return VisitResult::Stop;
1294 }
1295 }
1296 Expression::JSXFragment(node) => {
1297 if walk_jsx_children_mut(v, &mut node.children).is_stop() {
1298 return VisitResult::Stop;
1299 }
1300 }
1301 Expression::TSAsExpression(node) => {
1303 if walk_expression_mut(v, &mut node.expression).is_stop() {
1304 return VisitResult::Stop;
1305 }
1306 }
1307 Expression::TSSatisfiesExpression(node) => {
1308 if walk_expression_mut(v, &mut node.expression).is_stop() {
1309 return VisitResult::Stop;
1310 }
1311 }
1312 Expression::TSNonNullExpression(node) => {
1313 if walk_expression_mut(v, &mut node.expression).is_stop() {
1314 return VisitResult::Stop;
1315 }
1316 }
1317 Expression::TSTypeAssertion(node) => {
1318 if walk_expression_mut(v, &mut node.expression).is_stop() {
1319 return VisitResult::Stop;
1320 }
1321 }
1322 Expression::TSInstantiationExpression(node) => {
1323 if walk_expression_mut(v, &mut node.expression).is_stop() {
1324 return VisitResult::Stop;
1325 }
1326 }
1327 Expression::TypeCastExpression(node) => {
1328 if walk_expression_mut(v, &mut node.expression).is_stop() {
1329 return VisitResult::Stop;
1330 }
1331 }
1332 Expression::StringLiteral(_)
1334 | Expression::NumericLiteral(_)
1335 | Expression::BooleanLiteral(_)
1336 | Expression::NullLiteral(_)
1337 | Expression::BigIntLiteral(_)
1338 | Expression::RegExpLiteral(_)
1339 | Expression::MetaProperty(_)
1340 | Expression::PrivateName(_)
1341 | Expression::Super(_)
1342 | Expression::Import(_)
1343 | Expression::ThisExpression(_) => {}
1344 }
1345 VisitResult::Continue
1346}
1347
1348fn walk_jsx_mut(
1349 v: &mut impl MutVisitor,
1350 attrs: &mut [crate::jsx::JSXAttributeItem],
1351 children: &mut [crate::jsx::JSXChild],
1352) -> VisitResult {
1353 for attr in attrs.iter_mut() {
1354 match attr {
1355 crate::jsx::JSXAttributeItem::JSXAttribute(a) => {
1356 if let Some(ref mut val) = a.value {
1357 match val {
1358 crate::jsx::JSXAttributeValue::JSXExpressionContainer(c) => {
1359 if let crate::jsx::JSXExpressionContainerExpr::Expression(ref mut e) =
1360 c.expression
1361 {
1362 if walk_expression_mut(v, e).is_stop() {
1363 return VisitResult::Stop;
1364 }
1365 }
1366 }
1367 _ => {}
1368 }
1369 }
1370 }
1371 crate::jsx::JSXAttributeItem::JSXSpreadAttribute(s) => {
1372 if walk_expression_mut(v, &mut s.argument).is_stop() {
1373 return VisitResult::Stop;
1374 }
1375 }
1376 }
1377 }
1378 walk_jsx_children_mut(v, children)
1379}
1380
1381fn walk_jsx_children_mut(
1382 v: &mut impl MutVisitor,
1383 children: &mut [crate::jsx::JSXChild],
1384) -> VisitResult {
1385 for child in children.iter_mut() {
1386 match child {
1387 crate::jsx::JSXChild::JSXElement(el) => {
1388 if walk_jsx_mut(v, &mut el.opening_element.attributes, &mut el.children).is_stop() {
1389 return VisitResult::Stop;
1390 }
1391 }
1392 crate::jsx::JSXChild::JSXFragment(f) => {
1393 if walk_jsx_children_mut(v, &mut f.children).is_stop() {
1394 return VisitResult::Stop;
1395 }
1396 }
1397 crate::jsx::JSXChild::JSXExpressionContainer(c) => {
1398 if let crate::jsx::JSXExpressionContainerExpr::Expression(ref mut e) = c.expression
1399 {
1400 if walk_expression_mut(v, e).is_stop() {
1401 return VisitResult::Stop;
1402 }
1403 }
1404 }
1405 crate::jsx::JSXChild::JSXSpreadChild(s) => {
1406 if walk_expression_mut(v, &mut s.expression).is_stop() {
1407 return VisitResult::Stop;
1408 }
1409 }
1410 _ => {}
1411 }
1412 }
1413 VisitResult::Continue
1414}
1415
1416fn walk_variable_declaration_mut(
1419 v: &mut impl MutVisitor,
1420 decl: &mut VariableDeclaration,
1421) -> VisitResult {
1422 for declarator in decl.declarations.iter_mut() {
1423 if let Some(ref mut init) = declarator.init {
1424 if walk_expression_mut(v, init).is_stop() {
1425 return VisitResult::Stop;
1426 }
1427 }
1428 }
1429 VisitResult::Continue
1430}
1431
1432fn walk_declaration_mut(v: &mut impl MutVisitor, decl: &mut Declaration) -> VisitResult {
1433 match decl {
1434 Declaration::FunctionDeclaration(node) => {
1435 for s in node.body.body.iter_mut() {
1436 if walk_statement_mut(v, s).is_stop() {
1437 return VisitResult::Stop;
1438 }
1439 }
1440 }
1441 Declaration::VariableDeclaration(node) => {
1442 if walk_variable_declaration_mut(v, node).is_stop() {
1443 return VisitResult::Stop;
1444 }
1445 }
1446 Declaration::ClassDeclaration(node) => {
1447 if let Some(ref mut sc) = node.super_class {
1448 if walk_expression_mut(v, sc).is_stop() {
1449 return VisitResult::Stop;
1450 }
1451 }
1452 }
1453 _ => {}
1454 }
1455 VisitResult::Continue
1456}
1457
1458fn walk_export_default_decl_mut(
1459 v: &mut impl MutVisitor,
1460 decl: &mut ExportDefaultDecl,
1461) -> VisitResult {
1462 match decl {
1463 ExportDefaultDecl::FunctionDeclaration(node) => {
1464 for s in node.body.body.iter_mut() {
1465 if walk_statement_mut(v, s).is_stop() {
1466 return VisitResult::Stop;
1467 }
1468 }
1469 }
1470 ExportDefaultDecl::Expression(expr) => {
1471 if walk_expression_mut(v, expr).is_stop() {
1472 return VisitResult::Stop;
1473 }
1474 }
1475 ExportDefaultDecl::ClassDeclaration(node) => {
1476 if let Some(ref mut sc) = node.super_class {
1477 if walk_expression_mut(v, sc).is_stop() {
1478 return VisitResult::Stop;
1479 }
1480 }
1481 }
1482 ExportDefaultDecl::EnumDeclaration(_) => {
1483 }
1485 }
1486 VisitResult::Continue
1487}