@@ -30,31 +30,24 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSType<'a>> {
3030impl < ' a > NeedsParentheses < ' a > for AstNode < ' a , TSFunctionType < ' a > > {
3131 #[ inline]
3232 fn needs_parentheses ( & self , f : & Formatter < ' _ , ' a > ) -> bool {
33- match self . parent {
34- AstNodes :: TSConditionalType ( ty) => {
35- ty. extends_type ( ) . span ( ) == self . span ( ) || ty. check_type ( ) . span ( ) == self . span ( )
36- }
37- AstNodes :: TSUnionType ( _) | AstNodes :: TSIntersectionType ( _) => true ,
38- _ => false ,
39- }
33+ function_like_type_needs_parentheses ( self . span ( ) , self . parent , Some ( & self . return_type ) )
4034 }
4135}
4236
4337impl < ' a > NeedsParentheses < ' a > for AstNode < ' a , TSInferType < ' a > > {
4438 fn needs_parentheses ( & self , f : & Formatter < ' _ , ' a > ) -> bool {
45- matches ! ( self . parent, AstNodes :: TSArrayType ( _) | AstNodes :: TSTypeOperator ( _) )
39+ match self . parent {
40+ AstNodes :: TSIntersectionType ( _) | AstNodes :: TSUnionType ( _) => true ,
41+ AstNodes :: TSRestType ( _) => false ,
42+ _ => operator_type_or_higher_needs_parens ( self . span , self . parent ) ,
43+ }
4644 }
4745}
4846
4947impl < ' a > NeedsParentheses < ' a > for AstNode < ' a , TSConstructorType < ' a > > {
48+ #[ inline]
5049 fn needs_parentheses ( & self , f : & Formatter < ' _ , ' a > ) -> bool {
51- match self . parent {
52- AstNodes :: TSConditionalType ( ty) => {
53- ty. extends_type ( ) . span ( ) == self . span ( ) || ty. check_type ( ) . span ( ) == self . span ( )
54- }
55- AstNodes :: TSUnionType ( _) | AstNodes :: TSIntersectionType ( _) => true ,
56- _ => false ,
57- }
50+ function_like_type_needs_parentheses ( self . span ( ) , self . parent , Some ( & self . return_type ) )
5851 }
5952}
6053
@@ -71,9 +64,60 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSUnionType<'a>> {
7164}
7265
7366/// Returns `true` if a TS primary type needs parentheses
67+ /// Common logic for determining if function-like types (TSFunctionType, TSConstructorType)
68+ /// need parentheses based on their parent context.
69+ ///
70+ /// Ported from Biome's function_like_type_needs_parentheses
71+ fn function_like_type_needs_parentheses < ' a > (
72+ span : Span ,
73+ parent : & ' a AstNodes < ' a > ,
74+ return_type : Option < & ' a TSTypeAnnotation < ' a > > ,
75+ ) -> bool {
76+ match parent {
77+ // Arrow function return types need parens
78+ AstNodes :: TSTypeAnnotation ( type_annotation) => {
79+ matches ! ( type_annotation. parent, AstNodes :: ArrowFunctionExpression ( _) )
80+ }
81+ // In conditional types
82+ AstNodes :: TSConditionalType ( conditional) => {
83+ let is_check_type = conditional. check_type ( ) . span ( ) == span;
84+ if is_check_type {
85+ return true ;
86+ }
87+
88+ let is_extends_type = conditional. extends_type ( ) . span ( ) == span;
89+ if is_extends_type {
90+ // Need parentheses if return type is TSInferType with constraint
91+ // or TSTypePredicate with type annotation
92+ if let Some ( return_type) = return_type {
93+ match & return_type. type_annotation {
94+ TSType :: TSInferType ( infer_type) => {
95+ return infer_type. type_parameter . constraint . is_some ( ) ;
96+ }
97+ TSType :: TSTypePredicate ( predicate) => {
98+ return predicate. type_annotation . is_some ( ) ;
99+ }
100+ _ => { }
101+ }
102+ }
103+ }
104+ false
105+ }
106+ AstNodes :: TSUnionType ( _) | AstNodes :: TSIntersectionType ( _) => true ,
107+ _ => operator_type_or_higher_needs_parens ( span, parent) ,
108+ }
109+ }
110+
111+ /// Returns `true` if a TS primary type needs parentheses
112+ /// This is for types that have higher precedence operators as parents
74113fn operator_type_or_higher_needs_parens ( span : Span , parent : & AstNodes ) -> bool {
75114 match parent {
76- AstNodes :: TSArrayType ( _) | AstNodes :: TSTypeOperator ( _) | AstNodes :: TSRestType ( _) => true ,
115+ // These parent types always require parentheses for their operands
116+ AstNodes :: TSArrayType ( _)
117+ | AstNodes :: TSTypeOperator ( _)
118+ | AstNodes :: TSRestType ( _)
119+ | AstNodes :: TSOptionalType ( _) => true ,
120+ // Indexed access requires parens if this is the object type
77121 AstNodes :: TSIndexedAccessType ( indexed) => indexed. object_type . span ( ) == span,
78122 _ => false ,
79123 }
@@ -97,18 +141,13 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, TSConditionalType<'a>> {
97141 ty. extends_type ( ) . span ( ) == self . span ( ) || ty. check_type ( ) . span ( ) == self . span ( )
98142 }
99143 AstNodes :: TSUnionType ( _) | AstNodes :: TSIntersectionType ( _) => true ,
100- _ => false ,
144+ _ => operator_type_or_higher_needs_parens ( self . span , self . parent ) ,
101145 }
102146 }
103147}
104148
105149impl < ' a > NeedsParentheses < ' a > for AstNode < ' a , TSTypeOperator < ' a > > {
106150 fn needs_parentheses ( & self , f : & Formatter < ' _ , ' a > ) -> bool {
107- matches ! (
108- self . parent,
109- AstNodes :: TSArrayType ( _)
110- | AstNodes :: TSTypeOperator ( _)
111- | AstNodes :: TSIndexedAccessType ( _)
112- )
151+ operator_type_or_higher_needs_parens ( self . span ( ) , self . parent )
113152 }
114153}
0 commit comments