From 92ee77487f0fb929f7f3d8098906c519330198a7 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 12 Jul 2024 03:47:07 +0000 Subject: [PATCH] feat(semantic): add `ScopeFlags::CatchClause` for use in CatchClause (#4205) --- crates/oxc_ast/src/ast/js.rs | 2 +- crates/oxc_ast/src/generated/visit.rs | 2 +- crates/oxc_ast/src/generated/visit_mut.rs | 2 +- crates/oxc_semantic/src/builder.rs | 11 ++++------- crates/oxc_syntax/src/scope.rs | 5 +++++ tasks/coverage/parser_typescript.snap | 13 ------------- 6 files changed, 12 insertions(+), 23 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 68ace391b9094..beaf6b3e321ee 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1300,7 +1300,7 @@ pub struct TryStatement<'a> { } #[visited_node] -#[scope] +#[scope(flags(ScopeFlags::CatchClause))] #[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type"))] diff --git a/crates/oxc_ast/src/generated/visit.rs b/crates/oxc_ast/src/generated/visit.rs index 0a700bd012bc1..41e0805c0b18f 100644 --- a/crates/oxc_ast/src/generated/visit.rs +++ b/crates/oxc_ast/src/generated/visit.rs @@ -3692,7 +3692,7 @@ pub mod walk { pub fn walk_catch_clause<'a, V: Visit<'a>>(visitor: &mut V, it: &CatchClause<'a>) { let kind = AstKind::CatchClause(visitor.alloc(it)); visitor.enter_node(kind); - visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + visitor.enter_scope(ScopeFlags::CatchClause, &it.scope_id); if let Some(param) = &it.param { visitor.visit_catch_parameter(param); } diff --git a/crates/oxc_ast/src/generated/visit_mut.rs b/crates/oxc_ast/src/generated/visit_mut.rs index 26a696f663716..ca3de8cc3a195 100644 --- a/crates/oxc_ast/src/generated/visit_mut.rs +++ b/crates/oxc_ast/src/generated/visit_mut.rs @@ -3897,7 +3897,7 @@ pub mod walk_mut { pub fn walk_catch_clause<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut CatchClause<'a>) { let kind = AstType::CatchClause; visitor.enter_node(kind); - visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + visitor.enter_scope(ScopeFlags::CatchClause, &it.scope_id); if let Some(param) = &mut it.param { visitor.visit_catch_parameter(param); } diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index d11a05a8d035d..83091250feb1d 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -440,13 +440,10 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { self.current_scope_id = self.scope.add_scope(parent_scope_id, flags); scope_id.set(Some(self.current_scope_id)); - // TODO: replace node-based check with scope-based - if !flags.is_top() - && matches!(self.nodes.parent_kind(self.current_node_id), Some(AstKind::CatchClause(_))) - { - // Clone the `CatchClause` bindings and add them to the current scope. - // to make it easier to check redeclare errors. - if let Some(parent_scope_id) = parent_scope_id { + if let Some(parent_scope_id) = parent_scope_id { + if self.scope.get_flags(parent_scope_id).is_catch_clause() { + // Clone the `CatchClause` bindings and add them to the current scope. + // to make it easier to check redeclare errors. let bindings = self.scope.get_bindings(parent_scope_id).clone(); self.scope.get_bindings_mut(self.current_scope_id).extend(bindings); } diff --git a/crates/oxc_syntax/src/scope.rs b/crates/oxc_syntax/src/scope.rs index 637affb411dc6..a0f9f7a12cbd7 100644 --- a/crates/oxc_syntax/src/scope.rs +++ b/crates/oxc_syntax/src/scope.rs @@ -23,6 +23,7 @@ bitflags! { const Constructor = 1 << 6; const GetAccessor = 1 << 7; const SetAccessor = 1 << 8; + const CatchClause = 1 << 9; const Var = Self::Top.bits() | Self::Function.bits() | Self::ClassStaticBlock.bits() | Self::TsModuleBlock.bits(); const Modifiers = Self::Constructor.bits() | Self::GetAccessor.bits() | Self::SetAccessor.bits(); } @@ -81,4 +82,8 @@ impl ScopeFlags { pub fn is_set_or_get_accessor(&self) -> bool { self.intersects(Self::SetAccessor | Self::GetAccessor) } + + pub fn is_catch_clause(&self) -> bool { + self.contains(Self::CatchClause) + } } diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index c83bca47067a7..b0acdb5f6a398 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -9482,19 +9482,6 @@ Expect to Parse: "conformance/types/typeRelationships/typeAndMemberIdentity/obje 22 │ ╰──── - × Identifier `e` has already been declared - ╭─[compiler/redeclareParameterInCatchBlock.ts:27:9] - 26 │ - 27 │ } catch(e) { - · ┬ - · ╰── `e` has already been declared here - 28 │ function test() { - 29 │ let e; - · ┬ - · ╰── It can not be redeclared here - 30 │ } - ╰──── - × Unexpected flag a in regular expression literal ╭─[compiler/regularExpressionScanning.ts:3:12] 2 │ // Flags