diff --git a/crates/rome_formatter/src/source_map.rs b/crates/rome_formatter/src/source_map.rs index aeb2c527a0c1..3d24c982853f 100644 --- a/crates/rome_formatter/src/source_map.rs +++ b/crates/rome_formatter/src/source_map.rs @@ -1,5 +1,6 @@ use crate::{Printed, SourceMarker, TextRange}; use rome_rowan::{Language, SyntaxNode, SyntaxNodeText, TextSize}; +use std::cmp::Ordering; use std::collections::HashMap; /// A source map for mapping positions of a pre-processed tree back to the locations in the source tree. @@ -302,6 +303,15 @@ struct DeletedRange { } impl DeletedRange { + fn new(source_range: TextRange, transformed_offset: TextSize) -> Self { + debug_assert!(source_range.start() >= transformed_offset); + + Self { + source_range, + transformed_offset, + } + } + /// The number of deleted characters starting from [source offset](DeletedRange::source_start). fn len(&self) -> TextSize { self.source_range.len() @@ -382,13 +392,17 @@ impl TransformSourceMapBuilder { let mut merged_mappings = Vec::with_capacity(self.deleted_ranges.len()); if !self.deleted_ranges.is_empty() { - self.deleted_ranges.sort_by_key(|range| range.start()); + self.deleted_ranges + .sort_by(|a, b| match a.start().cmp(&b.start()) { + Ordering::Equal => a.end().cmp(&b.end()), + ordering => ordering, + }); - let mut last_mapping = DeletedRange { + let mut last_mapping = DeletedRange::new( // SAFETY: Safe because of the not empty check above - source_range: self.deleted_ranges[0], - transformed_offset: TextSize::default(), - }; + self.deleted_ranges[0], + TextSize::default(), + ); let mut transformed_offset = last_mapping.len(); @@ -399,10 +413,7 @@ impl TransformSourceMapBuilder { } else { merged_mappings.push(last_mapping); - last_mapping = DeletedRange { - source_range: range, - transformed_offset, - }; + last_mapping = DeletedRange::new(range, transformed_offset); } transformed_offset += range.len(); } diff --git a/crates/rome_js_formatter/src/js/declarations/variable_declaration.rs b/crates/rome_js_formatter/src/js/declarations/variable_declaration.rs index 34e2313261f0..2243320127d6 100644 --- a/crates/rome_js_formatter/src/js/declarations/variable_declaration.rs +++ b/crates/rome_js_formatter/src/js/declarations/variable_declaration.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use rome_formatter::write; +use rome_formatter::{format_args, write}; use rome_js_syntax::JsVariableDeclaration; use rome_js_syntax::JsVariableDeclarationFields; @@ -11,6 +11,13 @@ impl FormatNodeRule for FormatJsVariableDeclaration { fn fmt_fields(&self, node: &JsVariableDeclaration, f: &mut JsFormatter) -> FormatResult<()> { let JsVariableDeclarationFields { kind, declarators } = node.as_fields(); - write!(f, [kind.format(), space(), declarators.format()]) + write!( + f, + [group(&format_args![ + kind.format(), + space(), + declarators.format() + ])] + ) } } diff --git a/crates/rome_js_formatter/src/js/lists/variable_declarator_list.rs b/crates/rome_js_formatter/src/js/lists/variable_declarator_list.rs index 39f070c7f344..bc8894ac7b76 100644 --- a/crates/rome_js_formatter/src/js/lists/variable_declarator_list.rs +++ b/crates/rome_js_formatter/src/js/lists/variable_declarator_list.rs @@ -11,60 +11,56 @@ impl FormatRule for FormatJsVariableDeclaratorList { type Context = JsFormatContext; fn fmt(&self, node: &JsVariableDeclaratorList, f: &mut JsFormatter) -> FormatResult<()> { - let format_inner = format_with(|f| { - let length = node.len(); + let length = node.len(); - let is_parent_for_loop = node.syntax().grand_parent().map_or(false, |grand_parent| { - matches!( - grand_parent.kind(), - JsSyntaxKind::JS_FOR_STATEMENT - | JsSyntaxKind::JS_FOR_OF_STATEMENT - | JsSyntaxKind::JS_FOR_IN_STATEMENT - ) - }); - - let has_any_initializer = node.iter().any(|declarator| { - declarator.map_or(false, |declarator| declarator.initializer().is_some()) - }); + let is_parent_for_loop = node.syntax().grand_parent().map_or(false, |grand_parent| { + matches!( + grand_parent.kind(), + JsSyntaxKind::JS_FOR_STATEMENT + | JsSyntaxKind::JS_FOR_OF_STATEMENT + | JsSyntaxKind::JS_FOR_IN_STATEMENT + ) + }); - let format_separator = format_with(|f| { - if !is_parent_for_loop && has_any_initializer { - write!(f, [hard_line_break()]) - } else { - write!(f, [soft_line_break_or_space()]) - } - }); + let has_any_initializer = node.iter().any(|declarator| { + declarator.map_or(false, |declarator| declarator.initializer().is_some()) + }); - let mut declarators = node.iter().zip( - node.format_separated(JsSyntaxKind::COMMA) - .with_trailing_separator(TrailingSeparator::Disallowed), - ); + let format_separator = format_with(|f| { + if !is_parent_for_loop && has_any_initializer { + write!(f, [hard_line_break()]) + } else { + write!(f, [soft_line_break_or_space()]) + } + }); - let (first_declarator, format_first_declarator) = match declarators.next() { - Some((syntax, format_first_declarator)) => (syntax?, format_first_declarator), - None => return Err(FormatError::SyntaxError), - }; + let mut declarators = node.iter().zip( + node.format_separated(JsSyntaxKind::COMMA) + .with_trailing_separator(TrailingSeparator::Disallowed), + ); - if length == 1 && !first_declarator.syntax().has_leading_comments() { - return write!(f, [format_first_declarator]); - } + let (first_declarator, format_first_declarator) = match declarators.next() { + Some((syntax, format_first_declarator)) => (syntax?, format_first_declarator), + None => return Err(FormatError::SyntaxError), + }; - write!( - f, - [indent(&format_once(|f| { - write!(f, [format_first_declarator])?; + if length == 1 && !first_declarator.syntax().has_leading_comments() { + return write!(f, [format_first_declarator]); + } - if length > 1 { - write!(f, [format_separator])?; - } + write!( + f, + [indent(&format_once(|f| { + write!(f, [format_first_declarator])?; - f.join_with(&format_separator) - .entries(declarators.map(|(_, format)| format)) - .finish() - }))] - ) - }); + if length > 1 { + write!(f, [format_separator])?; + } - write!(f, [group(&format_inner)]) + f.join_with(&format_separator) + .entries(declarators.map(|(_, format)| format)) + .finish() + }))] + ) } } diff --git a/crates/rome_js_formatter/src/parentheses.rs b/crates/rome_js_formatter/src/parentheses.rs index 2bdd86f86319..1893ff011e07 100644 --- a/crates/rome_js_formatter/src/parentheses.rs +++ b/crates/rome_js_formatter/src/parentheses.rs @@ -44,9 +44,11 @@ use rome_js_syntax::{ JsAnyLiteralExpression, JsArrowFunctionExpression, JsAssignmentExpression, JsBinaryExpression, JsBinaryOperator, JsComputedMemberAssignment, JsComputedMemberExpression, JsConditionalExpression, JsLanguage, JsParenthesizedAssignment, JsParenthesizedExpression, - JsSequenceExpression, JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, + JsSequenceExpression, JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, TsConditionalType, + TsIndexedAccessType, TsIntersectionTypeElementList, TsParenthesizedType, TsType, + TsUnionTypeVariantList, }; -use rome_rowan::{declare_node_union, AstNode, SyntaxResult}; +use rome_rowan::{declare_node_union, AstNode, AstSeparatedList, SyntaxResult}; /// Node that may be parenthesized to ensure it forms valid syntax or to improve readability pub trait NeedsParentheses: AstNode { @@ -597,8 +599,76 @@ pub(crate) fn is_spread(node: &JsSyntaxNode, parent: &JsSyntaxNode) -> bool { ) } +/// Returns `true` if a TS primary type needs parentheses +pub(crate) fn operator_type_or_higher_needs_parens( + node: &JsSyntaxNode, + parent: &JsSyntaxNode, +) -> bool { + debug_assert_is_parent(node, parent); + + match parent.kind() { + JsSyntaxKind::TS_ARRAY_TYPE + | JsSyntaxKind::TS_TYPE_OPERATOR_TYPE + | JsSyntaxKind::TS_REST_TUPLE_TYPE_ELEMENT + | JsSyntaxKind::TS_OPTIONAL_TUPLE_TYPE_ELEMENT => true, + JsSyntaxKind::TS_INDEXED_ACCESS_TYPE => { + let indexed = TsIndexedAccessType::unwrap_cast(parent.clone()); + + indexed.object_type().map(AstNode::into_syntax).as_ref() == Ok(node) + } + _ => false, + } +} + +/// Tests if `node` is the check type of a [TsConditionalType] +/// +/// ```javascript +/// type s = A extends string ? string : number // true for `A`, false for `string` and `number` +/// ``` +pub(crate) fn is_check_type(node: &JsSyntaxNode, parent: &JsSyntaxNode) -> bool { + debug_assert_is_parent(node, parent); + + match parent.kind() { + JsSyntaxKind::TS_CONDITIONAL_TYPE => { + let conditional = TsConditionalType::unwrap_cast(parent.clone()); + + conditional.check_type().map(AstNode::into_syntax).as_ref() == Ok(node) + } + _ => false, + } +} + +/// Returns `true` if node is in a union or intersection type with more than one variant +/// +/// ```javascript +/// type A = &string // -> false for `string` because `string` is the only variant +/// type B = string & number // -> true for `string` or `number` +/// type C = |string // -> false +/// type D = string | number // -> true +/// ``` +pub(crate) fn is_in_many_type_union_or_intersection_list( + node: &JsSyntaxNode, + parent: &JsSyntaxNode, +) -> bool { + debug_assert_is_parent(node, parent); + + match parent.kind() { + JsSyntaxKind::TS_UNION_TYPE_VARIANT_LIST => { + let list = TsUnionTypeVariantList::unwrap_cast(parent.clone()); + + list.len() > 1 + } + JsSyntaxKind::TS_INTERSECTION_TYPE_ELEMENT_LIST => { + let list = TsIntersectionTypeElementList::unwrap_cast(parent.clone()); + + list.len() > 1 + } + _ => false, + } +} + declare_node_union! { - pub(crate) JsAnyParenthesized = JsParenthesizedExpression | JsParenthesizedAssignment + pub(crate) JsAnyParenthesized = JsParenthesizedExpression | JsParenthesizedAssignment | TsParenthesizedType } impl JsAnyParenthesized { @@ -606,6 +676,7 @@ impl JsAnyParenthesized { match self { JsAnyParenthesized::JsParenthesizedExpression(expression) => expression.l_paren_token(), JsAnyParenthesized::JsParenthesizedAssignment(assignment) => assignment.l_paren_token(), + JsAnyParenthesized::TsParenthesizedType(ty) => ty.l_paren_token(), } } @@ -617,6 +688,7 @@ impl JsAnyParenthesized { JsAnyParenthesized::JsParenthesizedAssignment(assignment) => { assignment.assignment().map(AstNode::into_syntax) } + JsAnyParenthesized::TsParenthesizedType(ty) => ty.ty().map(AstNode::into_syntax), } } @@ -624,6 +696,7 @@ impl JsAnyParenthesized { match self { JsAnyParenthesized::JsParenthesizedExpression(expression) => expression.r_paren_token(), JsAnyParenthesized::JsParenthesizedAssignment(assignment) => assignment.r_paren_token(), + JsAnyParenthesized::TsParenthesizedType(ty) => ty.r_paren_token(), } } } @@ -716,6 +789,86 @@ impl NeedsParentheses for JsAnyAssignmentPattern { } } +impl NeedsParentheses for TsType { + fn needs_parentheses(&self) -> bool { + match self { + TsType::TsAnyType(ty) => ty.needs_parentheses(), + TsType::TsArrayType(ty) => ty.needs_parentheses(), + TsType::TsBigIntLiteralType(ty) => ty.needs_parentheses(), + TsType::TsBigintType(ty) => ty.needs_parentheses(), + TsType::TsBooleanLiteralType(ty) => ty.needs_parentheses(), + TsType::TsBooleanType(ty) => ty.needs_parentheses(), + TsType::TsConditionalType(ty) => ty.needs_parentheses(), + TsType::TsConstructorType(ty) => ty.needs_parentheses(), + TsType::TsFunctionType(ty) => ty.needs_parentheses(), + TsType::TsImportType(ty) => ty.needs_parentheses(), + TsType::TsIndexedAccessType(ty) => ty.needs_parentheses(), + TsType::TsInferType(ty) => ty.needs_parentheses(), + TsType::TsIntersectionType(ty) => ty.needs_parentheses(), + TsType::TsMappedType(ty) => ty.needs_parentheses(), + TsType::TsNeverType(ty) => ty.needs_parentheses(), + TsType::TsNonPrimitiveType(ty) => ty.needs_parentheses(), + TsType::TsNullLiteralType(ty) => ty.needs_parentheses(), + TsType::TsNumberLiteralType(ty) => ty.needs_parentheses(), + TsType::TsNumberType(ty) => ty.needs_parentheses(), + TsType::TsObjectType(ty) => ty.needs_parentheses(), + TsType::TsParenthesizedType(ty) => ty.needs_parentheses(), + TsType::TsReferenceType(ty) => ty.needs_parentheses(), + TsType::TsStringLiteralType(ty) => ty.needs_parentheses(), + TsType::TsStringType(ty) => ty.needs_parentheses(), + TsType::TsSymbolType(ty) => ty.needs_parentheses(), + TsType::TsTemplateLiteralType(ty) => ty.needs_parentheses(), + TsType::TsThisType(ty) => ty.needs_parentheses(), + TsType::TsTupleType(ty) => ty.needs_parentheses(), + TsType::TsTypeOperatorType(ty) => ty.needs_parentheses(), + TsType::TsTypeofType(ty) => ty.needs_parentheses(), + TsType::TsUndefinedType(ty) => ty.needs_parentheses(), + TsType::TsUnionType(ty) => ty.needs_parentheses(), + TsType::TsUnknownType(ty) => ty.needs_parentheses(), + TsType::TsVoidType(ty) => ty.needs_parentheses(), + } + } + + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + match self { + TsType::TsAnyType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsArrayType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsBigIntLiteralType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsBigintType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsBooleanLiteralType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsBooleanType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsConditionalType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsConstructorType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsFunctionType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsImportType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsIndexedAccessType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsInferType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsIntersectionType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsMappedType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsNeverType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsNonPrimitiveType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsNullLiteralType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsNumberLiteralType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsNumberType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsObjectType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsParenthesizedType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsReferenceType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsStringLiteralType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsStringType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsSymbolType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsTemplateLiteralType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsThisType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsTupleType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsTypeOperatorType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsTypeofType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsUndefinedType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsUnionType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsUnknownType(ty) => ty.needs_parentheses_with_parent(parent), + TsType::TsVoidType(ty) => ty.needs_parentheses_with_parent(parent), + } + } +} + fn debug_assert_is_expression(node: &JsSyntaxNode) { debug_assert!( JsAnyExpression::can_cast(node.kind()), diff --git a/crates/rome_js_formatter/src/syntax_rewriter.rs b/crates/rome_js_formatter/src/syntax_rewriter.rs index df21cc23d04e..5c0724152206 100644 --- a/crates/rome_js_formatter/src/syntax_rewriter.rs +++ b/crates/rome_js_formatter/src/syntax_rewriter.rs @@ -3,6 +3,7 @@ use crate::TextRange; use rome_formatter::{TransformSourceMap, TransformSourceMapBuilder}; use rome_js_syntax::{ JsAnyAssignment, JsAnyExpression, JsLanguage, JsLogicalExpression, JsSyntaxKind, JsSyntaxNode, + TsType, }; use rome_rowan::syntax::SyntaxTrivia; use rome_rowan::{ @@ -81,6 +82,9 @@ impl JsFormatSyntaxRewriter { .with_assignment(JsAnyAssignment::unwrap_cast(inner)) .into_syntax() } + JsAnyParenthesized::TsParenthesizedType(ty) => { + ty.with_ty(TsType::unwrap_cast(inner)).into_syntax() + } }; VisitNodeSignal::Replace(updated) @@ -101,10 +105,14 @@ impl JsFormatSyntaxRewriter { ); let mut leading_trivia = first_token.leading_trivia().pieces().peekable(); + let mut first_new_line = None; // The leading whitespace before the opening parens replaces the whitespace before the node. while let Some(trivia) = leading_trivia.peek() { - if trivia.is_whitespace() || trivia.is_newline() { + if trivia.is_newline() && first_new_line.is_none() { + inner_offset += trivia.text_len(); + first_new_line = Some((inner_offset, leading_trivia.next().unwrap())); + } else if trivia.is_whitespace() || trivia.is_newline() { let trivia_len = trivia.text_len(); self.source_map .add_deleted_range(TextRange::at(inner_offset, trivia_len)); @@ -115,6 +123,19 @@ impl JsFormatSyntaxRewriter { } } + // Remove all leading new lines directly in front of the token but keep the leading new-line if it precedes a skipped token trivia or a comment. + if leading_trivia.peek().is_none() && first_new_line.is_some() { + let (inner_offset, new_line) = first_new_line.take().unwrap(); + + self.source_map + .add_deleted_range(TextRange::at(inner_offset, new_line.text_len())); + } + + let leading_trivia = chain_pieces( + first_new_line.map(|(_, trivia)| trivia).into_iter(), + leading_trivia, + ); + let new_leading = chain_pieces(l_paren_trivia, leading_trivia); let new_first = first_token.with_leading_trivia_pieces(new_leading); diff --git a/crates/rome_js_formatter/src/ts/expressions/template_literal_type.rs b/crates/rome_js_formatter/src/ts/expressions/template_literal_type.rs index fa131abe703a..2b1e18221ceb 100644 --- a/crates/rome_js_formatter/src/ts/expressions/template_literal_type.rs +++ b/crates/rome_js_formatter/src/ts/expressions/template_literal_type.rs @@ -1,8 +1,9 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::TsTemplateLiteralType; use rome_js_syntax::TsTemplateLiteralTypeFields; +use rome_js_syntax::{JsSyntaxNode, TsTemplateLiteralType}; #[derive(Debug, Clone, Default)] pub struct FormatTsTemplateLiteralType; @@ -24,4 +25,14 @@ impl FormatNodeRule for FormatTsTemplateLiteralType { ] ] } + + fn needs_parentheses(&self, item: &TsTemplateLiteralType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsTemplateLiteralType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/module/import_type.rs b/crates/rome_js_formatter/src/ts/module/import_type.rs index b6f6d8bb0731..4ee716ab5255 100644 --- a/crates/rome_js_formatter/src/ts/module/import_type.rs +++ b/crates/rome_js_formatter/src/ts/module/import_type.rs @@ -1,9 +1,10 @@ use crate::prelude::*; use crate::utils::{FormatLiteralStringToken, StringLiteralParentKind}; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::TsImportType; use rome_js_syntax::TsImportTypeFields; +use rome_js_syntax::{JsSyntaxNode, TsImportType}; #[derive(Debug, Clone, Default)] pub struct FormatTsImportType; @@ -39,4 +40,14 @@ impl FormatNodeRule for FormatTsImportType { ] ] } + + fn needs_parentheses(&self, item: &TsImportType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsImportType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/any_type.rs b/crates/rome_js_formatter/src/ts/types/any_type.rs index 0de012912456..0fb4cfa67337 100644 --- a/crates/rome_js_formatter/src/ts/types/any_type.rs +++ b/crates/rome_js_formatter/src/ts/types/any_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsAnyType, TsAnyTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsAnyType, TsAnyTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsAnyType; @@ -12,4 +13,15 @@ impl FormatNodeRule for FormatTsAnyType { write![f, [any_token.format()]] } + + fn needs_parentheses(&self, item: &TsAnyType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsAnyType { + #[inline] + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/array_type.rs b/crates/rome_js_formatter/src/ts/types/array_type.rs index 6a8dc6f5b4e9..399fd9d62bf0 100644 --- a/crates/rome_js_formatter/src/ts/types/array_type.rs +++ b/crates/rome_js_formatter/src/ts/types/array_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsArrayType, TsArrayTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsArrayType, TsArrayTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsArrayType; @@ -22,4 +23,15 @@ impl FormatNodeRule for FormatTsArrayType { ] ] } + + fn needs_parentheses(&self, item: &TsArrayType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsArrayType { + #[inline] + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/asserts_return_type.rs b/crates/rome_js_formatter/src/ts/types/asserts_return_type.rs index 911b3dee83fd..e9315e0a9e2c 100644 --- a/crates/rome_js_formatter/src/ts/types/asserts_return_type.rs +++ b/crates/rome_js_formatter/src/ts/types/asserts_return_type.rs @@ -1,8 +1,9 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::TsAssertsReturnType; use rome_js_syntax::TsAssertsReturnTypeFields; +use rome_js_syntax::{JsSyntaxNode, TsAssertsReturnType}; #[derive(Debug, Clone, Default)] pub struct FormatTsAssertsReturnType; @@ -25,4 +26,15 @@ impl FormatNodeRule for FormatTsAssertsReturnType { ] ] } + + fn needs_parentheses(&self, item: &TsAssertsReturnType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsAssertsReturnType { + #[inline] + fn needs_parentheses_with_parent(&self, _: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/big_int_literal_type.rs b/crates/rome_js_formatter/src/ts/types/big_int_literal_type.rs index d6c1ab3026cd..ce13b5562e89 100644 --- a/crates/rome_js_formatter/src/ts/types/big_int_literal_type.rs +++ b/crates/rome_js_formatter/src/ts/types/big_int_literal_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsBigIntLiteralType, TsBigIntLiteralTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsBigIntLiteralType, TsBigIntLiteralTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsBigIntLiteralType; @@ -15,4 +16,14 @@ impl FormatNodeRule for FormatTsBigIntLiteralType { write![f, [minus_token.format(), literal_token.format()]] } + + fn needs_parentheses(&self, item: &TsBigIntLiteralType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsBigIntLiteralType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/bigint_type.rs b/crates/rome_js_formatter/src/ts/types/bigint_type.rs index f12e37212b82..2facbdfe3e7c 100644 --- a/crates/rome_js_formatter/src/ts/types/bigint_type.rs +++ b/crates/rome_js_formatter/src/ts/types/bigint_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsBigintType, TsBigintTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsBigintType, TsBigintTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsBigintType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsBigintType { write![f, [bigint_token.format()]] } + + fn needs_parentheses(&self, item: &TsBigintType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsBigintType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/boolean_literal_type.rs b/crates/rome_js_formatter/src/ts/types/boolean_literal_type.rs index 33847e7dbc74..47f71787d63d 100644 --- a/crates/rome_js_formatter/src/ts/types/boolean_literal_type.rs +++ b/crates/rome_js_formatter/src/ts/types/boolean_literal_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsBooleanLiteralType, TsBooleanLiteralTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsBooleanLiteralType, TsBooleanLiteralTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsBooleanLiteralType; @@ -11,4 +12,14 @@ impl FormatNodeRule for FormatTsBooleanLiteralType { let TsBooleanLiteralTypeFields { literal } = node.as_fields(); write![f, [literal.format()]] } + + fn needs_parentheses(&self, item: &TsBooleanLiteralType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsBooleanLiteralType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/boolean_type.rs b/crates/rome_js_formatter/src/ts/types/boolean_type.rs index 90ee306da06f..fa299321eb87 100644 --- a/crates/rome_js_formatter/src/ts/types/boolean_type.rs +++ b/crates/rome_js_formatter/src/ts/types/boolean_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsBooleanType, TsBooleanTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsBooleanType, TsBooleanTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsBooleanType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsBooleanType { write![f, [boolean_token.format()]] } + + fn needs_parentheses(&self, item: &TsBooleanType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsBooleanType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/conditional_type.rs b/crates/rome_js_formatter/src/ts/types/conditional_type.rs index 16062fa36dac..a56b90c423e3 100644 --- a/crates/rome_js_formatter/src/ts/types/conditional_type.rs +++ b/crates/rome_js_formatter/src/ts/types/conditional_type.rs @@ -1,7 +1,12 @@ use crate::prelude::*; use crate::utils::JsAnyConditional; -use rome_js_syntax::TsConditionalType; +use crate::parentheses::{ + is_check_type, is_in_many_type_union_or_intersection_list, + operator_type_or_higher_needs_parens, NeedsParentheses, +}; +use rome_js_syntax::{JsSyntaxKind, JsSyntaxNode, TsConditionalType}; +use rome_rowan::AstNode; #[derive(Debug, Clone, Default)] pub struct FormatTsConditionalType; @@ -14,4 +19,101 @@ impl FormatNodeRule for FormatTsConditionalType { ) -> FormatResult<()> { JsAnyConditional::from(node.clone()).fmt(formatter) } + + fn needs_parentheses(&self, item: &TsConditionalType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsConditionalType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + match parent.kind() { + JsSyntaxKind::TS_CONDITIONAL_TYPE => { + let conditional = TsConditionalType::unwrap_cast(parent.clone()); + + let is_extends_type = conditional + .extends_type() + .map(AstNode::into_syntax) + .as_ref() + == Ok(self.syntax()); + + is_check_type(self.syntax(), parent) || is_extends_type + } + + _ => { + is_in_many_type_union_or_intersection_list(self.syntax(), parent) + || operator_type_or_higher_needs_parens(self.syntax(), parent) + } + } + } +} + +#[cfg(test)] +mod tests { + + use crate::{assert_needs_parentheses, assert_not_needs_parentheses}; + use rome_js_syntax::TsConditionalType; + + #[test] + fn needs_parentheses() { + assert_needs_parentheses!("type s = (A extends B ? C : D)[]", TsConditionalType); + + assert_needs_parentheses!("type s = unique (A extends B ? C : D);", TsConditionalType); + + assert_needs_parentheses!( + "type s = [number, ...(A extends B ? C : D)]", + TsConditionalType + ); + assert_needs_parentheses!("type s = [(A extends B ? C : D)?]", TsConditionalType); + + assert_needs_parentheses!("type s = (A extends B ? C : D)[a]", TsConditionalType); + assert_not_needs_parentheses!("type s = a[A extends B ? C : D]", TsConditionalType); + + assert_needs_parentheses!("type s = (A extends B ? C : D) & b", TsConditionalType); + assert_needs_parentheses!("type s = a & (A extends B ? C : D)", TsConditionalType); + + // This does require parentheses but the formatter will strip the leading `&`, leaving only the inner type + // thus, no parentheses are required + assert_not_needs_parentheses!("type s = &(A extends B ? C : D)", TsConditionalType); + + assert_needs_parentheses!("type s = (A extends B ? C : D) | b", TsConditionalType); + assert_needs_parentheses!("type s = a | (A extends B ? C : D)", TsConditionalType); + assert_not_needs_parentheses!("type s = |(A extends B ? C : D)", TsConditionalType); + + assert_needs_parentheses!( + "type s = (A extends B ? C : D) extends E ? F : G", + TsConditionalType[1] + ); + assert_not_needs_parentheses!( + "type s = (A extends B ? C : D) extends E ? F : G", + TsConditionalType[0] + ); + + assert_needs_parentheses!( + "type s = A extends (B extends C ? D : E) ? F : G", + TsConditionalType[1] + ); + assert_not_needs_parentheses!( + "type s = A extends (B extends C ? D : E) ? F : G", + TsConditionalType[0] + ); + + assert_not_needs_parentheses!( + "type s = A extends B ? (C extends D ? E : F) : G", + TsConditionalType[0] + ); + assert_not_needs_parentheses!( + "type s = A extends B ? (C extends D ? E : F) : G", + TsConditionalType[1] + ); + + assert_not_needs_parentheses!( + "type s = A extends B ? C : (D extends E ? F : G)", + TsConditionalType[0] + ); + assert_not_needs_parentheses!( + "type s = A extends B ? C : (D extends E ? F : G)", + TsConditionalType[1] + ); + } } diff --git a/crates/rome_js_formatter/src/ts/types/constructor_type.rs b/crates/rome_js_formatter/src/ts/types/constructor_type.rs index fddb1d9a230f..b39c3e0ebe52 100644 --- a/crates/rome_js_formatter/src/ts/types/constructor_type.rs +++ b/crates/rome_js_formatter/src/ts/types/constructor_type.rs @@ -1,8 +1,10 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; +use crate::ts::types::function_type::function_like_type_needs_parentheses; use rome_formatter::write; -use rome_js_syntax::TsConstructorType; use rome_js_syntax::TsConstructorTypeFields; +use rome_js_syntax::{JsSyntaxNode, TsConstructorType}; #[derive(Debug, Clone, Default)] pub struct FormatTsConstructorType; @@ -36,4 +38,61 @@ impl FormatNodeRule for FormatTsConstructorType { ] ] } + + fn needs_parentheses(&self, item: &TsConstructorType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsConstructorType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + function_like_type_needs_parentheses(self.syntax(), parent) + } +} + +#[cfg(test)] +mod tests { + + use crate::{assert_needs_parentheses, assert_not_needs_parentheses}; + use rome_js_syntax::TsConstructorType; + + #[test] + fn needs_parentheses() { + assert_needs_parentheses!("type s = (new () => string)[]", TsConstructorType); + + assert_needs_parentheses!("type s = unique (new () => string);", TsConstructorType); + + assert_needs_parentheses!( + "type s = [number, ...(new () => string)]", + TsConstructorType + ); + assert_needs_parentheses!("type s = [(new () => string)?]", TsConstructorType); + + assert_needs_parentheses!("type s = (new () => string)[a]", TsConstructorType); + assert_not_needs_parentheses!("type s = a[new () => string]", TsConstructorType); + + assert_needs_parentheses!("type s = (new () => string) & b", TsConstructorType); + assert_needs_parentheses!("type s = a & (new () => string)", TsConstructorType); + + // This does require parentheses but the formatter will strip the leading `&`, leaving only the inner type + // thus, no parentheses are required + assert_not_needs_parentheses!("type s = &(new () => string)", TsConstructorType); + + assert_needs_parentheses!("type s = (new () => string) | b", TsConstructorType); + assert_needs_parentheses!("type s = a | (new () => string)", TsConstructorType); + assert_not_needs_parentheses!("type s = |(new () => string)", TsConstructorType); + + assert_needs_parentheses!( + "type s = (new () => string) extends string ? string : number", + TsConstructorType + ); + assert_not_needs_parentheses!( + "type s = A extends string ? (new () => string) : number", + TsConstructorType + ); + assert_not_needs_parentheses!( + "type s = A extends string ? string : (new () => string)", + TsConstructorType + ) + } } diff --git a/crates/rome_js_formatter/src/ts/types/function_type.rs b/crates/rome_js_formatter/src/ts/types/function_type.rs index 0240fca7d493..d392640eee26 100644 --- a/crates/rome_js_formatter/src/ts/types/function_type.rs +++ b/crates/rome_js_formatter/src/ts/types/function_type.rs @@ -1,9 +1,13 @@ use crate::prelude::*; use crate::js::declarations::function_declaration::should_group_function_parameters; +use crate::parentheses::{ + is_check_type, is_in_many_type_union_or_intersection_list, + operator_type_or_higher_needs_parens, NeedsParentheses, +}; use rome_formatter::write; -use rome_js_syntax::TsFunctionType; use rome_js_syntax::TsFunctionTypeFields; +use rome_js_syntax::{JsSyntaxKind, JsSyntaxNode, TsFunctionType}; #[derive(Debug, Clone, Default)] pub struct FormatTsFunctionType; @@ -48,4 +52,78 @@ impl FormatNodeRule for FormatTsFunctionType { write!(f, [group(&format_inner)]) } + + fn needs_parentheses(&self, item: &TsFunctionType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsFunctionType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + function_like_type_needs_parentheses(self.syntax(), parent) + } +} + +pub(super) fn function_like_type_needs_parentheses( + node: &JsSyntaxNode, + parent: &JsSyntaxNode, +) -> bool { + match parent.kind() { + JsSyntaxKind::TS_RETURN_TYPE_ANNOTATION => { + let grand_parent = parent.parent(); + + grand_parent.map_or(false, |grand_parent| { + grand_parent.kind() == JsSyntaxKind::JS_ARROW_FUNCTION_EXPRESSION + }) + } + _ => { + is_check_type(node, parent) + || operator_type_or_higher_needs_parens(node, parent) + || is_in_many_type_union_or_intersection_list(node, parent) + } + } +} + +#[cfg(test)] +mod tests { + + use crate::{assert_needs_parentheses, assert_not_needs_parentheses}; + use rome_js_syntax::TsFunctionType; + + #[test] + fn needs_parentheses() { + assert_needs_parentheses!("type s = (() => string)[]", TsFunctionType); + + assert_needs_parentheses!("type s = unique (() => string);", TsFunctionType); + + assert_needs_parentheses!("type s = [number, ...(() => string)]", TsFunctionType); + assert_needs_parentheses!("type s = [(() => string)?]", TsFunctionType); + + assert_needs_parentheses!("type s = (() => string)[a]", TsFunctionType); + assert_not_needs_parentheses!("type s = a[() => string]", TsFunctionType); + + assert_needs_parentheses!("type s = (() => string) & b", TsFunctionType); + assert_needs_parentheses!("type s = a & (() => string)", TsFunctionType); + + // This does require parentheses but the formatter will strip the leading `&`, leaving only the inner type + // thus, no parentheses are required + assert_not_needs_parentheses!("type s = &(() => string)", TsFunctionType); + + assert_needs_parentheses!("type s = (() => string) | b", TsFunctionType); + assert_needs_parentheses!("type s = a | (() => string)", TsFunctionType); + assert_not_needs_parentheses!("type s = |(() => string)", TsFunctionType); + + assert_needs_parentheses!( + "type s = (() => string) extends string ? string : number", + TsFunctionType + ); + assert_not_needs_parentheses!( + "type s = A extends string ? (() => string) : number", + TsFunctionType + ); + assert_not_needs_parentheses!( + "type s = A extends string ? string : (() => string)", + TsFunctionType + ) + } } diff --git a/crates/rome_js_formatter/src/ts/types/indexed_access_type.rs b/crates/rome_js_formatter/src/ts/types/indexed_access_type.rs index 8ee0714549da..df9bb9bc517e 100644 --- a/crates/rome_js_formatter/src/ts/types/indexed_access_type.rs +++ b/crates/rome_js_formatter/src/ts/types/indexed_access_type.rs @@ -1,8 +1,9 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::TsIndexedAccessType; use rome_js_syntax::TsIndexedAccessTypeFields; +use rome_js_syntax::{JsSyntaxNode, TsIndexedAccessType}; #[derive(Debug, Clone, Default)] pub struct FormatTsIndexedAccessType; @@ -25,4 +26,14 @@ impl FormatNodeRule for FormatTsIndexedAccessType { ] ] } + + fn needs_parentheses(&self, item: &TsIndexedAccessType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsIndexedAccessType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/infer_type.rs b/crates/rome_js_formatter/src/ts/types/infer_type.rs index e9d47d0304b9..fd262f94b714 100644 --- a/crates/rome_js_formatter/src/ts/types/infer_type.rs +++ b/crates/rome_js_formatter/src/ts/types/infer_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::{operator_type_or_higher_needs_parens, NeedsParentheses}; use rome_formatter::write; -use rome_js_syntax::{TsInferType, TsInferTypeFields}; +use rome_js_syntax::{JsSyntaxKind, JsSyntaxNode, TsInferType, TsInferTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsInferType; @@ -14,4 +15,38 @@ impl FormatNodeRule for FormatTsInferType { } = node.as_fields(); write![f, [infer_token.format(), space(), type_parameter.format()]] } + + fn needs_parentheses(&self, item: &TsInferType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsInferType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + if parent.kind() == JsSyntaxKind::TS_REST_TUPLE_TYPE_ELEMENT { + false + } else { + operator_type_or_higher_needs_parens(self.syntax(), parent) + } + } +} + +#[cfg(test)] +mod tests { + + use crate::{assert_needs_parentheses, assert_not_needs_parentheses}; + use rome_js_syntax::TsInferType; + + #[test] + fn needs_parentheses() { + assert_needs_parentheses!("let s: (infer string)[] = symbol();", TsInferType); + + assert_needs_parentheses!("let s: unique (infer string);", TsInferType); + + assert_not_needs_parentheses!("let s: [number, ...infer string]", TsInferType); + assert_needs_parentheses!("let s: [(infer string)?]", TsInferType); + + assert_needs_parentheses!("let s: (infer string)[a]", TsInferType); + assert_not_needs_parentheses!("let s: a[(infer string)]", TsInferType); + } } diff --git a/crates/rome_js_formatter/src/ts/types/intersection_type.rs b/crates/rome_js_formatter/src/ts/types/intersection_type.rs index cfd021c439f5..12c0af04458e 100644 --- a/crates/rome_js_formatter/src/ts/types/intersection_type.rs +++ b/crates/rome_js_formatter/src/ts/types/intersection_type.rs @@ -1,7 +1,14 @@ use crate::prelude::*; +use crate::parentheses::{ + is_in_many_type_union_or_intersection_list, operator_type_or_higher_needs_parens, + NeedsParentheses, +}; use rome_formatter::{format_args, write}; -use rome_js_syntax::{JsSyntaxKind, TsIntersectionTypeFields}; +use rome_js_syntax::{ + JsSyntaxKind, JsSyntaxNode, TsIntersectionTypeElementList, TsIntersectionTypeFields, + TsUnionTypeVariantList, +}; use rome_js_syntax::{JsSyntaxToken, TsIntersectionType}; #[derive(Debug, Clone, Default)] @@ -26,6 +33,10 @@ impl FormatNodeRule for FormatTsIntersectionType { )))] ) } + + fn needs_parentheses(&self, item: &TsIntersectionType) -> bool { + item.needs_parentheses() + } } pub struct FormatTypeSetLeadingSeparator<'a> { @@ -49,3 +60,70 @@ impl Format for FormatTypeSetLeadingSeparator<'_> { } } } + +impl NeedsParentheses for TsIntersectionType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + union_or_intersection_type_needs_parentheses( + self.syntax(), + parent, + &TsIntersectionOrUnionTypeList::TsIntersectionTypeElementList(self.types()), + ) + } +} + +pub(super) fn union_or_intersection_type_needs_parentheses( + node: &JsSyntaxNode, + parent: &JsSyntaxNode, + types: &TsIntersectionOrUnionTypeList, +) -> bool { + debug_assert!(matches!( + node.kind(), + JsSyntaxKind::TS_INTERSECTION_TYPE | JsSyntaxKind::TS_UNION_TYPE + )); + + if is_in_many_type_union_or_intersection_list(node, parent) { + types.len() > 1 + } else { + operator_type_or_higher_needs_parens(node, parent) + } +} + +pub(super) enum TsIntersectionOrUnionTypeList { + TsIntersectionTypeElementList(TsIntersectionTypeElementList), + TsUnionTypeVariantList(TsUnionTypeVariantList), +} + +impl TsIntersectionOrUnionTypeList { + fn len(&self) -> usize { + match self { + TsIntersectionOrUnionTypeList::TsIntersectionTypeElementList(list) => list.len(), + TsIntersectionOrUnionTypeList::TsUnionTypeVariantList(list) => list.len(), + } + } +} + +#[cfg(test)] +mod tests { + + use crate::{assert_needs_parentheses, assert_not_needs_parentheses}; + use rome_js_syntax::TsIntersectionType; + + #[test] + fn needs_parentheses() { + assert_needs_parentheses!("let s: (string & number)[] = symbol();", TsIntersectionType); + + assert_needs_parentheses!("let s: unique (string & number);", TsIntersectionType); + + assert_needs_parentheses!("let s: [number, ...(string & number)]", TsIntersectionType); + assert_needs_parentheses!("let s: [(string & number)?]", TsIntersectionType); + + assert_needs_parentheses!("let s: (string & number)[a]", TsIntersectionType); + assert_not_needs_parentheses!("let s: a[(string & number)]", TsIntersectionType); + + assert_not_needs_parentheses!("let s: (&a) & (&b)", TsIntersectionType[1]); + assert_not_needs_parentheses!("let s: (&a) & (&b)", TsIntersectionType[2]); + + assert_needs_parentheses!("let s: (a & b) & (&c)", TsIntersectionType[1]); + assert_not_needs_parentheses!("let s: (a & b) & (&c)", TsIntersectionType[2]); + } +} diff --git a/crates/rome_js_formatter/src/ts/types/mapped_type.rs b/crates/rome_js_formatter/src/ts/types/mapped_type.rs index 9a83230888eb..94780fba3162 100644 --- a/crates/rome_js_formatter/src/ts/types/mapped_type.rs +++ b/crates/rome_js_formatter/src/ts/types/mapped_type.rs @@ -1,8 +1,9 @@ use crate::prelude::*; use crate::utils::FormatWithSemicolon; +use crate::parentheses::NeedsParentheses; use rome_formatter::{format_args, write}; -use rome_js_syntax::{TsMappedType, TsMappedTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsMappedType, TsMappedTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsMappedType; @@ -53,4 +54,14 @@ impl FormatNodeRule for FormatTsMappedType { .block_indent()] ) } + + fn needs_parentheses(&self, item: &TsMappedType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsMappedType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/never_type.rs b/crates/rome_js_formatter/src/ts/types/never_type.rs index 4ad6c25b519c..c90e04c15a4c 100644 --- a/crates/rome_js_formatter/src/ts/types/never_type.rs +++ b/crates/rome_js_formatter/src/ts/types/never_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsNeverType, TsNeverTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsNeverType, TsNeverTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsNeverType; @@ -11,4 +12,14 @@ impl FormatNodeRule for FormatTsNeverType { let TsNeverTypeFields { never_token } = node.as_fields(); write![f, [never_token.format()]] } + + fn needs_parentheses(&self, item: &TsNeverType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsNeverType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/non_primitive_type.rs b/crates/rome_js_formatter/src/ts/types/non_primitive_type.rs index 22771135a061..63125b8d7122 100644 --- a/crates/rome_js_formatter/src/ts/types/non_primitive_type.rs +++ b/crates/rome_js_formatter/src/ts/types/non_primitive_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsNonPrimitiveType, TsNonPrimitiveTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsNonPrimitiveType, TsNonPrimitiveTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsNonPrimitiveType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsNonPrimitiveType { write![f, [object_token.format()]] } + + fn needs_parentheses(&self, item: &TsNonPrimitiveType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsNonPrimitiveType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/null_literal_type.rs b/crates/rome_js_formatter/src/ts/types/null_literal_type.rs index f4288f01323a..ab8fd15cf908 100644 --- a/crates/rome_js_formatter/src/ts/types/null_literal_type.rs +++ b/crates/rome_js_formatter/src/ts/types/null_literal_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsNullLiteralType, TsNullLiteralTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsNullLiteralType, TsNullLiteralTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsNullLiteralType; @@ -11,4 +12,14 @@ impl FormatNodeRule for FormatTsNullLiteralType { let TsNullLiteralTypeFields { literal_token } = node.as_fields(); write![f, [literal_token.format()]] } + + fn needs_parentheses(&self, item: &TsNullLiteralType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsNullLiteralType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/number_literal_type.rs b/crates/rome_js_formatter/src/ts/types/number_literal_type.rs index a545b17e3976..e63b7b5b9fce 100644 --- a/crates/rome_js_formatter/src/ts/types/number_literal_type.rs +++ b/crates/rome_js_formatter/src/ts/types/number_literal_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsNumberLiteralType, TsNumberLiteralTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsNumberLiteralType, TsNumberLiteralTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsNumberLiteralType; @@ -14,4 +15,14 @@ impl FormatNodeRule for FormatTsNumberLiteralType { } = node.as_fields(); write![f, [minus_token.format(), literal_token.format()]] } + + fn needs_parentheses(&self, item: &TsNumberLiteralType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsNumberLiteralType { + fn needs_parentheses_with_parent(&self, _: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/number_type.rs b/crates/rome_js_formatter/src/ts/types/number_type.rs index 8bd8138fab69..80d7c05fb800 100644 --- a/crates/rome_js_formatter/src/ts/types/number_type.rs +++ b/crates/rome_js_formatter/src/ts/types/number_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsNumberType, TsNumberTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsNumberType, TsNumberTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsNumberType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsNumberType { write![f, [number_token.format()]] } + + fn needs_parentheses(&self, item: &TsNumberType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsNumberType { + fn needs_parentheses_with_parent(&self, _: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/object_type.rs b/crates/rome_js_formatter/src/ts/types/object_type.rs index f1c89491250a..34023eefa360 100644 --- a/crates/rome_js_formatter/src/ts/types/object_type.rs +++ b/crates/rome_js_formatter/src/ts/types/object_type.rs @@ -1,7 +1,8 @@ +use crate::parentheses::NeedsParentheses; use crate::prelude::*; use crate::utils::JsObjectLike; use rome_formatter::write; -use rome_js_syntax::TsObjectType; +use rome_js_syntax::{JsSyntaxNode, TsObjectType}; #[derive(Debug, Clone, Default)] pub struct FormatTsObjectType; @@ -10,4 +11,14 @@ impl FormatNodeRule for FormatTsObjectType { fn fmt_fields(&self, node: &TsObjectType, f: &mut JsFormatter) -> FormatResult<()> { write!(f, [JsObjectLike::from(node.clone())]) } + + fn needs_parentheses(&self, item: &TsObjectType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsObjectType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/parenthesized_type.rs b/crates/rome_js_formatter/src/ts/types/parenthesized_type.rs index 3ca62311b74c..335f8aaad170 100644 --- a/crates/rome_js_formatter/src/ts/types/parenthesized_type.rs +++ b/crates/rome_js_formatter/src/ts/types/parenthesized_type.rs @@ -1,8 +1,9 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::TsParenthesizedType; use rome_js_syntax::TsParenthesizedTypeFields; +use rome_js_syntax::{JsSyntaxNode, TsParenthesizedType}; #[derive(Debug, Clone, Default)] pub struct FormatTsParenthesizedType; @@ -17,10 +18,23 @@ impl FormatNodeRule for FormatTsParenthesizedType { write!( f, - [ - format_delimited(&l_paren_token?, &ty.format(), &r_paren_token?,) - .soft_block_indent() - ] + [l_paren_token.format(), &ty.format(), r_paren_token.format()] ) } + + fn needs_parentheses(&self, item: &TsParenthesizedType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsParenthesizedType { + #[inline] + fn needs_parentheses(&self) -> bool { + false + } + + #[inline] + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/reference_type.rs b/crates/rome_js_formatter/src/ts/types/reference_type.rs index 9e5c63632f93..07db99fc6e35 100644 --- a/crates/rome_js_formatter/src/ts/types/reference_type.rs +++ b/crates/rome_js_formatter/src/ts/types/reference_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsReferenceType, TsReferenceTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsReferenceType, TsReferenceTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsReferenceType; @@ -15,4 +16,14 @@ impl FormatNodeRule for FormatTsReferenceType { write![f, [name.format(), type_arguments.format()]] } + + fn needs_parentheses(&self, item: &TsReferenceType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsReferenceType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/string_literal_type.rs b/crates/rome_js_formatter/src/ts/types/string_literal_type.rs index 3bf49800b556..5f34901c5438 100644 --- a/crates/rome_js_formatter/src/ts/types/string_literal_type.rs +++ b/crates/rome_js_formatter/src/ts/types/string_literal_type.rs @@ -1,8 +1,9 @@ use crate::prelude::*; use crate::utils::{FormatLiteralStringToken, StringLiteralParentKind}; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsStringLiteralType, TsStringLiteralTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsStringLiteralType, TsStringLiteralTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsStringLiteralType; @@ -19,4 +20,14 @@ impl FormatNodeRule for FormatTsStringLiteralType { )] ) } + + fn needs_parentheses(&self, item: &TsStringLiteralType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsStringLiteralType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/string_type.rs b/crates/rome_js_formatter/src/ts/types/string_type.rs index 099d7a6f4279..816f6c9070c5 100644 --- a/crates/rome_js_formatter/src/ts/types/string_type.rs +++ b/crates/rome_js_formatter/src/ts/types/string_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsStringType, TsStringTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsStringType, TsStringTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsStringType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsStringType { write![f, [string_token.format()]] } + + fn needs_parentheses(&self, item: &TsStringType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsStringType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/symbol_type.rs b/crates/rome_js_formatter/src/ts/types/symbol_type.rs index 7aa921f54663..a8a137061bfd 100644 --- a/crates/rome_js_formatter/src/ts/types/symbol_type.rs +++ b/crates/rome_js_formatter/src/ts/types/symbol_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsSymbolType, TsSymbolTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsSymbolType, TsSymbolTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsSymbolType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsSymbolType { write![f, [symbol_token.format()]] } + + fn needs_parentheses(&self, item: &TsSymbolType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsSymbolType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/this_type.rs b/crates/rome_js_formatter/src/ts/types/this_type.rs index 3439e3eacac4..af876a4c3977 100644 --- a/crates/rome_js_formatter/src/ts/types/this_type.rs +++ b/crates/rome_js_formatter/src/ts/types/this_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsThisType, TsThisTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsThisType, TsThisTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsThisType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsThisType { write![f, [this_token.format()]] } + + fn needs_parentheses(&self, item: &TsThisType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsThisType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/tuple_type.rs b/crates/rome_js_formatter/src/ts/types/tuple_type.rs index fd6dd01eded5..cdaaae849636 100644 --- a/crates/rome_js_formatter/src/ts/types/tuple_type.rs +++ b/crates/rome_js_formatter/src/ts/types/tuple_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsTupleType, TsTupleTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsTupleType, TsTupleTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsTupleType; @@ -22,4 +23,14 @@ impl FormatNodeRule for FormatTsTupleType { ] ) } + + fn needs_parentheses(&self, item: &TsTupleType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsTupleType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/type_operator_type.rs b/crates/rome_js_formatter/src/ts/types/type_operator_type.rs index b445cd5dc46c..d5ed37b4726f 100644 --- a/crates/rome_js_formatter/src/ts/types/type_operator_type.rs +++ b/crates/rome_js_formatter/src/ts/types/type_operator_type.rs @@ -1,7 +1,11 @@ use crate::prelude::*; +use crate::parentheses::{operator_type_or_higher_needs_parens, NeedsParentheses}; use rome_formatter::write; -use rome_js_syntax::{TsTypeOperatorType, TsTypeOperatorTypeFields}; +use rome_js_syntax::{ + JsSyntaxNode, TsTypeOperatorType, TsTypeOperatorTypeFields, +}; +use rome_rowan::AstNode; #[derive(Debug, Clone, Default)] pub struct FormatTsTypeOperatorType; @@ -12,4 +16,35 @@ impl FormatNodeRule for FormatTsTypeOperatorType { write![f, [operator_token.format(), space(), ty.format()]] } + + fn needs_parentheses(&self, item: &TsTypeOperatorType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsTypeOperatorType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + operator_type_or_higher_needs_parens(self.syntax(), parent) + } +} + +#[cfg(test)] +mod tests { + + use crate::{assert_needs_parentheses, assert_not_needs_parentheses}; + use rome_js_syntax::TsTypeOperatorType; + + #[test] + fn needs_parentheses() { + assert_needs_parentheses!("let s: (unique symbol)[] = symbol();", TsTypeOperatorType); + + assert_needs_parentheses!("let s: unique (unique symbol);", TsTypeOperatorType[1]); + assert_not_needs_parentheses!("let s: unique (unique symbol);", TsTypeOperatorType[0]); + + assert_needs_parentheses!("let s: [number, ...(unique symbol)]", TsTypeOperatorType); + assert_needs_parentheses!("let s: [(unique symbol)?]", TsTypeOperatorType); + + assert_needs_parentheses!("let s: (unique symbol)[a]", TsTypeOperatorType); + assert_not_needs_parentheses!("let s: a[(unique symbol)]", TsTypeOperatorType); + } } diff --git a/crates/rome_js_formatter/src/ts/types/typeof_type.rs b/crates/rome_js_formatter/src/ts/types/typeof_type.rs index 37a7e821397f..666e6330363d 100644 --- a/crates/rome_js_formatter/src/ts/types/typeof_type.rs +++ b/crates/rome_js_formatter/src/ts/types/typeof_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsTypeofType, TsTypeofTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsTypeofType, TsTypeofTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsTypeofType; @@ -18,4 +19,14 @@ impl FormatNodeRule for FormatTsTypeofType { [typeof_token.format(), space(), expression_name.format()] ] } + + fn needs_parentheses(&self, item: &TsTypeofType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsTypeofType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/undefined_type.rs b/crates/rome_js_formatter/src/ts/types/undefined_type.rs index 54ed55045d11..ed00add990ee 100644 --- a/crates/rome_js_formatter/src/ts/types/undefined_type.rs +++ b/crates/rome_js_formatter/src/ts/types/undefined_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsUndefinedType, TsUndefinedTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsUndefinedType, TsUndefinedTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsUndefinedType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsUndefinedType { write![f, [undefined_token.format()]] } + + fn needs_parentheses(&self, item: &TsUndefinedType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsUndefinedType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/union_type.rs b/crates/rome_js_formatter/src/ts/types/union_type.rs index f9818bd0a5c3..6e20c2d25e58 100644 --- a/crates/rome_js_formatter/src/ts/types/union_type.rs +++ b/crates/rome_js_formatter/src/ts/types/union_type.rs @@ -1,8 +1,12 @@ +use crate::parentheses::NeedsParentheses; use crate::prelude::*; -use crate::ts::types::intersection_type::FormatTypeSetLeadingSeparator; -use rome_formatter::{write, Buffer}; -use rome_js_syntax::TsUnionTypeFields; +use crate::ts::types::intersection_type::{ + union_or_intersection_type_needs_parentheses, FormatTypeSetLeadingSeparator, + TsIntersectionOrUnionTypeList, +}; +use rome_formatter::{format_args, write, Buffer}; use rome_js_syntax::{JsSyntaxKind, TsUnionType}; +use rome_js_syntax::{JsSyntaxNode, TsUnionTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsUnionType; @@ -14,6 +18,24 @@ impl FormatNodeRule for FormatTsUnionType { types, } = node.as_fields(); + let body = format_with(|f| { + write!( + f, + [ + soft_line_break(), + FormatTypeSetLeadingSeparator { + separator: JsSyntaxKind::PIPE, + leading_separator: leading_separator_token.as_ref() + }, + types.format() + ] + ) + }); + + if node.needs_parentheses() { + return write!(f, [group(&format_args![indent(&body), soft_line_break()])]); + } + let should_indent = { let parent_kind = node.syntax().parent().map(|p| p.kind()); @@ -30,19 +52,6 @@ impl FormatNodeRule for FormatTsUnionType { ) }; - let body = format_with(|f| { - write!( - f, - [ - soft_line_break(), - FormatTypeSetLeadingSeparator { - separator: JsSyntaxKind::PIPE, - leading_separator: leading_separator_token.as_ref() - }, - types.format() - ] - ) - }); write![ f, [group(&format_with(|f| { @@ -54,4 +63,18 @@ impl FormatNodeRule for FormatTsUnionType { }))] ] } + + fn needs_parentheses(&self, item: &TsUnionType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsUnionType { + fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool { + union_or_intersection_type_needs_parentheses( + self.syntax(), + parent, + &TsIntersectionOrUnionTypeList::TsUnionTypeVariantList(self.types()), + ) + } } diff --git a/crates/rome_js_formatter/src/ts/types/unknown_type.rs b/crates/rome_js_formatter/src/ts/types/unknown_type.rs index dbb57205c521..297fb022eed2 100644 --- a/crates/rome_js_formatter/src/ts/types/unknown_type.rs +++ b/crates/rome_js_formatter/src/ts/types/unknown_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsUnknownType, TsUnknownTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsUnknownType, TsUnknownTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsUnknownType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsUnknownType { write![f, [unknown_token.format()]] } + + fn needs_parentheses(&self, item: &TsUnknownType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsUnknownType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/ts/types/void_type.rs b/crates/rome_js_formatter/src/ts/types/void_type.rs index 98d9137afb43..165e4e812717 100644 --- a/crates/rome_js_formatter/src/ts/types/void_type.rs +++ b/crates/rome_js_formatter/src/ts/types/void_type.rs @@ -1,7 +1,8 @@ use crate::prelude::*; +use crate::parentheses::NeedsParentheses; use rome_formatter::write; -use rome_js_syntax::{TsVoidType, TsVoidTypeFields}; +use rome_js_syntax::{JsSyntaxNode, TsVoidType, TsVoidTypeFields}; #[derive(Debug, Clone, Default)] pub struct FormatTsVoidType; @@ -12,4 +13,14 @@ impl FormatNodeRule for FormatTsVoidType { write![f, [void_token.format()]] } + + fn needs_parentheses(&self, item: &TsVoidType) -> bool { + item.needs_parentheses() + } +} + +impl NeedsParentheses for TsVoidType { + fn needs_parentheses_with_parent(&self, _parent: &JsSyntaxNode) -> bool { + false + } } diff --git a/crates/rome_js_formatter/src/utils/assignment_like.rs b/crates/rome_js_formatter/src/utils/assignment_like.rs index 705faa9c405d..324df87fd2f6 100644 --- a/crates/rome_js_formatter/src/utils/assignment_like.rs +++ b/crates/rome_js_formatter/src/utils/assignment_like.rs @@ -904,36 +904,25 @@ impl Format for JsAnyAssignmentLike { // 4. we write the left node inside the main buffer based on the layout let mut buffer = VecBuffer::new(f.state_mut()); let is_left_short = self.write_left(&mut Formatter::new(&mut buffer))?; - let formatted_element = buffer.into_element(); + let formatted_left = buffer.into_element(); // Compare name only if we are in a position of computing it. // If not (for example, left is not an identifier), then let's fallback to false, // so we can continue the chain of checks let layout = self.layout(is_left_short, f)?; - let left = format_once(|f| { + let left = format_once(|f| f.write_element(formatted_left)); + let right = format_with(|f| self.write_right(f)).memoized(); + + let inner_content = format_with(|f| { if matches!( &layout, AssignmentLikeLayout::BreakLeftHandSide | AssignmentLikeLayout::OnlyLeft ) { - write!( - f, - [&format_once(|f| { f.write_element(formatted_element) })] - ) + write!(f, [left])?; } else { - write!( - f, - [group(&format_once(|f| { - f.write_element(formatted_element) - }))] - ) + write!(f, [group(&left)])?; } - }); - - let right = format_with(|f| self.write_right(f)).memoized(); - - let inner_content = format_with(|f| { - write!(f, [left])?; if layout != AssignmentLikeLayout::SuppressedInitializer { self.write_operator(f)?; diff --git a/crates/rome_js_formatter/src/utils/conditional.rs b/crates/rome_js_formatter/src/utils/conditional.rs index d76165fd2c86..eb6a4eadc2c8 100644 --- a/crates/rome_js_formatter/src/utils/conditional.rs +++ b/crates/rome_js_formatter/src/utils/conditional.rs @@ -320,7 +320,7 @@ impl JsAnyConditional { .extends_type() .map(AstNode::into_syntax) .as_ref() - == Ok(self.syntax()) + == Ok(node) } } } diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/as/as.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/as/as.ts.snap index 012c2ea0a991..bec884096553 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/as/as.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/as/as.ts.snap @@ -72,19 +72,6 @@ const iter2 = createIterator(self.controller, child, self.tag as SyncFunctionCom const state = JSON.stringify({ next: window.location.href, nonce, -@@ -41,9 +41,9 @@ - thisIsAReallyReallyReallyReallyReallyLongIdentifier as SomeInterface; - const value2 = - thisIsAnIdentifier as thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongInterface; --const value3 = thisIsAReallyLongIdentifier as -- | SomeInterface -- | SomeOtherInterface; -+const value3 = thisIsAReallyLongIdentifier as ( -+ SomeInterface | SomeOtherInterface -+); - const value4 = thisIsAReallyLongIdentifier as { - prop1: string; - prop2: number; ``` # Output @@ -133,9 +120,9 @@ const value1 = thisIsAReallyReallyReallyReallyReallyLongIdentifier as SomeInterface; const value2 = thisIsAnIdentifier as thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongInterface; -const value3 = thisIsAReallyLongIdentifier as ( - SomeInterface | SomeOtherInterface -); +const value3 = thisIsAReallyLongIdentifier as + | SomeInterface + | SomeOtherInterface; const value4 = thisIsAReallyLongIdentifier as { prop1: string; prop2: number; diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/compiler/contextualSignatureInstantiation2.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/compiler/contextualSignatureInstantiation2.ts.snap index 99f5dca786e6..2ff9f6c44d15 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/compiler/contextualSignatureInstantiation2.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/compiler/contextualSignatureInstantiation2.ts.snap @@ -25,7 +25,7 @@ var r23 = dot(id)(id);``` - (g: (_: U) => T): ((r: U) => S) => - (x) => - f(g(x)); -+dot = (f: (_: T) => S) => (g: (_: U) => T): (r: U) => S => (x) => ++dot = (f: (_: T) => S) => (g: (_: U) => T): ((r: U) => S) => (x) => + f(g(x)); var id: (x: T) => T; var r23 = dot(id)(id); @@ -36,7 +36,7 @@ var r23 = dot(id)(id);``` ```js // dot f g x = f(g(x)) var dot: (f: (_: T) => S) => (g: (_: U) => T) => (_: U) => S; -dot = (f: (_: T) => S) => (g: (_: U) => T): (r: U) => S => (x) => +dot = (f: (_: T) => S) => (g: (_: U) => T): ((r: U) => S) => (x) => f(g(x)); var id: (x: T) => T; var r23 = dot(id)(id); diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/conditional-types/conditonal-types.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/conditional-types/conditonal-types.ts.snap deleted file mode 100644 index 28231eb2e6a3..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/conditional-types/conditonal-types.ts.snap +++ /dev/null @@ -1,137 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -export type DeepReadonly = T extends any[] ? DeepReadonlyArray : T extends object ? DeepReadonlyObject : T; - -type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; - -interface DeepReadonlyArray extends ReadonlyArray> {} - -type DeepReadonlyObject = { - readonly [P in NonFunctionPropertyNames]: DeepReadonly; -}; - -type TypeName = - T extends string ? "string" : - T extends number ? "number" : - T extends boolean ? "boolean" : - T extends undefined ? "undefined" : - T extends Function ? "function" : - "object"; - -type Type01 = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6; -type Type02 = 0 extends ((1 extends 2 ? 3 : 4)) ? 5 : 6; -type Type03 = 0 extends (((1 extends 2 ? 3 : 4))) ? 5 : 6; -type Type04 = 0 extends ((((1 extends 2 ? 3 : 4)))) ? 5 : 6; -type Type05 = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6; -type Type06 = ((0 extends 1 ? 2 : 3)) extends 4 ? 5 : 6; -type Type07 = (((0 extends 1 ? 2 : 3))) extends 4 ? 5 : 6; -type Type08 = ((((0 extends 1 ? 2 : 3)))) extends 4 ? 5 : 6; - -type T1 = () => void extends T ? U : V; -type T1a = () => (void extends T ? U : V); -type T1b = () => (void) extends T ? U : V; -type T2 = (() => void) extends T ? U : V; - -type U1 = new () => X extends T ? U : V; -type U1a = new () => (X extends T ? U : V); -type U1b = new () => (X) extends T ? U : V; -type U2 = (new () => X) extends T ? U : V; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -27,20 +27,20 @@ - : "object"; - - type Type01 = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6; --type Type02 = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6; --type Type03 = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6; --type Type04 = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6; -+type Type02 = 0 extends ((1 extends 2 ? 3 : 4)) ? 5 : 6; -+type Type03 = 0 extends (((1 extends 2 ? 3 : 4))) ? 5 : 6; -+type Type04 = 0 extends ((((1 extends 2 ? 3 : 4)))) ? 5 : 6; - type Type05 = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6; --type Type06 = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6; --type Type07 = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6; --type Type08 = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6; -+type Type06 = ((0 extends 1 ? 2 : 3)) extends 4 ? 5 : 6; -+type Type07 = (((0 extends 1 ? 2 : 3))) extends 4 ? 5 : 6; -+type Type08 = ((((0 extends 1 ? 2 : 3)))) extends 4 ? 5 : 6; - - type T1 = () => void extends T ? U : V; --type T1a = () => void extends T ? U : V; --type T1b = () => void extends T ? U : V; -+type T1a = () => (void extends T ? U : V); -+type T1b = () => (void) extends T ? U : V; - type T2 = (() => void) extends T ? U : V; - - type U1 = new () => X extends T ? U : V; --type U1a = new () => X extends T ? U : V; --type U1b = new () => X extends T ? U : V; -+type U1a = new () => (X extends T ? U : V); -+type U1b = new () => (X) extends T ? U : V; - type U2 = (new () => X) extends T ? U : V; -``` - -# Output - -```js -export type DeepReadonly = T extends any[] - ? DeepReadonlyArray - : T extends object - ? DeepReadonlyObject - : T; - -type NonFunctionPropertyNames = { - [K in keyof T]: T[K] extends Function ? never : K; -}[keyof T]; - -interface DeepReadonlyArray extends ReadonlyArray> {} - -type DeepReadonlyObject = { - readonly [P in NonFunctionPropertyNames]: DeepReadonly; -}; - -type TypeName = T extends string - ? "string" - : T extends number - ? "number" - : T extends boolean - ? "boolean" - : T extends undefined - ? "undefined" - : T extends Function - ? "function" - : "object"; - -type Type01 = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6; -type Type02 = 0 extends ((1 extends 2 ? 3 : 4)) ? 5 : 6; -type Type03 = 0 extends (((1 extends 2 ? 3 : 4))) ? 5 : 6; -type Type04 = 0 extends ((((1 extends 2 ? 3 : 4)))) ? 5 : 6; -type Type05 = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6; -type Type06 = ((0 extends 1 ? 2 : 3)) extends 4 ? 5 : 6; -type Type07 = (((0 extends 1 ? 2 : 3))) extends 4 ? 5 : 6; -type Type08 = ((((0 extends 1 ? 2 : 3)))) extends 4 ? 5 : 6; - -type T1 = () => void extends T ? U : V; -type T1a = () => (void extends T ? U : V); -type T1b = () => (void) extends T ? U : V; -type T2 = (() => void) extends T ? U : V; - -type U1 = new () => X extends T ? U : V; -type U1a = new () => (X extends T ? U : V); -type U1b = new () => (X) extends T ? U : V; -type U2 = (new () => X) extends T ? U : V; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/conformance/types/functions/TSFunctionTypeNoUnnecessaryParentheses.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/conformance/types/functions/TSFunctionTypeNoUnnecessaryParentheses.ts.snap deleted file mode 100644 index 8e19c3de6dd9..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/conformance/types/functions/TSFunctionTypeNoUnnecessaryParentheses.ts.snap +++ /dev/null @@ -1,34 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -class Foo { - bar: (() => boolean); -}``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,3 +1,3 @@ - class Foo { -- bar: () => boolean; -+ bar: (() => boolean); - } -``` - -# Output - -```js -class Foo { - bar: (() => boolean); -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/functionTypeLong.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/functionTypeLong.ts.snap deleted file mode 100644 index 6d3f1a8bfeaf..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/functionTypeLong.ts.snap +++ /dev/null @@ -1,48 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type AwkwardlyLongFunctionTypeDefinition = < - GenericTypeNumberOne, - GenericTypeNumberTwo, - GenericTypeNumberThree ->( - arg1: GenericTypeNumberOne, - arg2: GenericTypeNumberTwo, - arg3: GenericTypeNumberThree -) => (GenericTypeNumberOne | GenericTypeNumberTwo | GenericTypeNumberThree); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -6,4 +6,4 @@ - arg1: GenericTypeNumberOne, - arg2: GenericTypeNumberTwo, - arg3: GenericTypeNumberThree, --) => GenericTypeNumberOne | GenericTypeNumberTwo | GenericTypeNumberThree; -+) => (GenericTypeNumberOne | GenericTypeNumberTwo | GenericTypeNumberThree); -``` - -# Output - -```js -type AwkwardlyLongFunctionTypeDefinition = < - GenericTypeNumberOne, - GenericTypeNumberTwo, - GenericTypeNumberThree, ->( - arg1: GenericTypeNumberOne, - arg2: GenericTypeNumberTwo, - arg3: GenericTypeNumberThree, -) => (GenericTypeNumberOne | GenericTypeNumberTwo | GenericTypeNumberThree); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/function-type/type-annotation.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/function-type/type-annotation.ts.snap deleted file mode 100644 index ed2d581fa90f..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/function-type/type-annotation.ts.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const foo = (): () => void => (): void => null; -const bar = (): (() => void) => (): void => null; -const baz = (): ((() => void)) => (): void => null; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,3 +1,3 @@ --const foo = (): (() => void) => (): void => null; -+const foo = (): () => void => (): void => null; - const bar = (): (() => void) => (): void => null; --const baz = (): (() => void) => (): void => null; -+const baz = (): ((() => void)) => (): void => null; -``` - -# Output - -```js -const foo = (): () => void => (): void => null; -const bar = (): (() => void) => (): void => null; -const baz = (): ((() => void)) => (): void => null; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/intersection/intersection-parens.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/intersection/intersection-parens.ts.snap deleted file mode 100644 index 5958f8a1ab51..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/intersection/intersection-parens.ts.snap +++ /dev/null @@ -1,177 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type A = (number | string) & boolean; -type B = ((number | string)) & boolean; -type C = (((number | string))) & boolean; -type D = ((((number | string)))) & boolean; - -let b1 : C; -let b2 : & C; -let b3 : (& C); -let b4 : & (C); -let b5 : (& (C)); -let b6 : /*1*/ & C; -let b7 : /*1*/ & (C); -let b8 : /*1*/ (& C); -let b9 : (/*1*/ & C); -let b10: /*1*/ & /*2*/ C; -let b11: /*1*/ (& /*2*/ C); - -let bb1: /*1*/ & /*2*/ C & D; -let bb2: /*1*/ & /*2*/ C & /*3*/ D; -let bb3: /*1*/ & /*2*/ C & /*3*/ D /*5*/; - -type B2 = & C; -type B3 = (& C); -type B4 = & (C); -type B5 = (& (C)); -type B6 = /*1*/ & C; -type B7 = /*1*/ & (C); -type B8 = /*1*/ (& C); -type B9 = (/*1*/ & C); -type B10 = /*1*/ & /*2*/ C; -type B11 = /*1*/ (& /*2*/ C); -type B12 = /*1*/ & ( (C)); - -type Bb1 = /*1*/ & /*2*/ C & D; -type Bb2 = /*1*/ & /*2*/ C & /*3*/ D; -type Bb3 = /*1*/ & /*2*/ C & /*3*/ D /*4*/; - -type D1 = /*1*/ | a & b; -type D2 = /*1*/ | a & (b); -type D3 = /*1*/ | a & (| b); -type D4 = /*1*/ | (a & b); -type D5 = /*1*/ (| a & b); -type D6 /*0*/ = /*1*/ (| a & b); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,43 +1,43 @@ - type A = (number | string) & boolean; --type B = (number | string) & boolean; --type C = (number | string) & boolean; --type D = (number | string) & boolean; -+type B = ((number | string)) & boolean; -+type C = (((number | string))) & boolean; -+type D = ((((number | string)))) & boolean; - - let b1: C; - let b2: C; --let b3: C; --let b4: C; --let b5: C; -+let b3: (C); -+let b4: (C); -+let b5: ((C)); - let b6: /*1*/ C; --let b7: /*1*/ C; --let b8: /*1*/ C; --let b9: /*1*/ C; -+let b7: /*1*/ (C); -+let b8: /*1*/ (C); -+let b9: (/*1*/ C); - let b10: /*1*/ /*2*/ C; --let b11: /*1*/ /*2*/ C; -+let b11: /*1*/ (/*2*/ C); - - let bb1: /*1*/ /*2*/ C & D; - let bb2: /*1*/ /*2*/ C & /*3*/ D; - let bb3: /*1*/ /*2*/ C & /*3*/ D /*5*/; - - type B2 = C; --type B3 = C; --type B4 = C; --type B5 = C; -+type B3 = (C); -+type B4 = (C); -+type B5 = ((C)); - type B6 = /*1*/ C; --type B7 = /*1*/ C; --type B8 = /*1*/ C; --type B9 = /*1*/ C; -+type B7 = /*1*/ (C); -+type B8 = /*1*/ (C); -+type B9 = (/*1*/ C); - type B10 = /*1*/ /*2*/ C; --type B11 = /*1*/ /*2*/ C; --type B12 = /*1*/ C; -+type B11 = /*1*/ (/*2*/ C); -+type B12 = /*1*/ ((C)); - - type Bb1 = /*1*/ /*2*/ C & D; - type Bb2 = /*1*/ /*2*/ C & /*3*/ D; - type Bb3 = /*1*/ /*2*/ C & /*3*/ D /*4*/; - - type D1 = /*1*/ a & b; --type D2 = /*1*/ a & b; --type D3 = /*1*/ a & b; --type D4 = /*1*/ a & b; --type D5 = /*1*/ a & b; --type D6 /*0*/ = /*1*/ a & b; -+type D2 = /*1*/ a & (b); -+type D3 = /*1*/ a & (b); -+type D4 = /*1*/ (a & b); -+type D5 = /*1*/ (a & b); -+type D6 /*0*/ = /*1*/ (a & b); -``` - -# Output - -```js -type A = (number | string) & boolean; -type B = ((number | string)) & boolean; -type C = (((number | string))) & boolean; -type D = ((((number | string)))) & boolean; - -let b1: C; -let b2: C; -let b3: (C); -let b4: (C); -let b5: ((C)); -let b6: /*1*/ C; -let b7: /*1*/ (C); -let b8: /*1*/ (C); -let b9: (/*1*/ C); -let b10: /*1*/ /*2*/ C; -let b11: /*1*/ (/*2*/ C); - -let bb1: /*1*/ /*2*/ C & D; -let bb2: /*1*/ /*2*/ C & /*3*/ D; -let bb3: /*1*/ /*2*/ C & /*3*/ D /*5*/; - -type B2 = C; -type B3 = (C); -type B4 = (C); -type B5 = ((C)); -type B6 = /*1*/ C; -type B7 = /*1*/ (C); -type B8 = /*1*/ (C); -type B9 = (/*1*/ C); -type B10 = /*1*/ /*2*/ C; -type B11 = /*1*/ (/*2*/ C); -type B12 = /*1*/ ((C)); - -type Bb1 = /*1*/ /*2*/ C & D; -type Bb2 = /*1*/ /*2*/ C & /*3*/ D; -type Bb3 = /*1*/ /*2*/ C & /*3*/ D /*4*/; - -type D1 = /*1*/ a & b; -type D2 = /*1*/ a & (b); -type D3 = /*1*/ a & (b); -type D4 = /*1*/ (a & b); -type D5 = /*1*/ (a & b); -type D6 /*0*/ = /*1*/ (a & b); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyof/keyof.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyof/keyof.ts.snap deleted file mode 100644 index aa336a39fcf7..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyof/keyof.ts.snap +++ /dev/null @@ -1,57 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type A = keyof (T | U); -type B = keyof (X & Y); -type C = keyof T | U; -type D = keyof X & Y; -type E = (keyof T)[]; -type F = ((keyof T))[]; -type G = (keyof T1)["foo"]; -type H = ((keyof T1))["foo"]; -type I = (((keyof T1)))["foo"]; -type J = ((((keyof T1))))["foo"]; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -3,8 +3,8 @@ - type C = keyof T | U; - type D = keyof X & Y; - type E = (keyof T)[]; --type F = (keyof T)[]; -+type F = ((keyof T))[]; - type G = (keyof T1)["foo"]; --type H = (keyof T1)["foo"]; --type I = (keyof T1)["foo"]; --type J = (keyof T1)["foo"]; -+type H = ((keyof T1))["foo"]; -+type I = (((keyof T1)))["foo"]; -+type J = ((((keyof T1))))["foo"]; -``` - -# Output - -```js -type A = keyof (T | U); -type B = keyof (X & Y); -type C = keyof T | U; -type D = keyof X & Y; -type E = (keyof T)[]; -type F = ((keyof T))[]; -type G = (keyof T1)["foo"]; -type H = ((keyof T1))["foo"]; -type I = (((keyof T1)))["foo"]; -type J = ((((keyof T1))))["foo"]; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap index af019ba8041f..e1a8d4a8207a 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap @@ -1,8 +1,5 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs -assertion_line: 271 -info: - test_file: typescript/keyword-types/conditional-types.ts --- # Input @@ -30,26 +27,14 @@ export type UnwrappedResultRow = { ```diff --- Prettier +++ Rome -@@ -1,8 +1,14 @@ - export type UnwrappedResultRow = { -- [P in keyof T]: T[P] extends Req -- ? a -- : T[P] extends Opt -- ? b +@@ -3,6 +3,7 @@ + ? a + : T[P] extends Opt + ? b - : // TEST -- never; -+ [P in keyof T]: ( -+ T[P] extends Req -+ ? (a) -+ : ( -+ T[P] extends Opt -+ ? (b) -+ : ( -+ // TEST -+ never -+ ) -+ ) -+ ); ++ : ++ // TEST + never; }; ``` @@ -57,18 +42,13 @@ export type UnwrappedResultRow = { ```js export type UnwrappedResultRow = { - [P in keyof T]: ( - T[P] extends Req - ? (a) - : ( - T[P] extends Opt - ? (b) - : ( - // TEST - never - ) - ) - ); + [P in keyof T]: T[P] extends Req + ? a + : T[P] extends Opt + ? b + : + // TEST + never; }; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap index f2b504f2ffa3..d321dd2b756e 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap @@ -65,142 +65,103 @@ let foo: ( ```diff --- Prettier +++ Rome -@@ -1,26 +1,52 @@ +@@ -1,26 +1,39 @@ -let foo: // comment --any; ++let foo: ++// comment + any; -let foo: // comment --null; ++let foo: ++// comment + null; -let foo: // comment --this; ++let foo: ++// comment + this; -let foo: // comment --number; ++let foo: ++// comment + number; -let foo: // comment --void; ++let foo: ++// comment + void; -let foo: // comment --boolean; ++let foo: ++// comment + boolean; -let foo: // comment --bigint; ++let foo: ++// comment + bigint; -let foo: // comment --symbol; ++let foo: ++// comment + symbol; -let foo: // comment --string; ++let foo: ++// comment + string; -let foo: // comment --never; ++let foo: ++// comment + never; -let foo: // comment --object; ++let foo: ++// comment + object; -let foo: // comment --undefined; ++let foo: ++// comment + undefined; -let foo: // comment --unknown; -+let foo: ( -+ // comment -+ any -+); -+let foo: ( -+ // comment -+ null -+); -+let foo: ( -+ // comment -+ this -+); -+let foo: ( -+ // comment -+ number -+); -+let foo: ( -+ // comment -+ void -+); -+let foo: ( -+ // comment -+ boolean -+); -+let foo: ( -+ // comment -+ bigint -+); -+let foo: ( -+ // comment -+ symbol -+); -+let foo: ( -+ // comment -+ string -+); -+let foo: ( -+ // comment -+ never -+); -+let foo: ( -+ // comment -+ object -+); -+let foo: ( -+ // comment -+ undefined -+); -+let foo: ( -+ // comment -+ unknown -+); ++let foo: ++// comment + unknown; ``` # Output ```js -let foo: ( - // comment - any -); -let foo: ( - // comment - null -); -let foo: ( - // comment - this -); -let foo: ( - // comment - number -); -let foo: ( - // comment - void -); -let foo: ( - // comment - boolean -); -let foo: ( - // comment - bigint -); -let foo: ( - // comment - symbol -); -let foo: ( - // comment - string -); -let foo: ( - // comment - never -); -let foo: ( - // comment - object -); -let foo: ( - // comment - undefined -); -let foo: ( - // comment - unknown -); +let foo: +// comment +any; +let foo: +// comment +null; +let foo: +// comment +this; +let foo: +// comment +number; +let foo: +// comment +void; +let foo: +// comment +boolean; +let foo: +// comment +bigint; +let foo: +// comment +symbol; +let foo: +// comment +string; +let foo: +// comment +never; +let foo: +// comment +object; +let foo: +// comment +undefined; +let foo: +// comment +unknown; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/rest-type/infer-type.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/rest-type/infer-type.ts.snap deleted file mode 100644 index b52e8f798c7c..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/rest-type/infer-type.ts.snap +++ /dev/null @@ -1,58 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type Tail = T extends [infer U, ...infer R] ? R : never; - -// should remove parens from this, to avoid a type issue with TypeScript 4.0: -type Tail2 = T extends [infer U, ...(infer R)] ? R : never; - -// but not remove parens from this: -type Tail3 = T extends [infer U, ...(infer R)[]] ? R : never; - -type ReduceNextElement< - T extends readonly unknown[] -> = T extends readonly [infer V, ...infer R] ? [V, R] : never -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,7 +1,7 @@ - type Tail = T extends [infer U, ...infer R] ? R : never; - - // should remove parens from this, to avoid a type issue with TypeScript 4.0: --type Tail2 = T extends [infer U, ...infer R] ? R : never; -+type Tail2 = T extends [infer U, ...(infer R)] ? R : never; - - // but not remove parens from this: - type Tail3 = T extends [infer U, ...(infer R)[]] ? R : never; -``` - -# Output - -```js -type Tail = T extends [infer U, ...infer R] ? R : never; - -// should remove parens from this, to avoid a type issue with TypeScript 4.0: -type Tail2 = T extends [infer U, ...(infer R)] ? R : never; - -// but not remove parens from this: -type Tail3 = T extends [infer U, ...(infer R)[]] ? R : never; - -type ReduceNextElement = T extends readonly [ - infer V, - ...infer R, -] - ? [V, R] - : never; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/comments.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/comments.ts.snap deleted file mode 100644 index cb9141b69666..000000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/comments.ts.snap +++ /dev/null @@ -1,58 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type A1 = a /* 1 */ | b; -type A2 = a | /* 1 */ b; -type A3 = (a /* 1 */) | b; -type A4 = a | (/* 1 */ b); -type A5 = (a) /* 1 */ | b; -type A6 = a | /* 1 */ (b); - -type B1 = a /* 1 */ /* 2 */ | b; -type B2 = a /* 1 */ | /* 2 */ b; -type B3 = a | /* 1 */ /* 2 */ b; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,9 +1,9 @@ - type A1 = a /* 1 */ | b; - type A2 = a | /* 1 */ b; --type A3 = a /* 1 */ | b; --type A4 = a | /* 1 */ b; --type A5 = a /* 1 */ | b; --type A6 = a | /* 1 */ b; -+type A3 = (a /* 1 */) | b; -+type A4 = a | (/* 1 */ b); -+type A5 = (a) /* 1 */ | b; -+type A6 = a | /* 1 */ (b); - - type B1 = a /* 1 */ /* 2 */ | b; - type B2 = a /* 1 */ | /* 2 */ b; -``` - -# Output - -```js -type A1 = a /* 1 */ | b; -type A2 = a | /* 1 */ b; -type A3 = (a /* 1 */) | b; -type A4 = a | (/* 1 */ b); -type A5 = (a) /* 1 */ | b; -type A6 = a | /* 1 */ (b); - -type B1 = a /* 1 */ /* 2 */ | b; -type B2 = a /* 1 */ | /* 2 */ b; -type B3 = a | /* 1 */ /* 2 */ b; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap index 8b6eb213ae84..f4bf6bd2af6e 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap @@ -91,7 +91,7 @@ type T8 = number | (((((arg: any) => void)))); | A // The upload timed out | B -@@ -27,15 +34,17 @@ +@@ -27,9 +34,11 @@ // Uploading to aws3 and CreatePostMutation succeeded | D; @@ -105,19 +105,7 @@ type T8 = number | (((((arg: any) => void)))); + }; type T1 = (number | string)["toString"]; --type T2 = (number | string)["toString"]; --type T3 = (number | string)["toString"]; --type T4 = (number | string)["toString"]; -+type T2 = ((number | string))["toString"]; -+type T3 = (((number | string)))["toString"]; -+type T4 = ((((number | string))))["toString"]; - type T5 = number | ((arg: any) => void); --type T6 = number | ((arg: any) => void); --type T7 = number | ((arg: any) => void); --type T8 = number | ((arg: any) => void); -+type T6 = number | (((arg: any) => void)); -+type T7 = number | ((((arg: any) => void))); -+type T8 = number | (((((arg: any) => void)))); + type T2 = (number | string)["toString"]; ``` # Output @@ -166,13 +154,13 @@ type window = }; type T1 = (number | string)["toString"]; -type T2 = ((number | string))["toString"]; -type T3 = (((number | string)))["toString"]; -type T4 = ((((number | string))))["toString"]; +type T2 = (number | string)["toString"]; +type T3 = (number | string)["toString"]; +type T4 = (number | string)["toString"]; type T5 = number | ((arg: any) => void); -type T6 = number | (((arg: any) => void)); -type T7 = number | ((((arg: any) => void))); -type T8 = number | (((((arg: any) => void)))); +type T6 = number | ((arg: any) => void); +type T7 = number | ((arg: any) => void); +type T8 = number | ((arg: any) => void); ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap index ffcbccefab60..a542fbd87285 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap @@ -47,11 +47,11 @@ export type a = - // prettier-ignore - | qux1&qux2; + // foo -+ | foo1 & foo2 ++ | (foo1 & foo2) + // bar -+ | bar1 & bar2 ++ | (bar1 & bar2) + // prettier-ignore -+ | qux1 & qux2; ++ | (qux1 & qux2); export type a = - // foo @@ -63,13 +63,13 @@ export type a = - // baz - | (baz1 & baz2); + // foo -+ | foo1 & foo2 ++ | (foo1 & foo2) + // bar -+ | bar1 & bar2 ++ | (bar1 & bar2) + // prettier-ignore -+ | qux1 & qux2 ++ | (qux1 & qux2) + // baz -+ | baz1 & baz2; ++ | (baz1 & baz2); export type a = // prettier-ignore @@ -87,21 +87,21 @@ export type a = ```js export type a = // foo - | foo1 & foo2 + | (foo1 & foo2) // bar - | bar1 & bar2 + | (bar1 & bar2) // prettier-ignore - | qux1 & qux2; + | (qux1 & qux2); export type a = // foo - | foo1 & foo2 + | (foo1 & foo2) // bar - | bar1 & bar2 + | (bar1 & bar2) // prettier-ignore - | qux1 & qux2 + | (qux1 & qux2) // baz - | baz1 & baz2; + | (baz1 & baz2); export type a = // prettier-ignore diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/union-parens.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/union-parens.ts.snap index 4f33e76cfcb0..4ab582937c8b 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/union-parens.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/union-parens.ts.snap @@ -124,44 +124,8 @@ type Ctor = (new () => X) | Y; ```diff --- Prettier +++ Rome -@@ -1,10 +1,12 @@ --export type A = -- | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; -+export type A = ( -+ | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -+ | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -+); - --export type B = -- | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; -+export type B = ( -+ | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -+ | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -+); - - export type C = - | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -@@ -16,43 +18,44 @@ - - export type Multi = (string | number)[]; - --function f(): string | number {} -+function f(): (string | number) {} - --var x: string | number; --var y: string | number; -+var x: (string | number); -+var y: ((string | number)); - --class Foo {} -+class Foo {} - - interface Interface { - i: (X | Y) & Z; -- j: Partial; -+ j: Partial<(X | Y)>; +@@ -28,13 +28,15 @@ + j: Partial; } -type State = { @@ -176,124 +140,42 @@ type Ctor = (new () => X) | Y; + sharedProperty: any; + } + & ( -+ | { discriminant: "FOO"; foo: any } -+ | { discriminant: "BAR"; bar: any } -+ | { discriminant: "BAZ"; baz: any } ++ | { discriminant: "FOO"; foo: any } ++ | { discriminant: "BAR"; bar: any } ++ | { discriminant: "BAZ"; baz: any } + ); const foo1 = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as ( -- | string -- | undefined -+ string | undefined - )[]; - - const foo2: ( -- | AAAAAAAAAAAAAAAAAAAAAA -- | BBBBBBBBBBBBBBBBBBBBBB -- | CCCCCCCCCCCCCCCCCCCCCC -- | DDDDDDDDDDDDDDDDDDDDDD -+ | AAAAAAAAAAAAAAAAAAAAAA -+ | BBBBBBBBBBBBBBBBBBBBBB -+ | CCCCCCCCCCCCCCCCCCCCCC -+ | DDDDDDDDDDDDDDDDDDDDDD - )[] = []; - - const foo3: keyof ( -- | AAAAAAAAAAAAAAAAAAAAAA -- | BBBBBBBBBBBBBBBBBBBBBB -- | CCCCCCCCCCCCCCCCCCCCCC -- | DDDDDDDDDDDDDDDDDDDDDD + | string +@@ -58,11 +60,11 @@ + const foo4: + | foo + | ( +- | AAAAAAAAAAAAAAAAAAAAAA +- | BBBBBBBBBBBBBBBBBBBBBB +- | CCCCCCCCCCCCCCCCCCCCCC +- | DDDDDDDDDDDDDDDDDDDDDD +- ) = bar; + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD - ) = bar; - - const foo4: -@@ -62,19 +65,19 @@ - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD -- ) = bar; + ) = bar; let a1: C; let a2: C; --let a3: C; --let a4: C; --let a5: C; -+let a3: (C); -+let a4: (C); -+let a5: ((C)); - let a6: /*1*/ C; --let a7: /*1*/ C; --let a8: /*1*/ C; --let a9: /*1*/ C; -+let a7: /*1*/ (C); -+let a8: /*1*/ (C); -+let a9: (/*1*/ C); - let a10: /*1*/ /*2*/ C; --let a11: /*1*/ /*2*/ C; -+let a11: /*1*/ (/*2*/ C); - - let aa1: /*1*/ /*2*/ C | D; - let aa2: /*1*/ /*2*/ C | /*3*/ D; -@@ -82,27 +85,27 @@ - - type A1 = C; - type A2 = C; --type A3 = C; --type A4 = C; --type A5 = C; -+type A3 = (C); -+type A4 = (C); -+type A5 = ((C)); - type A6 = /*1*/ C; --type A7 = /*1*/ C; --type A8 = /*1*/ C; --type A9 = /*1*/ C; -+type A7 = /*1*/ (C); -+type A8 = /*1*/ (C); -+type A9 = (/*1*/ C); - type A10 = /*1*/ /*2*/ C; --type A11 = /*1*/ /*2*/ C; --type A12 = /*1*/ C; --type A13 = /*1*/ C; -+type A11 = /*1*/ (/*2*/ C); -+type A12 = /*1*/ ((C)); -+type A13 = /*1*/ ((C)); - - type Aa1 = /*1*/ /*2*/ C | D; - type Aa2 = /*1*/ /*2*/ C | /*3*/ D; - type Aa3 = /*1*/ /*2*/ C | /*3*/ D /*4*/; - - type C1 = /*1*/ a | b; --type C2 = /*1*/ a | b; --type C3 = /*1*/ a | b; --type C4 = /*1*/ a | b; --type C5 = /*1*/ a | b; --type C6 /*0*/ = /*1*/ a | b; -+type C2 = /*1*/ a | (b); -+type C3 = /*1*/ a | (b); -+type C4 = /*1*/ (a | b); -+type C5 = /*1*/ (a | b); -+type C6 /*0*/ = /*1*/ (a | b); - - type Ctor = (new () => X) | Y; ``` # Output ```js -export type A = ( - | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -); +export type A = + | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; -export type B = ( - | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -); +export type B = + | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; export type C = | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -305,16 +187,16 @@ export type D = export type Multi = (string | number)[]; -function f(): (string | number) {} +function f(): string | number {} -var x: (string | number); -var y: ((string | number)); +var x: string | number; +var y: string | number; -class Foo {} +class Foo {} interface Interface { i: (X | Y) & Z; - j: Partial<(X | Y)>; + j: Partial; } type State = @@ -322,49 +204,50 @@ type State = sharedProperty: any; } & ( - | { discriminant: "FOO"; foo: any } - | { discriminant: "BAR"; bar: any } - | { discriminant: "BAZ"; baz: any } + | { discriminant: "FOO"; foo: any } + | { discriminant: "BAR"; bar: any } + | { discriminant: "BAZ"; baz: any } ); const foo1 = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as ( - string | undefined + | string + | undefined )[]; const foo2: ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD )[] = []; const foo3: keyof ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD ) = bar; const foo4: | foo | ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD ) = bar; let a1: C; let a2: C; -let a3: (C); -let a4: (C); -let a5: ((C)); +let a3: C; +let a4: C; +let a5: C; let a6: /*1*/ C; -let a7: /*1*/ (C); -let a8: /*1*/ (C); -let a9: (/*1*/ C); +let a7: /*1*/ C; +let a8: /*1*/ C; +let a9: /*1*/ C; let a10: /*1*/ /*2*/ C; -let a11: /*1*/ (/*2*/ C); +let a11: /*1*/ /*2*/ C; let aa1: /*1*/ /*2*/ C | D; let aa2: /*1*/ /*2*/ C | /*3*/ D; @@ -372,28 +255,28 @@ let aa3: /*1*/ /*2*/ C | /*3*/ D /*4*/; type A1 = C; type A2 = C; -type A3 = (C); -type A4 = (C); -type A5 = ((C)); +type A3 = C; +type A4 = C; +type A5 = C; type A6 = /*1*/ C; -type A7 = /*1*/ (C); -type A8 = /*1*/ (C); -type A9 = (/*1*/ C); +type A7 = /*1*/ C; +type A8 = /*1*/ C; +type A9 = /*1*/ C; type A10 = /*1*/ /*2*/ C; -type A11 = /*1*/ (/*2*/ C); -type A12 = /*1*/ ((C)); -type A13 = /*1*/ ((C)); +type A11 = /*1*/ /*2*/ C; +type A12 = /*1*/ C; +type A13 = /*1*/ C; type Aa1 = /*1*/ /*2*/ C | D; type Aa2 = /*1*/ /*2*/ C | /*3*/ D; type Aa3 = /*1*/ /*2*/ C | /*3*/ D /*4*/; type C1 = /*1*/ a | b; -type C2 = /*1*/ a | (b); -type C3 = /*1*/ a | (b); -type C4 = /*1*/ (a | b); -type C5 = /*1*/ (a | b); -type C6 /*0*/ = /*1*/ (a | b); +type C2 = /*1*/ a | b; +type C3 = /*1*/ a | b; +type C4 = /*1*/ a | b; +type C5 = /*1*/ a | b; +type C6 /*0*/ = /*1*/ a | b; type Ctor = (new () => X) | Y; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/within-tuple.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/within-tuple.ts.snap index f27eb06b09a5..373399d0cb82 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/within-tuple.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/within-tuple.ts.snap @@ -77,7 +77,7 @@ type F = [ ```diff --- Prettier +++ Rome -@@ -1,92 +1,88 @@ +@@ -1,92 +1,78 @@ type A = [ - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB @@ -105,20 +105,18 @@ type F = [ - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD, --]; -- --type C = [ ++ | AAAAAAAAAAAAAAAAAAAAAA ++ | BBBBBBBBBBBBBBBBBBBBBB ++ | CCCCCCCCCCCCCCCCCCCCCC ++ | DDDDDDDDDDDDDDDDDDDDDD, + ]; + + type C = [ - | [ -+ ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC +- | AAAAAAAAAAAAAAAAAAAAAA +- | BBBBBBBBBBBBBBBBBBBBBB +- | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD, -+ | DDDDDDDDDDDDDDDDDDDDDD -+ ), -+]; -+ -+type C = [ + | [ + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB @@ -139,49 +137,37 @@ type F = [ ]; type D = [ - ( -- | AAAAAAAAAAAAAAAAAAAAAA -- | BBBBBBBBBBBBBBBBBBBBBB -- | CCCCCCCCCCCCCCCCCCCCCC +- ( + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD -+ | AAAAAAAAAAAAAAAAAAAAAA -+ | BBBBBBBBBBBBBBBBBBBBBB -+ | CCCCCCCCCCCCCCCCCCCCCC -+ | DDDDDDDDDDDDDDDDDDDDDD - ), - ( -- | AAAAAAAAAAAAAAAAAAAAAA -- | BBBBBBBBBBBBBBBBBBBBBB -- | CCCCCCCCCCCCCCCCCCCCCC +- ), +- ( ++ | DDDDDDDDDDDDDDDDDDDDDD, + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD -+ | AAAAAAAAAAAAAAAAAAAAAA -+ | BBBBBBBBBBBBBBBBBBBBBB -+ | CCCCCCCCCCCCCCCCCCCCCC -+ | DDDDDDDDDDDDDDDDDDDDDD - ), +- ), ++ | DDDDDDDDDDDDDDDDDDDDDD, ]; type D1 = [ - ( -- | AAAAAAAAAAAAAAAAAAAAAA -- | BBBBBBBBBBBBBBBBBBBBBB -- | CCCCCCCCCCCCCCCCCCCCCC +- ( + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD -+ | AAAAAAAAAAAAAAAAAAAAAA -+ | BBBBBBBBBBBBBBBBBBBBBB -+ | CCCCCCCCCCCCCCCCCCCCCC -+ | DDDDDDDDDDDDDDDDDDDDDD - ), - ( -- | AAAAAAAAAAAAAAAAAAAAAA -- | BBBBBBBBBBBBBBBBBBBBBB -- | CCCCCCCCCCCCCCCCCCCCCC +- ), +- ( ++ | DDDDDDDDDDDDDDDDDDDDDD, + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD -+ | AAAAAAAAAAAAAAAAAAAAAA -+ | BBBBBBBBBBBBBBBBBBBBBB -+ | CCCCCCCCCCCCCCCCCCCCCC -+ | DDDDDDDDDDDDDDDDDDDDDD - ), +- ), ++ | DDDDDDDDDDDDDDDDDDDDDD, ]; type D2 = [ @@ -233,12 +219,10 @@ type B = [ ]; type B1 = [ - ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD - ), + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD, ]; type C = [ @@ -257,33 +241,25 @@ type C = [ ]; type D = [ - ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD - ), - ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD - ), + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD, + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD, ]; type D1 = [ - ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD - ), - ( - | AAAAAAAAAAAAAAAAAAAAAA - | BBBBBBBBBBBBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDD - ), + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD, + | AAAAAAAAAAAAAAAAAAAAAA + | BBBBBBBBBBBBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDD, ]; type D2 = [ diff --git a/crates/rome_js_formatter/tests/specs/ts/expression/type_expression.ts.snap b/crates/rome_js_formatter/tests/specs/ts/expression/type_expression.ts.snap index cdeedea776ac..6e235fb82ed2 100644 --- a/crates/rome_js_formatter/tests/specs/ts/expression/type_expression.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/expression/type_expression.ts.snap @@ -181,7 +181,7 @@ type TupleD = [ ...name: string[], ]; -type PA = (string); +type PA = string; type FunctionType = < Aaaaaaaaaaaaaaaaaaaaa,