diff --git a/apps/oxlint/src-js/generated/deserialize.js b/apps/oxlint/src-js/generated/deserialize.js index a439747fb189b..ca9d2dc8b5885 100644 --- a/apps/oxlint/src-js/generated/deserialize.js +++ b/apps/oxlint/src-js/generated/deserialize.js @@ -5278,23 +5278,18 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, range: [start, end], parent, }), - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name; - key.parent = parent; - let { constraint } = typeParameter; - constraint !== null && (constraint.parent = parent); - let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; parent = previousParent; return node; diff --git a/apps/oxlint/src-js/generated/types.d.ts b/apps/oxlint/src-js/generated/types.d.ts index a77df689cf48e..db5bf105ce0df 100644 --- a/apps/oxlint/src-js/generated/types.d.ts +++ b/apps/oxlint/src-js/generated/types.d.ts @@ -1546,8 +1546,8 @@ export interface TSConstructorType extends Span { export interface TSMappedType extends Span { type: 'TSMappedType'; - key: TSTypeParameter['name']; - constraint: TSTypeParameter['constraint']; + key: BindingIdentifier; + constraint: TSType; nameType: TSType | null; typeAnnotation: TSType | null; optional: TSMappedTypeModifierOperator | false; diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 02da05921f60b..c266fcccea174 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -1483,15 +1483,12 @@ pub struct TSConstructorType<'a> { #[scope] #[derive(Debug)] #[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)] -#[estree( - add_fields(key = TSMappedTypeKey, constraint = TSMappedTypeConstraint), - field_order(key, constraint, name_type, type_annotation, optional, readonly, span), -)] pub struct TSMappedType<'a> { pub span: Span, - /// Key type parameter, e.g. `P` in `[P in keyof T]`. - #[estree(skip)] - pub type_parameter: Box<'a, TSTypeParameter<'a>>, + /// The type parameter name (e.g., `P` in `[P in keyof T]`) + pub key: BindingIdentifier<'a>, + /// The constraint (e.g., `keyof T` in `[P in keyof T]`) + pub constraint: TSType<'a>, pub name_type: Option>, pub type_annotation: Option>, /// Optional modifier on type annotation diff --git a/crates/oxc_ast/src/generated/assert_layouts.rs b/crates/oxc_ast/src/generated/assert_layouts.rs index 47397fa038bc9..f74ddbb238cce 100644 --- a/crates/oxc_ast/src/generated/assert_layouts.rs +++ b/crates/oxc_ast/src/generated/assert_layouts.rs @@ -1479,15 +1479,16 @@ const _: () = { assert!(offset_of!(TSConstructorType, scope_id) == 32); // Padding: 2 bytes - assert!(size_of::() == 56); + assert!(size_of::() == 96); assert!(align_of::() == 8); assert!(offset_of!(TSMappedType, span) == 0); - assert!(offset_of!(TSMappedType, type_parameter) == 8); - assert!(offset_of!(TSMappedType, name_type) == 16); - assert!(offset_of!(TSMappedType, type_annotation) == 32); - assert!(offset_of!(TSMappedType, optional) == 52); - assert!(offset_of!(TSMappedType, readonly) == 53); - assert!(offset_of!(TSMappedType, scope_id) == 48); + assert!(offset_of!(TSMappedType, key) == 8); + assert!(offset_of!(TSMappedType, constraint) == 40); + assert!(offset_of!(TSMappedType, name_type) == 56); + assert!(offset_of!(TSMappedType, type_annotation) == 72); + assert!(offset_of!(TSMappedType, optional) == 92); + assert!(offset_of!(TSMappedType, readonly) == 93); + assert!(offset_of!(TSMappedType, scope_id) == 88); assert!(size_of::() == 1); assert!(align_of::() == 1); @@ -3086,15 +3087,16 @@ const _: () = if cfg!(target_family = "wasm") || align_of::() == 8 { assert!(offset_of!(TSConstructorType, scope_id) == 20); // Padding: 2 bytes - assert!(size_of::() == 36); + assert!(size_of::() == 60); assert!(align_of::() == 4); assert!(offset_of!(TSMappedType, span) == 0); - assert!(offset_of!(TSMappedType, type_parameter) == 8); - assert!(offset_of!(TSMappedType, name_type) == 12); - assert!(offset_of!(TSMappedType, type_annotation) == 20); - assert!(offset_of!(TSMappedType, optional) == 32); - assert!(offset_of!(TSMappedType, readonly) == 33); - assert!(offset_of!(TSMappedType, scope_id) == 28); + assert!(offset_of!(TSMappedType, key) == 8); + assert!(offset_of!(TSMappedType, constraint) == 28); + assert!(offset_of!(TSMappedType, name_type) == 36); + assert!(offset_of!(TSMappedType, type_annotation) == 44); + assert!(offset_of!(TSMappedType, optional) == 56); + assert!(offset_of!(TSMappedType, readonly) == 57); + assert!(offset_of!(TSMappedType, scope_id) == 52); assert!(size_of::() == 1); assert!(align_of::() == 1); diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 329f211ad6276..228c976d0175b 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -10661,27 +10661,27 @@ impl<'a> AstBuilder<'a> { /// /// ## Parameters /// * `span`: The [`Span`] covering this node - /// * `type_parameter`: Key type parameter, e.g. `P` in `[P in keyof T]`. + /// * `key`: The type parameter name (e.g., `P` in `[P in keyof T]`) + /// * `constraint`: The constraint (e.g., `keyof T` in `[P in keyof T]`) /// * `name_type` /// * `type_annotation` /// * `optional`: Optional modifier on type annotation /// * `readonly`: Readonly modifier before keyed index signature #[inline] - pub fn ts_type_mapped_type( + pub fn ts_type_mapped_type( self, span: Span, - type_parameter: T1, + key: BindingIdentifier<'a>, + constraint: TSType<'a>, name_type: Option>, type_annotation: Option>, optional: Option, readonly: Option, - ) -> TSType<'a> - where - T1: IntoIn<'a, Box<'a, TSTypeParameter<'a>>>, - { + ) -> TSType<'a> { TSType::TSMappedType(self.alloc_ts_mapped_type( span, - type_parameter, + key, + constraint, name_type, type_annotation, optional, @@ -10695,29 +10695,29 @@ impl<'a> AstBuilder<'a> { /// /// ## Parameters /// * `span`: The [`Span`] covering this node - /// * `type_parameter`: Key type parameter, e.g. `P` in `[P in keyof T]`. + /// * `key`: The type parameter name (e.g., `P` in `[P in keyof T]`) + /// * `constraint`: The constraint (e.g., `keyof T` in `[P in keyof T]`) /// * `name_type` /// * `type_annotation` /// * `optional`: Optional modifier on type annotation /// * `readonly`: Readonly modifier before keyed index signature /// * `scope_id` #[inline] - pub fn ts_type_mapped_type_with_scope_id( + pub fn ts_type_mapped_type_with_scope_id( self, span: Span, - type_parameter: T1, + key: BindingIdentifier<'a>, + constraint: TSType<'a>, name_type: Option>, type_annotation: Option>, optional: Option, readonly: Option, scope_id: ScopeId, - ) -> TSType<'a> - where - T1: IntoIn<'a, Box<'a, TSTypeParameter<'a>>>, - { + ) -> TSType<'a> { TSType::TSMappedType(self.alloc_ts_mapped_type_with_scope_id( span, - type_parameter, + key, + constraint, name_type, type_annotation, optional, @@ -14329,27 +14329,27 @@ impl<'a> AstBuilder<'a> { /// /// ## Parameters /// * `span`: The [`Span`] covering this node - /// * `type_parameter`: Key type parameter, e.g. `P` in `[P in keyof T]`. + /// * `key`: The type parameter name (e.g., `P` in `[P in keyof T]`) + /// * `constraint`: The constraint (e.g., `keyof T` in `[P in keyof T]`) /// * `name_type` /// * `type_annotation` /// * `optional`: Optional modifier on type annotation /// * `readonly`: Readonly modifier before keyed index signature #[inline] - pub fn ts_mapped_type( + pub fn ts_mapped_type( self, span: Span, - type_parameter: T1, + key: BindingIdentifier<'a>, + constraint: TSType<'a>, name_type: Option>, type_annotation: Option>, optional: Option, readonly: Option, - ) -> TSMappedType<'a> - where - T1: IntoIn<'a, Box<'a, TSTypeParameter<'a>>>, - { + ) -> TSMappedType<'a> { TSMappedType { span, - type_parameter: type_parameter.into_in(self.allocator), + key, + constraint, name_type, type_annotation, optional, @@ -14365,28 +14365,28 @@ impl<'a> AstBuilder<'a> { /// /// ## Parameters /// * `span`: The [`Span`] covering this node - /// * `type_parameter`: Key type parameter, e.g. `P` in `[P in keyof T]`. + /// * `key`: The type parameter name (e.g., `P` in `[P in keyof T]`) + /// * `constraint`: The constraint (e.g., `keyof T` in `[P in keyof T]`) /// * `name_type` /// * `type_annotation` /// * `optional`: Optional modifier on type annotation /// * `readonly`: Readonly modifier before keyed index signature #[inline] - pub fn alloc_ts_mapped_type( + pub fn alloc_ts_mapped_type( self, span: Span, - type_parameter: T1, + key: BindingIdentifier<'a>, + constraint: TSType<'a>, name_type: Option>, type_annotation: Option>, optional: Option, readonly: Option, - ) -> Box<'a, TSMappedType<'a>> - where - T1: IntoIn<'a, Box<'a, TSTypeParameter<'a>>>, - { + ) -> Box<'a, TSMappedType<'a>> { Box::new_in( self.ts_mapped_type( span, - type_parameter, + key, + constraint, name_type, type_annotation, optional, @@ -14403,29 +14403,29 @@ impl<'a> AstBuilder<'a> { /// /// ## Parameters /// * `span`: The [`Span`] covering this node - /// * `type_parameter`: Key type parameter, e.g. `P` in `[P in keyof T]`. + /// * `key`: The type parameter name (e.g., `P` in `[P in keyof T]`) + /// * `constraint`: The constraint (e.g., `keyof T` in `[P in keyof T]`) /// * `name_type` /// * `type_annotation` /// * `optional`: Optional modifier on type annotation /// * `readonly`: Readonly modifier before keyed index signature /// * `scope_id` #[inline] - pub fn ts_mapped_type_with_scope_id( + pub fn ts_mapped_type_with_scope_id( self, span: Span, - type_parameter: T1, + key: BindingIdentifier<'a>, + constraint: TSType<'a>, name_type: Option>, type_annotation: Option>, optional: Option, readonly: Option, scope_id: ScopeId, - ) -> TSMappedType<'a> - where - T1: IntoIn<'a, Box<'a, TSTypeParameter<'a>>>, - { + ) -> TSMappedType<'a> { TSMappedType { span, - type_parameter: type_parameter.into_in(self.allocator), + key, + constraint, name_type, type_annotation, optional, @@ -14441,30 +14441,30 @@ impl<'a> AstBuilder<'a> { /// /// ## Parameters /// * `span`: The [`Span`] covering this node - /// * `type_parameter`: Key type parameter, e.g. `P` in `[P in keyof T]`. + /// * `key`: The type parameter name (e.g., `P` in `[P in keyof T]`) + /// * `constraint`: The constraint (e.g., `keyof T` in `[P in keyof T]`) /// * `name_type` /// * `type_annotation` /// * `optional`: Optional modifier on type annotation /// * `readonly`: Readonly modifier before keyed index signature /// * `scope_id` #[inline] - pub fn alloc_ts_mapped_type_with_scope_id( + pub fn alloc_ts_mapped_type_with_scope_id( self, span: Span, - type_parameter: T1, + key: BindingIdentifier<'a>, + constraint: TSType<'a>, name_type: Option>, type_annotation: Option>, optional: Option, readonly: Option, scope_id: ScopeId, - ) -> Box<'a, TSMappedType<'a>> - where - T1: IntoIn<'a, Box<'a, TSTypeParameter<'a>>>, - { + ) -> Box<'a, TSMappedType<'a>> { Box::new_in( self.ts_mapped_type_with_scope_id( span, - type_parameter, + key, + constraint, name_type, type_annotation, optional, diff --git a/crates/oxc_ast/src/generated/derive_clone_in.rs b/crates/oxc_ast/src/generated/derive_clone_in.rs index 3bd5fefb787bd..0e3353a791369 100644 --- a/crates/oxc_ast/src/generated/derive_clone_in.rs +++ b/crates/oxc_ast/src/generated/derive_clone_in.rs @@ -7554,7 +7554,8 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSMappedType<'_> { fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { TSMappedType { span: CloneIn::clone_in(&self.span, allocator), - type_parameter: CloneIn::clone_in(&self.type_parameter, allocator), + key: CloneIn::clone_in(&self.key, allocator), + constraint: CloneIn::clone_in(&self.constraint, allocator), name_type: CloneIn::clone_in(&self.name_type, allocator), type_annotation: CloneIn::clone_in(&self.type_annotation, allocator), optional: CloneIn::clone_in(&self.optional, allocator), @@ -7566,7 +7567,8 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSMappedType<'_> { fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { TSMappedType { span: CloneIn::clone_in_with_semantic_ids(&self.span, allocator), - type_parameter: CloneIn::clone_in_with_semantic_ids(&self.type_parameter, allocator), + key: CloneIn::clone_in_with_semantic_ids(&self.key, allocator), + constraint: CloneIn::clone_in_with_semantic_ids(&self.constraint, allocator), name_type: CloneIn::clone_in_with_semantic_ids(&self.name_type, allocator), type_annotation: CloneIn::clone_in_with_semantic_ids(&self.type_annotation, allocator), optional: CloneIn::clone_in_with_semantic_ids(&self.optional, allocator), diff --git a/crates/oxc_ast/src/generated/derive_content_eq.rs b/crates/oxc_ast/src/generated/derive_content_eq.rs index 46652d0c1387f..137a20eb95930 100644 --- a/crates/oxc_ast/src/generated/derive_content_eq.rs +++ b/crates/oxc_ast/src/generated/derive_content_eq.rs @@ -2364,7 +2364,8 @@ impl ContentEq for TSConstructorType<'_> { impl ContentEq for TSMappedType<'_> { fn content_eq(&self, other: &Self) -> bool { - ContentEq::content_eq(&self.type_parameter, &other.type_parameter) + ContentEq::content_eq(&self.key, &other.key) + && ContentEq::content_eq(&self.constraint, &other.constraint) && ContentEq::content_eq(&self.name_type, &other.name_type) && ContentEq::content_eq(&self.type_annotation, &other.type_annotation) && ContentEq::content_eq(&self.optional, &other.optional) diff --git a/crates/oxc_ast/src/generated/derive_dummy.rs b/crates/oxc_ast/src/generated/derive_dummy.rs index be1e5817eb624..efc5974169815 100644 --- a/crates/oxc_ast/src/generated/derive_dummy.rs +++ b/crates/oxc_ast/src/generated/derive_dummy.rs @@ -2692,11 +2692,12 @@ impl<'a> Dummy<'a> for TSConstructorType<'a> { impl<'a> Dummy<'a> for TSMappedType<'a> { /// Create a dummy [`TSMappedType`]. /// - /// Has cost of making 1 allocation (80 bytes). + /// Has cost of making 1 allocation (8 bytes). fn dummy(allocator: &'a Allocator) -> Self { Self { span: Dummy::dummy(allocator), - type_parameter: Dummy::dummy(allocator), + key: Dummy::dummy(allocator), + constraint: Dummy::dummy(allocator), name_type: Dummy::dummy(allocator), type_annotation: Dummy::dummy(allocator), optional: Dummy::dummy(allocator), diff --git a/crates/oxc_ast/src/generated/derive_estree.rs b/crates/oxc_ast/src/generated/derive_estree.rs index 707520425fcc8..aadae0449833b 100644 --- a/crates/oxc_ast/src/generated/derive_estree.rs +++ b/crates/oxc_ast/src/generated/derive_estree.rs @@ -3025,8 +3025,8 @@ impl ESTree for TSMappedType<'_> { fn serialize(&self, serializer: S) { let mut state = serializer.serialize_struct(); state.serialize_field("type", &JsonSafeString("TSMappedType")); - state.serialize_field("key", &crate::serialize::ts::TSMappedTypeKey(self)); - state.serialize_field("constraint", &crate::serialize::ts::TSMappedTypeConstraint(self)); + state.serialize_field("key", &self.key); + state.serialize_field("constraint", &self.constraint); state.serialize_field("nameType", &self.name_type); state.serialize_field("typeAnnotation", &self.type_annotation); state.serialize_field("optional", &crate::serialize::ts::TSMappedTypeOptional(self)); diff --git a/crates/oxc_ast/src/serialize/ts.rs b/crates/oxc_ast/src/serialize/ts.rs index 4bbbdf3862fca..d6736242907df 100644 --- a/crates/oxc_ast/src/serialize/ts.rs +++ b/crates/oxc_ast/src/serialize/ts.rs @@ -285,46 +285,6 @@ impl ESTree for TSMappedTypeOptional<'_, '_> { } } -/// Serializer for `key` field of `TSMappedType`. -#[ast_meta] -#[estree( - ts_type = "TSTypeParameter['name']", - raw_deser = " - const typeParameter = DESER[Box](POS_OFFSET.type_parameter), - key = typeParameter.name; - if (PARENT) key.parent = parent; - key - " -)] -pub struct TSMappedTypeKey<'a, 'b>(pub &'b TSMappedType<'a>); - -impl ESTree for TSMappedTypeKey<'_, '_> { - fn serialize(&self, serializer: S) { - self.0.type_parameter.name.serialize(serializer); - } -} - -/// Serializer for `constraint` field of `TSMappedType`. -/// -/// NOTE: Variable `typeParameter` in `raw_deser` is shared between `key` and `constraint` serializers. -/// They will be concatenated in the generated code. -#[ast_meta] -#[estree( - ts_type = "TSTypeParameter['constraint']", - raw_deser = " - const { constraint } = typeParameter; - if (PARENT && constraint !== null) constraint.parent = parent; - constraint - " -)] -pub struct TSMappedTypeConstraint<'a, 'b>(pub &'b TSMappedType<'a>); - -impl ESTree for TSMappedTypeConstraint<'_, '_> { - fn serialize(&self, serializer: S) { - self.0.type_parameter.constraint.serialize(serializer); - } -} - /// Serializer for `expression` field of `TSClassImplements`. /// /// Our AST represents `X.Y` in `class C implements X.Y {}` as a `TSQualifiedName`. diff --git a/crates/oxc_ast_macros/src/generated/structs.rs b/crates/oxc_ast_macros/src/generated/structs.rs index 9bda66c5de875..599b39548568c 100644 --- a/crates/oxc_ast_macros/src/generated/structs.rs +++ b/crates/oxc_ast_macros/src/generated/structs.rs @@ -296,7 +296,7 @@ pub static STRUCTS: phf::Map<&'static str, StructDetails> = ::phf::Map { ("UnicodePropertyEscape", StructDetails { field_order: Some(&[0, 3, 4, 1, 2]) }), ("ArrayExpression", StructDetails { field_order: None }), ("TSEnumDeclaration", StructDetails { field_order: Some(&[0, 1, 2, 4, 5, 3]) }), - ("TSMappedType", StructDetails { field_order: Some(&[0, 1, 2, 3, 5, 6, 4]) }), + ("TSMappedType", StructDetails { field_order: Some(&[0, 1, 2, 3, 4, 6, 7, 5]) }), ("Super", StructDetails { field_order: None }), ("CapturingGroup", StructDetails { field_order: None }), ("TSModuleBlock", StructDetails { field_order: None }), diff --git a/crates/oxc_ast_visit/src/generated/visit.rs b/crates/oxc_ast_visit/src/generated/visit.rs index c85076294c15a..9b0e023a35b5f 100644 --- a/crates/oxc_ast_visit/src/generated/visit.rs +++ b/crates/oxc_ast_visit/src/generated/visit.rs @@ -4015,7 +4015,8 @@ pub mod walk { visitor.enter_node(kind); visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); visitor.visit_span(&it.span); - visitor.visit_ts_type_parameter(&it.type_parameter); + visitor.visit_binding_identifier(&it.key); + visitor.visit_ts_type(&it.constraint); if let Some(name_type) = &it.name_type { visitor.visit_ts_type(name_type); } diff --git a/crates/oxc_ast_visit/src/generated/visit_mut.rs b/crates/oxc_ast_visit/src/generated/visit_mut.rs index 4ca253155e2c4..db444e9c33da2 100644 --- a/crates/oxc_ast_visit/src/generated/visit_mut.rs +++ b/crates/oxc_ast_visit/src/generated/visit_mut.rs @@ -4230,7 +4230,8 @@ pub mod walk_mut { visitor.enter_node(kind); visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); visitor.visit_span(&mut it.span); - visitor.visit_ts_type_parameter(&mut it.type_parameter); + visitor.visit_binding_identifier(&mut it.key); + visitor.visit_ts_type(&mut it.constraint); if let Some(name_type) = &mut it.name_type { visitor.visit_ts_type(name_type); } diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index cf977456fab5e..de2c195f70728 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -3138,15 +3138,9 @@ impl Gen for TSMappedType<'_> { None => {} } p.print_str("["); - self.type_parameter.name.print(p, ctx); - if let Some(constraint) = &self.type_parameter.constraint { - p.print_str(" in "); - constraint.print(p, ctx); - } - if let Some(default) = &self.type_parameter.default { - p.print_str(" = "); - default.print(p, ctx); - } + self.key.print(p, ctx); + p.print_str(" in "); + self.constraint.print(p, ctx); if let Some(name_type) = &self.name_type { p.print_str(" as "); name_type.print(p, ctx); diff --git a/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs b/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs index fb442d9150605..fd54afd633fbe 100644 --- a/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs +++ b/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs @@ -8693,7 +8693,18 @@ impl<'a> AstNode<'a, TSConstructorType<'a>> { impl<'a> AstNode<'a, TSMappedType<'a>> { #[inline] - pub fn type_parameter(&self) -> &AstNode<'a, TSTypeParameter<'a>> { + pub fn key(&self) -> &AstNode<'a, BindingIdentifier<'a>> { + let following_span = Some(self.inner.constraint.span()); + self.allocator.alloc(AstNode { + inner: &self.inner.key, + allocator: self.allocator, + parent: self.allocator.alloc(AstNodes::TSMappedType(transmute_self(self))), + following_span, + }) + } + + #[inline] + pub fn constraint(&self) -> &AstNode<'a, TSType<'a>> { let following_span = self .inner .name_type @@ -8702,7 +8713,7 @@ impl<'a> AstNode<'a, TSMappedType<'a>> { .or_else(|| self.inner.type_annotation.as_ref().map(GetSpan::span)) .or(self.following_span); self.allocator.alloc(AstNode { - inner: self.inner.type_parameter.as_ref(), + inner: &self.inner.constraint, allocator: self.allocator, parent: self.allocator.alloc(AstNodes::TSMappedType(transmute_self(self))), following_span, diff --git a/crates/oxc_formatter/src/write/mapped_type.rs b/crates/oxc_formatter/src/write/mapped_type.rs index fefeb92229a4a..a6fbeb4ee4dc5 100644 --- a/crates/oxc_formatter/src/write/mapped_type.rs +++ b/crates/oxc_formatter/src/write/mapped_type.rs @@ -13,25 +13,24 @@ use super::FormatWrite; impl<'a> FormatWrite<'a> for AstNode<'a, TSMappedType<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - if f.comments().is_suppressed(self.type_parameter.span.start) { + if f.comments().is_suppressed(self.key.span.start) { return write!(f, FormatSuppressedNode(self.span)); } - let type_parameter = self.type_parameter(); + let key = self.key(); + let constraint = self.constraint(); let name_type = self.name_type(); let should_expand = has_line_break_before_property_name(self, f.source_text()); - let type_annotation_has_leading_comment = - f.comments().has_comment_before(type_parameter.span.start); + let type_annotation_has_leading_comment = f.comments().has_comment_before(key.span.start); let format_inner = format_with(|f| { if should_expand { - let comments = - if f.comments().has_leading_own_line_comment(self.type_parameter.span.start) { - f.context().comments().comments_before(self.type_parameter.span.start) - } else { - f.context().comments().comments_before_character(self.span.start, b'[') - }; + let comments = if f.comments().has_leading_own_line_comment(self.key.span.start) { + f.context().comments().comments_before(self.key.span.start) + } else { + f.context().comments().comments_before_character(self.span.start, b'[') + }; write!(f, FormatLeadingComments::Comments(comments))?; } @@ -46,17 +45,12 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSMappedType<'a>> { let format_inner_inner = format_with(|f| { write!(f, "[")?; - write!(f, type_parameter.name())?; - if let Some(constraint) = &type_parameter.constraint() { - write!(f, [space(), "in", space(), constraint])?; - } - if let Some(default) = &type_parameter.default() { - write!(f, [space(), "=", space(), default])?; - } + write!(f, key)?; + write!(f, [space(), "in", space(), constraint])?; if let Some(name_type) = &name_type { write!(f, [space(), "as", space(), name_type])?; } - type_parameter.format_trailing_comments(f)?; + key.format_trailing_comments(f)?; write!(f, "]")?; if let Some(optional) = self.optional() { write!( @@ -105,5 +99,5 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSMappedType<'a>> { /// in B]: T} /// Because the break is _after_ the `A`. fn has_line_break_before_property_name(node: &TSMappedType, f: SourceText) -> bool { - f.contains_newline_between(node.span.start, node.type_parameter.span.start) + f.contains_newline_between(node.span.start, node.key.span.start) } diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_vars/ignored.rs b/crates/oxc_linter/src/rules/eslint/no_unused_vars/ignored.rs index e90c2f6c8ba4a..c35bf73e1772a 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_vars/ignored.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_vars/ignored.rs @@ -68,6 +68,8 @@ impl NoUnusedVars { | AstKind::TSModuleDeclaration(_) | AstKind::TSTypeAliasDeclaration(_) | AstKind::TSTypeParameter(_) => self.is_ignored_var(declared_binding), + // Mapped type keys are always considered used by definition + AstKind::TSMappedType(_) => true, AstKind::Function(func) => { func.r#type.is_typescript_syntax() || self.is_ignored_var(declared_binding) } diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_vars/usage.rs b/crates/oxc_linter/src/rules/eslint/no_unused_vars/usage.rs index eea9d65fd978d..c4cbb5853abb7 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_vars/usage.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_vars/usage.rs @@ -151,9 +151,11 @@ impl<'a> Symbol<'_, 'a> { // ``` // function foo(): foo { } // ``` - if self - .get_ref_relevant_node(reference) - .is_some_and(|node| self.declaration().span().contains_inclusive(node.span())) + // Exception: TSMappedType keys are used within the same node + if !matches!(self.declaration().kind(), AstKind::TSMappedType(_)) + && self.get_ref_relevant_node(reference).is_some_and(|node| { + self.declaration().span().contains_inclusive(node.span()) + }) { continue; } diff --git a/crates/oxc_parser/src/ts/types.rs b/crates/oxc_parser/src/ts/types.rs index c7c3bd63249d6..46e5e787d6b90 100644 --- a/crates/oxc_parser/src/ts/types.rs +++ b/crates/oxc_parser/src/ts/types.rs @@ -591,22 +591,12 @@ impl<'a> ParserImpl<'a> { } self.expect(Kind::LBrack); - let type_parameter_span = self.start_span(); if !self.cur_kind().is_identifier_name() { return self.unexpected(); } - let name = self.parse_binding_identifier(); + let key = self.parse_binding_identifier(); self.expect(Kind::In); let constraint = self.parse_ts_type(); - let type_parameter = self.alloc(self.ast.ts_type_parameter( - self.end_span(type_parameter_span), - name, - Some(constraint), - None, - false, - false, - false, - )); let name_type = if self.eat(Kind::As) { Some(self.parse_ts_type()) } else { None }; self.expect(Kind::RBrack); @@ -635,7 +625,8 @@ impl<'a> ParserImpl<'a> { self.ast.ts_type_mapped_type( self.end_span(span), - type_parameter, + key, + constraint, name_type, type_annotation, optional, diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index 824dd25c1d163..caaf51cfb4516 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -667,3 +667,15 @@ impl<'a> Binder<'a> for TSTypeParameter<'a> { self.name.symbol_id.set(Some(symbol_id)); } } + +impl<'a> Binder<'a> for TSMappedType<'a> { + fn bind(&self, builder: &mut SemanticBuilder) { + let symbol_id = builder.declare_symbol( + self.key.span, + &self.key.name, + SymbolFlags::TypeParameter, + SymbolFlags::TypeParameterExcludes, + ); + self.key.symbol_id.set(Some(symbol_id)); + } +} diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 781702baa3c06..fccdeba768432 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -2154,6 +2154,9 @@ impl<'a> SemanticBuilder<'a> { AstKind::TSTypeParameter(type_parameter) => { type_parameter.bind(self); } + AstKind::TSMappedType(mapped_type) => { + mapped_type.bind(self); + } AstKind::TSPropertySignature(signature) => { if signature.key.is_expression() { // interface A { [prop]: string } diff --git a/crates/oxc_traverse/src/generated/ancestor.rs b/crates/oxc_traverse/src/generated/ancestor.rs index 7d4a796bae5d5..4d08ac79fe322 100644 --- a/crates/oxc_traverse/src/generated/ancestor.rs +++ b/crates/oxc_traverse/src/generated/ancestor.rs @@ -295,28 +295,29 @@ pub(crate) enum AncestorType { TSConstructorTypeTypeParameters = 270, TSConstructorTypeParams = 271, TSConstructorTypeReturnType = 272, - TSMappedTypeTypeParameter = 273, - TSMappedTypeNameType = 274, - TSMappedTypeTypeAnnotation = 275, - TSTemplateLiteralTypeQuasis = 276, - TSTemplateLiteralTypeTypes = 277, - TSAsExpressionExpression = 278, - TSAsExpressionTypeAnnotation = 279, - TSSatisfiesExpressionExpression = 280, - TSSatisfiesExpressionTypeAnnotation = 281, - TSTypeAssertionTypeAnnotation = 282, - TSTypeAssertionExpression = 283, - TSImportEqualsDeclarationId = 284, - TSImportEqualsDeclarationModuleReference = 285, - TSExternalModuleReferenceExpression = 286, - TSNonNullExpressionExpression = 287, - DecoratorExpression = 288, - TSExportAssignmentExpression = 289, - TSNamespaceExportDeclarationId = 290, - TSInstantiationExpressionExpression = 291, - TSInstantiationExpressionTypeArguments = 292, - JSDocNullableTypeTypeAnnotation = 293, - JSDocNonNullableTypeTypeAnnotation = 294, + TSMappedTypeKey = 273, + TSMappedTypeConstraint = 274, + TSMappedTypeNameType = 275, + TSMappedTypeTypeAnnotation = 276, + TSTemplateLiteralTypeQuasis = 277, + TSTemplateLiteralTypeTypes = 278, + TSAsExpressionExpression = 279, + TSAsExpressionTypeAnnotation = 280, + TSSatisfiesExpressionExpression = 281, + TSSatisfiesExpressionTypeAnnotation = 282, + TSTypeAssertionTypeAnnotation = 283, + TSTypeAssertionExpression = 284, + TSImportEqualsDeclarationId = 285, + TSImportEqualsDeclarationModuleReference = 286, + TSExternalModuleReferenceExpression = 287, + TSNonNullExpressionExpression = 288, + DecoratorExpression = 289, + TSExportAssignmentExpression = 290, + TSNamespaceExportDeclarationId = 291, + TSInstantiationExpressionExpression = 292, + TSInstantiationExpressionTypeArguments = 293, + JSDocNullableTypeTypeAnnotation = 294, + JSDocNonNullableTypeTypeAnnotation = 295, } /// Ancestor type used in AST traversal. @@ -843,8 +844,9 @@ pub enum Ancestor<'a, 't> { AncestorType::TSConstructorTypeParams as u16, TSConstructorTypeReturnType(TSConstructorTypeWithoutReturnType<'a, 't>) = AncestorType::TSConstructorTypeReturnType as u16, - TSMappedTypeTypeParameter(TSMappedTypeWithoutTypeParameter<'a, 't>) = - AncestorType::TSMappedTypeTypeParameter as u16, + TSMappedTypeKey(TSMappedTypeWithoutKey<'a, 't>) = AncestorType::TSMappedTypeKey as u16, + TSMappedTypeConstraint(TSMappedTypeWithoutConstraint<'a, 't>) = + AncestorType::TSMappedTypeConstraint as u16, TSMappedTypeNameType(TSMappedTypeWithoutNameType<'a, 't>) = AncestorType::TSMappedTypeNameType as u16, TSMappedTypeTypeAnnotation(TSMappedTypeWithoutTypeAnnotation<'a, 't>) = @@ -1782,7 +1784,8 @@ impl<'a, 't> Ancestor<'a, 't> { pub fn is_ts_mapped_type(self) -> bool { matches!( self, - Self::TSMappedTypeTypeParameter(_) + Self::TSMappedTypeKey(_) + | Self::TSMappedTypeConstraint(_) | Self::TSMappedTypeNameType(_) | Self::TSMappedTypeTypeAnnotation(_) ) @@ -2133,6 +2136,7 @@ impl<'a, 't> Ancestor<'a, 't> { | Self::TSTypeParameterDefault(_) | Self::TSTypeAliasDeclarationTypeAnnotation(_) | Self::TSImportTypeArgument(_) + | Self::TSMappedTypeConstraint(_) | Self::TSMappedTypeNameType(_) | Self::TSMappedTypeTypeAnnotation(_) | Self::TSTemplateLiteralTypeTypes(_) @@ -2479,7 +2483,8 @@ impl<'a, 't> GetAddress for Ancestor<'a, 't> { Self::TSConstructorTypeTypeParameters(a) => a.address(), Self::TSConstructorTypeParams(a) => a.address(), Self::TSConstructorTypeReturnType(a) => a.address(), - Self::TSMappedTypeTypeParameter(a) => a.address(), + Self::TSMappedTypeKey(a) => a.address(), + Self::TSMappedTypeConstraint(a) => a.address(), Self::TSMappedTypeNameType(a) => a.address(), Self::TSMappedTypeTypeAnnotation(a) => a.address(), Self::TSTemplateLiteralTypeQuasis(a) => a.address(), @@ -14886,8 +14891,8 @@ impl<'a, 't> GetAddress for TSConstructorTypeWithoutReturnType<'a, 't> { } pub(crate) const OFFSET_TS_MAPPED_TYPE_SPAN: usize = offset_of!(TSMappedType, span); -pub(crate) const OFFSET_TS_MAPPED_TYPE_TYPE_PARAMETER: usize = - offset_of!(TSMappedType, type_parameter); +pub(crate) const OFFSET_TS_MAPPED_TYPE_KEY: usize = offset_of!(TSMappedType, key); +pub(crate) const OFFSET_TS_MAPPED_TYPE_CONSTRAINT: usize = offset_of!(TSMappedType, constraint); pub(crate) const OFFSET_TS_MAPPED_TYPE_NAME_TYPE: usize = offset_of!(TSMappedType, name_type); pub(crate) const OFFSET_TS_MAPPED_TYPE_TYPE_ANNOTATION: usize = offset_of!(TSMappedType, type_annotation); @@ -14897,17 +14902,92 @@ pub(crate) const OFFSET_TS_MAPPED_TYPE_SCOPE_ID: usize = offset_of!(TSMappedType #[repr(transparent)] #[derive(Clone, Copy, Debug)] -pub struct TSMappedTypeWithoutTypeParameter<'a, 't>( +pub struct TSMappedTypeWithoutKey<'a, 't>( pub(crate) *const TSMappedType<'a>, pub(crate) PhantomData<&'t ()>, ); -impl<'a, 't> TSMappedTypeWithoutTypeParameter<'a, 't> { +impl<'a, 't> TSMappedTypeWithoutKey<'a, 't> { #[inline] pub fn span(self) -> &'t Span { unsafe { &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_SPAN) as *const Span) } } + #[inline] + pub fn constraint(self) -> &'t TSType<'a> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_CONSTRAINT) as *const TSType<'a>) + } + } + + #[inline] + pub fn name_type(self) -> &'t Option> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_NAME_TYPE) + as *const Option>) + } + } + + #[inline] + pub fn type_annotation(self) -> &'t Option> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_TYPE_ANNOTATION) + as *const Option>) + } + } + + #[inline] + pub fn optional(self) -> &'t Option { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_OPTIONAL) + as *const Option) + } + } + + #[inline] + pub fn readonly(self) -> &'t Option { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_READONLY) + as *const Option) + } + } + + #[inline] + pub fn scope_id(self) -> &'t Cell> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_SCOPE_ID) + as *const Cell>) + } + } +} + +impl<'a, 't> GetAddress for TSMappedTypeWithoutKey<'a, 't> { + #[inline] + fn address(&self) -> Address { + Address::from_ptr(self.0) + } +} + +#[repr(transparent)] +#[derive(Clone, Copy, Debug)] +pub struct TSMappedTypeWithoutConstraint<'a, 't>( + pub(crate) *const TSMappedType<'a>, + pub(crate) PhantomData<&'t ()>, +); + +impl<'a, 't> TSMappedTypeWithoutConstraint<'a, 't> { + #[inline] + pub fn span(self) -> &'t Span { + unsafe { &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_SPAN) as *const Span) } + } + + #[inline] + pub fn key(self) -> &'t BindingIdentifier<'a> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_KEY) as *const BindingIdentifier<'a>) + } + } + #[inline] pub fn name_type(self) -> &'t Option> { unsafe { @@ -14949,7 +15029,7 @@ impl<'a, 't> TSMappedTypeWithoutTypeParameter<'a, 't> { } } -impl<'a, 't> GetAddress for TSMappedTypeWithoutTypeParameter<'a, 't> { +impl<'a, 't> GetAddress for TSMappedTypeWithoutConstraint<'a, 't> { #[inline] fn address(&self) -> Address { Address::from_ptr(self.0) @@ -14970,10 +15050,16 @@ impl<'a, 't> TSMappedTypeWithoutNameType<'a, 't> { } #[inline] - pub fn type_parameter(self) -> &'t Box<'a, TSTypeParameter<'a>> { + pub fn key(self) -> &'t BindingIdentifier<'a> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_TYPE_PARAMETER) - as *const Box<'a, TSTypeParameter<'a>>) + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_KEY) as *const BindingIdentifier<'a>) + } + } + + #[inline] + pub fn constraint(self) -> &'t TSType<'a> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_CONSTRAINT) as *const TSType<'a>) } } @@ -15031,10 +15117,16 @@ impl<'a, 't> TSMappedTypeWithoutTypeAnnotation<'a, 't> { } #[inline] - pub fn type_parameter(self) -> &'t Box<'a, TSTypeParameter<'a>> { + pub fn key(self) -> &'t BindingIdentifier<'a> { + unsafe { + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_KEY) as *const BindingIdentifier<'a>) + } + } + + #[inline] + pub fn constraint(self) -> &'t TSType<'a> { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_TYPE_PARAMETER) - as *const Box<'a, TSTypeParameter<'a>>) + &*((self.0 as *const u8).add(OFFSET_TS_MAPPED_TYPE_CONSTRAINT) as *const TSType<'a>) } } diff --git a/crates/oxc_traverse/src/generated/walk.rs b/crates/oxc_traverse/src/generated/walk.rs index e7f0d1faa9e89..58d57fee9076e 100644 --- a/crates/oxc_traverse/src/generated/walk.rs +++ b/crates/oxc_traverse/src/generated/walk.rs @@ -5319,13 +5319,17 @@ unsafe fn walk_ts_mapped_type<'a, State, Tr: Traverse<'a, State>>( .get() .unwrap(); ctx.set_current_scope_id(current_scope_id); - let pop_token = ctx.push_stack(Ancestor::TSMappedTypeTypeParameter( - ancestor::TSMappedTypeWithoutTypeParameter(node, PhantomData), - )); - walk_ts_type_parameter( + let pop_token = ctx + .push_stack(Ancestor::TSMappedTypeKey(ancestor::TSMappedTypeWithoutKey(node, PhantomData))); + walk_binding_identifier( traverser, - (&mut **((node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_TYPE_PARAMETER) - as *mut Box)) as *mut _, + (node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_KEY) as *mut BindingIdentifier, + ctx, + ); + ctx.retag_stack(AncestorType::TSMappedTypeConstraint); + walk_ts_type( + traverser, + (node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_CONSTRAINT) as *mut TSType, ctx, ); if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_NAME_TYPE) diff --git a/napi/parser/generated/deserialize/js.js b/napi/parser/generated/deserialize/js.js index ef2ceb2addc93..7addf1f787918 100644 --- a/napi/parser/generated/deserialize/js.js +++ b/napi/parser/generated/deserialize/js.js @@ -3948,19 +3948,16 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, }, - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name, - { constraint } = typeParameter, - optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; return node; } diff --git a/napi/parser/generated/deserialize/js_parent.js b/napi/parser/generated/deserialize/js_parent.js index c642a9cad873d..db45d78883679 100644 --- a/napi/parser/generated/deserialize/js_parent.js +++ b/napi/parser/generated/deserialize/js_parent.js @@ -4614,22 +4614,17 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, parent, }), - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name; - key.parent = parent; - let { constraint } = typeParameter; - constraint !== null && (constraint.parent = parent); - let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; parent = previousParent; return node; diff --git a/napi/parser/generated/deserialize/js_range.js b/napi/parser/generated/deserialize/js_range.js index 8e89617feee9d..81aa11a2900ee 100644 --- a/napi/parser/generated/deserialize/js_range.js +++ b/napi/parser/generated/deserialize/js_range.js @@ -4350,20 +4350,17 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, range: [start, end], }, - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name, - { constraint } = typeParameter, - optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; return node; } diff --git a/napi/parser/generated/deserialize/js_range_parent.js b/napi/parser/generated/deserialize/js_range_parent.js index dda30ff14cd4e..7b7b4153a3b65 100644 --- a/napi/parser/generated/deserialize/js_range_parent.js +++ b/napi/parser/generated/deserialize/js_range_parent.js @@ -4836,23 +4836,18 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, range: [start, end], parent, }), - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name; - key.parent = parent; - let { constraint } = typeParameter; - constraint !== null && (constraint.parent = parent); - let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; parent = previousParent; return node; diff --git a/napi/parser/generated/deserialize/ts.js b/napi/parser/generated/deserialize/ts.js index 6eff410cb6343..cd37d87c8304a 100644 --- a/napi/parser/generated/deserialize/ts.js +++ b/napi/parser/generated/deserialize/ts.js @@ -4206,19 +4206,16 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, }, - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name, - { constraint } = typeParameter, - optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; return node; } diff --git a/napi/parser/generated/deserialize/ts_parent.js b/napi/parser/generated/deserialize/ts_parent.js index 758dcfb9b75e3..0409e6528000b 100644 --- a/napi/parser/generated/deserialize/ts_parent.js +++ b/napi/parser/generated/deserialize/ts_parent.js @@ -4880,22 +4880,17 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, parent, }), - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name; - key.parent = parent; - let { constraint } = typeParameter; - constraint !== null && (constraint.parent = parent); - let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; parent = previousParent; return node; diff --git a/napi/parser/generated/deserialize/ts_range.js b/napi/parser/generated/deserialize/ts_range.js index 2fe83d5101619..e3da8d31e2125 100644 --- a/napi/parser/generated/deserialize/ts_range.js +++ b/napi/parser/generated/deserialize/ts_range.js @@ -4607,20 +4607,17 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, range: [start, end], }, - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name, - { constraint } = typeParameter, - optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; return node; } diff --git a/napi/parser/generated/deserialize/ts_range_parent.js b/napi/parser/generated/deserialize/ts_range_parent.js index fab01a6dbe62c..7756f4fcca9b2 100644 --- a/napi/parser/generated/deserialize/ts_range_parent.js +++ b/napi/parser/generated/deserialize/ts_range_parent.js @@ -5109,23 +5109,18 @@ function deserializeTSMappedType(pos) { nameType: null, typeAnnotation: null, optional: null, - readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53), + readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 93), start, end, range: [start, end], parent, }), - typeParameter = deserializeBoxTSTypeParameter(pos + 8), - key = typeParameter.name; - key.parent = parent; - let { constraint } = typeParameter; - constraint !== null && (constraint.parent = parent); - let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52); + optional = deserializeOptionTSMappedTypeModifierOperator(pos + 92); optional === null && (optional = false); - node.key = key; - node.constraint = constraint; - node.nameType = deserializeOptionTSType(pos + 16); - node.typeAnnotation = deserializeOptionTSType(pos + 32); + node.key = deserializeBindingIdentifier(pos + 8); + node.constraint = deserializeTSType(pos + 40); + node.nameType = deserializeOptionTSType(pos + 56); + node.typeAnnotation = deserializeOptionTSType(pos + 72); node.optional = optional; parent = previousParent; return node; diff --git a/napi/parser/generated/lazy/constructors.js b/napi/parser/generated/lazy/constructors.js index f91f7f9318efc..e139df84795cb 100644 --- a/napi/parser/generated/lazy/constructors.js +++ b/napi/parser/generated/lazy/constructors.js @@ -10885,24 +10885,34 @@ export class TSMappedType { return constructU32(internal.pos + 4, internal.ast); } + get key() { + const internal = this.#internal; + return new BindingIdentifier(internal.pos + 8, internal.ast); + } + + get constraint() { + const internal = this.#internal; + return constructTSType(internal.pos + 40, internal.ast); + } + get nameType() { const internal = this.#internal; - return constructOptionTSType(internal.pos + 16, internal.ast); + return constructOptionTSType(internal.pos + 56, internal.ast); } get typeAnnotation() { const internal = this.#internal; - return constructOptionTSType(internal.pos + 32, internal.ast); + return constructOptionTSType(internal.pos + 72, internal.ast); } get optional() { const internal = this.#internal; - return constructOptionTSMappedTypeModifierOperator(internal.pos + 52, internal.ast); + return constructOptionTSMappedTypeModifierOperator(internal.pos + 92, internal.ast); } get readonly() { const internal = this.#internal; - return constructOptionTSMappedTypeModifierOperator(internal.pos + 53, internal.ast); + return constructOptionTSMappedTypeModifierOperator(internal.pos + 93, internal.ast); } toJSON() { @@ -10910,6 +10920,8 @@ export class TSMappedType { type: 'TSMappedType', start: this.start, end: this.end, + key: this.key, + constraint: this.constraint, nameType: this.nameType, typeAnnotation: this.typeAnnotation, optional: this.optional, diff --git a/napi/parser/generated/lazy/walk.js b/napi/parser/generated/lazy/walk.js index a5ea4e160b423..c98cb7988946f 100644 --- a/napi/parser/generated/lazy/walk.js +++ b/napi/parser/generated/lazy/walk.js @@ -4452,8 +4452,10 @@ function walkTSMappedType(pos, ast, visitors) { if (enter !== null) enter(node); } - walkOptionTSType(pos + 16, ast, visitors); - walkOptionTSType(pos + 32, ast, visitors); + walkBindingIdentifier(pos + 8, ast, visitors); + walkTSType(pos + 40, ast, visitors); + walkOptionTSType(pos + 56, ast, visitors); + walkOptionTSType(pos + 72, ast, visitors); if (exit !== null) exit(node); } diff --git a/npm/oxc-types/types.d.ts b/npm/oxc-types/types.d.ts index ef5f12de0ce3d..163ea80ddc6cb 100644 --- a/npm/oxc-types/types.d.ts +++ b/npm/oxc-types/types.d.ts @@ -1542,8 +1542,8 @@ export interface TSConstructorType extends Span { export interface TSMappedType extends Span { type: 'TSMappedType'; - key: TSTypeParameter['name']; - constraint: TSTypeParameter['constraint']; + key: BindingIdentifier; + constraint: TSType; nameType: TSType | null; typeAnnotation: TSType | null; optional: TSMappedTypeModifierOperator | false; diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index ea133e2a6bd99..4d459702dc14e 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -21455,13 +21455,13 @@ Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(6), ScopeId(11), ScopeId(12), ScopeId(13), ScopeId(14), ScopeId(15), ScopeId(16)] rebuilt : ScopeId(0): [ScopeId(1)] Reference symbol mismatch for "object": -after transform: SymbolId(14) "object" +after transform: SymbolId(13) "object" rebuilt : Reference symbol mismatch for "string": -after transform: SymbolId(17) "string" +after transform: SymbolId(16) "string" rebuilt : Reference symbol mismatch for "optional": -after transform: SymbolId(18) "optional" +after transform: SymbolId(17) "optional" rebuilt : Unresolved references mismatch: after transform: ["Record"] @@ -21475,13 +21475,13 @@ Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(6), ScopeId(11), ScopeId(12), ScopeId(13), ScopeId(14), ScopeId(15), ScopeId(16)] rebuilt : ScopeId(0): [ScopeId(1)] Reference symbol mismatch for "object": -after transform: SymbolId(14) "object" +after transform: SymbolId(13) "object" rebuilt : Reference symbol mismatch for "string": -after transform: SymbolId(17) "string" +after transform: SymbolId(16) "string" rebuilt : Reference symbol mismatch for "optional": -after transform: SymbolId(18) "optional" +after transform: SymbolId(17) "optional" rebuilt : Unresolved references mismatch: after transform: ["Record"] @@ -48043,22 +48043,22 @@ Scope children mismatch: after transform: ScopeId(1): [ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5)] rebuilt : ScopeId(1): [] Reference symbol mismatch for "assign": -after transform: SymbolId(21) "assign" +after transform: SymbolId(18) "assign" rebuilt : Reference symbol mismatch for "assign": -after transform: SymbolId(21) "assign" +after transform: SymbolId(18) "assign" rebuilt : Reference symbol mismatch for "freeze": -after transform: SymbolId(25) "freeze" +after transform: SymbolId(22) "freeze" rebuilt : Reference symbol mismatch for "pick": -after transform: SymbolId(28) "pick" +after transform: SymbolId(25) "pick" rebuilt : Reference symbol mismatch for "mapObject": -after transform: SymbolId(33) "mapObject" +after transform: SymbolId(30) "mapObject" rebuilt : Reference symbol mismatch for "proxify": -after transform: SymbolId(40) "proxify" +after transform: SymbolId(37) "proxify" rebuilt : Unresolved references mismatch: after transform: ["Partial", "Pick", "Readonly", "Record"] @@ -57068,7 +57068,7 @@ Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(7), ScopeId(9), ScopeId(10), ScopeId(11), ScopeId(12)] rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)] Reference symbol mismatch for "ConflictTarget": -after transform: SymbolId(12) "ConflictTarget" +after transform: SymbolId(11) "ConflictTarget" rebuilt : Unresolved references mismatch: after transform: ["Error"]