@@ -43,7 +43,7 @@ use oxc_data_structures::stack::NonEmptyStack;
43
43
use oxc_ecmascript:: BoundNames ;
44
44
use oxc_semantic:: { ScopeFlags , ScopeId , SymbolFlags } ;
45
45
use oxc_span:: { Atom , SPAN } ;
46
- use oxc_traverse:: { BoundIdentifier , Traverse , TraverseCtx } ;
46
+ use oxc_traverse:: { Ancestor , BoundIdentifier , Traverse , TraverseCtx } ;
47
47
48
48
use crate :: { Helper , TransformCtx } ;
49
49
@@ -55,6 +55,10 @@ pub struct ExplicitResourceManagement<'a, 'ctx> {
55
55
/// keeps track of whether the current static block contains a `using` declaration
56
56
/// so that we can transform it in `exit_static_block`
57
57
static_blocks_stack : NonEmptyStack < bool > ,
58
+
59
+ /// keeps track of whether the current switch statement contains a `using` declaration
60
+ /// so that we can transform it in `exit_statement`
61
+ switch_stmt_stack : NonEmptyStack < bool > ,
58
62
}
59
63
60
64
impl < ' a , ' ctx > ExplicitResourceManagement < ' a , ' ctx > {
@@ -63,6 +67,7 @@ impl<'a, 'ctx> ExplicitResourceManagement<'a, 'ctx> {
63
67
ctx,
64
68
top_level_using : FxHashMap :: default ( ) ,
65
69
static_blocks_stack : NonEmptyStack :: new ( false ) ,
70
+ switch_stmt_stack : NonEmptyStack :: new ( false ) ,
66
71
}
67
72
}
68
73
}
@@ -173,9 +178,16 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> {
173
178
ctx : & mut TraverseCtx < ' a > ,
174
179
) {
175
180
if matches ! ( node. kind, VariableDeclarationKind :: Using | VariableDeclarationKind :: AwaitUsing )
176
- && ctx. parent ( ) . is_static_block ( )
177
181
{
178
- * self . static_blocks_stack . last_mut ( ) = true ;
182
+ match ctx. parent ( ) {
183
+ Ancestor :: StaticBlockBody ( _) => {
184
+ * self . static_blocks_stack . last_mut ( ) = true ;
185
+ }
186
+ Ancestor :: SwitchCaseConsequent ( _) => {
187
+ * self . switch_stmt_stack . last_mut ( ) = true ;
188
+ }
189
+ _ => { }
190
+ }
179
191
}
180
192
}
181
193
@@ -222,12 +234,23 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> {
222
234
#[ inline]
223
235
fn enter_statement ( & mut self , stmt : & mut Statement < ' a > , ctx : & mut TraverseCtx < ' a > ) {
224
236
match stmt {
237
+ // TODO: move this to exit_statement
225
238
Statement :: BlockStatement ( _) => self . transform_block_statement ( stmt, ctx) ,
226
- Statement :: SwitchStatement ( _) => self . transform_switch_statement ( stmt, ctx) ,
239
+ Statement :: SwitchStatement ( _) => {
240
+ self . switch_stmt_stack . push ( false ) ;
241
+ }
227
242
_ => { }
228
243
}
229
244
}
230
245
246
+ fn exit_statement ( & mut self , stmt : & mut Statement < ' a > , ctx : & mut TraverseCtx < ' a > ) {
247
+ if let Statement :: SwitchStatement ( _) = stmt {
248
+ if self . switch_stmt_stack . pop ( ) {
249
+ self . transform_switch_statement ( stmt, ctx) ;
250
+ }
251
+ }
252
+ }
253
+
231
254
/// Move any top level `using` declarations within a block statement,
232
255
/// allowing `enter_statement` to transform them.
233
256
fn enter_program ( & mut self , program : & mut Program < ' a > , ctx : & mut TraverseCtx < ' a > ) {
0 commit comments