diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index bf19b436867fe..e22f034a6c575 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -68,27 +68,40 @@ pub struct TSThisParameter<'a> { #[scope] #[derive(Debug)] #[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)] -#[estree(add_ts_def = " - interface TSEnumBody extends Span { - type: 'TSEnumBody'; - members: TSEnumMember[]; - } -")] pub struct TSEnumDeclaration<'a> { pub span: Span, pub id: BindingIdentifier<'a>, #[scope(enter_before)] - #[estree(rename = "body", via = TSEnumDeclarationBody)] - pub members: Vec<'a, TSEnumMember<'a>>, + pub body: TSEnumBody<'a>, /// `true` for const enums pub r#const: bool, pub declare: bool, pub scope_id: Cell>, } +/// Enum Body +/// +/// The body of a [`TSEnumDeclaration`]. +/// +/// ## Example +/// ```ts +/// enum Foo { A } +/// ^^^^^ +/// enum Bar +/// { B } +/// ^^^^^ +/// ``` +#[ast(visit)] +#[derive(Debug)] +#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)] +pub struct TSEnumBody<'a> { + pub span: Span, + pub members: Vec<'a, TSEnumMember<'a>>, +} + /// Enum Member /// -/// A member property in a [`TSEnumDeclaration`]. +/// A member property in a [`TSEnumBody`]. /// /// ## Example /// ```ts diff --git a/crates/oxc_ast/src/ast_kind_impl.rs b/crates/oxc_ast/src/ast_kind_impl.rs index e4dceea6889d1..6fc523f1c4b05 100644 --- a/crates/oxc_ast/src/ast_kind_impl.rs +++ b/crates/oxc_ast/src/ast_kind_impl.rs @@ -381,7 +381,7 @@ impl AstKind<'_> { Self::TSInstantiationExpression(_) => "TSInstantiationExpression".into(), Self::TSEnumDeclaration(decl) => format!("TSEnumDeclaration({})", &decl.id.name).into(), - + Self::TSEnumBody(_) => "TSEnumBody".into(), Self::TSEnumMember(_) => "TSEnumMember".into(), Self::TSImportEqualsDeclaration(_) => "TSImportEqualsDeclaration".into(), diff --git a/crates/oxc_ast/src/generated/assert_layouts.rs b/crates/oxc_ast/src/generated/assert_layouts.rs index 768445f337105..b5fff75b3c340 100644 --- a/crates/oxc_ast/src/generated/assert_layouts.rs +++ b/crates/oxc_ast/src/generated/assert_layouts.rs @@ -911,14 +911,19 @@ const _: () = { assert!(offset_of!(TSThisParameter, this_span) == 8); assert!(offset_of!(TSThisParameter, type_annotation) == 16); - assert!(size_of::() == 80); + assert!(size_of::() == 88); assert!(align_of::() == 8); assert!(offset_of!(TSEnumDeclaration, span) == 0); assert!(offset_of!(TSEnumDeclaration, id) == 8); - assert!(offset_of!(TSEnumDeclaration, members) == 40); - assert!(offset_of!(TSEnumDeclaration, r#const) == 72); - assert!(offset_of!(TSEnumDeclaration, declare) == 73); - assert!(offset_of!(TSEnumDeclaration, scope_id) == 76); + assert!(offset_of!(TSEnumDeclaration, body) == 40); + assert!(offset_of!(TSEnumDeclaration, r#const) == 80); + assert!(offset_of!(TSEnumDeclaration, declare) == 81); + assert!(offset_of!(TSEnumDeclaration, scope_id) == 84); + + assert!(size_of::() == 40); + assert!(align_of::() == 8); + assert!(offset_of!(TSEnumBody, span) == 0); + assert!(offset_of!(TSEnumBody, members) == 8); assert!(size_of::() == 40); assert!(align_of::() == 8); @@ -2301,14 +2306,19 @@ const _: () = { assert!(offset_of!(TSThisParameter, this_span) == 8); assert!(offset_of!(TSThisParameter, type_annotation) == 16); - assert!(size_of::() == 52); + assert!(size_of::() == 60); assert!(align_of::() == 4); assert!(offset_of!(TSEnumDeclaration, span) == 0); assert!(offset_of!(TSEnumDeclaration, id) == 8); - assert!(offset_of!(TSEnumDeclaration, members) == 28); - assert!(offset_of!(TSEnumDeclaration, r#const) == 44); - assert!(offset_of!(TSEnumDeclaration, declare) == 45); - assert!(offset_of!(TSEnumDeclaration, scope_id) == 48); + assert!(offset_of!(TSEnumDeclaration, body) == 28); + assert!(offset_of!(TSEnumDeclaration, r#const) == 52); + assert!(offset_of!(TSEnumDeclaration, declare) == 53); + assert!(offset_of!(TSEnumDeclaration, scope_id) == 56); + + assert!(size_of::() == 24); + assert!(align_of::() == 4); + assert!(offset_of!(TSEnumBody, span) == 0); + assert!(offset_of!(TSEnumBody, members) == 8); assert!(size_of::() == 24); assert!(align_of::() == 4); diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 66d4787d9a712..ba3890f8cc612 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -4225,7 +4225,7 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `id` - /// * `members` + /// * `body` /// * `const`: `true` for const enums /// * `declare` #[inline] @@ -4233,12 +4233,12 @@ impl<'a> AstBuilder<'a> { self, span: Span, id: BindingIdentifier<'a>, - members: Vec<'a, TSEnumMember<'a>>, + body: TSEnumBody<'a>, r#const: bool, declare: bool, ) -> Declaration<'a> { Declaration::TSEnumDeclaration( - self.alloc_ts_enum_declaration(span, id, members, r#const, declare), + self.alloc_ts_enum_declaration(span, id, body, r#const, declare), ) } @@ -4249,7 +4249,7 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `id` - /// * `members` + /// * `body` /// * `const`: `true` for const enums /// * `declare` /// * `scope_id` @@ -4258,14 +4258,14 @@ impl<'a> AstBuilder<'a> { self, span: Span, id: BindingIdentifier<'a>, - members: Vec<'a, TSEnumMember<'a>>, + body: TSEnumBody<'a>, r#const: bool, declare: bool, scope_id: ScopeId, ) -> Declaration<'a> { Declaration::TSEnumDeclaration( self.alloc_ts_enum_declaration_with_scope_id( - span, id, members, r#const, declare, scope_id, + span, id, body, r#const, declare, scope_id, ), ) } @@ -9642,7 +9642,7 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `id` - /// * `members` + /// * `body` /// * `const`: `true` for const enums /// * `declare` #[inline] @@ -9650,11 +9650,11 @@ impl<'a> AstBuilder<'a> { self, span: Span, id: BindingIdentifier<'a>, - members: Vec<'a, TSEnumMember<'a>>, + body: TSEnumBody<'a>, r#const: bool, declare: bool, ) -> TSEnumDeclaration<'a> { - TSEnumDeclaration { span, id, members, r#const, declare, scope_id: Default::default() } + TSEnumDeclaration { span, id, body, r#const, declare, scope_id: Default::default() } } /// Build a [`TSEnumDeclaration`], and store it in the memory arena. @@ -9665,7 +9665,7 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `id` - /// * `members` + /// * `body` /// * `const`: `true` for const enums /// * `declare` #[inline] @@ -9673,11 +9673,11 @@ impl<'a> AstBuilder<'a> { self, span: Span, id: BindingIdentifier<'a>, - members: Vec<'a, TSEnumMember<'a>>, + body: TSEnumBody<'a>, r#const: bool, declare: bool, ) -> Box<'a, TSEnumDeclaration<'a>> { - Box::new_in(self.ts_enum_declaration(span, id, members, r#const, declare), self.allocator) + Box::new_in(self.ts_enum_declaration(span, id, body, r#const, declare), self.allocator) } /// Build a [`TSEnumDeclaration`] with `scope_id`. @@ -9688,7 +9688,7 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `id` - /// * `members` + /// * `body` /// * `const`: `true` for const enums /// * `declare` /// * `scope_id` @@ -9697,19 +9697,12 @@ impl<'a> AstBuilder<'a> { self, span: Span, id: BindingIdentifier<'a>, - members: Vec<'a, TSEnumMember<'a>>, + body: TSEnumBody<'a>, r#const: bool, declare: bool, scope_id: ScopeId, ) -> TSEnumDeclaration<'a> { - TSEnumDeclaration { - span, - id, - members, - r#const, - declare, - scope_id: Cell::new(Some(scope_id)), - } + TSEnumDeclaration { span, id, body, r#const, declare, scope_id: Cell::new(Some(scope_id)) } } /// Build a [`TSEnumDeclaration`] with `scope_id`, and store it in the memory arena. @@ -9720,7 +9713,7 @@ impl<'a> AstBuilder<'a> { /// ## Parameters /// * `span`: The [`Span`] covering this node /// * `id` - /// * `members` + /// * `body` /// * `const`: `true` for const enums /// * `declare` /// * `scope_id` @@ -9729,17 +9722,27 @@ impl<'a> AstBuilder<'a> { self, span: Span, id: BindingIdentifier<'a>, - members: Vec<'a, TSEnumMember<'a>>, + body: TSEnumBody<'a>, r#const: bool, declare: bool, scope_id: ScopeId, ) -> Box<'a, TSEnumDeclaration<'a>> { Box::new_in( - self.ts_enum_declaration_with_scope_id(span, id, members, r#const, declare, scope_id), + self.ts_enum_declaration_with_scope_id(span, id, body, r#const, declare, scope_id), self.allocator, ) } + /// Build a [`TSEnumBody`]. + /// + /// ## Parameters + /// * `span`: The [`Span`] covering this node + /// * `members` + #[inline] + pub fn ts_enum_body(self, span: Span, members: Vec<'a, TSEnumMember<'a>>) -> TSEnumBody<'a> { + TSEnumBody { span, members } + } + /// Build a [`TSEnumMember`]. /// /// ## Parameters diff --git a/crates/oxc_ast/src/generated/ast_kind.rs b/crates/oxc_ast/src/generated/ast_kind.rs index 50f8802d4e41c..9f8901f7a139c 100644 --- a/crates/oxc_ast/src/generated/ast_kind.rs +++ b/crates/oxc_ast/src/generated/ast_kind.rs @@ -125,60 +125,61 @@ pub enum AstType { JSXText = 109, TSThisParameter = 110, TSEnumDeclaration = 111, - TSEnumMember = 112, - TSTypeAnnotation = 113, - TSLiteralType = 114, - TSConditionalType = 115, - TSUnionType = 116, - TSIntersectionType = 117, - TSParenthesizedType = 118, - TSIndexedAccessType = 119, - TSNamedTupleMember = 120, - TSAnyKeyword = 121, - TSStringKeyword = 122, - TSBooleanKeyword = 123, - TSNumberKeyword = 124, - TSNeverKeyword = 125, - TSIntrinsicKeyword = 126, - TSUnknownKeyword = 127, - TSNullKeyword = 128, - TSUndefinedKeyword = 129, - TSVoidKeyword = 130, - TSSymbolKeyword = 131, - TSThisType = 132, - TSObjectKeyword = 133, - TSBigIntKeyword = 134, - TSTypeReference = 135, - TSTypeName = 136, - TSQualifiedName = 137, - TSTypeParameterInstantiation = 138, - TSTypeParameter = 139, - TSTypeParameterDeclaration = 140, - TSTypeAliasDeclaration = 141, - TSClassImplements = 142, - TSInterfaceDeclaration = 143, - TSPropertySignature = 144, - TSMethodSignature = 145, - TSConstructSignatureDeclaration = 146, - TSInterfaceHeritage = 147, - TSModuleDeclaration = 148, - TSModuleBlock = 149, - TSTypeLiteral = 150, - TSInferType = 151, - TSTypeQuery = 152, - TSImportType = 153, - TSMappedType = 154, - TSTemplateLiteralType = 155, - TSAsExpression = 156, - TSSatisfiesExpression = 157, - TSTypeAssertion = 158, - TSImportEqualsDeclaration = 159, - TSModuleReference = 160, - TSExternalModuleReference = 161, - TSNonNullExpression = 162, - Decorator = 163, - TSExportAssignment = 164, - TSInstantiationExpression = 165, + TSEnumBody = 112, + TSEnumMember = 113, + TSTypeAnnotation = 114, + TSLiteralType = 115, + TSConditionalType = 116, + TSUnionType = 117, + TSIntersectionType = 118, + TSParenthesizedType = 119, + TSIndexedAccessType = 120, + TSNamedTupleMember = 121, + TSAnyKeyword = 122, + TSStringKeyword = 123, + TSBooleanKeyword = 124, + TSNumberKeyword = 125, + TSNeverKeyword = 126, + TSIntrinsicKeyword = 127, + TSUnknownKeyword = 128, + TSNullKeyword = 129, + TSUndefinedKeyword = 130, + TSVoidKeyword = 131, + TSSymbolKeyword = 132, + TSThisType = 133, + TSObjectKeyword = 134, + TSBigIntKeyword = 135, + TSTypeReference = 136, + TSTypeName = 137, + TSQualifiedName = 138, + TSTypeParameterInstantiation = 139, + TSTypeParameter = 140, + TSTypeParameterDeclaration = 141, + TSTypeAliasDeclaration = 142, + TSClassImplements = 143, + TSInterfaceDeclaration = 144, + TSPropertySignature = 145, + TSMethodSignature = 146, + TSConstructSignatureDeclaration = 147, + TSInterfaceHeritage = 148, + TSModuleDeclaration = 149, + TSModuleBlock = 150, + TSTypeLiteral = 151, + TSInferType = 152, + TSTypeQuery = 153, + TSImportType = 154, + TSMappedType = 155, + TSTemplateLiteralType = 156, + TSAsExpression = 157, + TSSatisfiesExpression = 158, + TSTypeAssertion = 159, + TSImportEqualsDeclaration = 160, + TSModuleReference = 161, + TSExternalModuleReference = 162, + TSNonNullExpression = 163, + Decorator = 164, + TSExportAssignment = 165, + TSInstantiationExpression = 166, } /// Untyped AST Node Kind @@ -305,6 +306,7 @@ pub enum AstKind<'a> { JSXText(&'a JSXText<'a>) = AstType::JSXText as u8, TSThisParameter(&'a TSThisParameter<'a>) = AstType::TSThisParameter as u8, TSEnumDeclaration(&'a TSEnumDeclaration<'a>) = AstType::TSEnumDeclaration as u8, + TSEnumBody(&'a TSEnumBody<'a>) = AstType::TSEnumBody as u8, TSEnumMember(&'a TSEnumMember<'a>) = AstType::TSEnumMember as u8, TSTypeAnnotation(&'a TSTypeAnnotation<'a>) = AstType::TSTypeAnnotation as u8, TSLiteralType(&'a TSLiteralType<'a>) = AstType::TSLiteralType as u8, @@ -494,6 +496,7 @@ impl GetSpan for AstKind<'_> { Self::JSXText(it) => it.span(), Self::TSThisParameter(it) => it.span(), Self::TSEnumDeclaration(it) => it.span(), + Self::TSEnumBody(it) => it.span(), Self::TSEnumMember(it) => it.span(), Self::TSTypeAnnotation(it) => it.span(), Self::TSLiteralType(it) => it.span(), @@ -1113,6 +1116,11 @@ impl<'a> AstKind<'a> { if let Self::TSEnumDeclaration(v) = self { Some(v) } else { None } } + #[inline] + pub fn as_ts_enum_body(self) -> Option<&'a TSEnumBody<'a>> { + if let Self::TSEnumBody(v) = self { Some(v) } else { None } + } + #[inline] pub fn as_ts_enum_member(self) -> Option<&'a TSEnumMember<'a>> { if let Self::TSEnumMember(v) = self { Some(v) } else { None } diff --git a/crates/oxc_ast/src/generated/derive_clone_in.rs b/crates/oxc_ast/src/generated/derive_clone_in.rs index 845165b04172e..3572998d3a85c 100644 --- a/crates/oxc_ast/src/generated/derive_clone_in.rs +++ b/crates/oxc_ast/src/generated/derive_clone_in.rs @@ -5702,7 +5702,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSEnumDeclaration<'_> { TSEnumDeclaration { span: CloneIn::clone_in(&self.span, allocator), id: CloneIn::clone_in(&self.id, allocator), - members: CloneIn::clone_in(&self.members, allocator), + body: CloneIn::clone_in(&self.body, allocator), r#const: CloneIn::clone_in(&self.r#const, allocator), declare: CloneIn::clone_in(&self.declare, allocator), scope_id: Default::default(), @@ -5713,7 +5713,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSEnumDeclaration<'_> { TSEnumDeclaration { span: CloneIn::clone_in_with_semantic_ids(&self.span, allocator), id: CloneIn::clone_in_with_semantic_ids(&self.id, allocator), - members: CloneIn::clone_in_with_semantic_ids(&self.members, allocator), + body: CloneIn::clone_in_with_semantic_ids(&self.body, allocator), r#const: CloneIn::clone_in_with_semantic_ids(&self.r#const, allocator), declare: CloneIn::clone_in_with_semantic_ids(&self.declare, allocator), scope_id: CloneIn::clone_in_with_semantic_ids(&self.scope_id, allocator), @@ -5721,6 +5721,24 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSEnumDeclaration<'_> { } } +impl<'new_alloc> CloneIn<'new_alloc> for TSEnumBody<'_> { + type Cloned = TSEnumBody<'new_alloc>; + + fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSEnumBody { + span: CloneIn::clone_in(&self.span, allocator), + members: CloneIn::clone_in(&self.members, allocator), + } + } + + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSEnumBody { + span: CloneIn::clone_in_with_semantic_ids(&self.span, allocator), + members: CloneIn::clone_in_with_semantic_ids(&self.members, allocator), + } + } +} + impl<'new_alloc> CloneIn<'new_alloc> for TSEnumMember<'_> { type Cloned = TSEnumMember<'new_alloc>; diff --git a/crates/oxc_ast/src/generated/derive_content_eq.rs b/crates/oxc_ast/src/generated/derive_content_eq.rs index 58d663134a7d8..5b379461ccbe5 100644 --- a/crates/oxc_ast/src/generated/derive_content_eq.rs +++ b/crates/oxc_ast/src/generated/derive_content_eq.rs @@ -1730,12 +1730,18 @@ impl ContentEq for TSThisParameter<'_> { impl ContentEq for TSEnumDeclaration<'_> { fn content_eq(&self, other: &Self) -> bool { ContentEq::content_eq(&self.id, &other.id) - && ContentEq::content_eq(&self.members, &other.members) + && ContentEq::content_eq(&self.body, &other.body) && ContentEq::content_eq(&self.r#const, &other.r#const) && ContentEq::content_eq(&self.declare, &other.declare) } } +impl ContentEq for TSEnumBody<'_> { + fn content_eq(&self, other: &Self) -> bool { + ContentEq::content_eq(&self.members, &other.members) + } +} + impl ContentEq for TSEnumMember<'_> { fn content_eq(&self, other: &Self) -> bool { ContentEq::content_eq(&self.id, &other.id) diff --git a/crates/oxc_ast/src/generated/derive_dummy.rs b/crates/oxc_ast/src/generated/derive_dummy.rs index e3b39eafa0288..f0f550bded168 100644 --- a/crates/oxc_ast/src/generated/derive_dummy.rs +++ b/crates/oxc_ast/src/generated/derive_dummy.rs @@ -1897,7 +1897,7 @@ impl<'a> Dummy<'a> for TSEnumDeclaration<'a> { Self { span: Dummy::dummy(allocator), id: Dummy::dummy(allocator), - members: Dummy::dummy(allocator), + body: Dummy::dummy(allocator), r#const: Dummy::dummy(allocator), declare: Dummy::dummy(allocator), scope_id: Dummy::dummy(allocator), @@ -1905,6 +1905,15 @@ impl<'a> Dummy<'a> for TSEnumDeclaration<'a> { } } +impl<'a> Dummy<'a> for TSEnumBody<'a> { + /// Create a dummy [`TSEnumBody`]. + /// + /// Does not allocate any data into arena. + fn dummy(allocator: &'a Allocator) -> Self { + Self { span: Dummy::dummy(allocator), members: Dummy::dummy(allocator) } + } +} + impl<'a> Dummy<'a> for TSEnumMember<'a> { /// Create a dummy [`TSEnumMember`]. /// diff --git a/crates/oxc_ast/src/generated/derive_estree.rs b/crates/oxc_ast/src/generated/derive_estree.rs index 122843c461b0b..c06f1ff4aa718 100644 --- a/crates/oxc_ast/src/generated/derive_estree.rs +++ b/crates/oxc_ast/src/generated/derive_estree.rs @@ -2285,13 +2285,24 @@ impl ESTree for TSEnumDeclaration<'_> { state.serialize_field("start", &self.span.start); state.serialize_field("end", &self.span.end); state.serialize_field("id", &self.id); - state.serialize_field("body", &crate::serialize::TSEnumDeclarationBody(self)); + state.serialize_field("body", &self.body); state.serialize_field("const", &self.r#const); state.serialize_field("declare", &self.declare); state.end(); } } +impl ESTree for TSEnumBody<'_> { + fn serialize(&self, serializer: S) { + let mut state = serializer.serialize_struct(); + state.serialize_field("type", &JsonSafeString("TSEnumBody")); + state.serialize_field("start", &self.span.start); + state.serialize_field("end", &self.span.end); + state.serialize_field("members", &self.members); + state.end(); + } +} + impl ESTree for TSEnumMember<'_> { fn serialize(&self, serializer: S) { let mut state = serializer.serialize_struct(); diff --git a/crates/oxc_ast/src/generated/derive_get_span.rs b/crates/oxc_ast/src/generated/derive_get_span.rs index d183aadebceff..9a546961eb8ff 100644 --- a/crates/oxc_ast/src/generated/derive_get_span.rs +++ b/crates/oxc_ast/src/generated/derive_get_span.rs @@ -1488,6 +1488,13 @@ impl GetSpan for TSEnumDeclaration<'_> { } } +impl GetSpan for TSEnumBody<'_> { + #[inline] + fn span(&self) -> Span { + self.span + } +} + impl GetSpan for TSEnumMember<'_> { #[inline] fn span(&self) -> Span { diff --git a/crates/oxc_ast/src/generated/derive_get_span_mut.rs b/crates/oxc_ast/src/generated/derive_get_span_mut.rs index e9181bbd21218..b094322fc5fb8 100644 --- a/crates/oxc_ast/src/generated/derive_get_span_mut.rs +++ b/crates/oxc_ast/src/generated/derive_get_span_mut.rs @@ -1488,6 +1488,13 @@ impl GetSpanMut for TSEnumDeclaration<'_> { } } +impl GetSpanMut for TSEnumBody<'_> { + #[inline] + fn span_mut(&mut self) -> &mut Span { + &mut self.span + } +} + impl GetSpanMut for TSEnumMember<'_> { #[inline] fn span_mut(&mut self) -> &mut Span { diff --git a/crates/oxc_ast/src/generated/derive_take_in.rs b/crates/oxc_ast/src/generated/derive_take_in.rs index 1080a18ffcdc6..48a458c9130c2 100644 --- a/crates/oxc_ast/src/generated/derive_take_in.rs +++ b/crates/oxc_ast/src/generated/derive_take_in.rs @@ -310,6 +310,8 @@ impl<'a> TakeIn<'a> for TSThisParameter<'a> {} impl<'a> TakeIn<'a> for TSEnumDeclaration<'a> {} +impl<'a> TakeIn<'a> for TSEnumBody<'a> {} + impl<'a> TakeIn<'a> for TSEnumMember<'a> {} impl<'a> TakeIn<'a> for TSEnumMemberName<'a> {} diff --git a/crates/oxc_ast/src/serialize.rs b/crates/oxc_ast/src/serialize.rs index b7d330400587f..72878c53fa9c6 100644 --- a/crates/oxc_ast/src/serialize.rs +++ b/crates/oxc_ast/src/serialize.rs @@ -1001,41 +1001,6 @@ impl ESTree for TSModuleDeclarationGlobal<'_, '_> { } } -/// Serializer for `body` field of `TSEnumDeclaration`. -/// This field is derived from `members` field. -/// -/// `Span` indicates within braces `{ ... }`. -/// ```ignore -/// enum Foo { ... } -/// | | TSEnumDeclaration.span -/// | | TSEnumBody.span -/// ^^ id_end + 1 for space -/// ``` -/// NOTE: + 1 is not sufficient for all cases, e.g. `enum Foo{}`, `enum Foo {}`, etc. -/// We may need to reconsider adding `TSEnumBody` as Rust AST. -#[ast_meta] -#[estree( - ts_type = "TSEnumBody", - raw_deser = " - const tsEnumDeclMembers = DESER[Vec](POS_OFFSET.members); - const bodyStart = THIS.id.end + 1; - {type: 'TSEnumBody', start: bodyStart, end: THIS.end, members: tsEnumDeclMembers} - " -)] -pub struct TSEnumDeclarationBody<'a, 'b>(pub &'b TSEnumDeclaration<'a>); - -impl ESTree for TSEnumDeclarationBody<'_, '_> { - fn serialize(&self, serializer: S) { - let mut state = serializer.serialize_struct(); - state.serialize_field("type", &JsonSafeString("TSEnumBody")); - let body_start = self.0.id.span.end + 1; - state.serialize_field("start", &body_start); - state.serialize_field("end", &self.0.span.end); - state.serialize_field("members", &self.0.members); - state.end(); - } -} - // -------------------- // Comments // -------------------- diff --git a/crates/oxc_ast_visit/src/generated/utf8_to_utf16_converter.rs b/crates/oxc_ast_visit/src/generated/utf8_to_utf16_converter.rs index a911a9bb7e88e..209af92c4f091 100644 --- a/crates/oxc_ast_visit/src/generated/utf8_to_utf16_converter.rs +++ b/crates/oxc_ast_visit/src/generated/utf8_to_utf16_converter.rs @@ -674,6 +674,12 @@ impl<'a> VisitMut<'a> for Utf8ToUtf16Converter<'_> { self.convert_offset(&mut it.span.end); } + fn visit_ts_enum_body(&mut self, it: &mut TSEnumBody<'a>) { + self.convert_offset(&mut it.span.start); + walk_mut::walk_ts_enum_body(self, it); + self.convert_offset(&mut it.span.end); + } + fn visit_ts_enum_member(&mut self, it: &mut TSEnumMember<'a>) { self.convert_offset(&mut it.span.start); walk_mut::walk_ts_enum_member(self, it); diff --git a/crates/oxc_ast_visit/src/generated/visit.rs b/crates/oxc_ast_visit/src/generated/visit.rs index 4bd619d2686c2..5809085545242 100644 --- a/crates/oxc_ast_visit/src/generated/visit.rs +++ b/crates/oxc_ast_visit/src/generated/visit.rs @@ -780,6 +780,11 @@ pub trait Visit<'a>: Sized { walk_ts_enum_declaration(self, it); } + #[inline] + fn visit_ts_enum_body(&mut self, it: &TSEnumBody<'a>) { + walk_ts_enum_body(self, it); + } + #[inline] fn visit_ts_enum_member(&mut self, it: &TSEnumMember<'a>) { walk_ts_enum_member(self, it); @@ -3174,11 +3179,20 @@ pub mod walk { visitor.visit_span(&it.span); visitor.visit_binding_identifier(&it.id); visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); - visitor.visit_ts_enum_members(&it.members); + visitor.visit_ts_enum_body(&it.body); visitor.leave_scope(); visitor.leave_node(kind); } + #[inline] + pub fn walk_ts_enum_body<'a, V: Visit<'a>>(visitor: &mut V, it: &TSEnumBody<'a>) { + let kind = AstKind::TSEnumBody(visitor.alloc(it)); + visitor.enter_node(kind); + visitor.visit_span(&it.span); + visitor.visit_ts_enum_members(&it.members); + visitor.leave_node(kind); + } + #[inline] pub fn walk_ts_enum_member<'a, V: Visit<'a>>(visitor: &mut V, it: &TSEnumMember<'a>) { let kind = AstKind::TSEnumMember(visitor.alloc(it)); diff --git a/crates/oxc_ast_visit/src/generated/visit_mut.rs b/crates/oxc_ast_visit/src/generated/visit_mut.rs index c0c53a14bd6cf..c625a57f9a2eb 100644 --- a/crates/oxc_ast_visit/src/generated/visit_mut.rs +++ b/crates/oxc_ast_visit/src/generated/visit_mut.rs @@ -772,6 +772,11 @@ pub trait VisitMut<'a>: Sized { walk_ts_enum_declaration(self, it); } + #[inline] + fn visit_ts_enum_body(&mut self, it: &mut TSEnumBody<'a>) { + walk_ts_enum_body(self, it); + } + #[inline] fn visit_ts_enum_member(&mut self, it: &mut TSEnumMember<'a>) { walk_ts_enum_member(self, it); @@ -3329,11 +3334,20 @@ pub mod walk_mut { visitor.visit_span(&mut it.span); visitor.visit_binding_identifier(&mut it.id); visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); - visitor.visit_ts_enum_members(&mut it.members); + visitor.visit_ts_enum_body(&mut it.body); visitor.leave_scope(); visitor.leave_node(kind); } + #[inline] + pub fn walk_ts_enum_body<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut TSEnumBody<'a>) { + let kind = AstType::TSEnumBody; + visitor.enter_node(kind); + visitor.visit_span(&mut it.span); + visitor.visit_ts_enum_members(&mut it.members); + visitor.leave_node(kind); + } + #[inline] pub fn walk_ts_enum_member<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut TSEnumMember<'a>) { let kind = AstType::TSEnumMember; diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 9b2ad30e51a97..c99237c1774b2 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -3733,6 +3733,12 @@ impl Gen for TSEnumDeclaration<'_> { p.print_str("enum "); self.id.print(p, ctx); p.print_space_before_identifier(); + self.body.print(p, ctx); + } +} + +impl Gen for TSEnumBody<'_> { + fn r#gen(&self, p: &mut Codegen, ctx: Context) { p.print_curly_braces(self.span, self.members.is_empty(), |p| { for (index, member) in self.members.iter().enumerate() { p.print_leading_comments(member.span().start); diff --git a/crates/oxc_formatter/src/generated/format.rs b/crates/oxc_formatter/src/generated/format.rs index a78311ac4b6b3..873608a06e193 100644 --- a/crates/oxc_formatter/src/generated/format.rs +++ b/crates/oxc_formatter/src/generated/format.rs @@ -1233,6 +1233,15 @@ impl<'a> Format<'a> for TSEnumDeclaration<'a> { } } +impl<'a> Format<'a> for TSEnumBody<'a> { + fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { + f.state_mut().stack.push(AstKind::TSEnumBody(hack(self))); + let result = self.write(f); + unsafe { f.state_mut().stack.pop_unchecked() }; + result + } +} + impl<'a> Format<'a> for TSEnumMember<'a> { fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { f.state_mut().stack.push(AstKind::TSEnumMember(hack(self))); diff --git a/crates/oxc_formatter/src/write/mod.rs b/crates/oxc_formatter/src/write/mod.rs index af911e0841438..62ff31eec9126 100644 --- a/crates/oxc_formatter/src/write/mod.rs +++ b/crates/oxc_formatter/src/write/mod.rs @@ -925,6 +925,12 @@ impl<'a> FormatWrite<'a> for TSEnumDeclaration<'a> { } } +impl<'a> FormatWrite<'a> for TSEnumBody<'a> { + fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { + Ok(()) + } +} + impl<'a> FormatWrite<'a> for TSEnumMember<'a> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { Ok(()) diff --git a/crates/oxc_isolated_declarations/src/enum.rs b/crates/oxc_isolated_declarations/src/enum.rs index e8f4a83a21198..60c50a117d49e 100644 --- a/crates/oxc_isolated_declarations/src/enum.rs +++ b/crates/oxc_isolated_declarations/src/enum.rs @@ -25,7 +25,7 @@ impl<'a> IsolatedDeclarations<'a> { let mut members = self.ast.vec(); let mut prev_initializer_value = Some(ConstantValue::Number(-1.0)); let mut prev_members = FxHashMap::default(); - for member in &decl.members { + for member in &decl.body.members { let value = if let Some(initializer) = &member.initializer { let computed_value = self.computed_constant_value(initializer, &decl.id.name, &prev_members); @@ -87,7 +87,7 @@ impl<'a> IsolatedDeclarations<'a> { Some(self.ast.declaration_ts_enum( decl.span, decl.id.clone_in(self.ast.allocator), - members, + self.ast.ts_enum_body(decl.body.span, members), decl.r#const, self.is_declare(), )) diff --git a/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs b/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs index dea1ef8839819..835468751b099 100644 --- a/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs +++ b/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs @@ -89,7 +89,7 @@ declare_oxc_lint!( impl Rule for NoDuplicateEnumValues { #[expect(clippy::float_cmp)] fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - let AstKind::TSEnumDeclaration(enum_body) = node.kind() else { + let AstKind::TSEnumBody(enum_body) = node.kind() else { return; }; let mut seen_number_values: Vec<(f64, Span)> = vec![]; diff --git a/crates/oxc_linter/src/rules/typescript/prefer_enum_initializers.rs b/crates/oxc_linter/src/rules/typescript/prefer_enum_initializers.rs index e209b5492f2ed..b7d98e6fe5ef8 100644 --- a/crates/oxc_linter/src/rules/typescript/prefer_enum_initializers.rs +++ b/crates/oxc_linter/src/rules/typescript/prefer_enum_initializers.rs @@ -47,11 +47,11 @@ declare_oxc_lint!( impl Rule for PreferEnumInitializers { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - let AstKind::TSEnumDeclaration(decl) = node.kind() else { + let AstKind::TSEnumBody(enum_body) = node.kind() else { return; }; - for (index, member) in decl.members.iter().enumerate() { + for (index, member) in enum_body.members.iter().enumerate() { if member.initializer.is_none() { if let TSEnumMemberName::Identifier(i) = &member.id { ctx.diagnostic(prefer_enum_initializers_diagnostic( diff --git a/crates/oxc_linter/src/rules/unicorn/no_invalid_fetch_options.rs b/crates/oxc_linter/src/rules/unicorn/no_invalid_fetch_options.rs index 931c3134239e7..b9f2222918150 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_invalid_fetch_options.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_invalid_fetch_options.rs @@ -135,7 +135,7 @@ fn is_invalid_fetch_options<'a>( let enum_member_res: Option = match decl.kind() { AstKind::TSEnumDeclaration(enum_decl) => { let member_string_lit: Option = - enum_decl.members.iter().find_map(|m| { + enum_decl.body.members.iter().find_map(|m| { if let Some(Expression::StringLiteral(str_lit)) = &m.initializer { diff --git a/crates/oxc_parser/src/ts/statement.rs b/crates/oxc_parser/src/ts/statement.rs index c2c86a3163152..c74c8438b1a59 100644 --- a/crates/oxc_parser/src/ts/statement.rs +++ b/crates/oxc_parser/src/ts/statement.rs @@ -25,14 +25,7 @@ impl<'a> ParserImpl<'a> { ) -> Result> { self.bump_any(); // bump `enum` let id = self.parse_binding_identifier()?; - self.expect(Kind::LCurly)?; - let members = self.parse_delimited_list( - Kind::RCurly, - Kind::Comma, - /* trailing_separator */ true, - Self::parse_ts_enum_member, - )?; - self.expect(Kind::RCurly)?; + let body = self.parse_ts_enum_body()?; let span = self.end_span(span); self.verify_modifiers( modifiers, @@ -42,12 +35,25 @@ impl<'a> ParserImpl<'a> { Ok(self.ast.declaration_ts_enum( span, id, - members, + body, modifiers.contains_const(), modifiers.contains_declare(), )) } + pub(crate) fn parse_ts_enum_body(&mut self) -> Result> { + let span = self.start_span(); + self.expect(Kind::LCurly)?; + let members = self.parse_delimited_list( + Kind::RCurly, + Kind::Comma, + /* trailing_separator */ true, + Self::parse_ts_enum_member, + )?; + self.expect(Kind::RCurly)?; + Ok(self.ast.ts_enum_body(self.end_span(span), members)) + } + pub(crate) fn parse_ts_enum_member(&mut self) -> Result> { let span = self.start_span(); let id = self.parse_ts_enum_member_name()?; diff --git a/crates/oxc_semantic/src/checker/typescript.rs b/crates/oxc_semantic/src/checker/typescript.rs index 09fbf03d6e774..fac7282f1c296 100644 --- a/crates/oxc_semantic/src/checker/typescript.rs +++ b/crates/oxc_semantic/src/checker/typescript.rs @@ -284,7 +284,7 @@ fn enum_member_must_have_initializer(span: Span) -> OxcDiagnostic { pub fn check_ts_enum_declaration<'a>(decl: &TSEnumDeclaration<'a>, ctx: &SemanticBuilder<'a>) { let mut need_initializer = false; - decl.members.iter().for_each(|member| { + decl.body.members.iter().for_each(|member| { #[expect(clippy::unnested_or_patterns)] if let Some(initializer) = &member.initializer { need_initializer = !matches!( diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/external-ref.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/external-ref.snap index 1c267c5377021..76f6debdf830a 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/external-ref.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/external-ref.snap @@ -35,7 +35,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/externa "flags": "ReferenceFlags(Read)", "id": 0, "name": "Foo", - "node_id": 8 + "node_id": 9 } ] } diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/literal-member-ref.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/literal-member-ref.snap index b6fd9caa84365..bface78dad713 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/literal-member-ref.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/literal-member-ref.snap @@ -21,7 +21,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/literal "flags": "ReferenceFlags(Read)", "id": 0, "name": "a", - "node_id": 8 + "node_id": 9 } ] }, diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/member-ref.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/member-ref.snap index 9f8dac8d5ff60..d64f34648ec32 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/member-ref.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/member-ref.snap @@ -21,7 +21,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/member- "flags": "ReferenceFlags(Read)", "id": 0, "name": "a", - "node_id": 8 + "node_id": 9 } ] }, diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/self-ref.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/self-ref.snap index 892811c07130d..c29901e953a52 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/self-ref.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/self-ref.snap @@ -42,7 +42,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/ts-enum/self-re "flags": "ReferenceFlags(Read)", "id": 0, "name": "Foo", - "node_id": 9 + "node_id": 10 } ] } diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/method-computed-name2.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/method-computed-name2.snap index dbc449d5dba01..76b05755a15f9 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/method-computed-name2.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/method-computed-name2.snap @@ -50,7 +50,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "flags": "ReferenceFlags(Read)", "id": 0, "name": "Foo", - "node_id": 11 + "node_id": 12 } ] }, diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/property-computed-name2.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/property-computed-name2.snap index a7fadc9a650fd..ac236e3c93b3f 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/property-computed-name2.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/signatures/property-computed-name2.snap @@ -42,7 +42,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "flags": "ReferenceFlags(Type)", "id": 0, "name": "Foo", - "node_id": 11 + "node_id": 12 } ] }, diff --git a/crates/oxc_semantic/tests/integration/scopes.rs b/crates/oxc_semantic/tests/integration/scopes.rs index 26fc5d997589a..113b43af3dad2 100644 --- a/crates/oxc_semantic/tests/integration/scopes.rs +++ b/crates/oxc_semantic/tests/integration/scopes.rs @@ -205,7 +205,7 @@ fn test_enums() { enum_decl_scope_id, "Enum declaration nodes should contain the scope ID they create, not the scope ID they're created in." ); - assert_eq!(enum_decl.members.len(), 3); + assert_eq!(enum_decl.body.members.len(), 3); } #[test] diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index d39aeefb7c360..80b5486d88801 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -98,15 +98,19 @@ impl<'a> TypeScriptEnum<'a> { NONE, ); - let has_potential_side_effect = decl.members.iter().any(|member| { + let has_potential_side_effect = decl.body.members.iter().any(|member| { matches!( member.initializer, Some(Expression::NewExpression(_) | Expression::CallExpression(_)) ) }); - let statements = - self.transform_ts_enum_members(decl.scope_id(), &mut decl.members, ¶m_binding, ctx); + let statements = self.transform_ts_enum_members( + decl.scope_id(), + &mut decl.body.members, + ¶m_binding, + ctx, + ); let body = ast.alloc_function_body(decl.span, ast.vec(), statements); let callee = ctx.ast.expression_function_with_scope_id_and_pure( SPAN, diff --git a/crates/oxc_traverse/src/generated/ancestor.rs b/crates/oxc_traverse/src/generated/ancestor.rs index ccc4d76a6cc88..31f3954619ce7 100644 --- a/crates/oxc_traverse/src/generated/ancestor.rs +++ b/crates/oxc_traverse/src/generated/ancestor.rs @@ -212,108 +212,109 @@ pub(crate) enum AncestorType { JSXSpreadChildExpression = 189, TSThisParameterTypeAnnotation = 190, TSEnumDeclarationId = 191, - TSEnumDeclarationMembers = 192, - TSEnumMemberId = 193, - TSEnumMemberInitializer = 194, - TSTypeAnnotationTypeAnnotation = 195, - TSLiteralTypeLiteral = 196, - TSConditionalTypeCheckType = 197, - TSConditionalTypeExtendsType = 198, - TSConditionalTypeTrueType = 199, - TSConditionalTypeFalseType = 200, - TSUnionTypeTypes = 201, - TSIntersectionTypeTypes = 202, - TSParenthesizedTypeTypeAnnotation = 203, - TSTypeOperatorTypeAnnotation = 204, - TSArrayTypeElementType = 205, - TSIndexedAccessTypeObjectType = 206, - TSIndexedAccessTypeIndexType = 207, - TSTupleTypeElementTypes = 208, - TSNamedTupleMemberElementType = 209, - TSNamedTupleMemberLabel = 210, - TSOptionalTypeTypeAnnotation = 211, - TSRestTypeTypeAnnotation = 212, - TSTypeReferenceTypeName = 213, - TSTypeReferenceTypeArguments = 214, - TSQualifiedNameLeft = 215, - TSQualifiedNameRight = 216, - TSTypeParameterInstantiationParams = 217, - TSTypeParameterName = 218, - TSTypeParameterConstraint = 219, - TSTypeParameterDefault = 220, - TSTypeParameterDeclarationParams = 221, - TSTypeAliasDeclarationId = 222, - TSTypeAliasDeclarationTypeParameters = 223, - TSTypeAliasDeclarationTypeAnnotation = 224, - TSClassImplementsExpression = 225, - TSClassImplementsTypeArguments = 226, - TSInterfaceDeclarationId = 227, - TSInterfaceDeclarationExtends = 228, - TSInterfaceDeclarationTypeParameters = 229, - TSInterfaceDeclarationBody = 230, - TSInterfaceBodyBody = 231, - TSPropertySignatureKey = 232, - TSPropertySignatureTypeAnnotation = 233, - TSIndexSignatureParameters = 234, - TSIndexSignatureTypeAnnotation = 235, - TSCallSignatureDeclarationTypeParameters = 236, - TSCallSignatureDeclarationThisParam = 237, - TSCallSignatureDeclarationParams = 238, - TSCallSignatureDeclarationReturnType = 239, - TSMethodSignatureKey = 240, - TSMethodSignatureTypeParameters = 241, - TSMethodSignatureThisParam = 242, - TSMethodSignatureParams = 243, - TSMethodSignatureReturnType = 244, - TSConstructSignatureDeclarationTypeParameters = 245, - TSConstructSignatureDeclarationParams = 246, - TSConstructSignatureDeclarationReturnType = 247, - TSIndexSignatureNameTypeAnnotation = 248, - TSInterfaceHeritageExpression = 249, - TSInterfaceHeritageTypeArguments = 250, - TSTypePredicateParameterName = 251, - TSTypePredicateTypeAnnotation = 252, - TSModuleDeclarationId = 253, - TSModuleDeclarationBody = 254, - TSModuleBlockDirectives = 255, - TSModuleBlockBody = 256, - TSTypeLiteralMembers = 257, - TSInferTypeTypeParameter = 258, - TSTypeQueryExprName = 259, - TSTypeQueryTypeArguments = 260, - TSImportTypeArgument = 261, - TSImportTypeOptions = 262, - TSImportTypeQualifier = 263, - TSImportTypeTypeArguments = 264, - TSFunctionTypeTypeParameters = 265, - TSFunctionTypeThisParam = 266, - TSFunctionTypeParams = 267, - TSFunctionTypeReturnType = 268, - TSConstructorTypeTypeParameters = 269, - TSConstructorTypeParams = 270, - TSConstructorTypeReturnType = 271, - TSMappedTypeTypeParameter = 272, - TSMappedTypeNameType = 273, - TSMappedTypeTypeAnnotation = 274, - TSTemplateLiteralTypeQuasis = 275, - TSTemplateLiteralTypeTypes = 276, - TSAsExpressionExpression = 277, - TSAsExpressionTypeAnnotation = 278, - TSSatisfiesExpressionExpression = 279, - TSSatisfiesExpressionTypeAnnotation = 280, - TSTypeAssertionExpression = 281, - TSTypeAssertionTypeAnnotation = 282, - TSImportEqualsDeclarationId = 283, - TSImportEqualsDeclarationModuleReference = 284, - TSExternalModuleReferenceExpression = 285, - TSNonNullExpressionExpression = 286, - DecoratorExpression = 287, - TSExportAssignmentExpression = 288, - TSNamespaceExportDeclarationId = 289, - TSInstantiationExpressionExpression = 290, - TSInstantiationExpressionTypeArguments = 291, - JSDocNullableTypeTypeAnnotation = 292, - JSDocNonNullableTypeTypeAnnotation = 293, + TSEnumDeclarationBody = 192, + TSEnumBodyMembers = 193, + TSEnumMemberId = 194, + TSEnumMemberInitializer = 195, + TSTypeAnnotationTypeAnnotation = 196, + TSLiteralTypeLiteral = 197, + TSConditionalTypeCheckType = 198, + TSConditionalTypeExtendsType = 199, + TSConditionalTypeTrueType = 200, + TSConditionalTypeFalseType = 201, + TSUnionTypeTypes = 202, + TSIntersectionTypeTypes = 203, + TSParenthesizedTypeTypeAnnotation = 204, + TSTypeOperatorTypeAnnotation = 205, + TSArrayTypeElementType = 206, + TSIndexedAccessTypeObjectType = 207, + TSIndexedAccessTypeIndexType = 208, + TSTupleTypeElementTypes = 209, + TSNamedTupleMemberElementType = 210, + TSNamedTupleMemberLabel = 211, + TSOptionalTypeTypeAnnotation = 212, + TSRestTypeTypeAnnotation = 213, + TSTypeReferenceTypeName = 214, + TSTypeReferenceTypeArguments = 215, + TSQualifiedNameLeft = 216, + TSQualifiedNameRight = 217, + TSTypeParameterInstantiationParams = 218, + TSTypeParameterName = 219, + TSTypeParameterConstraint = 220, + TSTypeParameterDefault = 221, + TSTypeParameterDeclarationParams = 222, + TSTypeAliasDeclarationId = 223, + TSTypeAliasDeclarationTypeParameters = 224, + TSTypeAliasDeclarationTypeAnnotation = 225, + TSClassImplementsExpression = 226, + TSClassImplementsTypeArguments = 227, + TSInterfaceDeclarationId = 228, + TSInterfaceDeclarationExtends = 229, + TSInterfaceDeclarationTypeParameters = 230, + TSInterfaceDeclarationBody = 231, + TSInterfaceBodyBody = 232, + TSPropertySignatureKey = 233, + TSPropertySignatureTypeAnnotation = 234, + TSIndexSignatureParameters = 235, + TSIndexSignatureTypeAnnotation = 236, + TSCallSignatureDeclarationTypeParameters = 237, + TSCallSignatureDeclarationThisParam = 238, + TSCallSignatureDeclarationParams = 239, + TSCallSignatureDeclarationReturnType = 240, + TSMethodSignatureKey = 241, + TSMethodSignatureTypeParameters = 242, + TSMethodSignatureThisParam = 243, + TSMethodSignatureParams = 244, + TSMethodSignatureReturnType = 245, + TSConstructSignatureDeclarationTypeParameters = 246, + TSConstructSignatureDeclarationParams = 247, + TSConstructSignatureDeclarationReturnType = 248, + TSIndexSignatureNameTypeAnnotation = 249, + TSInterfaceHeritageExpression = 250, + TSInterfaceHeritageTypeArguments = 251, + TSTypePredicateParameterName = 252, + TSTypePredicateTypeAnnotation = 253, + TSModuleDeclarationId = 254, + TSModuleDeclarationBody = 255, + TSModuleBlockDirectives = 256, + TSModuleBlockBody = 257, + TSTypeLiteralMembers = 258, + TSInferTypeTypeParameter = 259, + TSTypeQueryExprName = 260, + TSTypeQueryTypeArguments = 261, + TSImportTypeArgument = 262, + TSImportTypeOptions = 263, + TSImportTypeQualifier = 264, + TSImportTypeTypeArguments = 265, + TSFunctionTypeTypeParameters = 266, + TSFunctionTypeThisParam = 267, + TSFunctionTypeParams = 268, + TSFunctionTypeReturnType = 269, + TSConstructorTypeTypeParameters = 270, + TSConstructorTypeParams = 271, + TSConstructorTypeReturnType = 272, + TSMappedTypeTypeParameter = 273, + TSMappedTypeNameType = 274, + TSMappedTypeTypeAnnotation = 275, + TSTemplateLiteralTypeQuasis = 276, + TSTemplateLiteralTypeTypes = 277, + TSAsExpressionExpression = 278, + TSAsExpressionTypeAnnotation = 279, + TSSatisfiesExpressionExpression = 280, + TSSatisfiesExpressionTypeAnnotation = 281, + TSTypeAssertionExpression = 282, + TSTypeAssertionTypeAnnotation = 283, + TSImportEqualsDeclarationId = 284, + TSImportEqualsDeclarationModuleReference = 285, + TSExternalModuleReferenceExpression = 286, + TSNonNullExpressionExpression = 287, + DecoratorExpression = 288, + TSExportAssignmentExpression = 289, + TSNamespaceExportDeclarationId = 290, + TSInstantiationExpressionExpression = 291, + TSInstantiationExpressionTypeArguments = 292, + JSDocNullableTypeTypeAnnotation = 293, + JSDocNonNullableTypeTypeAnnotation = 294, } /// Ancestor type used in AST traversal. @@ -679,8 +680,9 @@ pub enum Ancestor<'a, 't> { AncestorType::TSThisParameterTypeAnnotation as u16, TSEnumDeclarationId(TSEnumDeclarationWithoutId<'a, 't>) = AncestorType::TSEnumDeclarationId as u16, - TSEnumDeclarationMembers(TSEnumDeclarationWithoutMembers<'a, 't>) = - AncestorType::TSEnumDeclarationMembers as u16, + TSEnumDeclarationBody(TSEnumDeclarationWithoutBody<'a, 't>) = + AncestorType::TSEnumDeclarationBody as u16, + TSEnumBodyMembers(TSEnumBodyWithoutMembers<'a, 't>) = AncestorType::TSEnumBodyMembers as u16, TSEnumMemberId(TSEnumMemberWithoutId<'a, 't>) = AncestorType::TSEnumMemberId as u16, TSEnumMemberInitializer(TSEnumMemberWithoutInitializer<'a, 't>) = AncestorType::TSEnumMemberInitializer as u16, @@ -1495,7 +1497,12 @@ impl<'a, 't> Ancestor<'a, 't> { #[inline] pub fn is_ts_enum_declaration(self) -> bool { - matches!(self, Self::TSEnumDeclarationId(_) | Self::TSEnumDeclarationMembers(_)) + matches!(self, Self::TSEnumDeclarationId(_) | Self::TSEnumDeclarationBody(_)) + } + + #[inline] + pub fn is_ts_enum_body(self) -> bool { + matches!(self, Self::TSEnumBodyMembers(_)) } #[inline] @@ -2382,7 +2389,8 @@ impl<'a, 't> GetAddress for Ancestor<'a, 't> { Self::JSXSpreadChildExpression(a) => a.address(), Self::TSThisParameterTypeAnnotation(a) => a.address(), Self::TSEnumDeclarationId(a) => a.address(), - Self::TSEnumDeclarationMembers(a) => a.address(), + Self::TSEnumDeclarationBody(a) => a.address(), + Self::TSEnumBodyMembers(a) => a.address(), Self::TSEnumMemberId(a) => a.address(), Self::TSEnumMemberInitializer(a) => a.address(), Self::TSTypeAnnotationTypeAnnotation(a) => a.address(), @@ -11116,7 +11124,7 @@ impl<'a, 't> GetAddress for TSThisParameterWithoutTypeAnnotation<'a, 't> { pub(crate) const OFFSET_TS_ENUM_DECLARATION_SPAN: usize = offset_of!(TSEnumDeclaration, span); pub(crate) const OFFSET_TS_ENUM_DECLARATION_ID: usize = offset_of!(TSEnumDeclaration, id); -pub(crate) const OFFSET_TS_ENUM_DECLARATION_MEMBERS: usize = offset_of!(TSEnumDeclaration, members); +pub(crate) const OFFSET_TS_ENUM_DECLARATION_BODY: usize = offset_of!(TSEnumDeclaration, body); pub(crate) const OFFSET_TS_ENUM_DECLARATION_CONST: usize = offset_of!(TSEnumDeclaration, r#const); pub(crate) const OFFSET_TS_ENUM_DECLARATION_DECLARE: usize = offset_of!(TSEnumDeclaration, declare); pub(crate) const OFFSET_TS_ENUM_DECLARATION_SCOPE_ID: usize = @@ -11136,10 +11144,9 @@ impl<'a, 't> TSEnumDeclarationWithoutId<'a, 't> { } #[inline] - pub fn members(self) -> &'t Vec<'a, TSEnumMember<'a>> { + pub fn body(self) -> &'t TSEnumBody<'a> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_ENUM_DECLARATION_MEMBERS) - as *const Vec<'a, TSEnumMember<'a>>) + &*((self.0 as *const u8).add(OFFSET_TS_ENUM_DECLARATION_BODY) as *const TSEnumBody<'a>) } } @@ -11171,12 +11178,12 @@ impl<'a, 't> GetAddress for TSEnumDeclarationWithoutId<'a, 't> { #[repr(transparent)] #[derive(Clone, Copy, Debug)] -pub struct TSEnumDeclarationWithoutMembers<'a, 't>( +pub struct TSEnumDeclarationWithoutBody<'a, 't>( pub(crate) *const TSEnumDeclaration<'a>, pub(crate) PhantomData<&'t ()>, ); -impl<'a, 't> TSEnumDeclarationWithoutMembers<'a, 't> { +impl<'a, 't> TSEnumDeclarationWithoutBody<'a, 't> { #[inline] pub fn span(self) -> &'t Span { unsafe { &*((self.0 as *const u8).add(OFFSET_TS_ENUM_DECLARATION_SPAN) as *const Span) } @@ -11209,7 +11216,31 @@ impl<'a, 't> TSEnumDeclarationWithoutMembers<'a, 't> { } } -impl<'a, 't> GetAddress for TSEnumDeclarationWithoutMembers<'a, 't> { +impl<'a, 't> GetAddress for TSEnumDeclarationWithoutBody<'a, 't> { + #[inline] + fn address(&self) -> Address { + Address::from_ptr(self.0) + } +} + +pub(crate) const OFFSET_TS_ENUM_BODY_SPAN: usize = offset_of!(TSEnumBody, span); +pub(crate) const OFFSET_TS_ENUM_BODY_MEMBERS: usize = offset_of!(TSEnumBody, members); + +#[repr(transparent)] +#[derive(Clone, Copy, Debug)] +pub struct TSEnumBodyWithoutMembers<'a, 't>( + pub(crate) *const TSEnumBody<'a>, + pub(crate) PhantomData<&'t ()>, +); + +impl<'a, 't> TSEnumBodyWithoutMembers<'a, 't> { + #[inline] + pub fn span(self) -> &'t Span { + unsafe { &*((self.0 as *const u8).add(OFFSET_TS_ENUM_BODY_SPAN) as *const Span) } + } +} + +impl<'a, 't> GetAddress for TSEnumBodyWithoutMembers<'a, 't> { #[inline] fn address(&self) -> Address { Address::from_ptr(self.0) diff --git a/crates/oxc_traverse/src/generated/traverse.rs b/crates/oxc_traverse/src/generated/traverse.rs index ccba66bf2d491..c922d85fc7487 100644 --- a/crates/oxc_traverse/src/generated/traverse.rs +++ b/crates/oxc_traverse/src/generated/traverse.rs @@ -1584,6 +1584,11 @@ pub trait Traverse<'a> { ) { } + #[inline] + fn enter_ts_enum_body(&mut self, node: &mut TSEnumBody<'a>, ctx: &mut TraverseCtx<'a>) {} + #[inline] + fn exit_ts_enum_body(&mut self, node: &mut TSEnumBody<'a>, ctx: &mut TraverseCtx<'a>) {} + #[inline] fn enter_ts_enum_member(&mut self, node: &mut TSEnumMember<'a>, ctx: &mut TraverseCtx<'a>) {} #[inline] diff --git a/crates/oxc_traverse/src/generated/walk.rs b/crates/oxc_traverse/src/generated/walk.rs index 40b02f5fe9dca..a819717583656 100644 --- a/crates/oxc_traverse/src/generated/walk.rs +++ b/crates/oxc_traverse/src/generated/walk.rs @@ -3740,15 +3740,33 @@ unsafe fn walk_ts_enum_declaration<'a, Tr: Traverse<'a>>( .get() .unwrap(); ctx.set_current_scope_id(current_scope_id); - ctx.retag_stack(AncestorType::TSEnumDeclarationMembers); - for item in &mut *((node as *mut u8).add(ancestor::OFFSET_TS_ENUM_DECLARATION_MEMBERS) + ctx.retag_stack(AncestorType::TSEnumDeclarationBody); + walk_ts_enum_body( + traverser, + (node as *mut u8).add(ancestor::OFFSET_TS_ENUM_DECLARATION_BODY) as *mut TSEnumBody, + ctx, + ); + ctx.pop_stack(pop_token); + ctx.set_current_scope_id(previous_scope_id); + traverser.exit_ts_enum_declaration(&mut *node, ctx); +} + +unsafe fn walk_ts_enum_body<'a, Tr: Traverse<'a>>( + traverser: &mut Tr, + node: *mut TSEnumBody<'a>, + ctx: &mut TraverseCtx<'a>, +) { + traverser.enter_ts_enum_body(&mut *node, ctx); + let pop_token = ctx.push_stack(Ancestor::TSEnumBodyMembers( + ancestor::TSEnumBodyWithoutMembers(node, PhantomData), + )); + for item in &mut *((node as *mut u8).add(ancestor::OFFSET_TS_ENUM_BODY_MEMBERS) as *mut Vec) { walk_ts_enum_member(traverser, item as *mut _, ctx); } ctx.pop_stack(pop_token); - ctx.set_current_scope_id(previous_scope_id); - traverser.exit_ts_enum_declaration(&mut *node, ctx); + traverser.exit_ts_enum_body(&mut *node, ctx); } unsafe fn walk_ts_enum_member<'a, Tr: Traverse<'a>>( diff --git a/napi/parser/deserialize-js.js b/napi/parser/deserialize-js.js index 516bc1cf4477f..ecb1838e8b4b6 100644 --- a/napi/parser/deserialize-js.js +++ b/napi/parser/deserialize-js.js @@ -1290,18 +1290,23 @@ function deserializeTSThisParameter(pos) { } function deserializeTSEnumDeclaration(pos) { - const end = deserializeU32(pos + 4), - id = deserializeBindingIdentifier(pos + 8); - const tsEnumDeclMembers = deserializeVecTSEnumMember(pos + 40); - const bodyStart = id.end + 1; return { type: 'TSEnumDeclaration', start: deserializeU32(pos), - end, - id, - body: { type: 'TSEnumBody', start: bodyStart, end: end, members: tsEnumDeclMembers }, - const: deserializeBool(pos + 72), - declare: deserializeBool(pos + 73), + end: deserializeU32(pos + 4), + id: deserializeBindingIdentifier(pos + 8), + body: deserializeTSEnumBody(pos + 40), + const: deserializeBool(pos + 80), + declare: deserializeBool(pos + 81), + }; +} + +function deserializeTSEnumBody(pos) { + return { + type: 'TSEnumBody', + start: deserializeU32(pos), + end: deserializeU32(pos + 4), + members: deserializeVecTSEnumMember(pos + 8), }; } diff --git a/napi/parser/deserialize-ts.js b/napi/parser/deserialize-ts.js index 216a6ded01d09..9b0a1a5e39b73 100644 --- a/napi/parser/deserialize-ts.js +++ b/napi/parser/deserialize-ts.js @@ -1366,18 +1366,23 @@ function deserializeTSThisParameter(pos) { } function deserializeTSEnumDeclaration(pos) { - const end = deserializeU32(pos + 4), - id = deserializeBindingIdentifier(pos + 8); - const tsEnumDeclMembers = deserializeVecTSEnumMember(pos + 40); - const bodyStart = id.end + 1; return { type: 'TSEnumDeclaration', start: deserializeU32(pos), - end, - id, - body: { type: 'TSEnumBody', start: bodyStart, end: end, members: tsEnumDeclMembers }, - const: deserializeBool(pos + 72), - declare: deserializeBool(pos + 73), + end: deserializeU32(pos + 4), + id: deserializeBindingIdentifier(pos + 8), + body: deserializeTSEnumBody(pos + 40), + const: deserializeBool(pos + 80), + declare: deserializeBool(pos + 81), + }; +} + +function deserializeTSEnumBody(pos) { + return { + type: 'TSEnumBody', + start: deserializeU32(pos), + end: deserializeU32(pos + 4), + members: deserializeVecTSEnumMember(pos + 8), }; } diff --git a/npm/oxc-types/types.d.ts b/npm/oxc-types/types.d.ts index 57caa000de49c..22253051d6e3a 100644 --- a/npm/oxc-types/types.d.ts +++ b/npm/oxc-types/types.d.ts @@ -946,7 +946,7 @@ export interface TSEnumDeclaration extends Span { export interface TSEnumBody extends Span { type: 'TSEnumBody'; - members: TSEnumMember[]; + members: Array; } export interface TSEnumMember extends Span { @@ -1761,6 +1761,7 @@ export type Node = | JSXText | TSThisParameter | TSEnumDeclaration + | TSEnumBody | TSEnumMember | TSTypeAnnotation | TSLiteralType