diff --git a/crates/oxc_formatter/src/parentheses/ts_type.rs b/crates/oxc_formatter/src/parentheses/ts_type.rs index 1431e43f8487c..812b7f1c41d63 100644 --- a/crates/oxc_formatter/src/parentheses/ts_type.rs +++ b/crates/oxc_formatter/src/parentheses/ts_type.rs @@ -18,6 +18,7 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSType<'a>> { AstNodes::TSUnionType(it) => it.needs_parentheses(f), AstNodes::TSIntersectionType(it) => it.needs_parentheses(f), AstNodes::TSConditionalType(it) => it.needs_parentheses(f), + AstNodes::TSTypeOperator(it) => it.needs_parentheses(f), _ => { // TODO: incomplete false @@ -41,7 +42,7 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSFunctionType<'a>> { impl<'a> NeedsParentheses<'a> for AstNode<'a, TSInferType<'a>> { fn needs_parentheses(&self, f: &Formatter<'_, 'a>) -> bool { - matches!(self.parent, AstNodes::TSArrayType(_)) + matches!(self.parent, AstNodes::TSArrayType(_) | AstNodes::TSTypeOperator(_)) } } @@ -59,13 +60,23 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSConstructorType<'a>> { impl<'a> NeedsParentheses<'a> for AstNode<'a, TSUnionType<'a>> { fn needs_parentheses(&self, f: &Formatter<'_, 'a>) -> bool { - matches!(self.parent, AstNodes::TSArrayType(_)) + matches!( + self.parent, + AstNodes::TSArrayType(_) + | AstNodes::TSTypeOperator(_) + | AstNodes::TSIndexedAccessType(_) + ) } } impl<'a> NeedsParentheses<'a> for AstNode<'a, TSIntersectionType<'a>> { fn needs_parentheses(&self, f: &Formatter<'_, 'a>) -> bool { - matches!(self.parent, AstNodes::TSArrayType(_)) + matches!( + self.parent, + AstNodes::TSArrayType(_) + | AstNodes::TSTypeOperator(_) + | AstNodes::TSIndexedAccessType(_) + ) } } @@ -80,3 +91,14 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSConditionalType<'a>> { } } } + +impl<'a> NeedsParentheses<'a> for AstNode<'a, TSTypeOperator<'a>> { + fn needs_parentheses(&self, f: &Formatter<'_, 'a>) -> bool { + matches!( + self.parent, + AstNodes::TSArrayType(_) + | AstNodes::TSTypeOperator(_) + | AstNodes::TSIndexedAccessType(_) + ) + } +} diff --git a/crates/oxc_formatter/src/write/mod.rs b/crates/oxc_formatter/src/write/mod.rs index 3d95ae5aa1a20..4f6d0d242baa6 100644 --- a/crates/oxc_formatter/src/write/mod.rs +++ b/crates/oxc_formatter/src/write/mod.rs @@ -1231,13 +1231,19 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSUnionType<'a>> { impl<'a> FormatWrite<'a> for AstNode<'a, TSIntersectionType<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { let mut types = self.types().iter(); + let needs_parentheses = self.needs_parentheses(f); + if needs_parentheses { + write!(f, "(")?; + } if let Some(item) = types.next() { write!(f, item)?; for item in types { write!(f, [" & ", item])?; } - return Ok(()); + } + if needs_parentheses { + write!(f, ")")?; } Ok(()) } @@ -1251,7 +1257,18 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSParenthesizedType<'a>> { impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeOperator<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - write!(f, [self.operator().to_str(), hard_space(), self.type_annotation()]) + let needs_parentheses = self.needs_parentheses(f); + if needs_parentheses { + write!(f, "(")?; + } + + write!(f, [self.operator().to_str(), hard_space(), self.type_annotation()])?; + + if needs_parentheses { + write!(f, ")")?; + } + + Ok(()) } } diff --git a/tasks/coverage/snapshots/formatter_typescript.snap b/tasks/coverage/snapshots/formatter_typescript.snap index 09b74d0b9fc1c..946ddfc830dc7 100644 --- a/tasks/coverage/snapshots/formatter_typescript.snap +++ b/tasks/coverage/snapshots/formatter_typescript.snap @@ -2,7 +2,7 @@ commit: 261630d6 formatter_typescript Summary: AST Parsed : 8816/8816 (100.00%) -Positive Passed: 8787/8816 (99.67%) +Positive Passed: 8788/8816 (99.68%) Mismatch: tasks/coverage/typescript/tests/cases/compiler/amdLikeInputDeclarationEmit.ts Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/arrayFromAsync.ts @@ -39,8 +39,6 @@ Mismatch: tasks/coverage/typescript/tests/cases/compiler/tryStatementInternalCom Mismatch: tasks/coverage/typescript/tests/cases/compiler/unionSignaturesWithThisParameter.ts -Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts -'readonly' type modifier is only permitted on array and tuple literal types. Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflicts.ts Classes may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototype Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/controlFlow/controlFlowAssignmentPatternOrder.ts diff --git a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md index f7fe7c31c0761..93f9fa52dcfb1 100644 --- a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md @@ -1,4 +1,4 @@ -ts compatibility: 401/573 (69.98%) +ts compatibility: 404/573 (70.51%) # Failed @@ -51,7 +51,7 @@ ts compatibility: 401/573 (69.98%) | typescript/compiler/mappedTypeWithCombinedTypeMappers.ts | 💥 | 91.89% | | typescript/compiler/privacyGloImport.ts | 💥 | 99.32% | | typescript/conditional-types/comments.ts | 💥💥 | 60.21% | -| typescript/conditional-types/conditonal-types.ts | 💥💥 | 77.84% | +| typescript/conditional-types/conditonal-types.ts | 💥💥 | 75.60% | | typescript/conditional-types/infer-type.ts | 💥💥 | 39.38% | | typescript/conditional-types/nested-in-condition.ts | 💥✨ | 15.79% | | typescript/conditional-types/new-ternary-spec.ts | 💥💥 | 47.09% | @@ -69,7 +69,6 @@ ts compatibility: 401/573 (69.98%) | typescript/conformance/types/functions/functionOverloadErrorsSyntax.ts | 💥 | 0.00% | | typescript/conformance/types/namespaceExportDeclaration/exportAsNamespace.d.ts | 💥 | 75.00% | | typescript/conformance/types/tuple/wideningTuples1.ts | 💥 | 80.00% | -| typescript/conformance/types/typeOperator/typeOperator.ts | 💥 | 0.00% | | typescript/conformance/types/typeParameters/typeParameterLists/innerTypeParameterShadowingOuterOne2.ts | 💥 | 93.33% | | typescript/conformance/types/union/unionTypeCallSignatures.ts | 💥 | 64.95% | | typescript/conformance/types/union/unionTypeCallSignatures3.ts | 💥 | 68.97% | @@ -111,12 +110,10 @@ ts compatibility: 401/573 (69.98%) | typescript/interface2/comments-declare.ts | 💥 | 66.67% | | typescript/interface2/comments.ts | 💥 | 78.87% | | typescript/interface2/break/break.ts | 💥💥💥 | 80.23% | -| typescript/intersection/intersection-parens.ts | 💥💥 | 58.06% | +| typescript/intersection/intersection-parens.ts | 💥💥 | 59.14% | | typescript/intersection/type-arguments.ts | 💥💥 | 46.67% | -| typescript/intersection/consistent-with-flow/comment.ts | 💥 | 0.00% | | typescript/intersection/consistent-with-flow/intersection-parens.ts | 💥 | 60.47% | | typescript/key-remapping-in-mapped-types/key-remapping.ts | 💥 | 23.53% | -| typescript/keyof/keyof.ts | 💥 | 20.00% | | typescript/keyword-types/conditional-types.ts | 💥 | 87.50% | | typescript/keywords/keywords-2.ts | 💥 | 79.41% | | typescript/last-argument-expansion/decorated-function.tsx | 💥 | 29.06% | @@ -133,8 +130,8 @@ ts compatibility: 401/573 (69.98%) | typescript/nosemi/index-signature.ts | 💥 | 75.00% | | typescript/object-multiline/multiline.ts | 💥✨ | 23.21% | | typescript/optional-type/complex.ts | 💥 | 0.00% | -| typescript/optional-variance/basic.ts | 💥 | 83.61% | -| typescript/optional-variance/with-jsx.tsx | 💥 | 83.61% | +| typescript/optional-variance/basic.ts | 💥 | 81.97% | +| typescript/optional-variance/with-jsx.tsx | 💥 | 81.97% | | typescript/override-modifiers/override-modifier.ts | 💥 | 25.00% | | typescript/prettier-ignore/mapped-types.ts | 💥 | 54.72% | | typescript/prettier-ignore/prettier-ignore-nested-unions.ts | 💥 | 15.79% | @@ -169,7 +166,7 @@ ts compatibility: 401/573 (69.98%) | typescript/typeparams/empty-parameters-with-arrow-function/issue-13817.ts | 💥 | 66.67% | | typescript/typeparams/trailing-comma/type-paramters.ts | 💥💥💥 | 28.57% | | typescript/union/comments.ts | 💥 | 15.38% | -| typescript/union/inlining.ts | 💥 | 45.67% | +| typescript/union/inlining.ts | 💥 | 51.97% | | typescript/union/union-parens.ts | 💥 | 58.00% | | typescript/union/with-type-params.ts | 💥 | 0.00% | | typescript/union/consistent-with-flow/prettier-ignore.ts | 💥 | 19.05% |