From dc6d45e2e6ac130da425f1bbf0d5d2d6440ccd8b Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Sun, 30 Jun 2024 07:57:47 +0000 Subject: [PATCH] feat(ast,codegen): add `TSParenthesizedType` and print type parentheses correctly (#3979) closes #3916 --- crates/oxc_ast/src/ast/macros.rs | 9 +- crates/oxc_ast/src/ast/ts.rs | 18 +- crates/oxc_ast/src/ast_builder.rs | 5 + crates/oxc_ast/src/ast_impl/ts.rs | 10 + crates/oxc_ast/src/ast_kind_impl.rs | 1 + crates/oxc_ast/src/generated/ast_kind.rs | 3 + crates/oxc_ast/src/generated/span.rs | 9 + crates/oxc_ast/src/visit/visit.rs | 1 + crates/oxc_codegen/src/gen.rs | 25 +-- crates/oxc_codegen/tests/mod.rs | 6 +- .../tests/snapshots/infer-return-type.snap | 2 +- .../tests/snapshots/readonly.snap | 2 +- .../src/rules/typescript/array_type.rs | 1 + crates/oxc_parser/src/ts/types.rs | 5 +- crates/oxc_prettier/src/format/mod.rs | 7 + crates/oxc_traverse/src/ancestor.rs | 210 ++++++++++-------- crates/oxc_traverse/src/traverse.rs | 15 ++ crates/oxc_traverse/src/walk.rs | 23 ++ 18 files changed, 233 insertions(+), 119 deletions(-) diff --git a/crates/oxc_ast/src/ast/macros.rs b/crates/oxc_ast/src/ast/macros.rs index b5ea9b761..8c8599641 100644 --- a/crates/oxc_ast/src/ast/macros.rs +++ b/crates/oxc_ast/src/ast/macros.rs @@ -616,14 +616,16 @@ macro_rules! inherit_variants { TSTypeReference(Box<'a, TSTypeReference<'a>>) = 32, /// Inherited from [`TSType`] TSUnionType(Box<'a, TSUnionType<'a>>) = 33, + /// Inherited from [`TSType`] + TSParenthesizedType(Box<'a, TSParenthesizedType<'a>>) = 34, // JSDoc /// Inherited from [`TSType`] - JSDocNullableType(Box<'a, JSDocNullableType<'a>>) = 34, + JSDocNullableType(Box<'a, JSDocNullableType<'a>>) = 35, /// Inherited from [`TSType`] - JSDocNonNullableType(Box<'a, JSDocNonNullableType<'a>>) = 35, + JSDocNonNullableType(Box<'a, JSDocNonNullableType<'a>>) = 36, /// Inherited from [`TSType`] - JSDocUnknownType(Box<'a, JSDocUnknownType>) = 36, + JSDocUnknownType(Box<'a, JSDocUnknownType>) = 37, $($rest)* } @@ -672,6 +674,7 @@ macro_rules! inherit_variants { TSTypeQuery, TSTypeReference, TSUnionType, + TSParenthesizedType, JSDocNullableType, JSDocNonNullableType, JSDocUnknownType, diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index dda675f56..d9669d6d0 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -172,10 +172,11 @@ pub enum TSType<'a> { TSTypeQuery(Box<'a, TSTypeQuery<'a>>) = 31, TSTypeReference(Box<'a, TSTypeReference<'a>>) = 32, TSUnionType(Box<'a, TSUnionType<'a>>) = 33, + TSParenthesizedType(Box<'a, TSParenthesizedType<'a>>) = 34, // JSDoc - JSDocNullableType(Box<'a, JSDocNullableType<'a>>) = 34, - JSDocNonNullableType(Box<'a, JSDocNonNullableType<'a>>) = 35, - JSDocUnknownType(Box<'a, JSDocUnknownType>) = 36, + JSDocNullableType(Box<'a, JSDocNullableType<'a>>) = 35, + JSDocNonNullableType(Box<'a, JSDocNonNullableType<'a>>) = 36, + JSDocUnknownType(Box<'a, JSDocUnknownType>) = 37, } /// Macro for matching `TSType`'s variants. @@ -216,6 +217,7 @@ macro_rules! match_ts_type { | $ty::TSTypeQuery(_) | $ty::TSTypeReference(_) | $ty::TSUnionType(_) + | $ty::TSParenthesizedType(_) | $ty::JSDocNullableType(_) | $ty::JSDocNonNullableType(_) | $ty::JSDocUnknownType(_) @@ -265,6 +267,16 @@ pub struct TSIntersectionType<'a> { pub types: Vec<'a, TSType<'a>>, } +#[visited_node] +#[derive(Debug, Hash)] +#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] +#[cfg_attr(feature = "serialize", serde(tag = "type"))] +pub struct TSParenthesizedType<'a> { + #[cfg_attr(feature = "serialize", serde(flatten))] + pub span: Span, + pub type_annotation: TSType<'a>, +} + /// keyof unique readonly /// /// diff --git a/crates/oxc_ast/src/ast_builder.rs b/crates/oxc_ast/src/ast_builder.rs index bd7d65bd1..e2a535522 100644 --- a/crates/oxc_ast/src/ast_builder.rs +++ b/crates/oxc_ast/src/ast_builder.rs @@ -1539,6 +1539,11 @@ impl<'a> AstBuilder<'a> { TSType::TSUnionType(self.alloc(TSUnionType { span, types })) } + #[inline] + pub fn ts_parenthesized_type(self, span: Span, ty: TSType<'a>) -> TSType<'a> { + TSType::TSParenthesizedType(self.alloc(TSParenthesizedType { span, type_annotation: ty })) + } + #[inline] pub fn ts_intersection_type(self, span: Span, types: Vec<'a, TSType<'a>>) -> TSType<'a> { TSType::TSIntersectionType(self.alloc(TSIntersectionType { span, types })) diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 8ec765af1..17973c988 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -128,6 +128,16 @@ impl<'a> Hash for TSTypeParameter<'a> { } } +impl<'a> TSType<'a> { + /// Remove nested parentheses from this type. + pub fn without_parenthesized(&self) -> &Self { + match self { + Self::TSParenthesizedType(expr) => expr.type_annotation.without_parenthesized(), + _ => self, + } + } +} + impl TSAccessibility { pub fn is_private(&self) -> bool { matches!(self, TSAccessibility::Private) diff --git a/crates/oxc_ast/src/ast_kind_impl.rs b/crates/oxc_ast/src/ast_kind_impl.rs index c02deb6f1..8b7d53a8f 100644 --- a/crates/oxc_ast/src/ast_kind_impl.rs +++ b/crates/oxc_ast/src/ast_kind_impl.rs @@ -299,6 +299,7 @@ impl<'a> AstKind<'a> { Self::TSTypeLiteral(_) => "TSTypeLiteral".into(), Self::TSTypeReference(_) => "TSTypeReference".into(), Self::TSUnionType(_) => "TSUnionType".into(), + Self::TSParenthesizedType(_) => "TSParenthesizedType".into(), Self::TSVoidKeyword(_) => "TSVoidKeyword".into(), Self::TSBigIntKeyword(_) => "TSBigIntKeyword".into(), Self::TSBooleanKeyword(_) => "TSBooleanKeyword".into(), diff --git a/crates/oxc_ast/src/generated/ast_kind.rs b/crates/oxc_ast/src/generated/ast_kind.rs index 0d8d9b1e3..d8d04f58f 100644 --- a/crates/oxc_ast/src/generated/ast_kind.rs +++ b/crates/oxc_ast/src/generated/ast_kind.rs @@ -107,6 +107,7 @@ pub enum AstType { TSLiteralType, TSUnionType, TSIntersectionType, + TSParenthesizedType, TSIndexedAccessType, TSNamedTupleMember, TSAnyKeyword, @@ -272,6 +273,7 @@ pub enum AstKind<'a> { TSLiteralType(&'a TSLiteralType<'a>), TSUnionType(&'a TSUnionType<'a>), TSIntersectionType(&'a TSIntersectionType<'a>), + TSParenthesizedType(&'a TSParenthesizedType<'a>), TSIndexedAccessType(&'a TSIndexedAccessType<'a>), TSNamedTupleMember(&'a TSNamedTupleMember<'a>), TSAnyKeyword(&'a TSAnyKeyword), @@ -438,6 +440,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::TSLiteralType(it) => it.span(), Self::TSUnionType(it) => it.span(), Self::TSIntersectionType(it) => it.span(), + Self::TSParenthesizedType(it) => it.span(), Self::TSIndexedAccessType(it) => it.span(), Self::TSNamedTupleMember(it) => it.span(), Self::TSAnyKeyword(it) => it.span(), diff --git a/crates/oxc_ast/src/generated/span.rs b/crates/oxc_ast/src/generated/span.rs index babc64442..8bcf4ffe4 100644 --- a/crates/oxc_ast/src/generated/span.rs +++ b/crates/oxc_ast/src/generated/span.rs @@ -1384,6 +1384,7 @@ impl<'a> GetSpan for TSType<'a> { Self::TSTypeQuery(it) => it.span(), Self::TSTypeReference(it) => it.span(), Self::TSUnionType(it) => it.span(), + Self::TSParenthesizedType(it) => it.span(), Self::JSDocNullableType(it) => it.span(), Self::JSDocNonNullableType(it) => it.span(), Self::JSDocUnknownType(it) => it.span(), @@ -1412,6 +1413,13 @@ impl<'a> GetSpan for TSIntersectionType<'a> { } } +impl<'a> GetSpan for TSParenthesizedType<'a> { + #[inline] + fn span(&self) -> Span { + self.span + } +} + impl<'a> GetSpan for TSTypeOperator<'a> { #[inline] fn span(&self) -> Span { @@ -1500,6 +1508,7 @@ impl<'a> GetSpan for TSTupleElement<'a> { Self::TSTypeQuery(it) => it.span(), Self::TSTypeReference(it) => it.span(), Self::TSUnionType(it) => it.span(), + Self::TSParenthesizedType(it) => it.span(), Self::JSDocNullableType(it) => it.span(), Self::JSDocNonNullableType(it) => it.span(), Self::JSDocUnknownType(it) => it.span(), diff --git a/crates/oxc_ast/src/visit/visit.rs b/crates/oxc_ast/src/visit/visit.rs index 7642617f1..818ae6d30 100644 --- a/crates/oxc_ast/src/visit/visit.rs +++ b/crates/oxc_ast/src/visit/visit.rs @@ -2815,6 +2815,7 @@ pub mod walk { TSType::TSTypeQuery(ty) => visitor.visit_ts_type_query(ty), TSType::TSTypeReference(ty) => visitor.visit_ts_type_reference(ty), TSType::TSUnionType(ty) => visitor.visit_ts_union_type(ty), + TSType::TSParenthesizedType(ty) => visitor.visit_ts_type(&ty.type_annotation), // JSDoc TSType::JSDocNullableType(_) | TSType::JSDocNonNullableType(_) diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 3b80d4652..acaad30d4 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -2670,6 +2670,7 @@ impl<'a, const MINIFY: bool> Gen for TSType<'a> { Self::TSArrayType(ty) => ty.gen(p, ctx), Self::TSTupleType(ty) => ty.gen(p, ctx), Self::TSUnionType(ty) => ty.gen(p, ctx), + Self::TSParenthesizedType(ty) => ty.gen(p, ctx), Self::TSIntersectionType(ty) => ty.gen(p, ctx), Self::TSConditionalType(ty) => ty.gen(p, ctx), Self::TSInferType(ty) => ty.gen(p, ctx), @@ -2708,9 +2709,8 @@ impl<'a, const MINIFY: bool> Gen for TSType<'a> { impl<'a, const MINIFY: bool> Gen for TSArrayType<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { - p.print_str(b"("); self.element_type.gen(p, ctx); - p.print_str(b")[]"); + p.print_str(b"[]"); } } @@ -2728,18 +2728,22 @@ impl<'a, const MINIFY: bool> Gen for TSUnionType<'a> { self.types[0].gen(p, ctx); return; } - p.print_str(b"("); for (index, item) in self.types.iter().enumerate() { if index != 0 { p.print_soft_space(); p.print_str(b"|"); p.print_soft_space(); } - p.print_str(b"("); item.gen(p, ctx); - p.print_str(b")"); } - p.print_str(b")"); + } +} + +impl<'a, const MINIFY: bool> Gen for TSParenthesizedType<'a> { + fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { + p.print(b'('); + self.type_annotation.gen(p, ctx); + p.print(b')'); } } @@ -2749,28 +2753,23 @@ impl<'a, const MINIFY: bool> Gen for TSIntersectionType<'a> { self.types[0].gen(p, ctx); return; } - - p.print_str(b"("); for (index, item) in self.types.iter().enumerate() { if index != 0 { p.print_soft_space(); p.print_str(b"&"); p.print_soft_space(); } - p.print_str(b"("); item.gen(p, ctx); - p.print_str(b")"); } - p.print_str(b")"); } } impl<'a, const MINIFY: bool> Gen for TSConditionalType<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { self.check_type.gen(p, ctx); - p.print_str(b" extends ("); + p.print_str(b" extends "); self.extends_type.gen(p, ctx); - p.print_str(b") ? "); + p.print_str(b" ? "); self.true_type.gen(p, ctx); p.print_str(b" : "); self.false_type.gen(p, ctx); diff --git a/crates/oxc_codegen/tests/mod.rs b/crates/oxc_codegen/tests/mod.rs index 01ce07c98..c7422ac9c 100644 --- a/crates/oxc_codegen/tests/mod.rs +++ b/crates/oxc_codegen/tests/mod.rs @@ -147,7 +147,7 @@ fn typescript() { test_ts( "let x: string[] = ['abc', 'def', 'ghi'];", - "let x: (string)[] = ['abc', 'def', 'ghi'];\n", + "let x: string[] = ['abc', 'def', 'ghi'];\n", false, ); test_ts( @@ -160,8 +160,8 @@ fn typescript() { "let x: [string, number] = ['abc', 123];\n", false, ); - test_ts("let x: string | number = 'abc';", "let x: ((string) | (number)) = 'abc';\n", false); - test_ts("let x: string & number = 'abc';", "let x: ((string) & (number)) = 'abc';\n", false); + test_ts("let x: string | number = 'abc';", "let x: string | number = 'abc';\n", false); + test_ts("let x: string & number = 'abc';", "let x: string & number = 'abc';\n", false); test_ts("let x: typeof String = 'string';", "let x: typeof String = 'string';\n", false); test_ts("let x: keyof string = 'length';", "let x: keyof string = 'length';\n", false); test_ts( diff --git a/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap b/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap index f577f2951..10baf48c5 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap @@ -5,7 +5,7 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/infer-return-type.ts ==================== .D.TS ==================== declare function foo(): number; -declare function bar(): ((number) | (undefined)); +declare function bar(): number | undefined; declare function baz(); declare function qux(): string; diff --git a/crates/oxc_isolated_declarations/tests/snapshots/readonly.snap b/crates/oxc_isolated_declarations/tests/snapshots/readonly.snap index 8aabed4ae..fb2c57bbe 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/readonly.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/readonly.snap @@ -5,4 +5,4 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/readonly.ts ==================== .D.TS ==================== export declare const EMPTY_OBJ: {readonly [key: string]: any}; -export declare const EMPTY_ARR: readonly (never)[]; +export declare const EMPTY_ARR: readonly never[]; diff --git a/crates/oxc_linter/src/rules/typescript/array_type.rs b/crates/oxc_linter/src/rules/typescript/array_type.rs index c1933508f..62fca50b8 100644 --- a/crates/oxc_linter/src/rules/typescript/array_type.rs +++ b/crates/oxc_linter/src/rules/typescript/array_type.rs @@ -182,6 +182,7 @@ fn check_and_report_error_generic( if matches!(config, ArrayOption::Array) { return; } + let type_param = type_param.without_parenthesized(); if matches!(config, ArrayOption::ArraySimple) && is_simple_type(type_param) { return; } diff --git a/crates/oxc_parser/src/ts/types.rs b/crates/oxc_parser/src/ts/types.rs index 53b3dfc3f..9e785372b 100644 --- a/crates/oxc_parser/src/ts/types.rs +++ b/crates/oxc_parser/src/ts/types.rs @@ -889,10 +889,11 @@ impl<'a> ParserImpl<'a> { } fn parse_parenthesized_type(&mut self) -> Result> { + let span = self.start_span(); self.bump_any(); // bump `(` - let result = self.parse_ts_type()?; + let ty = self.parse_ts_type()?; self.expect(Kind::RParen)?; - Ok(result) + Ok(self.ast.ts_parenthesized_type(self.end_span(span), ty)) } fn parse_literal_type_node(&mut self, negative: bool) -> Result> { diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index 559dc7c04..9e42b4d66 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -686,6 +686,7 @@ impl<'a> Format<'a> for TSType<'a> { TSType::TSTypeQuery(v) => v.format(p), TSType::TSTypeReference(v) => v.format(p), TSType::TSUnionType(v) => v.format(p), + TSType::TSParenthesizedType(v) => v.format(p), TSType::JSDocNullableType(v) => v.format(p), TSType::JSDocNonNullableType(v) => v.format(p), TSType::JSDocUnknownType(v) => v.format(p), @@ -920,6 +921,12 @@ impl<'a> Format<'a> for TSTypeReference<'a> { } } +impl<'a> Format<'a> for TSParenthesizedType<'a> { + fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { + wrap!(p, self, TSParenthesizedType, { self.type_annotation.format(p) }) + } +} + impl<'a> Format<'a> for TSUnionType<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() diff --git a/crates/oxc_traverse/src/ancestor.rs b/crates/oxc_traverse/src/ancestor.rs index d88c9012a..45e5e901c 100644 --- a/crates/oxc_traverse/src/ancestor.rs +++ b/crates/oxc_traverse/src/ancestor.rs @@ -230,99 +230,100 @@ pub(crate) enum AncestorType { TSConditionalTypeFalseType = 198, TSUnionTypeTypes = 199, TSIntersectionTypeTypes = 200, - TSTypeOperatorTypeAnnotation = 201, - TSArrayTypeElementType = 202, - TSIndexedAccessTypeObjectType = 203, - TSIndexedAccessTypeIndexType = 204, - TSTupleTypeElementTypes = 205, - TSNamedTupleMemberElementType = 206, - TSNamedTupleMemberLabel = 207, - TSOptionalTypeTypeAnnotation = 208, - TSRestTypeTypeAnnotation = 209, - TSTypeReferenceTypeName = 210, - TSTypeReferenceTypeParameters = 211, - TSQualifiedNameLeft = 212, - TSQualifiedNameRight = 213, - TSTypeParameterInstantiationParams = 214, - TSTypeParameterName = 215, - TSTypeParameterConstraint = 216, - TSTypeParameterDefault = 217, - TSTypeParameterDeclarationParams = 218, - TSTypeAliasDeclarationId = 219, - TSTypeAliasDeclarationTypeAnnotation = 220, - TSTypeAliasDeclarationTypeParameters = 221, - TSClassImplementsExpression = 222, - TSClassImplementsTypeParameters = 223, - TSInterfaceDeclarationId = 224, - TSInterfaceDeclarationBody = 225, - TSInterfaceDeclarationTypeParameters = 226, - TSInterfaceDeclarationExtends = 227, - TSInterfaceBodyBody = 228, - TSPropertySignatureKey = 229, - TSPropertySignatureTypeAnnotation = 230, - TSIndexSignatureParameters = 231, - TSIndexSignatureTypeAnnotation = 232, - TSCallSignatureDeclarationThisParam = 233, - TSCallSignatureDeclarationParams = 234, - TSCallSignatureDeclarationReturnType = 235, - TSCallSignatureDeclarationTypeParameters = 236, - TSMethodSignatureKey = 237, - TSMethodSignatureThisParam = 238, - TSMethodSignatureParams = 239, - TSMethodSignatureReturnType = 240, - TSMethodSignatureTypeParameters = 241, - TSConstructSignatureDeclarationParams = 242, - TSConstructSignatureDeclarationReturnType = 243, - TSConstructSignatureDeclarationTypeParameters = 244, - TSIndexSignatureNameTypeAnnotation = 245, - TSInterfaceHeritageExpression = 246, - TSInterfaceHeritageTypeParameters = 247, - TSTypePredicateParameterName = 248, - TSTypePredicateTypeAnnotation = 249, - TSModuleDeclarationId = 250, - TSModuleDeclarationBody = 251, - TSModuleBlockDirectives = 252, - TSModuleBlockBody = 253, - TSTypeLiteralMembers = 254, - TSInferTypeTypeParameter = 255, - TSTypeQueryExprName = 256, - TSTypeQueryTypeParameters = 257, - TSImportTypeParameter = 258, - TSImportTypeQualifier = 259, - TSImportTypeAttributes = 260, - TSImportTypeTypeParameters = 261, - TSImportAttributesElements = 262, - TSImportAttributeName = 263, - TSImportAttributeValue = 264, - TSFunctionTypeThisParam = 265, - TSFunctionTypeParams = 266, - TSFunctionTypeReturnType = 267, - TSFunctionTypeTypeParameters = 268, - TSConstructorTypeParams = 269, - TSConstructorTypeReturnType = 270, - TSConstructorTypeTypeParameters = 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, - TSInstantiationExpressionTypeParameters = 291, - JSDocNullableTypeTypeAnnotation = 292, - JSDocNonNullableTypeTypeAnnotation = 293, + TSParenthesizedTypeTypeAnnotation = 201, + TSTypeOperatorTypeAnnotation = 202, + TSArrayTypeElementType = 203, + TSIndexedAccessTypeObjectType = 204, + TSIndexedAccessTypeIndexType = 205, + TSTupleTypeElementTypes = 206, + TSNamedTupleMemberElementType = 207, + TSNamedTupleMemberLabel = 208, + TSOptionalTypeTypeAnnotation = 209, + TSRestTypeTypeAnnotation = 210, + TSTypeReferenceTypeName = 211, + TSTypeReferenceTypeParameters = 212, + TSQualifiedNameLeft = 213, + TSQualifiedNameRight = 214, + TSTypeParameterInstantiationParams = 215, + TSTypeParameterName = 216, + TSTypeParameterConstraint = 217, + TSTypeParameterDefault = 218, + TSTypeParameterDeclarationParams = 219, + TSTypeAliasDeclarationId = 220, + TSTypeAliasDeclarationTypeAnnotation = 221, + TSTypeAliasDeclarationTypeParameters = 222, + TSClassImplementsExpression = 223, + TSClassImplementsTypeParameters = 224, + TSInterfaceDeclarationId = 225, + TSInterfaceDeclarationBody = 226, + TSInterfaceDeclarationTypeParameters = 227, + TSInterfaceDeclarationExtends = 228, + TSInterfaceBodyBody = 229, + TSPropertySignatureKey = 230, + TSPropertySignatureTypeAnnotation = 231, + TSIndexSignatureParameters = 232, + TSIndexSignatureTypeAnnotation = 233, + TSCallSignatureDeclarationThisParam = 234, + TSCallSignatureDeclarationParams = 235, + TSCallSignatureDeclarationReturnType = 236, + TSCallSignatureDeclarationTypeParameters = 237, + TSMethodSignatureKey = 238, + TSMethodSignatureThisParam = 239, + TSMethodSignatureParams = 240, + TSMethodSignatureReturnType = 241, + TSMethodSignatureTypeParameters = 242, + TSConstructSignatureDeclarationParams = 243, + TSConstructSignatureDeclarationReturnType = 244, + TSConstructSignatureDeclarationTypeParameters = 245, + TSIndexSignatureNameTypeAnnotation = 246, + TSInterfaceHeritageExpression = 247, + TSInterfaceHeritageTypeParameters = 248, + TSTypePredicateParameterName = 249, + TSTypePredicateTypeAnnotation = 250, + TSModuleDeclarationId = 251, + TSModuleDeclarationBody = 252, + TSModuleBlockDirectives = 253, + TSModuleBlockBody = 254, + TSTypeLiteralMembers = 255, + TSInferTypeTypeParameter = 256, + TSTypeQueryExprName = 257, + TSTypeQueryTypeParameters = 258, + TSImportTypeParameter = 259, + TSImportTypeQualifier = 260, + TSImportTypeAttributes = 261, + TSImportTypeTypeParameters = 262, + TSImportAttributesElements = 263, + TSImportAttributeName = 264, + TSImportAttributeValue = 265, + TSFunctionTypeThisParam = 266, + TSFunctionTypeParams = 267, + TSFunctionTypeReturnType = 268, + TSFunctionTypeTypeParameters = 269, + TSConstructorTypeParams = 270, + TSConstructorTypeReturnType = 271, + TSConstructorTypeTypeParameters = 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, + TSInstantiationExpressionTypeParameters = 292, + JSDocNullableTypeTypeAnnotation = 293, + JSDocNonNullableTypeTypeAnnotation = 294, } /// Ancestor type used in AST traversal. @@ -683,6 +684,8 @@ pub enum Ancestor<'a> { TSUnionTypeTypes(TSUnionTypeWithoutTypes<'a>) = AncestorType::TSUnionTypeTypes as u16, TSIntersectionTypeTypes(TSIntersectionTypeWithoutTypes<'a>) = AncestorType::TSIntersectionTypeTypes as u16, + TSParenthesizedTypeTypeAnnotation(TSParenthesizedTypeWithoutTypeAnnotation<'a>) = + AncestorType::TSParenthesizedTypeTypeAnnotation as u16, TSTypeOperatorTypeAnnotation(TSTypeOperatorWithoutTypeAnnotation<'a>) = AncestorType::TSTypeOperatorTypeAnnotation as u16, TSArrayTypeElementType(TSArrayTypeWithoutElementType<'a>) = @@ -1511,6 +1514,11 @@ impl<'a> Ancestor<'a> { matches!(self, Self::TSIntersectionTypeTypes(_)) } + #[inline] + pub fn is_ts_parenthesized_type(&self) -> bool { + matches!(self, Self::TSParenthesizedTypeTypeAnnotation(_)) + } + #[inline] pub fn is_ts_type_operator(&self) -> bool { matches!(self, Self::TSTypeOperatorTypeAnnotation(_)) @@ -2088,6 +2096,7 @@ impl<'a> Ancestor<'a> { | Self::TSConditionalTypeFalseType(_) | Self::TSUnionTypeTypes(_) | Self::TSIntersectionTypeTypes(_) + | Self::TSParenthesizedTypeTypeAnnotation(_) | Self::TSTypeOperatorTypeAnnotation(_) | Self::TSArrayTypeElementType(_) | Self::TSIndexedAccessTypeObjectType(_) @@ -8996,6 +9005,21 @@ impl<'a> TSIntersectionTypeWithoutTypes<'a> { } } +pub(crate) const OFFSET_TS_PARENTHESIZED_TYPE_SPAN: usize = offset_of!(TSParenthesizedType, span); +pub(crate) const OFFSET_TS_PARENTHESIZED_TYPE_TYPE_ANNOTATION: usize = + offset_of!(TSParenthesizedType, type_annotation); + +#[repr(transparent)] +#[derive(Debug)] +pub struct TSParenthesizedTypeWithoutTypeAnnotation<'a>(pub(crate) *const TSParenthesizedType<'a>); + +impl<'a> TSParenthesizedTypeWithoutTypeAnnotation<'a> { + #[inline] + pub fn span(&self) -> &Span { + unsafe { &*((self.0 as *const u8).add(OFFSET_TS_PARENTHESIZED_TYPE_SPAN) as *const Span) } + } +} + pub(crate) const OFFSET_TS_TYPE_OPERATOR_SPAN: usize = offset_of!(TSTypeOperator, span); pub(crate) const OFFSET_TS_TYPE_OPERATOR_OPERATOR: usize = offset_of!(TSTypeOperator, operator); pub(crate) const OFFSET_TS_TYPE_OPERATOR_TYPE_ANNOTATION: usize = diff --git a/crates/oxc_traverse/src/traverse.rs b/crates/oxc_traverse/src/traverse.rs index 0d7d0d5a9..fa9596d06 100644 --- a/crates/oxc_traverse/src/traverse.rs +++ b/crates/oxc_traverse/src/traverse.rs @@ -1638,6 +1638,21 @@ pub trait Traverse<'a> { ) { } + #[inline] + fn enter_ts_parenthesized_type( + &mut self, + node: &mut TSParenthesizedType<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + } + #[inline] + fn exit_ts_parenthesized_type( + &mut self, + node: &mut TSParenthesizedType<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + } + #[inline] fn enter_ts_type_operator(&mut self, node: &mut TSTypeOperator<'a>, ctx: &mut TraverseCtx<'a>) { } diff --git a/crates/oxc_traverse/src/walk.rs b/crates/oxc_traverse/src/walk.rs index b0b9328fd..3284189f9 100644 --- a/crates/oxc_traverse/src/walk.rs +++ b/crates/oxc_traverse/src/walk.rs @@ -3896,6 +3896,9 @@ pub(crate) unsafe fn walk_ts_type<'a, Tr: Traverse<'a>>( walk_ts_type_reference(traverser, (&mut **node) as *mut _, ctx) } TSType::TSUnionType(node) => walk_ts_union_type(traverser, (&mut **node) as *mut _, ctx), + TSType::TSParenthesizedType(node) => { + walk_ts_parenthesized_type(traverser, (&mut **node) as *mut _, ctx) + } TSType::JSDocNullableType(node) => { walk_js_doc_nullable_type(traverser, (&mut **node) as *mut _, ctx) } @@ -3980,6 +3983,25 @@ pub(crate) unsafe fn walk_ts_intersection_type<'a, Tr: Traverse<'a>>( traverser.exit_ts_intersection_type(&mut *node, ctx); } +pub(crate) unsafe fn walk_ts_parenthesized_type<'a, Tr: Traverse<'a>>( + traverser: &mut Tr, + node: *mut TSParenthesizedType<'a>, + ctx: &mut TraverseCtx<'a>, +) { + traverser.enter_ts_parenthesized_type(&mut *node, ctx); + ctx.push_stack(Ancestor::TSParenthesizedTypeTypeAnnotation( + ancestor::TSParenthesizedTypeWithoutTypeAnnotation(node), + )); + walk_ts_type( + traverser, + (node as *mut u8).add(ancestor::OFFSET_TS_PARENTHESIZED_TYPE_TYPE_ANNOTATION) + as *mut TSType, + ctx, + ); + ctx.pop_stack(); + traverser.exit_ts_parenthesized_type(&mut *node, ctx); +} + pub(crate) unsafe fn walk_ts_type_operator<'a, Tr: Traverse<'a>>( traverser: &mut Tr, node: *mut TSTypeOperator<'a>, @@ -4165,6 +4187,7 @@ pub(crate) unsafe fn walk_ts_tuple_element<'a, Tr: Traverse<'a>>( | TSTupleElement::TSTypeQuery(_) | TSTupleElement::TSTypeReference(_) | TSTupleElement::TSUnionType(_) + | TSTupleElement::TSParenthesizedType(_) | TSTupleElement::JSDocNullableType(_) | TSTupleElement::JSDocNonNullableType(_) | TSTupleElement::JSDocUnknownType(_) => walk_ts_type(traverser, node as *mut _, ctx),