diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 68ace391b9094..c6fe4cae68c4d 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1590,14 +1590,14 @@ pub struct Class<'a> { #[cfg_attr(feature = "serialize", serde(flatten))] pub span: Span, pub decorators: Vec<'a, Decorator<'a>>, - #[scope(enter_before)] pub id: Option>, + #[scope(enter_before)] + pub type_parameters: Option>>, #[visit_as(ClassHeritage)] pub super_class: Option>, - pub body: Box<'a, ClassBody<'a>>, - pub type_parameters: Option>>, pub super_type_parameters: Option>>, pub implements: Option>>, + pub body: Box<'a, ClassBody<'a>>, pub r#abstract: bool, pub declare: bool, pub scope_id: Cell>, diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index ae26e5d3ad281..b7aaf26eadad1 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -230,7 +230,8 @@ pub use match_ts_type; /// /// #[visited_node] -#[derive(Debug, Hash)] +#[scope] +#[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSConditionalType<'a> { @@ -240,6 +241,7 @@ pub struct TSConditionalType<'a> { pub extends_type: TSType<'a>, pub true_type: TSType<'a>, pub false_type: TSType<'a>, + pub scope_id: Cell>, } /// string | string[] | (() => string) | { s: string } @@ -579,8 +581,7 @@ pub struct TSTypeParameterInstantiation<'a> { } #[visited_node] -#[scope] -#[derive(Debug)] +#[derive(Debug, Hash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSTypeParameter<'a> { @@ -592,7 +593,6 @@ pub struct TSTypeParameter<'a> { pub r#in: bool, pub out: bool, pub r#const: bool, - pub scope_id: Cell>, } #[visited_node] @@ -606,16 +606,19 @@ pub struct TSTypeParameterDeclaration<'a> { } #[visited_node] -#[derive(Debug, Hash)] +#[scope] +#[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSTypeAliasDeclaration<'a> { #[cfg_attr(feature = "serialize", serde(flatten))] pub span: Span, pub id: BindingIdentifier<'a>, + #[scope(enter_before)] pub type_parameters: Option>>, pub type_annotation: TSType<'a>, pub declare: bool, + pub scope_id: Cell>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -642,17 +645,20 @@ pub struct TSClassImplements<'a> { /// /// interface `BindingIdentifier` `TypeParameters_opt` `InterfaceExtendsClause_opt` `ObjectType` #[visited_node] -#[derive(Debug, Hash)] +#[scope] +#[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSInterfaceDeclaration<'a> { #[cfg_attr(feature = "serialize", serde(flatten))] pub span: Span, pub id: BindingIdentifier<'a>, + #[scope(enter_before)] pub extends: Option>>, pub type_parameters: Option>>, pub body: Box<'a, TSInterfaceBody<'a>>, pub declare: bool, + pub scope_id: Cell>, } #[visited_node] @@ -726,7 +732,8 @@ pub enum TSMethodSignatureKind { } #[visited_node] -#[derive(Debug, Hash)] +#[scope] +#[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSMethodSignature<'a> { @@ -740,10 +747,12 @@ pub struct TSMethodSignature<'a> { pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, pub type_parameters: Option>>, + pub scope_id: Cell>, } #[visited_node] -#[derive(Debug, Hash)] +#[scope] +#[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSConstructSignatureDeclaration<'a> { @@ -752,6 +761,7 @@ pub struct TSConstructSignatureDeclaration<'a> { pub params: Box<'a, FormalParameters<'a>>, pub return_type: Option>>, pub type_parameters: Option>>, + pub scope_id: Cell>, } #[visited_node] @@ -994,7 +1004,8 @@ pub struct TSConstructorType<'a> { } #[visited_node] -#[derive(Debug, Hash)] +#[scope] +#[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] pub struct TSMappedType<'a> { @@ -1005,6 +1016,7 @@ pub struct TSMappedType<'a> { pub type_annotation: Option>, pub optional: TSMappedTypeModifierOperator, pub readonly: TSMappedTypeModifierOperator, + pub scope_id: Cell>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 975e2e9a9c28d..65384029c3b93 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -103,31 +103,6 @@ impl<'a> TSTypeName<'a> { } } -impl<'a> TSTypeParameter<'a> { - pub fn new( - span: Span, - name: BindingIdentifier<'a>, - constraint: Option>, - default: Option>, - r#in: bool, - out: bool, - r#const: bool, - ) -> Self { - Self { span, name, constraint, default, r#in, out, r#const, scope_id: Cell::default() } - } -} - -impl<'a> Hash for TSTypeParameter<'a> { - fn hash(&self, state: &mut H) { - self.name.hash(state); - self.constraint.hash(state); - self.default.hash(state); - self.r#in.hash(state); - self.out.hash(state); - self.r#const.hash(state); - } -} - impl<'a> TSType<'a> { /// Remove nested parentheses from this type. pub fn without_parenthesized(&self) -> &Self { @@ -233,3 +208,68 @@ impl ImportOrExportKind { matches!(self, Self::Type) } } + +impl<'a> Hash for TSMappedType<'a> { + fn hash(&self, state: &mut H) { + self.span.hash(state); + self.type_parameter.hash(state); + self.name_type.hash(state); + self.type_annotation.hash(state); + self.optional.hash(state); + self.readonly.hash(state); + } +} + +impl<'a> Hash for TSConditionalType<'a> { + fn hash(&self, state: &mut H) { + self.span.hash(state); + self.check_type.hash(state); + self.extends_type.hash(state); + self.true_type.hash(state); + self.false_type.hash(state); + } +} + +impl<'a> Hash for TSInterfaceDeclaration<'a> { + fn hash(&self, state: &mut H) { + self.span.hash(state); + self.id.hash(state); + self.type_parameters.hash(state); + self.extends.hash(state); + self.body.hash(state); + self.declare.hash(state); + } +} + +impl<'a> Hash for TSTypeAliasDeclaration<'a> { + fn hash(&self, state: &mut H) { + self.span.hash(state); + self.id.hash(state); + self.type_parameters.hash(state); + self.type_annotation.hash(state); + self.declare.hash(state); + } +} + +impl<'a> Hash for TSMethodSignature<'a> { + fn hash(&self, state: &mut H) { + self.span.hash(state); + self.key.hash(state); + self.computed.hash(state); + self.optional.hash(state); + self.kind.hash(state); + self.this_param.hash(state); + self.params.hash(state); + self.return_type.hash(state); + self.type_parameters.hash(state); + } +} + +impl<'a> Hash for TSConstructSignatureDeclaration<'a> { + fn hash(&self, state: &mut H) { + self.span.hash(state); + self.params.hash(state); + self.return_type.hash(state); + self.type_parameters.hash(state); + } +} diff --git a/crates/oxc_ast/src/ast_kind_impl.rs b/crates/oxc_ast/src/ast_kind_impl.rs index 8b7d53a8f0aa5..bcf1b56ba3dec 100644 --- a/crates/oxc_ast/src/ast_kind_impl.rs +++ b/crates/oxc_ast/src/ast_kind_impl.rs @@ -345,6 +345,9 @@ impl<'a> AstKind<'a> { Self::TSNamedTupleMember(_) => "TSNamedTupleMember".into(), Self::TSPropertySignature(_) => "TSPropertySignature".into(), + Self::TSConditionalType(_) => "TSConditionalType".into(), + Self::TSMappedType(_) => "TSMappedType".into(), + Self::TSConstructSignatureDeclaration(_) => "TSConstructSignatureDeclaration".into(), } } } diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index a254161a27360..36fa79697dbd1 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -485,29 +485,29 @@ impl<'a> AstBuilder<'a> { span: Span, decorators: Vec<'a, Decorator<'a>>, id: Option>, + type_parameters: T1, super_class: Option>, - body: T1, - type_parameters: T2, - super_type_parameters: T3, + super_type_parameters: T2, implements: Option>>, + body: T3, r#abstract: bool, declare: bool, ) -> Expression<'a> where - T1: IntoIn<'a, Box<'a, ClassBody<'a>>>, - T2: IntoIn<'a, Option>>>, - T3: IntoIn<'a, Option>>>, + T1: IntoIn<'a, Option>>>, + T2: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Box<'a, ClassBody<'a>>>, { Expression::ClassExpression(self.alloc(self.class( r#type, span, decorators, id, - super_class, - body, type_parameters, + super_class, super_type_parameters, implements, + body, r#abstract, declare, ))) @@ -2728,29 +2728,29 @@ impl<'a> AstBuilder<'a> { span: Span, decorators: Vec<'a, Decorator<'a>>, id: Option>, + type_parameters: T1, super_class: Option>, - body: T1, - type_parameters: T2, - super_type_parameters: T3, + super_type_parameters: T2, implements: Option>>, + body: T3, r#abstract: bool, declare: bool, ) -> Declaration<'a> where - T1: IntoIn<'a, Box<'a, ClassBody<'a>>>, - T2: IntoIn<'a, Option>>>, - T3: IntoIn<'a, Option>>>, + T1: IntoIn<'a, Option>>>, + T2: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Box<'a, ClassBody<'a>>>, { Declaration::ClassDeclaration(self.alloc(self.class( r#type, span, decorators, id, - super_class, - body, type_parameters, + super_class, super_type_parameters, implements, + body, r#abstract, declare, ))) @@ -3942,29 +3942,29 @@ impl<'a> AstBuilder<'a> { span: Span, decorators: Vec<'a, Decorator<'a>>, id: Option>, + type_parameters: T1, super_class: Option>, - body: T1, - type_parameters: T2, - super_type_parameters: T3, + super_type_parameters: T2, implements: Option>>, + body: T3, r#abstract: bool, declare: bool, ) -> Class<'a> where - T1: IntoIn<'a, Box<'a, ClassBody<'a>>>, - T2: IntoIn<'a, Option>>>, - T3: IntoIn<'a, Option>>>, + T1: IntoIn<'a, Option>>>, + T2: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Box<'a, ClassBody<'a>>>, { Class { r#type, span, decorators, id, - super_class, - body: body.into_in(self.allocator), type_parameters: type_parameters.into_in(self.allocator), + super_class, super_type_parameters: super_type_parameters.into_in(self.allocator), implements, + body: body.into_in(self.allocator), r#abstract, declare, scope_id: Default::default(), @@ -3978,29 +3978,29 @@ impl<'a> AstBuilder<'a> { span: Span, decorators: Vec<'a, Decorator<'a>>, id: Option>, + type_parameters: T1, super_class: Option>, - body: T1, - type_parameters: T2, - super_type_parameters: T3, + super_type_parameters: T2, implements: Option>>, + body: T3, r#abstract: bool, declare: bool, ) -> Box<'a, Class<'a>> where - T1: IntoIn<'a, Box<'a, ClassBody<'a>>>, - T2: IntoIn<'a, Option>>>, - T3: IntoIn<'a, Option>>>, + T1: IntoIn<'a, Option>>>, + T2: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Box<'a, ClassBody<'a>>>, { self.class( r#type, span, decorators, id, - super_class, - body, type_parameters, + super_class, super_type_parameters, implements, + body, r#abstract, declare, ) @@ -4943,29 +4943,29 @@ impl<'a> AstBuilder<'a> { span: Span, decorators: Vec<'a, Decorator<'a>>, id: Option>, + type_parameters: T1, super_class: Option>, - body: T1, - type_parameters: T2, - super_type_parameters: T3, + super_type_parameters: T2, implements: Option>>, + body: T3, r#abstract: bool, declare: bool, ) -> ExportDefaultDeclarationKind<'a> where - T1: IntoIn<'a, Box<'a, ClassBody<'a>>>, - T2: IntoIn<'a, Option>>>, - T3: IntoIn<'a, Option>>>, + T1: IntoIn<'a, Option>>>, + T2: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Box<'a, ClassBody<'a>>>, { ExportDefaultDeclarationKind::ClassDeclaration(self.alloc(self.class( r#type, span, decorators, id, - super_class, - body, type_parameters, + super_class, super_type_parameters, implements, + body, r#abstract, declare, ))) @@ -6062,7 +6062,14 @@ impl<'a> AstBuilder<'a> { true_type: TSType<'a>, false_type: TSType<'a>, ) -> TSConditionalType<'a> { - TSConditionalType { span, check_type, extends_type, true_type, false_type } + TSConditionalType { + span, + check_type, + extends_type, + true_type, + false_type, + scope_id: Default::default(), + } } #[inline] @@ -6542,16 +6549,7 @@ impl<'a> AstBuilder<'a> { out: bool, r#const: bool, ) -> TSTypeParameter<'a> { - TSTypeParameter { - span, - name, - constraint, - default, - r#in, - out, - r#const, - scope_id: Default::default(), - } + TSTypeParameter { span, name, constraint, default, r#in, out, r#const } } #[inline] @@ -6605,6 +6603,7 @@ impl<'a> AstBuilder<'a> { type_parameters: type_parameters.into_in(self.allocator), type_annotation, declare, + scope_id: Default::default(), } } @@ -6675,6 +6674,7 @@ impl<'a> AstBuilder<'a> { type_parameters: type_parameters.into_in(self.allocator), body: body.into_in(self.allocator), declare, + scope_id: Default::default(), } } @@ -7013,6 +7013,7 @@ impl<'a> AstBuilder<'a> { params: params.into_in(self.allocator), return_type: return_type.into_in(self.allocator), type_parameters: type_parameters.into_in(self.allocator), + scope_id: Default::default(), } } @@ -7066,6 +7067,7 @@ impl<'a> AstBuilder<'a> { params: params.into_in(self.allocator), return_type: return_type.into_in(self.allocator), type_parameters: type_parameters.into_in(self.allocator), + scope_id: Default::default(), } } @@ -7678,6 +7680,7 @@ impl<'a> AstBuilder<'a> { type_annotation, optional, readonly, + scope_id: Default::default(), } } diff --git a/crates/oxc_ast/src/generated/ast_kind.rs b/crates/oxc_ast/src/generated/ast_kind.rs index 91ca373eb477e..91eed09b2b849 100644 --- a/crates/oxc_ast/src/generated/ast_kind.rs +++ b/crates/oxc_ast/src/generated/ast_kind.rs @@ -107,6 +107,7 @@ pub enum AstType { TSEnumMember, TSTypeAnnotation, TSLiteralType, + TSConditionalType, TSUnionType, TSIntersectionType, TSParenthesizedType, @@ -137,6 +138,7 @@ pub enum AstType { TSInterfaceDeclaration, TSPropertySignature, TSMethodSignature, + TSConstructSignatureDeclaration, TSInterfaceHeritage, TSModuleDeclaration, TSModuleBlock, @@ -144,6 +146,7 @@ pub enum AstType { TSInferType, TSTypeQuery, TSImportType, + TSMappedType, TSTemplateLiteralType, TSAsExpression, TSSatisfiesExpression, @@ -273,6 +276,7 @@ pub enum AstKind<'a> { TSEnumMember(&'a TSEnumMember<'a>), TSTypeAnnotation(&'a TSTypeAnnotation<'a>), TSLiteralType(&'a TSLiteralType<'a>), + TSConditionalType(&'a TSConditionalType<'a>), TSUnionType(&'a TSUnionType<'a>), TSIntersectionType(&'a TSIntersectionType<'a>), TSParenthesizedType(&'a TSParenthesizedType<'a>), @@ -303,6 +307,7 @@ pub enum AstKind<'a> { TSInterfaceDeclaration(&'a TSInterfaceDeclaration<'a>), TSPropertySignature(&'a TSPropertySignature<'a>), TSMethodSignature(&'a TSMethodSignature<'a>), + TSConstructSignatureDeclaration(&'a TSConstructSignatureDeclaration<'a>), TSInterfaceHeritage(&'a TSInterfaceHeritage<'a>), TSModuleDeclaration(&'a TSModuleDeclaration<'a>), TSModuleBlock(&'a TSModuleBlock<'a>), @@ -310,6 +315,7 @@ pub enum AstKind<'a> { TSInferType(&'a TSInferType<'a>), TSTypeQuery(&'a TSTypeQuery<'a>), TSImportType(&'a TSImportType<'a>), + TSMappedType(&'a TSMappedType<'a>), TSTemplateLiteralType(&'a TSTemplateLiteralType<'a>), TSAsExpression(&'a TSAsExpression<'a>), TSSatisfiesExpression(&'a TSSatisfiesExpression<'a>), @@ -440,6 +446,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::TSEnumMember(it) => it.span(), Self::TSTypeAnnotation(it) => it.span(), Self::TSLiteralType(it) => it.span(), + Self::TSConditionalType(it) => it.span(), Self::TSUnionType(it) => it.span(), Self::TSIntersectionType(it) => it.span(), Self::TSParenthesizedType(it) => it.span(), @@ -470,6 +477,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::TSInterfaceDeclaration(it) => it.span(), Self::TSPropertySignature(it) => it.span(), Self::TSMethodSignature(it) => it.span(), + Self::TSConstructSignatureDeclaration(it) => it.span(), Self::TSInterfaceHeritage(it) => it.span(), Self::TSModuleDeclaration(it) => it.span(), Self::TSModuleBlock(it) => it.span(), @@ -477,6 +485,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::TSInferType(it) => it.span(), Self::TSTypeQuery(it) => it.span(), Self::TSImportType(it) => it.span(), + Self::TSMappedType(it) => it.span(), Self::TSTemplateLiteralType(it) => it.span(), Self::TSAsExpression(it) => it.span(), Self::TSSatisfiesExpression(it) => it.span(), diff --git a/crates/oxc_ast/src/generated/visit.rs b/crates/oxc_ast/src/generated/visit.rs index fa2697957a008..68948edfe13fd 100644 --- a/crates/oxc_ast/src/generated/visit.rs +++ b/crates/oxc_ast/src/generated/visit.rs @@ -803,6 +803,16 @@ pub trait Visit<'a>: Sized { walk_class_heritage(self, it); } + #[inline] + fn visit_ts_class_implementses(&mut self, it: &Vec<'a, TSClassImplements<'a>>) { + walk_ts_class_implementses(self, it); + } + + #[inline] + fn visit_ts_class_implements(&mut self, it: &TSClassImplements<'a>) { + walk_ts_class_implements(self, it); + } + #[inline] fn visit_class_body(&mut self, it: &ClassBody<'a>) { walk_class_body(self, it); @@ -843,16 +853,6 @@ pub trait Visit<'a>: Sized { walk_accessor_property(self, it); } - #[inline] - fn visit_ts_class_implementses(&mut self, it: &Vec<'a, TSClassImplements<'a>>) { - walk_ts_class_implementses(self, it); - } - - #[inline] - fn visit_ts_class_implements(&mut self, it: &TSClassImplements<'a>) { - walk_ts_class_implements(self, it); - } - #[inline] fn visit_conditional_expression(&mut self, it: &ConditionalExpression<'a>) { walk_conditional_expression(self, it); @@ -2033,11 +2033,15 @@ pub mod walk { #[inline] pub fn walk_ts_conditional_type<'a, V: Visit<'a>>(visitor: &mut V, it: &TSConditionalType<'a>) { - // NOTE: AstKind doesn't exists! + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + let kind = AstKind::TSConditionalType(visitor.alloc(it)); + visitor.enter_node(kind); visitor.visit_ts_type(&it.check_type); visitor.visit_ts_type(&it.extends_type); visitor.visit_ts_type(&it.true_type); visitor.visit_ts_type(&it.false_type); + visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -2073,7 +2077,6 @@ pub mod walk { #[inline] pub fn walk_ts_type_parameter<'a, V: Visit<'a>>(visitor: &mut V, it: &TSTypeParameter<'a>) { - visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); let kind = AstKind::TSTypeParameter(visitor.alloc(it)); visitor.enter_node(kind); visitor.visit_binding_identifier(&it.name); @@ -2084,7 +2087,6 @@ pub mod walk { visitor.visit_ts_type(default); } visitor.leave_node(kind); - visitor.leave_scope(); } #[inline] @@ -2265,7 +2267,9 @@ pub mod walk { #[inline] pub fn walk_ts_mapped_type<'a, V: Visit<'a>>(visitor: &mut V, it: &TSMappedType<'a>) { - // NOTE: AstKind doesn't exists! + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + let kind = AstKind::TSMappedType(visitor.alloc(it)); + visitor.enter_node(kind); visitor.visit_ts_type_parameter(&it.type_parameter); if let Some(name_type) = &it.name_type { visitor.visit_ts_type(name_type); @@ -2273,6 +2277,8 @@ pub mod walk { if let Some(type_annotation) = &it.type_annotation { visitor.visit_ts_type(type_annotation); } + visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -2436,7 +2442,9 @@ pub mod walk { visitor: &mut V, it: &TSConstructSignatureDeclaration<'a>, ) { - // NOTE: AstKind doesn't exists! + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + let kind = AstKind::TSConstructSignatureDeclaration(visitor.alloc(it)); + visitor.enter_node(kind); visitor.visit_formal_parameters(&it.params); if let Some(return_type) = &it.return_type { visitor.visit_ts_type_annotation(return_type); @@ -2444,10 +2452,13 @@ pub mod walk { if let Some(type_parameters) = &it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } + visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] pub fn walk_ts_method_signature<'a, V: Visit<'a>>(visitor: &mut V, it: &TSMethodSignature<'a>) { + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); let kind = AstKind::TSMethodSignature(visitor.alloc(it)); visitor.enter_node(kind); visitor.visit_property_key(&it.key); @@ -2462,6 +2473,7 @@ pub mod walk { visitor.visit_ts_type_parameter_declaration(type_parameters); } visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -2925,23 +2937,23 @@ pub mod walk { let kind = AstKind::Class(visitor.alloc(it)); visitor.enter_node(kind); visitor.visit_decorators(&it.decorators); - visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(id) = &it.id { visitor.visit_binding_identifier(id); } - if let Some(super_class) = &it.super_class { - visitor.visit_class_heritage(super_class); - } - visitor.visit_class_body(&it.body); + visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(type_parameters) = &it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } + if let Some(super_class) = &it.super_class { + visitor.visit_class_heritage(super_class); + } if let Some(super_type_parameters) = &it.super_type_parameters { visitor.visit_ts_type_parameter_instantiation(super_type_parameters); } if let Some(implements) = &it.implements { visitor.visit_ts_class_implementses(implements); } + visitor.visit_class_body(&it.body); visitor.leave_node(kind); visitor.leave_scope(); } @@ -2953,6 +2965,27 @@ pub mod walk { visitor.leave_node(kind); } + #[inline] + pub fn walk_ts_class_implementses<'a, V: Visit<'a>>( + visitor: &mut V, + it: &Vec<'a, TSClassImplements<'a>>, + ) { + for el in it.iter() { + visitor.visit_ts_class_implements(el); + } + } + + #[inline] + pub fn walk_ts_class_implements<'a, V: Visit<'a>>(visitor: &mut V, it: &TSClassImplements<'a>) { + let kind = AstKind::TSClassImplements(visitor.alloc(it)); + visitor.enter_node(kind); + visitor.visit_ts_type_name(&it.expression); + if let Some(type_parameters) = &it.type_parameters { + visitor.visit_ts_type_parameter_instantiation(type_parameters); + } + visitor.leave_node(kind); + } + #[inline] pub fn walk_class_body<'a, V: Visit<'a>>(visitor: &mut V, it: &ClassBody<'a>) { let kind = AstKind::ClassBody(visitor.alloc(it)); @@ -3072,27 +3105,6 @@ pub mod walk { } } - #[inline] - pub fn walk_ts_class_implementses<'a, V: Visit<'a>>( - visitor: &mut V, - it: &Vec<'a, TSClassImplements<'a>>, - ) { - for el in it.iter() { - visitor.visit_ts_class_implements(el); - } - } - - #[inline] - pub fn walk_ts_class_implements<'a, V: Visit<'a>>(visitor: &mut V, it: &TSClassImplements<'a>) { - let kind = AstKind::TSClassImplements(visitor.alloc(it)); - visitor.enter_node(kind); - visitor.visit_ts_type_name(&it.expression); - if let Some(type_parameters) = &it.type_parameters { - visitor.visit_ts_type_parameter_instantiation(type_parameters); - } - visitor.leave_node(kind); - } - #[inline] pub fn walk_conditional_expression<'a, V: Visit<'a>>( visitor: &mut V, @@ -3764,11 +3776,13 @@ pub mod walk { let kind = AstKind::TSTypeAliasDeclaration(visitor.alloc(it)); visitor.enter_node(kind); visitor.visit_binding_identifier(&it.id); + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); if let Some(type_parameters) = &it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } visitor.visit_ts_type(&it.type_annotation); visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -3779,6 +3793,7 @@ pub mod walk { let kind = AstKind::TSInterfaceDeclaration(visitor.alloc(it)); visitor.enter_node(kind); visitor.visit_binding_identifier(&it.id); + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); if let Some(extends) = &it.extends { visitor.visit_ts_interface_heritages(extends); } @@ -3787,6 +3802,7 @@ pub mod walk { } visitor.visit_ts_interface_body(&it.body); visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] diff --git a/crates/oxc_ast/src/generated/visit_mut.rs b/crates/oxc_ast/src/generated/visit_mut.rs index 6c89eb0823911..5023c6008ffb3 100644 --- a/crates/oxc_ast/src/generated/visit_mut.rs +++ b/crates/oxc_ast/src/generated/visit_mut.rs @@ -795,6 +795,16 @@ pub trait VisitMut<'a>: Sized { walk_class_heritage(self, it); } + #[inline] + fn visit_ts_class_implementses(&mut self, it: &mut Vec<'a, TSClassImplements<'a>>) { + walk_ts_class_implementses(self, it); + } + + #[inline] + fn visit_ts_class_implements(&mut self, it: &mut TSClassImplements<'a>) { + walk_ts_class_implements(self, it); + } + #[inline] fn visit_class_body(&mut self, it: &mut ClassBody<'a>) { walk_class_body(self, it); @@ -835,16 +845,6 @@ pub trait VisitMut<'a>: Sized { walk_accessor_property(self, it); } - #[inline] - fn visit_ts_class_implementses(&mut self, it: &mut Vec<'a, TSClassImplements<'a>>) { - walk_ts_class_implementses(self, it); - } - - #[inline] - fn visit_ts_class_implements(&mut self, it: &mut TSClassImplements<'a>) { - walk_ts_class_implements(self, it); - } - #[inline] fn visit_conditional_expression(&mut self, it: &mut ConditionalExpression<'a>) { walk_conditional_expression(self, it); @@ -2088,11 +2088,15 @@ pub mod walk_mut { visitor: &mut V, it: &mut TSConditionalType<'a>, ) { - // NOTE: AstType doesn't exists! + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + let kind = AstType::TSConditionalType; + visitor.enter_node(kind); visitor.visit_ts_type(&mut it.check_type); visitor.visit_ts_type(&mut it.extends_type); visitor.visit_ts_type(&mut it.true_type); visitor.visit_ts_type(&mut it.false_type); + visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -2134,7 +2138,6 @@ pub mod walk_mut { visitor: &mut V, it: &mut TSTypeParameter<'a>, ) { - visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); let kind = AstType::TSTypeParameter; visitor.enter_node(kind); visitor.visit_binding_identifier(&mut it.name); @@ -2145,7 +2148,6 @@ pub mod walk_mut { visitor.visit_ts_type(default); } visitor.leave_node(kind); - visitor.leave_scope(); } #[inline] @@ -2341,7 +2343,9 @@ pub mod walk_mut { #[inline] pub fn walk_ts_mapped_type<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut TSMappedType<'a>) { - // NOTE: AstType doesn't exists! + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + let kind = AstType::TSMappedType; + visitor.enter_node(kind); visitor.visit_ts_type_parameter(&mut it.type_parameter); if let Some(name_type) = &mut it.name_type { visitor.visit_ts_type(name_type); @@ -2349,6 +2353,8 @@ pub mod walk_mut { if let Some(type_annotation) = &mut it.type_annotation { visitor.visit_ts_type(type_annotation); } + visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -2524,7 +2530,9 @@ pub mod walk_mut { visitor: &mut V, it: &mut TSConstructSignatureDeclaration<'a>, ) { - // NOTE: AstType doesn't exists! + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + let kind = AstType::TSConstructSignatureDeclaration; + visitor.enter_node(kind); visitor.visit_formal_parameters(&mut it.params); if let Some(return_type) = &mut it.return_type { visitor.visit_ts_type_annotation(return_type); @@ -2532,6 +2540,8 @@ pub mod walk_mut { if let Some(type_parameters) = &mut it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } + visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -2539,6 +2549,7 @@ pub mod walk_mut { visitor: &mut V, it: &mut TSMethodSignature<'a>, ) { + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); let kind = AstType::TSMethodSignature; visitor.enter_node(kind); visitor.visit_property_key(&mut it.key); @@ -2553,6 +2564,7 @@ pub mod walk_mut { visitor.visit_ts_type_parameter_declaration(type_parameters); } visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -3049,23 +3061,23 @@ pub mod walk_mut { let kind = AstType::Class; visitor.enter_node(kind); visitor.visit_decorators(&mut it.decorators); - visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(id) = &mut it.id { visitor.visit_binding_identifier(id); } - if let Some(super_class) = &mut it.super_class { - visitor.visit_class_heritage(super_class); - } - visitor.visit_class_body(&mut it.body); + visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(type_parameters) = &mut it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } + if let Some(super_class) = &mut it.super_class { + visitor.visit_class_heritage(super_class); + } if let Some(super_type_parameters) = &mut it.super_type_parameters { visitor.visit_ts_type_parameter_instantiation(super_type_parameters); } if let Some(implements) = &mut it.implements { visitor.visit_ts_class_implementses(implements); } + visitor.visit_class_body(&mut it.body); visitor.leave_node(kind); visitor.leave_scope(); } @@ -3077,6 +3089,30 @@ pub mod walk_mut { visitor.leave_node(kind); } + #[inline] + pub fn walk_ts_class_implementses<'a, V: VisitMut<'a>>( + visitor: &mut V, + it: &mut Vec<'a, TSClassImplements<'a>>, + ) { + for el in it.iter_mut() { + visitor.visit_ts_class_implements(el); + } + } + + #[inline] + pub fn walk_ts_class_implements<'a, V: VisitMut<'a>>( + visitor: &mut V, + it: &mut TSClassImplements<'a>, + ) { + let kind = AstType::TSClassImplements; + visitor.enter_node(kind); + visitor.visit_ts_type_name(&mut it.expression); + if let Some(type_parameters) = &mut it.type_parameters { + visitor.visit_ts_type_parameter_instantiation(type_parameters); + } + visitor.leave_node(kind); + } + #[inline] pub fn walk_class_body<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut ClassBody<'a>) { let kind = AstType::ClassBody; @@ -3205,30 +3241,6 @@ pub mod walk_mut { } } - #[inline] - pub fn walk_ts_class_implementses<'a, V: VisitMut<'a>>( - visitor: &mut V, - it: &mut Vec<'a, TSClassImplements<'a>>, - ) { - for el in it.iter_mut() { - visitor.visit_ts_class_implements(el); - } - } - - #[inline] - pub fn walk_ts_class_implements<'a, V: VisitMut<'a>>( - visitor: &mut V, - it: &mut TSClassImplements<'a>, - ) { - let kind = AstType::TSClassImplements; - visitor.enter_node(kind); - visitor.visit_ts_type_name(&mut it.expression); - if let Some(type_parameters) = &mut it.type_parameters { - visitor.visit_ts_type_parameter_instantiation(type_parameters); - } - visitor.leave_node(kind); - } - #[inline] pub fn walk_conditional_expression<'a, V: VisitMut<'a>>( visitor: &mut V, @@ -3969,11 +3981,13 @@ pub mod walk_mut { let kind = AstType::TSTypeAliasDeclaration; visitor.enter_node(kind); visitor.visit_binding_identifier(&mut it.id); + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); if let Some(type_parameters) = &mut it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } visitor.visit_ts_type(&mut it.type_annotation); visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] @@ -3984,6 +3998,7 @@ pub mod walk_mut { let kind = AstType::TSInterfaceDeclaration; visitor.enter_node(kind); visitor.visit_binding_identifier(&mut it.id); + visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); if let Some(extends) = &mut it.extends { visitor.visit_ts_interface_heritages(extends); } @@ -3992,6 +4007,7 @@ pub mod walk_mut { } visitor.visit_ts_interface_body(&mut it.body); visitor.leave_node(kind); + visitor.leave_scope(); } #[inline] diff --git a/crates/oxc_isolated_declarations/src/class.rs b/crates/oxc_isolated_declarations/src/class.rs index 7c93e6f7300fd..20ef7f00915d8 100644 --- a/crates/oxc_isolated_declarations/src/class.rs +++ b/crates/oxc_isolated_declarations/src/class.rs @@ -490,11 +490,11 @@ impl<'a> IsolatedDeclarations<'a> { decl.span, self.ast.vec(), self.ast.copy(&decl.id), - self.ast.copy(&decl.super_class), - body, self.ast.copy(&decl.type_parameters), + self.ast.copy(&decl.super_class), self.ast.copy(&decl.super_type_parameters), self.ast.copy(&decl.implements), + body, decl.r#abstract, declare.unwrap_or_else(|| self.is_declare()), )) diff --git a/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs b/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs index 4be6dd539e167..ae376e75072ba 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs @@ -52,7 +52,7 @@ impl Rule for NoDuplicateHead { return; } - let scope_id = symbols.get_scope_id(symbol_id); + let Some(scope_id) = symbols.get_scope_id(symbol_id) else { return }; if scope_id != ctx.scopes().root_scope_id() { return; } diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index 77ab8288b3369..f606af61cf96a 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -99,11 +99,11 @@ impl<'a> ParserImpl<'a> { self.end_span(start_span), decorators, id, - super_class, - body, type_parameters, + super_class, super_type_parameters, implements, + body, modifiers.contains_abstract(), modifiers.contains_declare(), )) diff --git a/crates/oxc_semantic/examples/simple.rs b/crates/oxc_semantic/examples/simple.rs index 1283c9b73ba93..237d07992b7d1 100644 --- a/crates/oxc_semantic/examples/simple.rs +++ b/crates/oxc_semantic/examples/simple.rs @@ -17,7 +17,7 @@ fn main() -> std::io::Result<()> { let path = Path::new(&name); let source_text = Arc::new(std::fs::read_to_string(path)?); let allocator = Allocator::default(); - let source_type = SourceType::from_path(path).unwrap(); + let source_type = SourceType::from_path(path).unwrap().with_always_strict(false); let ret = Parser::new(&allocator, &source_text, source_type).parse(); let program = allocator.alloc(ret.program); @@ -31,7 +31,7 @@ fn main() -> std::io::Result<()> { let error_message: String = semantic .errors .into_iter() - .map(|error| error.with_source_code(Arc::clone(&source_text)).to_string()) + .map(|error| format!("{:?}", error.with_source_code(Arc::clone(&source_text)))) .join("\n\n"); println!("Semantic analysis failed:\n\n{error_message}",); diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index ce14e8a08a682..fc548926c35bb 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -34,7 +34,12 @@ impl<'a> Binder for VariableDeclarator<'a> { if self.kind.is_lexical() { self.id.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); + let symbol_id = builder.declare_symbol_on_current_scope( + ident.span, + &ident.name, + includes, + excludes, + ); ident.symbol_id.set(Some(symbol_id)); }); return; @@ -80,12 +85,16 @@ impl<'a> Binder for Class<'a> { fn bind(&self, builder: &mut SemanticBuilder) { let Some(ident) = &self.id else { return }; if !self.declare { - let symbol_id = builder.declare_symbol( - ident.span, - &ident.name, - SymbolFlags::Class, - SymbolFlags::ClassExcludes, - ); + let symbol_id = if self.is_declaration() { + builder.declare_symbol_on_current_scope( + ident.span, + &ident.name, + SymbolFlags::Class, + SymbolFlags::ClassExcludes, + ) + } else { + builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Class) + }; ident.symbol_id.set(Some(symbol_id)); } } @@ -143,12 +152,8 @@ impl<'a> Binder for Function<'a> { } else if self.r#type == FunctionType::FunctionExpression { // https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression // 5. Perform ! funcEnv.CreateImmutableBinding(name, false). - let symbol_id = builder.declare_symbol( - ident.span, - &ident.name, - SymbolFlags::Function, - SymbolFlags::empty(), - ); + let symbol_id = + builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Function); ident.symbol_id.set(Some(symbol_id)); } } @@ -196,7 +201,12 @@ impl<'a> Binder for BindingRestElement<'a> { let excludes = SymbolFlags::FunctionScopedVariable | SymbolFlags::FunctionScopedVariableExcludes; self.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); + let symbol_id = builder.declare_symbol_on_current_scope( + ident.span, + &ident.name, + includes, + excludes, + ); ident.symbol_id.set(Some(symbol_id)); }); } @@ -235,7 +245,12 @@ impl<'a> Binder for FormalParameter<'a> { }; self.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); + let symbol_id = builder.declare_symbol_on_current_scope( + ident.span, + &ident.name, + includes, + excludes, + ); ident.symbol_id.set(Some(symbol_id)); }); } @@ -254,7 +269,7 @@ impl<'a> Binder for CatchParameter<'a> { ident.symbol_id.set(Some(symbol_id)); } else { self.pattern.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol( + let symbol_id = builder.declare_symbol_on_current_scope( ident.span, &ident.name, SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable, @@ -267,7 +282,7 @@ impl<'a> Binder for CatchParameter<'a> { } fn declare_symbol_for_import_specifier(ident: &BindingIdentifier, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol( + let symbol_id = builder.declare_symbol_on_current_scope( ident.span, &ident.name, SymbolFlags::ImportBinding, @@ -302,7 +317,7 @@ impl<'a> Binder for TSImportEqualsDeclaration<'a> { impl<'a> Binder for TSTypeAliasDeclaration<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol( + let symbol_id = builder.declare_symbol_on_current_scope( self.id.span, &self.id.name, SymbolFlags::TypeAlias, @@ -314,7 +329,7 @@ impl<'a> Binder for TSTypeAliasDeclaration<'a> { impl<'a> Binder for TSInterfaceDeclaration<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol( + let symbol_id = builder.declare_symbol_on_current_scope( self.id.span, &self.id.name, SymbolFlags::Interface, @@ -333,7 +348,12 @@ impl<'a> Binder for TSEnumDeclaration<'a> { } else { SymbolFlags::RegularEnumExcludes }; - let symbol_id = builder.declare_symbol(self.id.span, &self.id.name, includes, excludes); + let symbol_id = builder.declare_symbol_on_current_scope( + self.id.span, + &self.id.name, + includes, + excludes, + ); self.id.symbol_id.set(Some(symbol_id)); } } @@ -350,7 +370,7 @@ impl<'a> Binder for TSEnumMember<'a> { TSEnumMemberName::StaticNumericLiteral(n) => Cow::Owned(n.value.to_string()), match_expression!(TSEnumMemberName) => panic!("TODO: implement"), }; - builder.declare_symbol( + builder.declare_symbol_on_current_scope( self.span, &name, SymbolFlags::EnumMember, @@ -364,7 +384,7 @@ impl<'a> Binder for TSModuleDeclaration<'a> { // At declaration time a module has no value declaration it is only when a value declaration // is made inside a the scope of a module that the symbol is modified let ambient = if self.declare { SymbolFlags::Ambient } else { SymbolFlags::None }; - builder.declare_symbol( + builder.declare_symbol_on_current_scope( self.span, self.id.name().as_str(), SymbolFlags::NameSpaceModule | ambient, @@ -375,7 +395,7 @@ impl<'a> Binder for TSModuleDeclaration<'a> { impl<'a> Binder for TSTypeParameter<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol( + let symbol_id = builder.declare_symbol_on_current_scope( self.name.span, &self.name.name, SymbolFlags::TypeParameter, diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 5fcb1ef40e0b3..d54035e2fab6d 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -266,7 +266,6 @@ impl<'a> SemanticBuilder<'a> { pub fn strict_mode(&self) -> bool { self.current_scope_flags().is_strict_mode() - || self.current_node_flags.contains(NodeFlags::Class) } pub fn set_function_node_flag(&mut self, flag: NodeFlags) { @@ -275,6 +274,15 @@ impl<'a> SemanticBuilder<'a> { } } + /// Declares a `Symbol` for the node, adds it to symbol table + /// + /// includes: the `SymbolFlags` that node has in addition to its declaration type (eg: export, ambient, etc.) + pub fn declare_symbol(&mut self, span: Span, name: &str, includes: SymbolFlags) -> SymbolId { + let includes = includes | self.current_symbol_flags; + let name = CompactStr::new(name); + self.symbols.create_symbol(span, name, self.current_node_id, includes, None) + } + /// Declares a `Symbol` for the node, adds it to symbol table, and binds it to the scope. /// /// includes: the `SymbolFlags` that node has in addition to its declaration type (eg: export, ambient, etc.) @@ -296,14 +304,13 @@ impl<'a> SemanticBuilder<'a> { } let includes = includes | self.current_symbol_flags; - let name = CompactStr::new(name); - let symbol_id = self.symbols.create_symbol(span, name.clone(), includes, scope_id); - self.symbols.add_declaration(self.current_node_id); - self.scope.add_binding(scope_id, name, symbol_id); + let symbol_id = self.declare_symbol(span, name, includes); + self.symbols.set_scope_id(symbol_id, scope_id); + self.scope.add_binding(scope_id, CompactStr::new(name), symbol_id); symbol_id } - pub fn declare_symbol( + pub fn declare_symbol_on_current_scope( &mut self, span: Span, name: &str, @@ -354,11 +361,9 @@ impl<'a> SemanticBuilder<'a> { includes: SymbolFlags, ) -> SymbolId { let includes = includes | self.current_symbol_flags; - let name = CompactStr::new(name); - let symbol_id = - self.symbols.create_symbol(span, name.clone(), includes, self.current_scope_id); - self.symbols.add_declaration(self.current_node_id); - self.scope.get_bindings_mut(scope_id).insert(name, symbol_id); + let symbol_id = self.declare_symbol(span, name, includes); + self.symbols.set_scope_id(symbol_id, scope_id); + self.scope.get_bindings_mut(scope_id).insert(CompactStr::new(name), symbol_id); symbol_id } @@ -372,7 +377,22 @@ impl<'a> SemanticBuilder<'a> { } fn resolve_reference_ids(&mut self, name: CompactStr, reference_ids: Vec) { - if let Some(symbol_id) = self.scope.get_binding(self.current_scope_id, &name) { + if let Some(symbol_id) = + self.scope.get_binding(self.current_scope_id, &name).or_else(|| { + self.symbols.get_symbol_id_from_declaration(self.current_node_id).and_then( + |symbol_id| { + let flag = self.symbols.get_flag(symbol_id); + if (flag.is_class() || flag.is_function()) + && self.symbols.get_name(symbol_id) == name + { + Some(symbol_id) + } else { + None + } + }, + ) + }) + { for reference_id in &reference_ids { self.symbols.references[*reference_id].set_symbol_id(symbol_id); } @@ -426,6 +446,12 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { if flags.contains(ScopeFlags::Top) { None } else { Some(self.current_scope_id) }; let mut flags = flags; + + if !flags.is_strict_mode() && self.current_node_flags.has_class() { + // NOTE A class definition is always strict mode code. + flags |= ScopeFlags::StrictMode; + }; + if let Some(parent_scope_id) = parent_scope_id { flags = self.scope.get_new_scope_flags(flags, parent_scope_id); } @@ -1442,46 +1468,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { self.leave_scope(); } - fn visit_class(&mut self, class: &Class<'a>) { - // Class level decorators are transpiled as functions outside of the class taking the class - // itself as argument. They should be visited before class is entered. E.g., they inherit - // strict mode from the enclosing scope rather than from class. - for decorator in &class.decorators { - self.visit_decorator(decorator); - } - let kind = AstKind::Class(self.alloc(class)); - - // FIXME(don): Should we enter a scope when visiting class declarations? - let is_class_expr = class.r#type == ClassType::ClassExpression; - if is_class_expr { - // Class expressions create a temporary scope with the class name as its only variable - // E.g., `let c = class A { foo() { console.log(A) } }` - self.enter_scope(ScopeFlags::empty(), &class.scope_id); - } - - self.enter_node(kind); - - if let Some(id) = &class.id { - self.visit_binding_identifier(id); - } - if let Some(parameters) = &class.type_parameters { - self.visit_ts_type_parameter_declaration(parameters); - } - - if let Some(super_class) = &class.super_class { - self.visit_class_heritage(super_class); - } - if let Some(super_parameters) = &class.super_type_parameters { - self.visit_ts_type_parameter_instantiation(super_parameters); - } - self.visit_class_body(&class.body); - - self.leave_node(kind); - if is_class_expr { - self.leave_scope(); - } - } - fn visit_arrow_function_expression(&mut self, expr: &ArrowFunctionExpression<'a>) { let kind = AstKind::ArrowFunctionExpression(self.alloc(expr)); self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow, &expr.scope_id); diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index 52376d4ff4974..1a856d968f4d0 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -121,7 +121,7 @@ impl<'a> Semantic<'a> { } /// Find which scope a symbol is declared in - pub fn symbol_scope(&self, symbol_id: SymbolId) -> ScopeId { + pub fn symbol_scope(&self, symbol_id: SymbolId) -> Option { self.symbols.get_scope_id(symbol_id) } @@ -198,7 +198,7 @@ mod tests { .iter_bindings() .find(|(_scope_id, _symbol_id, name)| name.as_str() == "Fn") .unwrap(); - assert_eq!(semantic.symbols.get_scope_id(top_level_a.1), top_level_a.0); + assert_eq!(semantic.symbols.get_scope_id(top_level_a.1), Some(top_level_a.0)); } #[test] diff --git a/crates/oxc_semantic/src/symbol.rs b/crates/oxc_semantic/src/symbol.rs index 80bc798c1a0fa..7fe1cbf16aa6a 100644 --- a/crates/oxc_semantic/src/symbol.rs +++ b/crates/oxc_semantic/src/symbol.rs @@ -7,6 +7,8 @@ pub use oxc_syntax::{ scope::ScopeId, symbol::{SymbolFlags, SymbolId}, }; +use rustc_hash::FxHashMap; + #[cfg(feature = "serialize")] use serde::Serialize; #[cfg(feature = "serialize")] @@ -32,9 +34,10 @@ pub struct SymbolTable { pub spans: IndexVec, pub names: IndexVec, pub flags: IndexVec, - pub scope_ids: IndexVec, + pub scope_ids: IndexVec>, /// Pointer to the AST Node where this symbol is declared pub declarations: IndexVec, + pub declaration_symbol: FxHashMap, pub resolved_references: IndexVec>, pub references: IndexVec, pub redeclare_variables: IndexVec>, @@ -63,6 +66,10 @@ impl SymbolTable { .find_map(|(symbol, inner_span)| if inner_span == span { Some(symbol) } else { None }) } + pub fn get_symbol_id_from_declaration(&self, declaration: AstNodeId) -> Option { + self.declaration_symbol.get(&declaration).copied() + } + pub fn get_symbol_id_from_name(&self, name: &str) -> Option { self.names.iter_enumerated().find_map(|(symbol, inner_name)| { if inner_name.as_str() == name { @@ -97,16 +104,20 @@ impl SymbolTable { self.flags[symbol_id] |= includes; } - pub fn get_scope_id(&self, symbol_id: SymbolId) -> ScopeId { + pub fn set_scope_id(&mut self, symbol_id: SymbolId, scope_id: ScopeId) { + self.scope_ids[symbol_id] = Some(scope_id); + } + + pub fn get_scope_id(&self, symbol_id: SymbolId) -> Option { self.scope_ids[symbol_id] } pub fn get_scope_id_from_span(&self, span: &Span) -> Option { - self.get_symbol_id_from_span(span).map(|symbol_id| self.get_scope_id(symbol_id)) + self.get_symbol_id_from_span(span).and_then(|symbol_id| self.get_scope_id(symbol_id)) } pub fn get_scope_id_from_name(&self, name: &str) -> Option { - self.get_symbol_id_from_name(name).map(|symbol_id| self.get_scope_id(symbol_id)) + self.get_symbol_id_from_name(name).and_then(|symbol_id| self.get_scope_id(symbol_id)) } pub fn get_declaration(&self, symbol_id: SymbolId) -> AstNodeId { @@ -117,19 +128,19 @@ impl SymbolTable { &mut self, span: Span, name: CompactStr, + declaration: AstNodeId, flag: SymbolFlags, - scope_id: ScopeId, + scope_id: Option, ) -> SymbolId { _ = self.spans.push(span); _ = self.names.push(name); + _ = self.declarations.push(declaration); _ = self.flags.push(flag); _ = self.scope_ids.push(scope_id); _ = self.resolved_references.push(vec![]); - self.redeclare_variables.push(vec![]) - } - - pub fn add_declaration(&mut self, node_id: AstNodeId) { - self.declarations.push(node_id); + let symbol_id = self.redeclare_variables.push(vec![]); + self.declaration_symbol.insert(declaration, symbol_id); + symbol_id } pub fn add_redeclare_variable(&mut self, symbol_id: SymbolId, span: Span) { diff --git a/crates/oxc_semantic/tests/integration/scopes.rs b/crates/oxc_semantic/tests/integration/scopes.rs index be50154e2b5d5..235d0b979ab17 100644 --- a/crates/oxc_semantic/tests/integration/scopes.rs +++ b/crates/oxc_semantic/tests/integration/scopes.rs @@ -76,7 +76,7 @@ fn test_function_level_strict() { .is_in_scope(ScopeFlags::StrictMode | ScopeFlags::Function) .expect(|(semantic, symbol_id)| -> Result<(), &'static str> { let scope_id = semantic.symbol_scope(symbol_id); - let Some(parent_scope_id) = semantic.scopes().get_parent_id(scope_id) else { + let Some(parent_scope_id) = scope_id.and_then(|scope_id| semantic.scopes().get_parent_id(scope_id)) else { return Err("Expected x's scope to have a parent") }; let parent_flags = semantic.scopes().get_flags(parent_scope_id); diff --git a/crates/oxc_semantic/tests/integration/symbols.rs b/crates/oxc_semantic/tests/integration/symbols.rs index 8b43297749a19..1208700a91c69 100644 --- a/crates/oxc_semantic/tests/integration/symbols.rs +++ b/crates/oxc_semantic/tests/integration/symbols.rs @@ -27,10 +27,6 @@ fn test_function_simple() { #[test] fn test_function_expressions() { - SemanticTester::js("const x = function y() {}") - .has_some_symbol("y") - .contains_flags(SymbolFlags::Function) - .test(); SemanticTester::js("const x = () => {}") .has_some_symbol("x") .contains_flags(SymbolFlags::BlockScopedVariable | SymbolFlags::ConstVariable) @@ -114,3 +110,126 @@ fn test_export_flag() { tester.has_root_symbol("b").contains_flags(SymbolFlags::Export).test(); tester.has_root_symbol("c").contains_flags(SymbolFlags::Export).test(); } + +#[test] +fn test_multiple_ts_type_alias_declaration() { + let tester = SemanticTester::ts( + " + type A = AB + type B = AB + ", + ); + + tester + .has_symbol("AB") + .contains_flags(SymbolFlags::TypeParameter) + .has_number_of_references(1) + .test(); +} + +#[test] +fn test_function_with_type_parameter() { + let tester = SemanticTester::ts( + " + function mdl() { + function mdl2() { + function mdl3() { + return '' as M; + } + } + } + function kfc() { + function kfc2() { + function kfc3() { + return '' as K; + } + } + } + ", + ); + + tester.has_symbol("M").has_number_of_references(1).test(); + tester.has_symbol("K").has_number_of_references(0).test(); +} + +#[test] +fn test_class_with_type_parameter() { + let tester = SemanticTester::ts( + " + class Cls { + a: T; + method(b: T | K) {} + func() { + type D = T; + return null as D + } + } + type B = any; + class ClassB { + b: B; + } + ", + ); + + tester.has_symbol("T").has_number_of_references(3).test(); + tester.has_symbol("K").has_number_of_references(1).test(); + tester.has_symbol("D").has_number_of_references(1).test(); + + // type B is not referenced + tester.has_symbol("B").has_number_of_references(0).test(); +} + +#[test] +fn test_ts_mapped_type() { + let tester = SemanticTester::ts( + " + type M = { [K in keyof T]: T[K] }; + type Y = any; + type X = { [Y in keyof T]: T[Y] }; + ", + ); + + tester.has_symbol("T").has_number_of_references(2).test(); + tester.has_symbol("K").has_number_of_references(1).test(); + + // type Y is not referenced + tester.has_symbol("Y").has_number_of_references(0).test(); +} + +#[test] +fn test_ts_interface_declaration_with_type_parameter() { + let tester = SemanticTester::ts( + " + type A = any; + interface ITA { + a: A; + } + interface ITB { + b: B; + } + ", + ); + + tester.has_symbol("B").has_number_of_references(1).test(); + + // type A is not referenced + tester.has_symbol("A").has_number_of_references(0).test(); +} + +#[test] +fn test_ts_infer_type() { + let tester = SemanticTester::ts( + " + type T = T extends infer U ? U : never; + + type C = any; + type K = K extends infer C ? K : never; + ", + ); + + tester.has_symbol("T").has_number_of_references(1).test(); + tester.has_symbol("U").has_number_of_references(1).test(); + + // type C is not referenced + tester.has_symbol("C").has_number_of_references(0).test(); +} diff --git a/crates/oxc_semantic/tests/integration/util/mod.rs b/crates/oxc_semantic/tests/integration/util/mod.rs index 3cdd9f154a059..75efcd1d007af 100644 --- a/crates/oxc_semantic/tests/integration/util/mod.rs +++ b/crates/oxc_semantic/tests/integration/util/mod.rs @@ -189,6 +189,14 @@ impl<'a> SemanticTester<'a> { SymbolTester::new_at_root(self, self.build(), name) } + /// Find first symbol by name in the source code. + /// + /// ## Fails + /// 1. No symbol with the given name exists, + pub fn has_symbol(&self, name: &str) -> SymbolTester { + SymbolTester::new_first_binding(self, self.build(), name) + } + /// Tests that a class with the given name exists /// /// ## Fails diff --git a/crates/oxc_semantic/tests/integration/util/symbol_tester.rs b/crates/oxc_semantic/tests/integration/util/symbol_tester.rs index ccc1929e9f78b..e4d4cf54b7651 100644 --- a/crates/oxc_semantic/tests/integration/util/symbol_tester.rs +++ b/crates/oxc_semantic/tests/integration/util/symbol_tester.rs @@ -1,7 +1,8 @@ use std::rc::Rc; use oxc_diagnostics::{Error, OxcDiagnostic}; -use oxc_semantic::{Reference, ScopeFlags, Semantic, SymbolFlags, SymbolId}; +use oxc_semantic::{Reference, ScopeFlags, ScopeId, Semantic, SymbolFlags, SymbolId}; +use oxc_span::CompactStr; use super::{Expect, SemanticTester}; @@ -71,6 +72,27 @@ impl<'a> SymbolTester<'a> { (Rc::clone(&self.semantic), *self.test_result.as_ref().unwrap()) } + pub(super) fn new_first_binding( + parent: &'a SemanticTester, + semantic: Semantic<'a>, + target: &str, + ) -> Self { + let symbols_with_target_name: Option<(ScopeId, SymbolId, &CompactStr)> = + semantic.scopes().iter_bindings().find(|(_, _, name)| name.as_str() == target); + + let data = match symbols_with_target_name { + Some((_, symbol_id, _)) => Ok(symbol_id), + None => Err(OxcDiagnostic::error(format!("Could not find declaration for {target}"))), + }; + + SymbolTester { + parent, + semantic: Rc::new(semantic), + target_symbol_name: target.to_string(), + test_result: data, + } + } + /// Checks if the resolved symbol contains all flags in `flags`, using [`SymbolFlags::contains()`] #[must_use] pub fn contains_flags(mut self, flags: SymbolFlags) -> Self { @@ -198,8 +220,9 @@ impl<'a> SymbolTester<'a> { self.test_result = match self.test_result { Ok(symbol_id) => { let scope_id = self.semantic.symbol_scope(symbol_id); - let scope_flags = self.semantic.scopes().get_flags(scope_id); - if scope_flags.contains(expected_flags) { + let scope_flags = + scope_id.map(|scope_id| self.semantic.scopes().get_flags(scope_id)); + if scope_flags.is_some_and(|flags| flags.contains(expected_flags)) { Ok(symbol_id) } else { Err(OxcDiagnostic::error(format!( @@ -219,8 +242,9 @@ impl<'a> SymbolTester<'a> { self.test_result = match self.test_result { Ok(symbol_id) => { let scope_id = self.semantic.symbol_scope(symbol_id); - let scope_flags = self.semantic.scopes().get_flags(scope_id); - if scope_flags.contains(excluded_flags) { + let scope_flags = + scope_id.map(|scope_id| self.semantic.scopes().get_flags(scope_id)); + if scope_flags.is_some_and(|flag| flag.contains(excluded_flags)) { Err(OxcDiagnostic::error(format!( "Binding {target_name} is in a scope with excluded flags.\n\tExpected: not {excluded_flags:?}\n\tActual: {scope_flags:?}" ))) diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index ba1de0af45093..1438a903d7d74 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -2,6 +2,7 @@ use std::cell::Cell; use oxc_allocator::Vec; use oxc_ast::{ast::*, visit::walk_mut, VisitMut}; +use oxc_semantic::AstNodeId; use oxc_span::{Atom, Span, SPAN}; use oxc_syntax::{ number::{NumberBase, ToJsInt32, ToJsString}, @@ -77,8 +78,9 @@ impl<'a> TypeScriptEnum<'a> { let param_symbol_id = ctx.symbols_mut().create_symbol( decl.id.span, enum_name.to_compact_str(), + AstNodeId::dummy(), SymbolFlags::FunctionScopedVariable, - func_scope_id, + Some(func_scope_id), ); let ident = BindingIdentifier { span: decl.id.span, diff --git a/crates/oxc_traverse/src/ancestor.rs b/crates/oxc_traverse/src/ancestor.rs index 02f78af89c23e..d647618251adf 100644 --- a/crates/oxc_traverse/src/ancestor.rs +++ b/crates/oxc_traverse/src/ancestor.rs @@ -158,11 +158,11 @@ pub(crate) enum AncestorType { YieldExpressionArgument = 126, ClassDecorators = 127, ClassId = 128, - ClassSuperClass = 129, - ClassBody = 130, - ClassTypeParameters = 131, - ClassSuperTypeParameters = 132, - ClassImplements = 133, + ClassTypeParameters = 129, + ClassSuperClass = 130, + ClassSuperTypeParameters = 131, + ClassImplements = 132, + ClassBody = 133, ClassBodyBody = 134, MethodDefinitionDecorators = 135, MethodDefinitionKey = 136, @@ -557,12 +557,12 @@ pub enum Ancestor<'a> { AncestorType::YieldExpressionArgument as u16, ClassDecorators(ClassWithoutDecorators<'a>) = AncestorType::ClassDecorators as u16, ClassId(ClassWithoutId<'a>) = AncestorType::ClassId as u16, - ClassSuperClass(ClassWithoutSuperClass<'a>) = AncestorType::ClassSuperClass as u16, - ClassBody(ClassWithoutBody<'a>) = AncestorType::ClassBody as u16, ClassTypeParameters(ClassWithoutTypeParameters<'a>) = AncestorType::ClassTypeParameters as u16, + ClassSuperClass(ClassWithoutSuperClass<'a>) = AncestorType::ClassSuperClass as u16, ClassSuperTypeParameters(ClassWithoutSuperTypeParameters<'a>) = AncestorType::ClassSuperTypeParameters as u16, ClassImplements(ClassWithoutImplements<'a>) = AncestorType::ClassImplements as u16, + ClassBody(ClassWithoutBody<'a>) = AncestorType::ClassBody as u16, ClassBodyBody(ClassBodyWithoutBody<'a>) = AncestorType::ClassBodyBody as u16, MethodDefinitionDecorators(MethodDefinitionWithoutDecorators<'a>) = AncestorType::MethodDefinitionDecorators as u16, @@ -1284,11 +1284,11 @@ impl<'a> Ancestor<'a> { self, Self::ClassDecorators(_) | Self::ClassId(_) - | Self::ClassSuperClass(_) - | Self::ClassBody(_) | Self::ClassTypeParameters(_) + | Self::ClassSuperClass(_) | Self::ClassSuperTypeParameters(_) | Self::ClassImplements(_) + | Self::ClassBody(_) ) } @@ -6135,12 +6135,12 @@ pub(crate) const OFFSET_CLASS_TYPE: usize = offset_of!(Class, r#type); pub(crate) const OFFSET_CLASS_SPAN: usize = offset_of!(Class, span); pub(crate) const OFFSET_CLASS_DECORATORS: usize = offset_of!(Class, decorators); pub(crate) const OFFSET_CLASS_ID: usize = offset_of!(Class, id); -pub(crate) const OFFSET_CLASS_SUPER_CLASS: usize = offset_of!(Class, super_class); -pub(crate) const OFFSET_CLASS_BODY: usize = offset_of!(Class, body); pub(crate) const OFFSET_CLASS_TYPE_PARAMETERS: usize = offset_of!(Class, type_parameters); +pub(crate) const OFFSET_CLASS_SUPER_CLASS: usize = offset_of!(Class, super_class); pub(crate) const OFFSET_CLASS_SUPER_TYPE_PARAMETERS: usize = offset_of!(Class, super_type_parameters); pub(crate) const OFFSET_CLASS_IMPLEMENTS: usize = offset_of!(Class, implements); +pub(crate) const OFFSET_CLASS_BODY: usize = offset_of!(Class, body); pub(crate) const OFFSET_CLASS_ABSTRACT: usize = offset_of!(Class, r#abstract); pub(crate) const OFFSET_CLASS_DECLARE: usize = offset_of!(Class, declare); pub(crate) const OFFSET_CLASS_SCOPE_ID: usize = offset_of!(Class, scope_id); @@ -6168,22 +6168,17 @@ impl<'a> ClassWithoutDecorators<'a> { } #[inline] - pub fn super_class(&self) -> &Option> { + pub fn type_parameters(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) + &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) + as *const Option>>) } } #[inline] - pub fn body(&self) -> &Box<'a, ClassBody<'a>> { - unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } - } - - #[inline] - pub fn type_parameters(&self) -> &Option>> { + pub fn super_class(&self) -> &Option> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) } } @@ -6203,6 +6198,11 @@ impl<'a> ClassWithoutDecorators<'a> { } } + #[inline] + pub fn body(&self) -> &Box<'a, ClassBody<'a>> { + unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } + } + #[inline] pub fn r#abstract(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_ABSTRACT) as *const bool) } @@ -6244,22 +6244,17 @@ impl<'a> ClassWithoutId<'a> { } #[inline] - pub fn super_class(&self) -> &Option> { + pub fn type_parameters(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) + &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) + as *const Option>>) } } #[inline] - pub fn body(&self) -> &Box<'a, ClassBody<'a>> { - unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } - } - - #[inline] - pub fn type_parameters(&self) -> &Option>> { + pub fn super_class(&self) -> &Option> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) } } @@ -6279,6 +6274,11 @@ impl<'a> ClassWithoutId<'a> { } } + #[inline] + pub fn body(&self) -> &Box<'a, ClassBody<'a>> { + unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } + } + #[inline] pub fn r#abstract(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_ABSTRACT) as *const bool) } @@ -6299,9 +6299,9 @@ impl<'a> ClassWithoutId<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct ClassWithoutSuperClass<'a>(pub(crate) *const Class<'a>); +pub struct ClassWithoutTypeParameters<'a>(pub(crate) *const Class<'a>); -impl<'a> ClassWithoutSuperClass<'a> { +impl<'a> ClassWithoutTypeParameters<'a> { #[inline] pub fn r#type(&self) -> &ClassType { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE) as *const ClassType) } @@ -6327,15 +6327,9 @@ impl<'a> ClassWithoutSuperClass<'a> { } #[inline] - pub fn body(&self) -> &Box<'a, ClassBody<'a>> { - unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } - } - - #[inline] - pub fn type_parameters(&self) -> &Option>> { + pub fn super_class(&self) -> &Option> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) } } @@ -6355,6 +6349,11 @@ impl<'a> ClassWithoutSuperClass<'a> { } } + #[inline] + pub fn body(&self) -> &Box<'a, ClassBody<'a>> { + unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } + } + #[inline] pub fn r#abstract(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_ABSTRACT) as *const bool) } @@ -6375,9 +6374,9 @@ impl<'a> ClassWithoutSuperClass<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct ClassWithoutBody<'a>(pub(crate) *const Class<'a>); +pub struct ClassWithoutSuperClass<'a>(pub(crate) *const Class<'a>); -impl<'a> ClassWithoutBody<'a> { +impl<'a> ClassWithoutSuperClass<'a> { #[inline] pub fn r#type(&self) -> &ClassType { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE) as *const ClassType) } @@ -6402,13 +6401,6 @@ impl<'a> ClassWithoutBody<'a> { } } - #[inline] - pub fn super_class(&self) -> &Option> { - unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) - } - } - #[inline] pub fn type_parameters(&self) -> &Option>> { unsafe { @@ -6433,6 +6425,11 @@ impl<'a> ClassWithoutBody<'a> { } } + #[inline] + pub fn body(&self) -> &Box<'a, ClassBody<'a>> { + unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } + } + #[inline] pub fn r#abstract(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_ABSTRACT) as *const bool) } @@ -6453,9 +6450,9 @@ impl<'a> ClassWithoutBody<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct ClassWithoutTypeParameters<'a>(pub(crate) *const Class<'a>); +pub struct ClassWithoutSuperTypeParameters<'a>(pub(crate) *const Class<'a>); -impl<'a> ClassWithoutTypeParameters<'a> { +impl<'a> ClassWithoutSuperTypeParameters<'a> { #[inline] pub fn r#type(&self) -> &ClassType { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE) as *const ClassType) } @@ -6481,22 +6478,17 @@ impl<'a> ClassWithoutTypeParameters<'a> { } #[inline] - pub fn super_class(&self) -> &Option> { + pub fn type_parameters(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) + &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) + as *const Option>>) } } #[inline] - pub fn body(&self) -> &Box<'a, ClassBody<'a>> { - unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } - } - - #[inline] - pub fn super_type_parameters(&self) -> &Option>> { + pub fn super_class(&self) -> &Option> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_TYPE_PARAMETERS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) } } @@ -6508,6 +6500,11 @@ impl<'a> ClassWithoutTypeParameters<'a> { } } + #[inline] + pub fn body(&self) -> &Box<'a, ClassBody<'a>> { + unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } + } + #[inline] pub fn r#abstract(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_ABSTRACT) as *const bool) } @@ -6528,9 +6525,9 @@ impl<'a> ClassWithoutTypeParameters<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct ClassWithoutSuperTypeParameters<'a>(pub(crate) *const Class<'a>); +pub struct ClassWithoutImplements<'a>(pub(crate) *const Class<'a>); -impl<'a> ClassWithoutSuperTypeParameters<'a> { +impl<'a> ClassWithoutImplements<'a> { #[inline] pub fn r#type(&self) -> &ClassType { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE) as *const ClassType) } @@ -6556,31 +6553,31 @@ impl<'a> ClassWithoutSuperTypeParameters<'a> { } #[inline] - pub fn super_class(&self) -> &Option> { + pub fn type_parameters(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) + &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) + as *const Option>>) } } #[inline] - pub fn body(&self) -> &Box<'a, ClassBody<'a>> { - unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } + pub fn super_class(&self) -> &Option> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) + } } #[inline] - pub fn type_parameters(&self) -> &Option>> { + pub fn super_type_parameters(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_TYPE_PARAMETERS) + as *const Option>>) } } #[inline] - pub fn implements(&self) -> &Option>> { - unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_IMPLEMENTS) - as *const Option>>) - } + pub fn body(&self) -> &Box<'a, ClassBody<'a>> { + unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } } #[inline] @@ -6603,9 +6600,9 @@ impl<'a> ClassWithoutSuperTypeParameters<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct ClassWithoutImplements<'a>(pub(crate) *const Class<'a>); +pub struct ClassWithoutBody<'a>(pub(crate) *const Class<'a>); -impl<'a> ClassWithoutImplements<'a> { +impl<'a> ClassWithoutBody<'a> { #[inline] pub fn r#type(&self) -> &ClassType { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE) as *const ClassType) } @@ -6631,22 +6628,17 @@ impl<'a> ClassWithoutImplements<'a> { } #[inline] - pub fn super_class(&self) -> &Option> { + pub fn type_parameters(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) + &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) + as *const Option>>) } } #[inline] - pub fn body(&self) -> &Box<'a, ClassBody<'a>> { - unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_BODY) as *const Box<'a, ClassBody<'a>>) } - } - - #[inline] - pub fn type_parameters(&self) -> &Option>> { + pub fn super_class(&self) -> &Option> { unsafe { - &*((self.0 as *const u8).add(OFFSET_CLASS_TYPE_PARAMETERS) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_CLASS_SUPER_CLASS) as *const Option>) } } @@ -6658,6 +6650,14 @@ impl<'a> ClassWithoutImplements<'a> { } } + #[inline] + pub fn implements(&self) -> &Option>> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_CLASS_IMPLEMENTS) + as *const Option>>) + } + } + #[inline] pub fn r#abstract(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_CLASS_ABSTRACT) as *const bool) } @@ -8839,6 +8839,8 @@ pub(crate) const OFFSET_TS_CONDITIONAL_TYPE_TRUE_TYPE: usize = offset_of!(TSConditionalType, true_type); pub(crate) const OFFSET_TS_CONDITIONAL_TYPE_FALSE_TYPE: usize = offset_of!(TSConditionalType, false_type); +pub(crate) const OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID: usize = + offset_of!(TSConditionalType, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -8872,6 +8874,14 @@ impl<'a> TSConditionalTypeWithoutCheckType<'a> { as *const TSType<'a>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -8906,6 +8916,14 @@ impl<'a> TSConditionalTypeWithoutExtendsType<'a> { as *const TSType<'a>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -8941,6 +8959,14 @@ impl<'a> TSConditionalTypeWithoutTrueType<'a> { as *const TSType<'a>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -8975,6 +9001,14 @@ impl<'a> TSConditionalTypeWithoutFalseType<'a> { &*((self.0 as *const u8).add(OFFSET_TS_CONDITIONAL_TYPE_TRUE_TYPE) as *const TSType<'a>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) + as *const Cell>) + } + } } pub(crate) const OFFSET_TS_UNION_TYPE_SPAN: usize = offset_of!(TSUnionType, span); @@ -9318,7 +9352,6 @@ pub(crate) const OFFSET_TS_TYPE_PARAMETER_DEFAULT: usize = offset_of!(TSTypePara pub(crate) const OFFSET_TS_TYPE_PARAMETER_IN: usize = offset_of!(TSTypeParameter, r#in); pub(crate) const OFFSET_TS_TYPE_PARAMETER_OUT: usize = offset_of!(TSTypeParameter, out); pub(crate) const OFFSET_TS_TYPE_PARAMETER_CONST: usize = offset_of!(TSTypeParameter, r#const); -pub(crate) const OFFSET_TS_TYPE_PARAMETER_SCOPE_ID: usize = offset_of!(TSTypeParameter, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -9360,14 +9393,6 @@ impl<'a> TSTypeParameterWithoutName<'a> { pub fn r#const(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_TS_TYPE_PARAMETER_CONST) as *const bool) } } - - #[inline] - pub fn scope_id(&self) -> &Cell> { - unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_TYPE_PARAMETER_SCOPE_ID) - as *const Cell>) - } - } } #[repr(transparent)] @@ -9410,14 +9435,6 @@ impl<'a> TSTypeParameterWithoutConstraint<'a> { pub fn r#const(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_TS_TYPE_PARAMETER_CONST) as *const bool) } } - - #[inline] - pub fn scope_id(&self) -> &Cell> { - unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_TYPE_PARAMETER_SCOPE_ID) - as *const Cell>) - } - } } #[repr(transparent)] @@ -9460,14 +9477,6 @@ impl<'a> TSTypeParameterWithoutDefault<'a> { pub fn r#const(&self) -> &bool { unsafe { &*((self.0 as *const u8).add(OFFSET_TS_TYPE_PARAMETER_CONST) as *const bool) } } - - #[inline] - pub fn scope_id(&self) -> &Cell> { - unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_TYPE_PARAMETER_SCOPE_ID) - as *const Cell>) - } - } } pub(crate) const OFFSET_TS_TYPE_PARAMETER_DECLARATION_SPAN: usize = @@ -9500,6 +9509,8 @@ pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_TYPE_ANNOTATION: usize = offset_of!(TSTypeAliasDeclaration, type_annotation); pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE: usize = offset_of!(TSTypeAliasDeclaration, declare); +pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID: usize = + offset_of!(TSTypeAliasDeclaration, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -9535,6 +9546,14 @@ impl<'a> TSTypeAliasDeclarationWithoutId<'a> { &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -9573,6 +9592,14 @@ impl<'a> TSTypeAliasDeclarationWithoutTypeParameters<'a> { &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -9611,6 +9638,14 @@ impl<'a> TSTypeAliasDeclarationWithoutTypeAnnotation<'a> { &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } pub(crate) const OFFSET_TS_CLASS_IMPLEMENTS_SPAN: usize = offset_of!(TSClassImplements, span); @@ -9668,6 +9703,8 @@ pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_BODY: usize = offset_of!(TSInterfaceDeclaration, body); pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_DECLARE: usize = offset_of!(TSInterfaceDeclaration, declare); +pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID: usize = + offset_of!(TSInterfaceDeclaration, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -9711,6 +9748,14 @@ impl<'a> TSInterfaceDeclarationWithoutId<'a> { &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -9755,6 +9800,14 @@ impl<'a> TSInterfaceDeclarationWithoutExtends<'a> { &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -9801,6 +9854,14 @@ impl<'a> TSInterfaceDeclarationWithoutTypeParameters<'a> { &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -9845,6 +9906,14 @@ impl<'a> TSInterfaceDeclarationWithoutBody<'a> { &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } pub(crate) const OFFSET_TS_INTERFACE_BODY_SPAN: usize = offset_of!(TSInterfaceBody, span); @@ -10188,6 +10257,8 @@ pub(crate) const OFFSET_TS_METHOD_SIGNATURE_RETURN_TYPE: usize = offset_of!(TSMethodSignature, return_type); pub(crate) const OFFSET_TS_METHOD_SIGNATURE_TYPE_PARAMETERS: usize = offset_of!(TSMethodSignature, type_parameters); +pub(crate) const OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID: usize = + offset_of!(TSMethodSignature, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -10248,6 +10319,14 @@ impl<'a> TSMethodSignatureWithoutKey<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -10308,6 +10387,14 @@ impl<'a> TSMethodSignatureWithoutThisParam<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -10368,6 +10455,14 @@ impl<'a> TSMethodSignatureWithoutParams<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -10428,6 +10523,14 @@ impl<'a> TSMethodSignatureWithoutReturnType<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -10488,6 +10591,14 @@ impl<'a> TSMethodSignatureWithoutTypeParameters<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *const Cell>) + } + } } pub(crate) const OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SPAN: usize = @@ -10498,6 +10609,8 @@ pub(crate) const OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_RETURN_TYPE: usize = offset_of!(TSConstructSignatureDeclaration, return_type); pub(crate) const OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_TYPE_PARAMETERS: usize = offset_of!(TSConstructSignatureDeclaration, type_parameters); +pub(crate) const OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID: usize = + offset_of!(TSConstructSignatureDeclaration, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -10529,6 +10642,14 @@ impl<'a> TSConstructSignatureDeclarationWithoutParams<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -10561,6 +10682,14 @@ impl<'a> TSConstructSignatureDeclarationWithoutReturnType<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -10593,6 +10722,14 @@ impl<'a> TSConstructSignatureDeclarationWithoutTypeParameters<'a> { as *const Option>>) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID) + as *const Cell>) + } + } } pub(crate) const OFFSET_TS_INDEX_SIGNATURE_NAME_SPAN: usize = @@ -11410,6 +11547,7 @@ pub(crate) const OFFSET_TS_MAPPED_TYPE_TYPE_ANNOTATION: usize = offset_of!(TSMappedType, type_annotation); pub(crate) const OFFSET_TS_MAPPED_TYPE_OPTIONAL: usize = offset_of!(TSMappedType, optional); pub(crate) const OFFSET_TS_MAPPED_TYPE_READONLY: usize = offset_of!(TSMappedType, readonly); +pub(crate) const OFFSET_TS_MAPPED_TYPE_SCOPE_ID: usize = offset_of!(TSMappedType, scope_id); #[repr(transparent)] #[derive(Debug)] @@ -11452,6 +11590,14 @@ impl<'a> TSMappedTypeWithoutTypeParameter<'a> { as *const TSMappedTypeModifierOperator) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -11495,6 +11641,14 @@ impl<'a> TSMappedTypeWithoutNameType<'a> { as *const TSMappedTypeModifierOperator) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_SCOPE_ID) + as *const Cell>) + } + } } #[repr(transparent)] @@ -11538,6 +11692,14 @@ impl<'a> TSMappedTypeWithoutTypeAnnotation<'a> { as *const TSMappedTypeModifierOperator) } } + + #[inline] + pub fn scope_id(&self) -> &Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_SCOPE_ID) + as *const Cell>) + } + } } pub(crate) const OFFSET_TS_TEMPLATE_LITERAL_TYPE_SPAN: usize = diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index b67a3adaa72e3..c7cb4d242f30d 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -245,7 +245,13 @@ impl TraverseScoping { let name = CompactStr::new(&self.find_uid_name(name)); // Add binding to scope - let symbol_id = self.symbols.create_symbol(SPAN, name.clone(), flags, scope_id); + let symbol_id = self.symbols.create_symbol( + SPAN, + name.clone(), + AstNodeId::dummy(), + flags, + Some(scope_id), + ); self.scopes.add_binding(scope_id, name, symbol_id); symbol_id } @@ -576,8 +582,4 @@ impl<'a> Visit<'a> for ChildScopeCollector { fn visit_ts_module_declaration(&mut self, decl: &TSModuleDeclaration<'a>) { self.scope_ids.push(decl.scope_id.get().unwrap()); } - - fn visit_ts_type_parameter(&mut self, ty: &TSTypeParameter<'a>) { - self.scope_ids.push(ty.scope_id.get().unwrap()); - } } diff --git a/crates/oxc_traverse/src/walk.rs b/crates/oxc_traverse/src/walk.rs index 9361a1aa78dda..bd434f405e382 100644 --- a/crates/oxc_traverse/src/walk.rs +++ b/crates/oxc_traverse/src/walk.rs @@ -2459,6 +2459,12 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( { walk_decorator(traverser, item as *mut _, ctx); } + if let Some(field) = + &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_ID) as *mut Option) + { + ctx.retag_stack(AncestorType::ClassId); + walk_binding_identifier(traverser, field as *mut _, ctx); + } let mut previous_scope_id = None; if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_CLASS_SCOPE_ID) as *mut Cell>)) @@ -2467,11 +2473,11 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( previous_scope_id = Some(ctx.current_scope_id()); ctx.set_current_scope_id(scope_id); } - if let Some(field) = - &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_ID) as *mut Option) + if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_TYPE_PARAMETERS) + as *mut Option>) { - ctx.retag_stack(AncestorType::ClassId); - walk_binding_identifier(traverser, field as *mut _, ctx); + ctx.retag_stack(AncestorType::ClassTypeParameters); + walk_ts_type_parameter_declaration(traverser, (&mut **field) as *mut _, ctx); } if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_SUPER_CLASS) as *mut Option) @@ -2479,19 +2485,6 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( ctx.retag_stack(AncestorType::ClassSuperClass); walk_expression(traverser, field as *mut _, ctx); } - ctx.retag_stack(AncestorType::ClassBody); - walk_class_body( - traverser, - (&mut **((node as *mut u8).add(ancestor::OFFSET_CLASS_BODY) as *mut Box)) - as *mut _, - ctx, - ); - if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_TYPE_PARAMETERS) - as *mut Option>) - { - ctx.retag_stack(AncestorType::ClassTypeParameters); - walk_ts_type_parameter_declaration(traverser, (&mut **field) as *mut _, ctx); - } if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_SUPER_TYPE_PARAMETERS) as *mut Option>) { @@ -2506,6 +2499,13 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( walk_ts_class_implements(traverser, item as *mut _, ctx); } } + ctx.retag_stack(AncestorType::ClassBody); + walk_class_body( + traverser, + (&mut **((node as *mut u8).add(ancestor::OFFSET_CLASS_BODY) as *mut Box)) + as *mut _, + ctx, + ); ctx.pop_stack(); if let Some(previous_scope_id) = previous_scope_id { ctx.set_current_scope_id(previous_scope_id); @@ -3925,6 +3925,14 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>( node: *mut TSConditionalType<'a>, ctx: &mut TraverseCtx<'a>, ) { + let mut previous_scope_id = None; + if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) + as *mut Cell>)) + .get() + { + previous_scope_id = Some(ctx.current_scope_id()); + ctx.set_current_scope_id(scope_id); + } traverser.enter_ts_conditional_type(&mut *node, ctx); ctx.push_stack(Ancestor::TSConditionalTypeCheckType( ancestor::TSConditionalTypeWithoutCheckType(node), @@ -3954,6 +3962,9 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>( ); ctx.pop_stack(); traverser.exit_ts_conditional_type(&mut *node, ctx); + if let Some(previous_scope_id) = previous_scope_id { + ctx.set_current_scope_id(previous_scope_id); + } } pub(crate) unsafe fn walk_ts_union_type<'a, Tr: Traverse<'a>>( @@ -4417,14 +4428,6 @@ pub(crate) unsafe fn walk_ts_type_parameter<'a, Tr: Traverse<'a>>( node: *mut TSTypeParameter<'a>, ctx: &mut TraverseCtx<'a>, ) { - let mut previous_scope_id = None; - if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_TS_TYPE_PARAMETER_SCOPE_ID) - as *mut Cell>)) - .get() - { - previous_scope_id = Some(ctx.current_scope_id()); - ctx.set_current_scope_id(scope_id); - } traverser.enter_ts_type_parameter(&mut *node, ctx); ctx.push_stack(Ancestor::TSTypeParameterName(ancestor::TSTypeParameterWithoutName(node))); walk_binding_identifier( @@ -4446,9 +4449,6 @@ pub(crate) unsafe fn walk_ts_type_parameter<'a, Tr: Traverse<'a>>( } ctx.pop_stack(); traverser.exit_ts_type_parameter(&mut *node, ctx); - if let Some(previous_scope_id) = previous_scope_id { - ctx.set_current_scope_id(previous_scope_id); - } } pub(crate) unsafe fn walk_ts_type_parameter_declaration<'a, Tr: Traverse<'a>>( @@ -4485,6 +4485,15 @@ pub(crate) unsafe fn walk_ts_type_alias_declaration<'a, Tr: Traverse<'a>>( as *mut BindingIdentifier, ctx, ); + let mut previous_scope_id = None; + if let Some(scope_id) = (*((node as *mut u8) + .add(ancestor::OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + { + previous_scope_id = Some(ctx.current_scope_id()); + ctx.set_current_scope_id(scope_id); + } if let Some(field) = &mut *((node as *mut u8) .add(ancestor::OFFSET_TS_TYPE_ALIAS_DECLARATION_TYPE_PARAMETERS) as *mut Option>) @@ -4500,6 +4509,9 @@ pub(crate) unsafe fn walk_ts_type_alias_declaration<'a, Tr: Traverse<'a>>( ctx, ); ctx.pop_stack(); + if let Some(previous_scope_id) = previous_scope_id { + ctx.set_current_scope_id(previous_scope_id); + } traverser.exit_ts_type_alias_declaration(&mut *node, ctx); } @@ -4543,6 +4555,15 @@ pub(crate) unsafe fn walk_ts_interface_declaration<'a, Tr: Traverse<'a>>( as *mut BindingIdentifier, ctx, ); + let mut previous_scope_id = None; + if let Some(scope_id) = (*((node as *mut u8) + .add(ancestor::OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + { + previous_scope_id = Some(ctx.current_scope_id()); + ctx.set_current_scope_id(scope_id); + } if let Some(field) = &mut *((node as *mut u8) .add(ancestor::OFFSET_TS_INTERFACE_DECLARATION_EXTENDS) as *mut Option>) @@ -4567,6 +4588,9 @@ pub(crate) unsafe fn walk_ts_interface_declaration<'a, Tr: Traverse<'a>>( ctx, ); ctx.pop_stack(); + if let Some(previous_scope_id) = previous_scope_id { + ctx.set_current_scope_id(previous_scope_id); + } traverser.exit_ts_interface_declaration(&mut *node, ctx); } @@ -4707,6 +4731,14 @@ pub(crate) unsafe fn walk_ts_method_signature<'a, Tr: Traverse<'a>>( node: *mut TSMethodSignature<'a>, ctx: &mut TraverseCtx<'a>, ) { + let mut previous_scope_id = None; + if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *mut Cell>)) + .get() + { + previous_scope_id = Some(ctx.current_scope_id()); + ctx.set_current_scope_id(scope_id); + } traverser.enter_ts_method_signature(&mut *node, ctx); ctx.push_stack(Ancestor::TSMethodSignatureKey(ancestor::TSMethodSignatureWithoutKey(node))); walk_property_key( @@ -4744,6 +4776,9 @@ pub(crate) unsafe fn walk_ts_method_signature<'a, Tr: Traverse<'a>>( } ctx.pop_stack(); traverser.exit_ts_method_signature(&mut *node, ctx); + if let Some(previous_scope_id) = previous_scope_id { + ctx.set_current_scope_id(previous_scope_id); + } } pub(crate) unsafe fn walk_ts_construct_signature_declaration<'a, Tr: Traverse<'a>>( @@ -4751,6 +4786,15 @@ pub(crate) unsafe fn walk_ts_construct_signature_declaration<'a, Tr: Traverse<'a node: *mut TSConstructSignatureDeclaration<'a>, ctx: &mut TraverseCtx<'a>, ) { + let mut previous_scope_id = None; + if let Some(scope_id) = (*((node as *mut u8) + .add(ancestor::OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + { + previous_scope_id = Some(ctx.current_scope_id()); + ctx.set_current_scope_id(scope_id); + } traverser.enter_ts_construct_signature_declaration(&mut *node, ctx); ctx.push_stack(Ancestor::TSConstructSignatureDeclarationParams( ancestor::TSConstructSignatureDeclarationWithoutParams(node), @@ -4777,6 +4821,9 @@ pub(crate) unsafe fn walk_ts_construct_signature_declaration<'a, Tr: Traverse<'a } ctx.pop_stack(); traverser.exit_ts_construct_signature_declaration(&mut *node, ctx); + if let Some(previous_scope_id) = previous_scope_id { + ctx.set_current_scope_id(previous_scope_id); + } } pub(crate) unsafe fn walk_ts_index_signature_name<'a, Tr: Traverse<'a>>( @@ -5205,6 +5252,14 @@ pub(crate) unsafe fn walk_ts_mapped_type<'a, Tr: Traverse<'a>>( node: *mut TSMappedType<'a>, ctx: &mut TraverseCtx<'a>, ) { + let mut previous_scope_id = None; + if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_SCOPE_ID) + as *mut Cell>)) + .get() + { + previous_scope_id = Some(ctx.current_scope_id()); + ctx.set_current_scope_id(scope_id); + } traverser.enter_ts_mapped_type(&mut *node, ctx); ctx.push_stack(Ancestor::TSMappedTypeTypeParameter( ancestor::TSMappedTypeWithoutTypeParameter(node), @@ -5230,6 +5285,9 @@ pub(crate) unsafe fn walk_ts_mapped_type<'a, Tr: Traverse<'a>>( } ctx.pop_stack(); traverser.exit_ts_mapped_type(&mut *node, ctx); + if let Some(previous_scope_id) = previous_scope_id { + ctx.set_current_scope_id(previous_scope_id); + } } pub(crate) unsafe fn walk_ts_template_literal_type<'a, Tr: Traverse<'a>>( diff --git a/tasks/ast_codegen/src/generators/ast_kind.rs b/tasks/ast_codegen/src/generators/ast_kind.rs index 3c080272dc591..a836b5cd1cde3 100644 --- a/tasks/ast_codegen/src/generators/ast_kind.rs +++ b/tasks/ast_codegen/src/generators/ast_kind.rs @@ -8,7 +8,7 @@ use super::generated_header; pub struct AstKindGenerator; -pub const BLACK_LIST: [&str; 69] = [ +pub const BLACK_LIST: [&str; 66] = [ "Expression", "ObjectPropertyKind", "TemplateElement", @@ -41,7 +41,6 @@ pub const BLACK_LIST: [&str; 69] = [ "TSEnumMemberName", "TSLiteral", "TSType", - "TSConditionalType", "TSTypeOperator", "TSArrayType", "TSTupleType", @@ -52,7 +51,6 @@ pub const BLACK_LIST: [&str; 69] = [ "TSSignature", "TSIndexSignature", "TSCallSignatureDeclaration", - "TSConstructSignatureDeclaration", "TSIndexSignatureName", "TSTypePredicate", "TSTypePredicateName", @@ -64,7 +62,6 @@ pub const BLACK_LIST: [&str; 69] = [ "TSImportAttributeName", "TSFunctionType", "TSConstructorType", - "TSMappedType", "TSModuleReference", "TSExportAssignment", "TSNamespaceExportDeclaration", diff --git a/tasks/coverage/parser_test262.snap b/tasks/coverage/parser_test262.snap index 214a54144fb7c..7f24f39228e43 100644 --- a/tasks/coverage/parser_test262.snap +++ b/tasks/coverage/parser_test262.snap @@ -12629,6 +12629,14 @@ Expect Syntax Error: "language/import/import-attributes/json-named-bindings.js" × Cannot use `await` as an identifier in an async context ╭─[language/expressions/class/static-init-await-binding.js:21:12] 20 │ static { + 21 │ (class await {}); + · ───── + 22 │ } + ╰──── + + × Cannot use await in class static initialization block + ╭─[language/expressions/class/static-init-await-binding.js:21:12] + 20 │ static { 21 │ (class await {}); · ───── 22 │ } diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index 2f46024cd6191..28b1498356c1a 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -3,7 +3,7 @@ commit: d8086f14 parser_typescript Summary: AST Parsed : 5279/5283 (99.92%) Positive Passed: 5271/5283 (99.77%) -Negative Passed: 1094/4875 (22.44%) +Negative Passed: 1095/4875 (22.46%) Expect Syntax Error: "compiler/ClassDeclaration10.ts" Expect Syntax Error: "compiler/ClassDeclaration11.ts" Expect Syntax Error: "compiler/ClassDeclaration13.ts" @@ -3466,7 +3466,6 @@ Expect Syntax Error: "conformance/types/literal/templateLiteralTypes5.ts" Expect Syntax Error: "conformance/types/literal/templateLiteralTypes7.ts" Expect Syntax Error: "conformance/types/literal/templateLiteralTypesPatterns.ts" Expect Syntax Error: "conformance/types/literal/templateLiteralTypesPatternsPrefixSuffixAssignability.ts" -Expect Syntax Error: "conformance/types/localTypes/localTypes4.ts" Expect Syntax Error: "conformance/types/mapped/mappedTypeAsClauseRelationships.ts" Expect Syntax Error: "conformance/types/mapped/mappedTypeAsClauses.ts" Expect Syntax Error: "conformance/types/mapped/mappedTypeConstraints2.ts" @@ -9735,6 +9734,30 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 22 │ ╰──── + × The keyword 'public' is reserved + ╭─[compiler/strictModeReservedWordInClassDeclaration.ts:23:20] + 22 │ + 23 │ class E implements public { } + · ────── + 24 │ + ╰──── + + × The keyword 'public' is reserved + ╭─[compiler/strictModeReservedWordInClassDeclaration.ts:25:20] + 24 │ + 25 │ class F implements public.private.B { } + · ────── + 26 │ class F1 implements public.private.implements { } + ╰──── + + × The keyword 'public' is reserved + ╭─[compiler/strictModeReservedWordInClassDeclaration.ts:26:21] + 25 │ class F implements public.private.B { } + 26 │ class F1 implements public.private.implements { } + · ────── + 27 │ class G extends package { } + ╰──── + × The keyword 'package' is reserved ╭─[compiler/strictModeReservedWordInClassDeclaration.ts:27:17] 26 │ class F1 implements public.private.implements { } @@ -20240,6 +20263,18 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 2 │ const a = import ╰──── + × Identifier `T` has already been declared + ╭─[conformance/types/localTypes/localTypes4.ts:18:16] + 17 │ // Type parameters and top-level local types are in same declaration space + 18 │ function f() { + · ┬ + · ╰── It can not be redeclared here + 19 │ interface T { } + · ┬ + · ╰── `T` has already been declared here + 20 │ return undefined; + ╰──── + × Expected `}` but found `Identifier` ╭─[conformance/types/mapped/mappedTypeProperties.ts:9:5] 8 │ [placeType in PlaceType]: void;