1use std::path::Path;
9
10use oxc_allocator::{Allocator, TakeIn, Vec as ArenaVec};
11use oxc_ast::{AstBuilder, ast::*};
12use oxc_diagnostics::OxcDiagnostic;
13use oxc_semantic::Scoping;
14use oxc_span::SPAN;
15use oxc_traverse::{Traverse, traverse_mut};
16
17mod common;
19mod compiler_assumptions;
20mod context;
21mod options;
22mod state;
23mod utils;
24
25mod es2015;
27mod es2016;
28mod es2017;
29mod es2018;
30mod es2019;
31mod es2020;
32mod es2021;
33mod es2022;
34mod es2026;
35mod jsx;
36mod proposals;
37mod regexp;
38mod typescript;
39
40mod decorator;
41mod plugins;
42
43use common::Common;
44use context::{TransformCtx, TraverseCtx};
45use decorator::Decorator;
46use es2015::ES2015;
47use es2016::ES2016;
48use es2017::ES2017;
49use es2018::ES2018;
50use es2019::ES2019;
51use es2020::ES2020;
52use es2021::ES2021;
53use es2022::ES2022;
54use es2026::ES2026;
55use jsx::Jsx;
56use regexp::RegExp;
57use rustc_hash::FxHashMap;
58use state::TransformState;
59use typescript::TypeScript;
60
61use crate::plugins::Plugins;
62pub use crate::{
63 common::helper_loader::{Helper, HelperLoaderMode, HelperLoaderOptions},
64 compiler_assumptions::CompilerAssumptions,
65 decorator::DecoratorOptions,
66 es2015::{ArrowFunctionsOptions, ES2015Options},
67 es2016::ES2016Options,
68 es2017::ES2017Options,
69 es2018::ES2018Options,
70 es2019::ES2019Options,
71 es2020::ES2020Options,
72 es2021::ES2021Options,
73 es2022::{ClassPropertiesOptions, ES2022Options},
74 es2026::ES2026Options,
75 jsx::{JsxOptions, JsxRuntime, ReactRefreshOptions},
76 options::{
77 ESTarget, Engine, EngineTargets, EnvOptions, Module, TransformOptions,
78 babel::{BabelEnvOptions, BabelOptions},
79 },
80 plugins::{PluginsOptions, StyledComponentsOptions},
81 proposals::ProposalOptions,
82 typescript::{RewriteExtensionsMode, TypeScriptOptions},
83};
84
85#[non_exhaustive]
86pub struct TransformerReturn {
87 pub errors: std::vec::Vec<OxcDiagnostic>,
88 pub scoping: Scoping,
89 #[deprecated = "Internal usage only"]
91 pub helpers_used: FxHashMap<Helper, String>,
92}
93
94pub struct Transformer<'a> {
95 ctx: TransformCtx<'a>,
96 allocator: &'a Allocator,
97
98 typescript: TypeScriptOptions,
99 decorator: DecoratorOptions,
100 plugins: PluginsOptions,
101 jsx: JsxOptions,
102 env: EnvOptions,
103 #[expect(dead_code)]
104 proposals: ProposalOptions,
105}
106
107impl<'a> Transformer<'a> {
108 pub fn new(allocator: &'a Allocator, source_path: &Path, options: &TransformOptions) -> Self {
109 let ctx = TransformCtx::new(source_path, options);
110 Self {
111 ctx,
112 allocator,
113 typescript: options.typescript.clone(),
114 decorator: options.decorator,
115 plugins: options.plugins.clone(),
116 jsx: options.jsx.clone(),
117 env: options.env,
118 proposals: options.proposals,
119 }
120 }
121
122 pub fn build_with_scoping(
123 mut self,
124 scoping: Scoping,
125 program: &mut Program<'a>,
126 ) -> TransformerReturn {
127 let allocator = self.allocator;
128 let ast_builder = AstBuilder::new(allocator);
129
130 self.ctx.source_type = program.source_type;
131 self.ctx.source_text = program.source_text;
132
133 if program.source_type.is_jsx() {
134 jsx::update_options_with_comments(
135 &program.comments,
136 &mut self.typescript,
137 &mut self.jsx,
138 &self.ctx,
139 );
140 }
141
142 let mut transformer = TransformerImpl {
143 common: Common::new(&self.env, &self.ctx),
144 decorator: Decorator::new(self.decorator, &self.ctx),
145 plugins: Plugins::new(self.plugins, &self.ctx),
146 x0_typescript: program
147 .source_type
148 .is_typescript()
149 .then(|| TypeScript::new(&self.typescript, &self.ctx)),
150 x1_jsx: Jsx::new(self.jsx, self.env.es2018.object_rest_spread, ast_builder, &self.ctx),
151 x2_es2026: ES2026::new(self.env.es2026, &self.ctx),
152 x2_es2022: ES2022::new(
153 self.env.es2022,
154 !self.typescript.allow_declare_fields
155 || self.typescript.remove_class_fields_without_initializer,
156 &self.ctx,
157 ),
158 x2_es2021: ES2021::new(self.env.es2021, &self.ctx),
159 x2_es2020: ES2020::new(self.env.es2020, &self.ctx),
160 x2_es2019: ES2019::new(self.env.es2019),
161 x2_es2018: ES2018::new(self.env.es2018, &self.ctx),
162 x2_es2016: ES2016::new(self.env.es2016, &self.ctx),
163 x2_es2017: ES2017::new(self.env.es2017, &self.ctx),
164 x3_es2015: ES2015::new(self.env.es2015, &self.ctx),
165 x4_regexp: RegExp::new(self.env.regexp, &self.ctx),
166 };
167
168 let state = TransformState::default();
169 let scoping = traverse_mut(&mut transformer, allocator, program, scoping, state);
170 let helpers_used = self.ctx.helper_loader.used_helpers.borrow_mut().drain().collect();
171 #[expect(deprecated)]
172 TransformerReturn { errors: self.ctx.take_errors(), scoping, helpers_used }
173 }
174}
175
176struct TransformerImpl<'a, 'ctx> {
177 x0_typescript: Option<TypeScript<'a, 'ctx>>,
179 decorator: Decorator<'a, 'ctx>,
180 plugins: Plugins<'a, 'ctx>,
181 x1_jsx: Jsx<'a, 'ctx>,
182 x2_es2026: ES2026<'a, 'ctx>,
183 x2_es2022: ES2022<'a, 'ctx>,
184 x2_es2021: ES2021<'a, 'ctx>,
185 x2_es2020: ES2020<'a, 'ctx>,
186 x2_es2019: ES2019,
187 x2_es2018: ES2018<'a, 'ctx>,
188 x2_es2017: ES2017<'a, 'ctx>,
189 x2_es2016: ES2016<'a, 'ctx>,
190 #[expect(unused)]
191 x3_es2015: ES2015<'a, 'ctx>,
192 x4_regexp: RegExp<'a, 'ctx>,
193 common: Common<'a, 'ctx>,
194}
195
196impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
197 fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
198 if let Some(typescript) = self.x0_typescript.as_mut() {
199 typescript.enter_program(program, ctx);
200 }
201 self.plugins.enter_program(program, ctx);
202 self.x1_jsx.enter_program(program, ctx);
203 self.x2_es2026.enter_program(program, ctx);
204 }
205
206 fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
207 self.decorator.exit_program(program, ctx);
208 self.x1_jsx.exit_program(program, ctx);
209 if let Some(typescript) = self.x0_typescript.as_mut() {
210 typescript.exit_program(program, ctx);
211 }
212 self.x2_es2022.exit_program(program, ctx);
213 self.x2_es2020.exit_program(program, ctx);
214 self.x2_es2018.exit_program(program, ctx);
215 self.common.exit_program(program, ctx);
216 }
217
218 fn enter_arrow_function_expression(
220 &mut self,
221 arrow: &mut ArrowFunctionExpression<'a>,
222 ctx: &mut TraverseCtx<'a>,
223 ) {
224 self.common.enter_arrow_function_expression(arrow, ctx);
225 if let Some(typescript) = self.x0_typescript.as_mut() {
226 typescript.enter_arrow_function_expression(arrow, ctx);
227 }
228 self.x2_es2018.enter_arrow_function_expression(arrow, ctx);
229 }
230
231 fn enter_variable_declaration(
232 &mut self,
233 decl: &mut VariableDeclaration<'a>,
234 ctx: &mut TraverseCtx<'a>,
235 ) {
236 self.x2_es2018.enter_variable_declaration(decl, ctx);
237 }
238
239 fn enter_variable_declarator(
240 &mut self,
241 decl: &mut VariableDeclarator<'a>,
242 ctx: &mut TraverseCtx<'a>,
243 ) {
244 if let Some(typescript) = self.x0_typescript.as_mut() {
245 typescript.enter_variable_declarator(decl, ctx);
246 }
247 self.plugins.enter_variable_declarator(decl, ctx);
248 }
249
250 fn enter_big_int_literal(&mut self, node: &mut BigIntLiteral<'a>, ctx: &mut TraverseCtx<'a>) {
251 self.x2_es2020.enter_big_int_literal(node, ctx);
252 }
253
254 fn enter_await_expression(
255 &mut self,
256 node: &mut AwaitExpression<'a>,
257 ctx: &mut TraverseCtx<'a>,
258 ) {
259 self.x2_es2022.enter_await_expression(node, ctx);
260 }
261
262 fn enter_import_specifier(
263 &mut self,
264 node: &mut ImportSpecifier<'a>,
265 ctx: &mut TraverseCtx<'a>,
266 ) {
267 self.x2_es2020.enter_import_specifier(node, ctx);
268 }
269
270 fn enter_export_specifier(
271 &mut self,
272 node: &mut ExportSpecifier<'a>,
273 ctx: &mut TraverseCtx<'a>,
274 ) {
275 self.x2_es2020.enter_export_specifier(node, ctx);
276 }
277
278 fn enter_binding_identifier(
279 &mut self,
280 node: &mut BindingIdentifier<'a>,
281 ctx: &mut TraverseCtx<'a>,
282 ) {
283 self.common.enter_binding_identifier(node, ctx);
284 }
285
286 fn enter_identifier_reference(
287 &mut self,
288 node: &mut IdentifierReference<'a>,
289 ctx: &mut TraverseCtx<'a>,
290 ) {
291 self.common.enter_identifier_reference(node, ctx);
292 }
293
294 fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, ctx: &mut TraverseCtx<'a>) {
295 if let Some(typescript) = self.x0_typescript.as_mut() {
296 typescript.enter_binding_pattern(pat, ctx);
297 }
298 }
299
300 fn enter_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) {
301 if let Some(typescript) = self.x0_typescript.as_mut() {
302 typescript.enter_call_expression(expr, ctx);
303 }
304 self.plugins.enter_call_expression(expr, ctx);
305 self.x1_jsx.enter_call_expression(expr, ctx);
306 }
307
308 fn enter_chain_element(&mut self, element: &mut ChainElement<'a>, ctx: &mut TraverseCtx<'a>) {
309 if let Some(typescript) = self.x0_typescript.as_mut() {
310 typescript.enter_chain_element(element, ctx);
311 }
312 }
313
314 fn enter_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) {
315 self.decorator.enter_class(class, ctx);
316 if let Some(typescript) = self.x0_typescript.as_mut() {
317 typescript.enter_class(class, ctx);
318 }
319 }
320
321 fn exit_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) {
322 self.decorator.exit_class(class, ctx);
323 if let Some(typescript) = self.x0_typescript.as_mut() {
324 typescript.exit_class(class, ctx);
325 }
326 self.x2_es2022.exit_class(class, ctx);
327 self.decorator.exit_class_at_end(class, ctx);
329 }
330
331 fn enter_class_body(&mut self, body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) {
332 self.x2_es2022.enter_class_body(body, ctx);
333 }
334
335 fn enter_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) {
336 self.common.enter_static_block(block, ctx);
337 self.x2_es2022.enter_static_block(block, ctx);
338 }
339
340 fn exit_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) {
341 self.common.exit_static_block(block, ctx);
342 self.x2_es2026.exit_static_block(block, ctx);
343 self.x2_es2022.exit_static_block(block, ctx);
344 }
345
346 #[inline]
347 fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
348 self.common.enter_expression(expr, ctx);
349 if let Some(typescript) = self.x0_typescript.as_mut() {
350 typescript.enter_expression(expr, ctx);
351 }
352 self.plugins.enter_expression(expr, ctx);
353 self.x2_es2022.enter_expression(expr, ctx);
354 self.x2_es2021.enter_expression(expr, ctx);
355 self.x2_es2020.enter_expression(expr, ctx);
356 self.x2_es2018.enter_expression(expr, ctx);
357 self.x2_es2016.enter_expression(expr, ctx);
358 self.x4_regexp.enter_expression(expr, ctx);
359 }
360
361 fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
362 self.common.exit_expression(expr, ctx);
363 self.x1_jsx.exit_expression(expr, ctx);
364 self.x2_es2022.exit_expression(expr, ctx);
365 self.x2_es2018.exit_expression(expr, ctx);
366 self.x2_es2017.exit_expression(expr, ctx);
367 }
368
369 fn enter_simple_assignment_target(
370 &mut self,
371 node: &mut SimpleAssignmentTarget<'a>,
372 ctx: &mut TraverseCtx<'a>,
373 ) {
374 if let Some(typescript) = self.x0_typescript.as_mut() {
375 typescript.enter_simple_assignment_target(node, ctx);
376 }
377 }
378
379 fn enter_assignment_target(
380 &mut self,
381 node: &mut AssignmentTarget<'a>,
382 ctx: &mut TraverseCtx<'a>,
383 ) {
384 if let Some(typescript) = self.x0_typescript.as_mut() {
385 typescript.enter_assignment_target(node, ctx);
386 }
387 self.x2_es2022.enter_assignment_target(node, ctx);
388 }
389
390 fn enter_formal_parameters(
391 &mut self,
392 node: &mut FormalParameters<'a>,
393 ctx: &mut TraverseCtx<'a>,
394 ) {
395 self.x2_es2020.enter_formal_parameters(node, ctx);
396 }
397
398 fn exit_formal_parameters(
399 &mut self,
400 node: &mut FormalParameters<'a>,
401 ctx: &mut TraverseCtx<'a>,
402 ) {
403 self.x2_es2020.exit_formal_parameters(node, ctx);
404 }
405
406 fn enter_formal_parameter(
407 &mut self,
408 param: &mut FormalParameter<'a>,
409 ctx: &mut TraverseCtx<'a>,
410 ) {
411 if let Some(typescript) = self.x0_typescript.as_mut() {
412 typescript.enter_formal_parameter(param, ctx);
413 }
414 }
415
416 fn enter_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
417 self.common.enter_function(func, ctx);
418 self.x2_es2018.enter_function(func, ctx);
419 }
420
421 fn exit_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
422 if let Some(typescript) = self.x0_typescript.as_mut() {
423 typescript.exit_function(func, ctx);
424 }
425 self.x1_jsx.exit_function(func, ctx);
426 self.x2_es2018.exit_function(func, ctx);
427 self.x2_es2017.exit_function(func, ctx);
428 self.common.exit_function(func, ctx);
429 }
430
431 fn enter_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) {
432 self.common.enter_function_body(body, ctx);
433 self.x2_es2026.enter_function_body(body, ctx);
434 }
435
436 fn exit_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) {
437 self.common.exit_function_body(body, ctx);
438 }
439
440 fn enter_jsx_element(&mut self, node: &mut JSXElement<'a>, ctx: &mut TraverseCtx<'a>) {
441 if let Some(typescript) = self.x0_typescript.as_mut() {
442 typescript.enter_jsx_element(node, ctx);
443 }
444 }
445
446 fn enter_jsx_element_name(&mut self, node: &mut JSXElementName<'a>, ctx: &mut TraverseCtx<'a>) {
447 self.common.enter_jsx_element_name(node, ctx);
448 }
449
450 fn enter_jsx_member_expression_object(
451 &mut self,
452 node: &mut JSXMemberExpressionObject<'a>,
453 ctx: &mut TraverseCtx<'a>,
454 ) {
455 self.common.enter_jsx_member_expression_object(node, ctx);
456 }
457
458 fn enter_jsx_fragment(&mut self, node: &mut JSXFragment<'a>, ctx: &mut TraverseCtx<'a>) {
459 if let Some(typescript) = self.x0_typescript.as_mut() {
460 typescript.enter_jsx_fragment(node, ctx);
461 }
462 }
463
464 fn enter_jsx_opening_element(
465 &mut self,
466 elem: &mut JSXOpeningElement<'a>,
467 ctx: &mut TraverseCtx<'a>,
468 ) {
469 if let Some(typescript) = self.x0_typescript.as_mut() {
470 typescript.enter_jsx_opening_element(elem, ctx);
471 }
472 self.x1_jsx.enter_jsx_opening_element(elem, ctx);
473 }
474
475 fn enter_method_definition(
476 &mut self,
477 def: &mut MethodDefinition<'a>,
478 ctx: &mut TraverseCtx<'a>,
479 ) {
480 self.decorator.enter_method_definition(def, ctx);
481 if let Some(typescript) = self.x0_typescript.as_mut() {
482 typescript.enter_method_definition(def, ctx);
483 }
484 }
485
486 fn exit_method_definition(
487 &mut self,
488 def: &mut MethodDefinition<'a>,
489 ctx: &mut TraverseCtx<'a>,
490 ) {
491 self.decorator.exit_method_definition(def, ctx);
492 }
493
494 fn enter_new_expression(&mut self, expr: &mut NewExpression<'a>, ctx: &mut TraverseCtx<'a>) {
495 if let Some(typescript) = self.x0_typescript.as_mut() {
496 typescript.enter_new_expression(expr, ctx);
497 }
498 }
499
500 fn enter_property_definition(
501 &mut self,
502 def: &mut PropertyDefinition<'a>,
503 ctx: &mut TraverseCtx<'a>,
504 ) {
505 self.decorator.enter_property_definition(def, ctx);
506 if let Some(typescript) = self.x0_typescript.as_mut() {
507 typescript.enter_property_definition(def, ctx);
508 }
509 self.x2_es2022.enter_property_definition(def, ctx);
510 }
511
512 fn exit_property_definition(
513 &mut self,
514 def: &mut PropertyDefinition<'a>,
515 ctx: &mut TraverseCtx<'a>,
516 ) {
517 self.decorator.exit_property_definition(def, ctx);
518 self.x2_es2022.exit_property_definition(def, ctx);
519 }
520
521 fn enter_accessor_property(
522 &mut self,
523 node: &mut AccessorProperty<'a>,
524 ctx: &mut TraverseCtx<'a>,
525 ) {
526 self.decorator.enter_accessor_property(node, ctx);
527 if let Some(typescript) = self.x0_typescript.as_mut() {
528 typescript.enter_accessor_property(node, ctx);
529 }
530 }
531
532 fn exit_accessor_property(
533 &mut self,
534 node: &mut AccessorProperty<'a>,
535 ctx: &mut TraverseCtx<'a>,
536 ) {
537 self.decorator.exit_accessor_property(node, ctx);
538 }
539
540 fn enter_statements(
541 &mut self,
542 stmts: &mut ArenaVec<'a, Statement<'a>>,
543 ctx: &mut TraverseCtx<'a>,
544 ) {
545 self.common.enter_statements(stmts, ctx);
546 if let Some(typescript) = self.x0_typescript.as_mut() {
547 typescript.enter_statements(stmts, ctx);
548 }
549 }
550
551 fn exit_arrow_function_expression(
552 &mut self,
553 arrow: &mut ArrowFunctionExpression<'a>,
554 ctx: &mut TraverseCtx<'a>,
555 ) {
556 self.common.exit_arrow_function_expression(arrow, ctx);
557
558 let statements = &mut arrow.body.statements;
563 if arrow.expression && statements.len() > 1 {
564 arrow.expression = false;
565
566 for stmt in statements.iter_mut().rev() {
578 let Statement::ExpressionStatement(expr_stmt) = stmt else {
579 continue;
580 };
581 let expression = Some(expr_stmt.expression.take_in(ctx.ast));
582 *stmt = ctx.ast.statement_return(SPAN, expression);
583 return;
584 }
585 unreachable!("At least one statement should be expression statement")
586 }
587 }
588
589 fn exit_statements(
590 &mut self,
591 stmts: &mut ArenaVec<'a, Statement<'a>>,
592 ctx: &mut TraverseCtx<'a>,
593 ) {
594 if let Some(typescript) = self.x0_typescript.as_mut() {
595 typescript.exit_statements(stmts, ctx);
596 }
597 self.common.exit_statements(stmts, ctx);
598 }
599
600 fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
601 if let Some(typescript) = self.x0_typescript.as_mut() {
602 typescript.exit_statement(stmt, ctx);
603 }
604 self.decorator.exit_statement(stmt, ctx);
605 self.x2_es2018.exit_statement(stmt, ctx);
606 self.x2_es2017.exit_statement(stmt, ctx);
607 }
608
609 fn enter_tagged_template_expression(
610 &mut self,
611 expr: &mut TaggedTemplateExpression<'a>,
612 ctx: &mut TraverseCtx<'a>,
613 ) {
614 if let Some(typescript) = self.x0_typescript.as_mut() {
615 typescript.enter_tagged_template_expression(expr, ctx);
616 }
617 }
618
619 fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
620 self.decorator.enter_statement(stmt, ctx);
621 if let Some(typescript) = self.x0_typescript.as_mut() {
622 typescript.enter_statement(stmt, ctx);
623 }
624 self.x2_es2018.enter_statement(stmt, ctx);
625 self.x2_es2026.enter_statement(stmt, ctx);
626 }
627
628 fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) {
629 if let Some(typescript) = self.x0_typescript.as_mut() {
630 typescript.enter_declaration(decl, ctx);
631 }
632 }
633
634 fn enter_if_statement(&mut self, stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
635 if let Some(typescript) = self.x0_typescript.as_mut() {
636 typescript.enter_if_statement(stmt, ctx);
637 }
638 }
639
640 fn enter_while_statement(&mut self, stmt: &mut WhileStatement<'a>, ctx: &mut TraverseCtx<'a>) {
641 if let Some(typescript) = self.x0_typescript.as_mut() {
642 typescript.enter_while_statement(stmt, ctx);
643 }
644 }
645
646 fn enter_do_while_statement(
647 &mut self,
648 stmt: &mut DoWhileStatement<'a>,
649 ctx: &mut TraverseCtx<'a>,
650 ) {
651 if let Some(typescript) = self.x0_typescript.as_mut() {
652 typescript.enter_do_while_statement(stmt, ctx);
653 }
654 }
655
656 fn enter_for_statement(&mut self, stmt: &mut ForStatement<'a>, ctx: &mut TraverseCtx<'a>) {
657 if let Some(typescript) = self.x0_typescript.as_mut() {
658 typescript.enter_for_statement(stmt, ctx);
659 }
660 }
661
662 fn enter_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
663 if let Some(typescript) = self.x0_typescript.as_mut() {
664 typescript.enter_for_of_statement(stmt, ctx);
665 }
666 self.x2_es2026.enter_for_of_statement(stmt, ctx);
667 self.x2_es2018.enter_for_of_statement(stmt, ctx);
668 }
669
670 fn enter_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>, ctx: &mut TraverseCtx<'a>) {
671 if let Some(typescript) = self.x0_typescript.as_mut() {
672 typescript.enter_for_in_statement(stmt, ctx);
673 }
674 self.x2_es2018.enter_for_in_statement(stmt, ctx);
675 }
676
677 fn enter_try_statement(&mut self, stmt: &mut TryStatement<'a>, ctx: &mut TraverseCtx<'a>) {
678 self.x2_es2026.enter_try_statement(stmt, ctx);
679 }
680
681 fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {
682 self.x2_es2019.enter_catch_clause(clause, ctx);
683 self.x2_es2018.enter_catch_clause(clause, ctx);
684 }
685
686 fn enter_import_declaration(
687 &mut self,
688 node: &mut ImportDeclaration<'a>,
689 ctx: &mut TraverseCtx<'a>,
690 ) {
691 if let Some(typescript) = self.x0_typescript.as_mut() {
692 typescript.enter_import_declaration(node, ctx);
693 }
694 }
695
696 fn enter_export_all_declaration(
697 &mut self,
698 node: &mut ExportAllDeclaration<'a>,
699 ctx: &mut TraverseCtx<'a>,
700 ) {
701 if let Some(typescript) = self.x0_typescript.as_mut() {
702 typescript.enter_export_all_declaration(node, ctx);
703 }
704 self.x2_es2020.enter_export_all_declaration(node, ctx);
705 }
706
707 fn enter_export_named_declaration(
708 &mut self,
709 node: &mut ExportNamedDeclaration<'a>,
710 ctx: &mut TraverseCtx<'a>,
711 ) {
712 if let Some(typescript) = self.x0_typescript.as_mut() {
713 typescript.enter_export_named_declaration(node, ctx);
714 }
715 }
716
717 fn enter_ts_export_assignment(
718 &mut self,
719 export_assignment: &mut TSExportAssignment<'a>,
720 ctx: &mut TraverseCtx<'a>,
721 ) {
722 if let Some(typescript) = self.x0_typescript.as_mut() {
723 typescript.enter_ts_export_assignment(export_assignment, ctx);
724 }
725 }
726
727 fn enter_decorator(
728 &mut self,
729 node: &mut oxc_ast::ast::Decorator<'a>,
730 ctx: &mut TraverseCtx<'a>,
731 ) {
732 self.decorator.enter_decorator(node, ctx);
733 }
734}