From 7e9d9961331b2952dbe1d74fcd813d7a41ef7a6c Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Tue, 27 Sep 2022 12:37:47 +0200 Subject: [PATCH] feat(rome_js_formatter): Member chain formatting --- .../expressions/arrow_function_expression.rs | 2 +- .../src/js/expressions/call_arguments.rs | 190 +++-- .../src/js/expressions/call_expression.rs | 49 +- .../expressions/computed_member_expression.rs | 32 +- .../expressions/static_member_expression.rs | 32 +- .../expressions/type_assertion_expression.rs | 53 +- .../src/utils/assignment_like.rs | 8 +- .../src/utils/member_chain/chain_member.rs | 221 +++--- .../src/utils/member_chain/groups.rs | 302 ++++--- .../src/utils/member_chain/mod.rs | 748 ++++++++++++------ .../src/utils/member_chain/simple_argument.rs | 97 ++- crates/rome_js_formatter/src/utils/mod.rs | 3 +- .../declarations/variable_declaration.js.snap | 114 ++- .../expression/member-chain/computed.js.snap | 3 +- .../static_member_expression.js.snap | 28 +- .../js/assignment/call-with-template.js.snap | 56 -- .../prettier/js/assignment/lone-arg.js.snap | 77 -- .../closure-compiler-type-cast.js.snap | 190 ----- .../comment-in-the-middle.js.snap | 57 -- .../functional_compose.js.snap | 20 +- .../functional-composition/rxjs_pipe.js.snap | 61 -- .../specs/prettier/js/member/expand.js.snap | 117 --- .../prettier/js/method-chain/13018.js.snap | 69 -- .../js/method-chain/bracket_0-1.js.snap | 34 - .../prettier/js/method-chain/comment.js.snap | 160 ---- .../js/method-chain/computed-merge.js.snap | 65 -- .../prettier/js/method-chain/computed.js.snap | 43 - .../js/method-chain/conditional.js.snap | 95 --- .../specs/prettier/js/method-chain/d3.js.snap | 87 -- .../js/method-chain/first_long.js.snap | 53 +- .../method-chain/fluent-configuration.js.snap | 63 -- .../js/method-chain/issue-3594.js.snap | 53 -- .../js/method-chain/issue-4125.js.snap | 124 +-- .../prettier/js/method-chain/logical.js.snap | 36 +- .../js/method-chain/multiple-members.js.snap | 133 ---- .../prettier/js/method-chain/square_0.js.snap | 52 -- .../prettier/js/method-chain/test.js.snap | 15 +- .../prettier/js/method-chain/this.js.snap | 37 - .../js/multiparser-css/issue-11797.js.snap | 16 +- .../js/optional-chaining/comments.js.snap | 148 ---- .../js/preserve-line/member-chain.js.snap | 191 ----- .../specs/prettier/js/require/require.js.snap | 75 -- .../styled-jsx-with-expressions.js.snap | 14 +- .../specs/prettier/js/template/call.js.snap | 73 -- .../specs/prettier/js/template/inline.js.snap | 99 --- .../js/ternaries/indent-after-paren.js.snap | 675 ---------------- .../typescript/cast/generic-cast.ts.snap | 321 -------- .../custom/typeParameters/variables.ts.snap | 87 -- .../typescript/ternaries/indent.ts.snap | 160 ---- .../typeparams/class-method.ts.snap | 55 +- editors/vscode/src/commands/syntaxTree.ts | 18 +- npm/backend-jsonrpc/src/command.ts | 2 +- npm/backend-jsonrpc/src/index.ts | 10 +- npm/backend-jsonrpc/src/socket.ts | 6 +- npm/backend-jsonrpc/src/transport.ts | 20 +- npm/backend-jsonrpc/tests/transport.test.mjs | 74 +- npm/backend-jsonrpc/tests/workspace.test.mjs | 10 +- website/.eleventy.js | 17 +- 58 files changed, 1343 insertions(+), 4307 deletions(-) delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/assignment/call-with-template.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/assignment/lone-arg.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/closure-compiler-type-cast.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/comment-in-the-middle.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/rxjs_pipe.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/member/expand.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/13018.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/bracket_0-1.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/comment.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed-merge.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/conditional.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/d3.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/fluent-configuration.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-3594.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/multiple-members.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/square_0.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/method-chain/this.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/optional-chaining/comments.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/preserve-line/member-chain.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/require/require.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/template/call.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/template/inline.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/js/ternaries/indent-after-paren.js.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/typescript/cast/generic-cast.ts.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/typescript/ternaries/indent.ts.snap diff --git a/crates/rome_js_formatter/src/js/expressions/arrow_function_expression.rs b/crates/rome_js_formatter/src/js/expressions/arrow_function_expression.rs index 09dfd0afc87..27d633b36e4 100644 --- a/crates/rome_js_formatter/src/js/expressions/arrow_function_expression.rs +++ b/crates/rome_js_formatter/src/js/expressions/arrow_function_expression.rs @@ -544,7 +544,7 @@ fn template_literal_contains_new_line(template: &JsTemplate) -> bool { /// ``` /// /// Returns `false` because the template isn't on the same line as the '+' token. -fn is_multiline_template_starting_on_same_line(template: &JsTemplate) -> bool { +pub(crate) fn is_multiline_template_starting_on_same_line(template: &JsTemplate) -> bool { let contains_new_line = template_literal_contains_new_line(template); let starts_on_same_line = template.syntax().first_token().map_or(false, |token| { diff --git a/crates/rome_js_formatter/src/js/expressions/call_arguments.rs b/crates/rome_js_formatter/src/js/expressions/call_arguments.rs index ab166b2be4f..b2bd7f9a8ba 100644 --- a/crates/rome_js_formatter/src/js/expressions/call_arguments.rs +++ b/crates/rome_js_formatter/src/js/expressions/call_arguments.rs @@ -1,10 +1,12 @@ +use crate::js::expressions::arrow_function_expression::is_multiline_template_starting_on_same_line; use crate::prelude::*; use crate::utils::{is_call_like_expression, write_arguments_multi_line}; use rome_formatter::{format_args, write, CstFormatContext}; use rome_js_syntax::{ JsAnyCallArgument, JsAnyExpression, JsAnyFunctionBody, JsAnyLiteralExpression, JsAnyName, JsAnyStatement, JsArrayExpression, JsArrowFunctionExpression, JsCallArgumentList, - JsCallArguments, JsCallArgumentsFields, JsCallExpression, TsReferenceType, + JsCallArguments, JsCallArgumentsFields, JsCallExpression, JsExpressionStatement, + TsReferenceType, }; use rome_rowan::{AstSeparatedList, SyntaxResult, SyntaxTokenText}; @@ -33,6 +35,28 @@ impl FormatNodeRule for FormatJsCallArguments { ); } + let call_expression = node.parent::(); + + if is_commonjs_or_amd_call(node, call_expression.as_ref())? + || is_multiline_template_only_args(node) + { + return write!( + f, + [ + l_paren_token.format(), + format_with(|f| { + f.join_with(space()) + .entries( + args.format_separated(",") + .with_trailing_separator(TrailingSeparator::Omit), + ) + .finish() + }), + r_paren_token.format() + ] + ); + } + let mut iter = args.iter(); let first_argument = iter.next(); let second_argument = iter.next(); @@ -97,19 +121,29 @@ impl FormatNodeRule for FormatJsCallArguments { .map(|e| e.memoized()) .collect(); - let an_argument_breaks = - separated - .iter_mut() - .enumerate() - .any(|(index, element)| match element.inspect(f) { - Ok(element) => { - let in_relevant_range = should_group_first_argument && index > 0 - || (should_group_last_argument && index < args.len() - 1); + let mut any_argument_breaks = false; + let mut first_last_breaks = false; - in_relevant_range && element.will_break() - } - Err(_) => false, - }); + for (index, argument) in separated.iter_mut().enumerate() { + let breaks = argument.inspect(f)?.will_break(); + + any_argument_breaks = any_argument_breaks || breaks; + + if (should_group_first_argument && index > 0) + || (should_group_last_argument && index < args.len() - 1) + { + first_last_breaks = first_last_breaks || breaks; + if breaks { + break; + } + } + } + + let format_flat_arguments = format_with(|f| { + f.join_with(soft_line_break_or_space()) + .entries(separated.iter()) + .finish() + }); // We now cache them the delimiters tokens. This is needed because `[rome_formatter::best_fitting]` will try to // print each version first @@ -125,27 +159,18 @@ impl FormatNodeRule for FormatJsCallArguments { // function, but here we use a different way to print the trailing separator write!( f, - [ - &l_paren, - &group(&format_with(|f| { - write!( - f, - [ - &soft_block_indent(&format_args![ - format_with(|f| { - write_arguments_multi_line(separated.iter(), f) - }), - soft_line_break() - ]), - &r_paren - ] - ) + [group(&format_args![ + l_paren, + soft_block_indent(&format_with(|f| { + write_arguments_multi_line(separated.iter(), f) })), - ] + r_paren + ]) + .should_expand(true)] ) }); - if an_argument_breaks { + if first_last_breaks { return write!(f, [all_arguments_expanded]); } @@ -160,39 +185,26 @@ impl FormatNodeRule for FormatJsCallArguments { let mut iter = separated.iter(); // SAFETY: check on the existence of at least one argument are done before let first = iter.next().unwrap(); - f.join_with(&space()) - .entry(&format_with(|f| { - write!(f, [&format_args![first, expand_parent()]]) - })) - .entries(iter) - .finish()?; + f.join_with(&space()).entry(&first).entries(iter).finish()?; } else { // special formatting of the last element let mut iter = separated.iter(); // SAFETY: check on the existence of at least one argument are done before let last = iter.next_back().unwrap(); - - f.join_with(&space()) - .entries(iter) - .entry(&format_with(|f| { - write!(f, [&format_args![last, expand_parent()]]) - })) - .finish()?; + f.join_with(&space()).entries(iter).entry(&last).finish()?; } write!(f, [r_paren]) }); + if any_argument_breaks { + write!(f, [expand_parent()])?; + } + write!( f, [best_fitting![ - format_args![ - l_paren, - group(&format_with(|f| { - write_arguments_multi_line(separated.iter(), f) - })), - r_paren, - ], - edge_arguments_do_not_break, + format_args![l_paren, format_flat_arguments, r_paren], + group(&edge_arguments_do_not_break).should_expand(true), all_arguments_expanded ]] ) @@ -209,7 +221,7 @@ impl FormatNodeRule for FormatJsCallArguments { write_arguments_multi_line(separated, f) })), r_paren, - ]),] + ])] ) } } @@ -412,6 +424,80 @@ fn could_group_expression_argument( Ok(result) } +fn is_commonjs_or_amd_call( + arguments: &JsCallArguments, + call: Option<&JsCallExpression>, +) -> SyntaxResult { + let call = match call { + Some(call) => call, + None => return Ok(false), + }; + + let callee = call.callee()?; + + Ok(match callee { + JsAnyExpression::JsIdentifierExpression(identifier) => { + let reference = identifier.name()?; + + if reference.has_name("require") { + true + } else if reference.has_name("define") { + let in_statement = call.parent::().is_some(); + + if in_statement { + let args = arguments.args(); + match args.len() { + 1 => true, + 2 => matches!( + args.first(), + Some(Ok(JsAnyCallArgument::JsAnyExpression( + JsAnyExpression::JsArrayExpression(_) + ))) + ), + 3 => { + let mut iter = args.iter(); + let first = iter.next(); + let second = iter.next(); + matches!( + (first, second), + ( + Some(Ok(JsAnyCallArgument::JsAnyExpression( + JsAnyExpression::JsAnyLiteralExpression( + JsAnyLiteralExpression::JsStringLiteralExpression(_) + ) + ))), + Some(Ok(JsAnyCallArgument::JsAnyExpression( + JsAnyExpression::JsArrayExpression(_) + ))) + ) + ) + } + _ => false, + } + } else { + false + } + } else { + false + } + } + _ => false, + }) +} + +fn is_multiline_template_only_args(arguments: &JsCallArguments) -> bool { + let args = arguments.args(); + + match args.first() { + Some(Ok(JsAnyCallArgument::JsAnyExpression(JsAnyExpression::JsTemplate(template)))) + if args.len() == 1 => + { + is_multiline_template_starting_on_same_line(&template) + } + _ => false, + } +} + /// This function is used to check if the code is a hook-like code: /// /// ```js diff --git a/crates/rome_js_formatter/src/js/expressions/call_expression.rs b/crates/rome_js_formatter/src/js/expressions/call_expression.rs index 3d1d3560d68..ebf7c54b1a8 100644 --- a/crates/rome_js_formatter/src/js/expressions/call_expression.rs +++ b/crates/rome_js_formatter/src/js/expressions/call_expression.rs @@ -1,17 +1,58 @@ use crate::prelude::*; +use rome_formatter::write; use crate::parentheses::NeedsParentheses; -use crate::utils::get_member_chain; -use rome_js_syntax::{JsCallExpression, JsSyntaxKind, JsSyntaxNode}; +use crate::utils::member_chain::MemberChain; +use rome_js_syntax::{ + JsAnyExpression, JsCallExpression, JsCallExpressionFields, JsSyntaxKind, JsSyntaxNode, +}; #[derive(Debug, Clone, Default)] pub struct FormatJsCallExpression; impl FormatNodeRule for FormatJsCallExpression { fn fmt_fields(&self, node: &JsCallExpression, f: &mut JsFormatter) -> FormatResult<()> { - let member_chain = get_member_chain(node, f)?; + let JsCallExpressionFields { + callee, + optional_chain_token, + type_arguments, + arguments, + } = node.as_fields(); - member_chain.fmt(f) + let callee = callee?; + + if matches!( + callee, + JsAnyExpression::JsStaticMemberExpression(_) + | JsAnyExpression::JsComputedMemberExpression(_) + ) && !callee.needs_parentheses() + { + let member_chain = MemberChain::from_call_expression( + node.clone(), + f.comments(), + f.options().tab_width(), + )?; + + member_chain.fmt(f) + } else { + let format_inner = format_with(|f| { + write!( + f, + [ + callee.format(), + optional_chain_token.format(), + type_arguments.format(), + arguments.format() + ] + ) + }); + + if matches!(callee, JsAnyExpression::JsCallExpression(_)) { + write!(f, [group(&format_inner)]) + } else { + write!(f, [format_inner]) + } + } } fn needs_parentheses(&self, item: &JsCallExpression) -> bool { diff --git a/crates/rome_js_formatter/src/js/expressions/computed_member_expression.rs b/crates/rome_js_formatter/src/js/expressions/computed_member_expression.rs index 649f6ee37ba..fa8dbe8804c 100644 --- a/crates/rome_js_formatter/src/js/expressions/computed_member_expression.rs +++ b/crates/rome_js_formatter/src/js/expressions/computed_member_expression.rs @@ -34,17 +34,32 @@ impl Format for JsAnyComputedMemberLike { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { write!(f, [self.object().format()])?; - match self.member()? { + FormatComputedMemberLookup(self).fmt(f) + } +} + +/// Formats the lookup portion (everything except the object) of a computed member like. +pub(crate) struct FormatComputedMemberLookup<'a>(&'a JsAnyComputedMemberLike); + +impl<'a> FormatComputedMemberLookup<'a> { + pub(crate) fn new(member_like: &'a JsAnyComputedMemberLike) -> Self { + Self(member_like) + } +} + +impl Format for FormatComputedMemberLookup<'_> { + fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + match self.0.member()? { JsAnyExpression::JsAnyLiteralExpression( JsAnyLiteralExpression::JsNumberLiteralExpression(literal), ) => { write!( f, [ - self.optional_chain_token().format(), - self.l_brack_token().format(), + self.0.optional_chain_token().format(), + self.0.l_brack_token().format(), literal.format(), - self.r_brack_token().format() + self.0.r_brack_token().format() ] ) } @@ -52,12 +67,11 @@ impl Format for JsAnyComputedMemberLike { write![ f, [group(&format_args![ - self.optional_chain_token().format(), - self.l_brack_token().format(), - soft_line_break(), + self.0.optional_chain_token().format(), + self.0.l_brack_token().format(), soft_block_indent(&member.format()), - self.r_brack_token().format() - ]),] + self.0.r_brack_token().format() + ])] ] } } diff --git a/crates/rome_js_formatter/src/js/expressions/static_member_expression.rs b/crates/rome_js_formatter/src/js/expressions/static_member_expression.rs index 8110a73eec7..c02f95ced9a 100644 --- a/crates/rome_js_formatter/src/js/expressions/static_member_expression.rs +++ b/crates/rome_js_formatter/src/js/expressions/static_member_expression.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use crate::js::expressions::computed_member_expression::JsAnyComputedMemberLike; use crate::parentheses::NeedsParentheses; +use crate::utils::member_chain::MemberChainLabel; use rome_formatter::{format_args, write}; use rome_js_syntax::{ JsAnyAssignment, JsAnyAssignmentPattern, JsAnyExpression, JsAnyName, JsAssignmentExpression, @@ -38,13 +39,34 @@ declare_node_union! { impl Format for JsAnyStaticMemberLike { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - write!(f, [self.object().format()])?; + let is_member_chain = { + let mut recording = f.start_recording(); + write!(recording, [self.object().format()])?; - let layout = self.layout()?; + recording + .stop() + .has_label(LabelId::of::()) + }; + + let layout = self.layout(is_member_chain)?; match layout { StaticMemberLikeLayout::NoBreak => { - write!(f, [self.operator_token().format(), self.member().format()]) + let format_no_break = format_with(|f| { + write!(f, [self.operator_token().format(), self.member().format()]) + }); + + if is_member_chain { + write!( + f, + [labelled( + LabelId::of::(), + &format_no_break + )] + ) + } else { + write!(f, [format_no_break]) + } } StaticMemberLikeLayout::BreakAfterObject => { write!( @@ -84,7 +106,7 @@ impl JsAnyStaticMemberLike { } } - fn layout(&self) -> SyntaxResult { + fn layout(&self, is_member_chain: bool) -> SyntaxResult { let parent = self.syntax().parent(); let object = self.object()?; @@ -108,7 +130,7 @@ impl JsAnyStaticMemberLike { _ => false, }; - if no_break { + if no_break || is_member_chain { return Ok(StaticMemberLikeLayout::NoBreak); } } diff --git a/crates/rome_js_formatter/src/ts/expressions/type_assertion_expression.rs b/crates/rome_js_formatter/src/ts/expressions/type_assertion_expression.rs index 254da605f18..e0f9e2bdbee 100644 --- a/crates/rome_js_formatter/src/ts/expressions/type_assertion_expression.rs +++ b/crates/rome_js_formatter/src/ts/expressions/type_assertion_expression.rs @@ -1,8 +1,8 @@ use crate::prelude::*; use crate::parentheses::{is_callee, is_member_object, is_spread, is_tag, NeedsParentheses}; -use rome_formatter::write; -use rome_js_syntax::JsSyntaxNode; +use rome_formatter::{format_args, write}; +use rome_js_syntax::{JsAnyExpression, JsSyntaxNode}; use rome_js_syntax::{JsSyntaxKind, TsTypeAssertionExpression, TsTypeAssertionExpressionFields}; #[derive(Debug, Clone, Default)] @@ -21,15 +21,46 @@ impl FormatNodeRule for FormatTsTypeAssertionExpressi expression, } = node.as_fields(); - write![ - f, - [ - l_angle_token.format(), - group(&soft_block_indent(&ty.format())), - r_angle_token.format(), - expression.format() - ] - ] + let expression = expression?; + + let break_after_cast = !matches!( + expression, + JsAnyExpression::JsArrayExpression(_) | JsAnyExpression::JsObjectExpression(_) + ); + + let format_cast = format_with(|f| { + write!( + f, + [ + l_angle_token.format(), + group(&soft_block_indent(&ty.format())), + r_angle_token.format(), + ] + ) + }); + + if break_after_cast { + let format_cast = format_cast.memoized(); + let format_expression = expression.format().memoized(); + + write!( + f, + [best_fitting![ + format_args![format_cast, format_expression], + format_args![ + format_cast, + group(&format_args![ + text("("), + block_indent(&format_expression), + text(")") + ]) + ], + format_args![format_cast, format_expression] + ]] + ) + } else { + write![f, [format_cast, expression.format()]] + } } fn needs_parentheses(&self, item: &TsTypeAssertionExpression) -> bool { diff --git a/crates/rome_js_formatter/src/utils/assignment_like.rs b/crates/rome_js_formatter/src/utils/assignment_like.rs index 50e50699c99..d580182598d 100644 --- a/crates/rome_js_formatter/src/utils/assignment_like.rs +++ b/crates/rome_js_formatter/src/utils/assignment_like.rs @@ -992,7 +992,7 @@ impl Format for JsAnyAssignmentLike { /// [Prettier applies]: https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/assignment.js#L329 fn is_poorly_breakable_member_or_call_chain( expression: &JsAnyExpression, - f: &mut Formatter, + f: &Formatter, ) -> SyntaxResult { let threshold = f.options().line_width().value() / 4; @@ -1041,7 +1041,11 @@ fn is_poorly_breakable_member_or_call_chain( } for call_expression in call_expressions { - if is_member_call_chain(&call_expression, f)? { + if is_member_call_chain( + call_expression.clone(), + f.comments(), + f.options().tab_width(), + )? { return Ok(false); } diff --git a/crates/rome_js_formatter/src/utils/member_chain/chain_member.rs b/crates/rome_js_formatter/src/utils/member_chain/chain_member.rs index 3d74b494279..d678ec187d7 100644 --- a/crates/rome_js_formatter/src/utils/member_chain/chain_member.rs +++ b/crates/rome_js_formatter/src/utils/member_chain/chain_member.rs @@ -1,34 +1,51 @@ -use crate::context::TabWidth; +use crate::js::expressions::computed_member_expression::FormatComputedMemberLookup; use crate::prelude::*; use rome_formatter::write; use rome_js_syntax::{ - JsAnyExpression, JsCallExpression, JsCallExpressionFields, JsComputedMemberExpression, - JsComputedMemberExpressionFields, JsIdentifierExpression, JsImportCallExpression, - JsNewExpression, JsStaticMemberExpression, JsStaticMemberExpressionFields, JsSyntaxNode, - JsThisExpression, + JsCallExpression, JsCallExpressionFields, JsComputedMemberExpression, JsImportCallExpression, + JsStaticMemberExpression, JsStaticMemberExpressionFields, JsSyntaxNode, + TsNonNullAssertionExpression, TsNonNullAssertionExpressionFields, }; -use rome_rowan::{AstNode, SyntaxResult}; +use rome_rowan::AstNode; use std::fmt::Debug; +#[derive(Copy, Clone, Debug)] +pub(crate) enum CallExpressionPosition { + /// At the start of a call chain. + /// `of` in + /// `of().test` + Start, + + /// Somewhere in the middle. + /// `a.b().c()` + Middle, + + /// At the end of a call chain (root) + /// `a.b.c()` + End, +} + /// Data structure that holds the node with its formatted version #[derive(Clone, Debug)] pub(crate) enum ChainMember { /// Holds onto a [rome_js_syntax::JsStaticMemberExpression] StaticMember { expression: JsStaticMemberExpression, - root: bool, }, /// Holds onto a [rome_js_syntax::JsCallExpression] CallExpression { expression: JsCallExpression, - root: bool, + position: CallExpressionPosition, }, /// Holds onto a [rome_js_syntax::JsComputedMemberExpression] ComputedMember { expression: JsComputedMemberExpression, - root: bool, + }, + + TsNonNullAssertionExpression { + expression: TsNonNullAssertionExpression, }, /// Any other node that are not [rome_js_syntax::JsCallExpression] or [rome_js_syntax::JsStaticMemberExpression] @@ -37,23 +54,28 @@ pub(crate) enum ChainMember { } impl ChainMember { - /// checks if the current node is a [rome_js_syntax::JsCallExpression], [rome_js_syntax::JsImportExpression] or a [rome_js_syntax::JsNewExpression] - pub fn is_loose_call_expression(&self) -> bool { + /// checks if the current node is a [rome_js_syntax::JsCallExpression], or a [rome_js_syntax::JsImportExpression] + pub fn is_call_like_expression(&self) -> bool { match self { ChainMember::CallExpression { .. } => true, ChainMember::Node(node) => { JsImportCallExpression::can_cast(node.kind()) - | JsNewExpression::can_cast(node.kind()) + | JsCallExpression::can_cast(node.kind()) } _ => false, } } + pub(crate) const fn is_call_expression(&self) -> bool { + matches!(self, ChainMember::CallExpression { .. }) + } + pub(crate) fn syntax(&self) -> &JsSyntaxNode { match self { ChainMember::StaticMember { expression, .. } => expression.syntax(), ChainMember::CallExpression { expression, .. } => expression.syntax(), ChainMember::ComputedMember { expression, .. } => expression.syntax(), + ChainMember::TsNonNullAssertionExpression { expression } => expression.syntax(), ChainMember::Node(node) => node, } } @@ -62,147 +84,120 @@ impl ChainMember { matches!(self, ChainMember::ComputedMember { .. }) } - pub(crate) fn is_this_expression(&self) -> bool { + pub(super) fn needs_empty_line_before(&self) -> bool { match self { - ChainMember::Node(node) => JsThisExpression::can_cast(node.kind()), - _ => false, - } - } + ChainMember::StaticMember { expression } => { + let operator = expression.operator_token(); - pub(crate) fn is_identifier_expression(&self) -> bool { - match self { - ChainMember::Node(node) => JsIdentifierExpression::can_cast(node.kind()), - _ => false, - } - } - - /// There are cases like Object.keys(), Observable.of(), _.values() where - /// they are the subject of all the chained calls and therefore should - /// be kept on the same line: - /// - /// ```js - /// Object.keys(items) - /// .filter(x => x) - /// .map(x => x) - /// ``` - /// In order to detect those cases, we use an heuristic: if the first - /// node is an identifier with the name starting with a capital - /// letter or just a sequence of _$. The rationale is that they are - /// likely to be factories. - /// - /// Comment from [Prettier] - /// - /// [Prettier]: https://github.com/prettier/prettier/blob/main/src/language-js/print/member-chain.js#L252-L266 - pub(crate) fn is_factory(&self, check_left_hand_side: bool) -> SyntaxResult { - fn check_str(text: &str) -> bool { - text.chars().next().map_or(false, |c| c.is_uppercase()) - || text.starts_with('_') - || text.starts_with('$') - } - - if let ChainMember::StaticMember { expression, .. } = self { - if check_left_hand_side { - if let JsAnyExpression::JsIdentifierExpression(identifier_expression) = - expression.object()? - { - let value_token = identifier_expression.name()?.value_token()?; - let text = value_token.text_trimmed(); - Ok(check_str(text)) - } else { - Ok(false) + match operator { + Ok(operator) => get_lines_before_token(&operator) > 1, + _ => false, } - } else { - Ok(check_str(expression.member()?.text().as_str())) } - } else if let ChainMember::Node(node, ..) = self { - if let Some(identifier_expression) = JsIdentifierExpression::cast(node.clone()) { - let value_token = identifier_expression.name()?.value_token()?; - let text = value_token.text_trimmed(); - Ok(check_str(text)) - } else { - Ok(false) - } - } else { - Ok(false) - } - } + ChainMember::ComputedMember { expression } => { + let l_brack_token = expression.l_brack_token(); - pub(crate) fn has_short_name(&self, tab_width: TabWidth) -> SyntaxResult { - if let ChainMember::StaticMember { expression, .. } = self { - if let JsAnyExpression::JsIdentifierExpression(identifier_expression) = - expression.object()? - { - let value_token = identifier_expression.name()?.value_token()?; - let text = value_token.text_trimmed(); - Ok(text.len() <= u8::from(tab_width) as usize) - } else { - Ok(false) + match l_brack_token { + Ok(l_brack_token) => { + get_lines_before_token( + &expression.optional_chain_token().unwrap_or(l_brack_token), + ) > 1 + } + _ => false, + } } - } else { - Ok(false) + _ => false, } } } impl Format for ChainMember { fn fmt(&self, f: &mut JsFormatter) -> FormatResult<()> { + if self.needs_empty_line_before() { + write!(f, [empty_line()])?; + } + match self { - ChainMember::StaticMember { expression, root } => { + ChainMember::StaticMember { expression } => { let JsStaticMemberExpressionFields { // Formatted as part of the previous item object: _, operator_token, member, } = expression.as_fields(); - write![ + + write!( f, [ - (!root).then_some(format_leading_comments(expression.syntax())), + format_leading_comments(expression.syntax()), operator_token.format(), member.format(), - (!root).then_some(format_trailing_comments(expression.syntax())) + format_trailing_comments(expression.syntax()) ] - ] + ) } - ChainMember::CallExpression { expression, root } => { - let JsCallExpressionFields { - // Formatted as part of the previous item - callee: _, - optional_chain_token, - type_arguments, - arguments, + ChainMember::TsNonNullAssertionExpression { expression } => { + let TsNonNullAssertionExpressionFields { + expression: _, + excl_token, } = expression.as_fields(); write!( f, [ - (!root).then_some(format_leading_comments(expression.syntax())), - optional_chain_token.format(), - type_arguments.format(), - arguments.format(), - (!root).then_some(format_trailing_comments(expression.syntax())) + format_leading_comments(expression.syntax()), + excl_token.format(), + format_trailing_comments(expression.syntax()) ] ) } - ChainMember::ComputedMember { expression, root } => { - let JsComputedMemberExpressionFields { + + ChainMember::CallExpression { + expression, + position, + } => { + let JsCallExpressionFields { // Formatted as part of the previous item - object: _, + callee: _, optional_chain_token, - l_brack_token, - member, - r_brack_token, + type_arguments, + arguments, } = expression.as_fields(); + + match position { + CallExpressionPosition::Start => write!(f, [expression.format()]), + CallExpressionPosition::Middle => { + write!( + f, + [ + format_leading_comments(expression.syntax()), + optional_chain_token.format(), + type_arguments.format(), + arguments.format(), + format_trailing_comments(expression.syntax()) + ] + ) + } + CallExpressionPosition::End => { + write!( + f, + [ + optional_chain_token.format(), + type_arguments.format(), + arguments.format(), + ] + ) + } + } + } + ChainMember::ComputedMember { expression } => { write!( f, [ - (!root).then_some(format_leading_comments(expression.syntax())), - optional_chain_token.format(), - l_brack_token.format(), - member.format(), - r_brack_token.format(), - (!root).then_some(format_trailing_comments(expression.syntax())) + format_leading_comments(expression.syntax()), + FormatComputedMemberLookup::new(&expression.clone().into()), + format_trailing_comments(expression.syntax()) ] ) } diff --git a/crates/rome_js_formatter/src/utils/member_chain/groups.rs b/crates/rome_js_formatter/src/utils/member_chain/groups.rs index 7dcf3479008..3e38ef09987 100644 --- a/crates/rome_js_formatter/src/utils/member_chain/groups.rs +++ b/crates/rome_js_formatter/src/utils/member_chain/groups.rs @@ -1,114 +1,103 @@ -use crate::context::TabWidth; use crate::parentheses::NeedsParentheses; use crate::prelude::*; use crate::utils::member_chain::chain_member::ChainMember; use rome_formatter::write; -use rome_js_syntax::JsCallExpression; -use rome_rowan::SyntaxResult; -use std::mem; +use std::cell::RefCell; +#[derive(Default)] pub(super) struct MemberChainGroupsBuilder { /// keeps track of the groups created groups: Vec, /// keeps track of the current group that is being created/updated - current_group: MemberChainGroup, - - /// If the current group is inside an expression statement. - /// - /// This information is important when evaluating the break of the groups. - in_expression_statement: bool, - - tab_width: TabWidth, + current_group: Option, } impl MemberChainGroupsBuilder { - pub fn new(in_expression_statement: bool, tab_width: TabWidth) -> Self { - Self { - in_expression_statement, - groups: Vec::new(), - current_group: MemberChainGroup::default(), - tab_width, - } - } - /// starts a new group - pub fn start_group(&mut self, flatten_item: ChainMember) { - debug_assert!(self.current_group.members.is_empty()); - self.current_group.members.push(flatten_item); + pub fn start_group(&mut self, member: ChainMember) { + debug_assert!(self.current_group.is_none()); + let mut group = MemberChainGroup::default(); + group.members.push(member); + self.current_group = Some(group); } /// continues of starts a new group - pub fn start_or_continue_group(&mut self, flatten_item: ChainMember) { - if self.current_group.members.is_empty() { - self.start_group(flatten_item); - } else { - self.continue_group(flatten_item); + pub fn start_or_continue_group(&mut self, member: ChainMember) { + match &mut self.current_group { + None => self.start_group(member), + Some(group) => group.members.push(member), } } - /// adds the passed element to the current group - pub fn continue_group(&mut self, flatten_item: ChainMember) { - debug_assert!(!self.current_group.members.is_empty()); - self.current_group.members.push(flatten_item); + /// adds the passed element to the current group. + /// + /// # Panics + /// + /// If there's no started group. + pub fn continue_group(&mut self, member: ChainMember) { + match &mut self.current_group { + None => { + panic!("It is necessary to start a group first using `start_group`."); + } + Some(group) => { + group.members.push(member); + } + } } - /// clears the current group, and adds a new group to the groups + /// clears the current group, and adds it to the groups collection pub fn close_group(&mut self) { - if !self.current_group.members.is_empty() { - let mut elements = MemberChainGroup::default(); - std::mem::swap(&mut elements, &mut self.current_group); - self.groups.push(elements); + if let Some(group) = self.current_group.take() { + self.groups.push(group); } } - pub(super) fn finish(self) -> MemberChainGroups { - debug_assert!(self.current_group.members().is_empty()); + pub(super) fn finish(self) -> TailChainGroups { + let mut groups = self.groups; - MemberChainGroups { - groups: self.groups, - tab_width: self.tab_width, - in_expression_statement: self.in_expression_statement, - cutoff: 1, + if let Some(group) = self.current_group { + groups.push(group); } + + TailChainGroups { groups } } } +/// Groups following on the head group. +/// +/// May be empty if all members are part of the head group #[derive(Clone, Debug)] -/// Handles creation of groups while scanning the flatten items -pub(super) struct MemberChainGroups { - /// keeps track of the groups created +pub(super) struct TailChainGroups { groups: Vec, - - /// If the current group is inside an expression statement. - /// - /// This information is important when evaluating the break of the groups. - in_expression_statement: bool, - - tab_width: TabWidth, - - /// This is a threshold of when we should start breaking the groups - /// - /// By default, it's 1, meaning that we start breaking after the first group. - cutoff: u8, } -impl MemberChainGroups { +impl TailChainGroups { + /// Returns `true` if there are no tail groups. pub(crate) fn is_empty(&self) -> bool { self.groups.is_empty() } - /// This function checks if the current grouping should be merged with the first group. - pub fn should_merge( - &self, - head_group: &MemberChainGroup, - comments: &JsComments, - ) -> SyntaxResult { - Ok(!self.groups.len() >= 1 - && self.should_not_wrap(head_group)? - && !self.groups[0] - .members - .first() - .map_or(false, |item| comments.has_comments(item.syntax()))) + /// Returns the number of tail groups. + pub(crate) fn len(&self) -> usize { + self.groups.len() + } + + /// Returns the first group + pub(crate) fn first(&self) -> Option<&MemberChainGroup> { + self.groups.first() + } + + /// Returns the last group + pub(crate) fn last(&self) -> Option<&MemberChainGroup> { + self.groups.last() + } + + /// Removes the first group and returns it + pub(super) fn pop_first(&mut self) -> Option { + match self.groups.len() { + 0 => None, + _ => Some(self.groups.remove(0)), + } } /// Checks if the groups contain comments. @@ -120,8 +109,8 @@ impl MemberChainGroups { || comments.has_leading_comments(item.syntax()) }); - let cutoff_has_leading_comments = if self.groups.len() >= self.cutoff as usize { - let group = self.groups.get(self.cutoff as usize); + let cutoff_has_leading_comments = if !self.groups.is_empty() { + let group = self.groups.get(1); if let Some(group) = group { let first_item = group.members.first(); first_item.map_or(false, |first_item| { @@ -137,99 +126,50 @@ impl MemberChainGroups { has_comments || cutoff_has_leading_comments } - /// Filters the stack of [FlattenItem] and return only the ones that - /// contain [JsCallExpression]. The function returns the actual nodes. - pub fn get_call_expressions(&self) -> impl Iterator { - self.groups - .iter() - .flat_map(|group| group.members.iter()) - .filter_map(|item| { - if let ChainMember::CallExpression { expression, .. } = item { - Some(expression) - } else { - None - } - }) + /// Here we check if the length of the groups exceeds the cutoff or there are comments + /// This function is the inverse of the prettier function + /// [Prettier applies]: https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/member-chain.js#L342 + pub(crate) fn is_member_call_chain(&self, comments: &JsComments) -> bool { + self.groups.len() > 1 || self.has_comments(comments) } - /// This is an heuristic needed to check when the first element of the group - /// Should be part of the "head" or the "tail". - fn should_not_wrap(&self, first_group: &MemberChainGroup) -> SyntaxResult { - let tab_with = self.tab_width; - let has_computed_property = if self.groups.len() > 1 { - // SAFETY: guarded by the previous check - let group = &self.groups[0]; - group - .members - .first() - .map_or(false, |item| item.is_computed_expression()) - } else { - false - }; - - if first_group.members().len() == 1 { - // SAFETY: access is guarded by the previous check - let first_node = first_group.members().first().unwrap(); - - return Ok(first_node.is_this_expression() - || (first_node.is_identifier_expression() - && (first_node.is_factory(true)? - // If an identifier has a name that is shorter than the tab with, then we join it with the "head" - || (self.in_expression_statement - && first_node.has_short_name(tab_with)?) - || has_computed_property))); - } - - let last_node_is_factory = self - .groups - .iter() - .flat_map(|group| group.members.iter()) - .last() - .map_or(false, |item| item.is_factory(false).unwrap_or(false)); - - Ok(last_node_is_factory || has_computed_property) + /// Returns an iterator over the groups. + pub(super) fn iter(&self) -> impl Iterator + DoubleEndedIterator { + self.groups.iter() } - /// Here we check if the first group can be merged to the head. If so, then - /// we move out the first group out of the groups - pub(crate) fn should_merge_with_first_group( - &mut self, - head_group: &MemberChainGroup, - comments: &JsComments, - ) -> Option> { - if self.should_merge(head_group, comments).unwrap_or(false) { - let mut new_groups = self.groups.split_off(1); - // self.groups is now the head (one element), while `new_groups` is a new vector without the - // first element. - // As we need to achieve the opposite, we now swap them. - mem::swap(&mut self.groups, &mut new_groups); - Some(new_groups) - } else { - None + /// Test if any group except the last group [break](FormatElements::will_break). + pub(super) fn any_except_last_will_break(&self, f: &mut JsFormatter) -> FormatResult { + for group in &self.groups[..self.groups.len().saturating_sub(1)] { + if group.will_break(f)? { + return Ok(true); + } } - } - /// Here we check if the length of the groups exceeds the cutoff or there are comments - /// This function is the inverse of the prettier function - /// [Prettier applies]: https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/member-chain.js#L342 - pub(crate) fn is_member_call_chain(&self, comments: &JsComments) -> bool { - self.groups.len() > self.cutoff as usize || self.has_comments(comments) + Ok(false) } - pub(super) fn iter(&self) -> impl Iterator { - self.groups.iter() + /// Returns an iterator over all members + pub(super) fn members(&self) -> impl Iterator + DoubleEndedIterator { + self.groups.iter().flat_map(|group| group.members().iter()) } } -impl Format for MemberChainGroups { +impl Format for TailChainGroups { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { f.join().entries(self.groups.iter()).finish() } } -#[derive(Debug, Clone, Default)] +#[derive(Clone, Default)] pub(super) struct MemberChainGroup { members: Vec, + + /// Stores the formatted result of this group. + /// + /// Manual implementation of `Memoized` to only memorizing the formatted result + /// if [MemberChainGroup::will_break] is called but not otherwise. + formatted: RefCell>, } impl MemberChainGroup { @@ -237,12 +177,35 @@ impl MemberChainGroup { self.members } - fn members(&self) -> &[ChainMember] { + /// Returns the chain members of the group. + pub(super) fn members(&self) -> &[ChainMember] { &self.members } - pub(super) fn expand_group(&mut self, group: impl IntoIterator) { - self.members.extend(group) + /// Extends the members of this group with the passed in members + pub(super) fn extend_members(&mut self, members: impl IntoIterator) { + self.members.extend(members) + } + + /// Tests if the formatted result of this group results in a [break](FormatElements::will_break). + pub(super) fn will_break(&self, f: &mut JsFormatter) -> FormatResult { + let mut cell = self.formatted.borrow_mut(); + let result = match cell.as_ref() { + Some(formatted) => formatted.will_break(), + None => { + let interned = f.intern(&FormatMemberChainGroup { group: self })?; + + if let Some(interned) = interned { + let breaks = interned.will_break(); + *cell = Some(interned); + breaks + } else { + false + } + } + }; + + Ok(result) } pub(super) fn has_comments(&self, comments: &JsComments) -> bool { @@ -261,13 +224,40 @@ impl MemberChainGroup { impl From> for MemberChainGroup { fn from(entries: Vec) -> Self { - Self { members: entries } + Self { + members: entries, + formatted: RefCell::new(None), + } + } +} + +impl std::fmt::Debug for MemberChainGroup { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("MemberChainGroup") + .field(&self.members) + .finish() } } impl Format for MemberChainGroup { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - let last = self.members.last(); + if let Some(formatted) = self.formatted.borrow().as_ref() { + return f.write_element(formatted.clone()); + } + + FormatMemberChainGroup { group: self }.fmt(f) + } +} + +pub struct FormatMemberChainGroup<'a> { + group: &'a MemberChainGroup, +} + +impl Format for FormatMemberChainGroup<'_> { + fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + let group = self.group; + + let last = group.members.last(); let needs_parens = last.map_or(false, |last| match last { ChainMember::StaticMember { expression, .. } => expression.needs_parentheses(), @@ -275,7 +265,7 @@ impl Format for MemberChainGroup { _ => false, }); - let format_entries = format_with(|f| f.join().entries(self.members.iter()).finish()); + let format_entries = format_with(|f| f.join().entries(group.members.iter()).finish()); if needs_parens { write!(f, [text("("), format_entries, text(")")]) diff --git a/crates/rome_js_formatter/src/utils/member_chain/mod.rs b/crates/rome_js_formatter/src/utils/member_chain/mod.rs index 0d5c0019603..a99b3410ebd 100644 --- a/crates/rome_js_formatter/src/utils/member_chain/mod.rs +++ b/crates/rome_js_formatter/src/utils/member_chain/mod.rs @@ -106,30 +106,153 @@ mod chain_member; mod groups; mod simple_argument; +use crate::context::TabWidth; +use crate::parentheses::is_callee; use crate::prelude::*; -use crate::utils::member_chain::chain_member::ChainMember; +use crate::utils::member_chain::chain_member::{CallExpressionPosition, ChainMember}; use crate::utils::member_chain::groups::{ - MemberChainGroup, MemberChainGroups, MemberChainGroupsBuilder, + MemberChainGroup, MemberChainGroupsBuilder, TailChainGroups, }; use crate::utils::member_chain::simple_argument::SimpleArgument; -use rome_formatter::{format_args, write, Buffer, CstFormatContext}; -use rome_js_syntax::{JsAnyExpression, JsCallExpression, JsExpressionStatement}; +use rome_formatter::{write, Buffer}; +use rome_js_syntax::{ + JsAnyCallArgument, JsAnyExpression, JsAnyLiteralExpression, JsCallExpression, + JsIdentifierExpression, JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, JsThisExpression, +}; use rome_rowan::{AstNode, SyntaxResult}; +use std::iter::FusedIterator; + +pub(crate) enum MemberChainLabel {} #[derive(Debug, Clone)] pub(crate) struct MemberChain { - calls_count: usize, + root: JsCallExpression, head: MemberChainGroup, - tail: MemberChainGroups, + tail: TailChainGroups, } impl MemberChain { - /// It tells if the groups should be break on multiple lines - pub(crate) fn groups_should_break(&self, comments: &JsComments) -> FormatResult { - if self.tail.is_empty() { - return Ok(false); + pub(crate) fn from_call_expression( + call_expression: JsCallExpression, + comments: &JsComments, + tab_width: TabWidth, + ) -> SyntaxResult { + let parent = call_expression.syntax().parent(); + let mut chain_members = + ChainMembersIterator::new(call_expression.clone().into(), comments).collect::>(); + chain_members.reverse(); + + // as explained before, the first group is particular, so we calculate it + let (head_group, remaining_members) = + split_members_into_head_and_remaining_groups(chain_members); + + // `flattened_items` now contains only the nodes that should have a sequence of + // `[ StaticMemberExpression -> AnyNode + JsCallExpression ]` + let tail_groups = compute_remaining_groups(remaining_members, comments); + + let mut member_chain = MemberChain { + head: head_group, + tail: tail_groups, + root: call_expression, + }; + + // Here we check if the first element of Groups::groups can be moved inside the head. + // If so, then we extract it and concatenate it together with the head. + member_chain.maybe_merge_with_first_group(comments, tab_width, parent.as_ref()); + + Ok(member_chain) + } + + /// Here we check if the first group can be merged to the head. If so, then + /// we move out the first group out of the groups + fn maybe_merge_with_first_group( + &mut self, + comments: &JsComments, + tab_width: TabWidth, + parent: Option<&JsSyntaxNode>, + ) { + if self.should_merge_tail_with_head(parent, tab_width, comments) { + let group = self.tail.pop_first().unwrap(); + self.head.extend_members(group.into_members()); + } + } + + /// This function checks if the current grouping should be merged with the first group. + fn should_merge_tail_with_head( + &self, + parent: Option<&JsSyntaxNode>, + tab_width: TabWidth, + comments: &JsComments, + ) -> bool { + let first_group = match self.tail.first() { + None => { + return false; + } + Some(first_group) => first_group, + }; + + let has_comments = first_group + .members() + .first() + .map_or(false, |member| comments.has_comments(member.syntax())); + + if has_comments { + return false; } + let has_computed_property = first_group + .members() + .first() + .map_or(false, |item| item.is_computed_expression()); + + if self.head.members().len() == 1 { + let only_member = &self.head.members()[0]; + + let in_expression_statement = parent.map_or(false, |parent| { + parent.kind() == JsSyntaxKind::JS_EXPRESSION_STATEMENT + }); + + match only_member { + ChainMember::Node(node) => { + if JsThisExpression::can_cast(node.kind()) { + true + } else if let Some(identifier) = JsIdentifierExpression::cast_ref(node) { + let is_factory = identifier + .name() + .and_then(|name| name.value_token()) + .as_ref() + .map_or(false, is_factory); + + has_computed_property || + is_factory || + // If an identifier has a name that is shorter than the tab with, then we join it with the "head" + (in_expression_statement + && has_short_name(&identifier, tab_width)) + } else { + false + } + } + _ => false, + } + } else if let Some(ChainMember::StaticMember { expression }) = self.head.members().last() { + let member = expression.member().ok(); + + let is_factory = member + .as_ref() + .and_then(|member| member.as_js_name()) + .and_then(|name| name.value_token().ok()) + .as_ref() + .map_or(false, is_factory); + + has_computed_property || is_factory + } else { + false + } + } + + /// It tells if the groups should be break on multiple lines + fn groups_should_break(&self, f: &mut JsFormatter) -> FormatResult { + let comments = f.comments(); let node_has_comments = self.head.has_comments(comments) || self.tail.has_comments(comments); @@ -137,230 +260,263 @@ impl MemberChain { return Ok(true); } - // Do not allow the group to break if it only contains a single call expression - if self.calls_count <= 1 { - return Ok(false); + let mut call_expressions = self + .members() + .filter_map(|member| match member { + ChainMember::CallExpression { expression, .. } => Some(expression), + _ => None, + }) + .peekable(); + + let mut calls_count = 0u32; + let mut any_has_function_like_argument = false; + let mut any_complex_args = false; + + while let Some(call) = call_expressions.next() { + calls_count += 1; + + if call_expressions.peek().is_some() { + any_has_function_like_argument = + any_has_function_like_argument || has_arrow_or_function_expression_arg(call) + } + + any_complex_args = any_complex_args || !has_simple_arguments(call); } - // we want to check the simplicity of the call expressions only if we have at least - // two of them - // Check prettier: https://github.com/prettier/prettier/blob/main/src/language-js/print/member-chain.js#L389 - let call_expressions_are_not_simple = - self.calls_count > 2 && self.call_expressions_are_not_simple()?; + if calls_count > 2 && any_complex_args { + return Ok(true); + } - // TODO: add here will_break logic + if self.last_call_breaks(f)? && any_has_function_like_argument { + return Ok(true); + } - Ok(call_expressions_are_not_simple) + if !self.tail.is_empty() && self.head.will_break(f)? { + return Ok(true); + } + + if self.tail.any_except_last_will_break(f)? { + return Ok(true); + } + + Ok(false) } /// We retrieve all the call expressions inside the group and we check if /// their arguments are not simple. - fn call_expressions_are_not_simple(&self) -> SyntaxResult { - Ok(self.tail.get_call_expressions().any(|call_expression| { - call_expression.arguments().map_or(false, |arguments| { - !arguments - .args() - .iter() - .filter_map(|argument| argument.ok()) - .all(|argument| SimpleArgument::new(argument).is_simple(0)) - }) - })) + fn last_call_breaks(&self, f: &mut JsFormatter) -> FormatResult { + let last_group = self.last_group(); + + if let Some(ChainMember::CallExpression { .. }) = last_group.members().last() { + last_group.will_break(f) + } else { + Ok(false) + } + } + + fn last_group(&self) -> &MemberChainGroup { + self.tail.last().unwrap_or(&self.head) + } + + /// Returns an iterator over all members in the member chain + fn members(&self) -> impl Iterator + DoubleEndedIterator { + self.head.members().iter().chain(self.tail.members()) + } + + fn has_comments(&self, comments: &JsComments) -> bool { + let mut members = self.members(); + + if let Some(first) = members.next() { + if comments.has_trailing_comments(first.syntax()) { + return true; + } + } + + // Ignore the root member because comments are printed before/after the member chain. + members.next_back(); + + for member in members { + if comments.has_leading_comments(member.syntax()) + || comments.has_trailing_comments(member.syntax()) + { + return true; + } + } + + false } } impl Format for MemberChain { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - // TODO use Alternatives once available - write!(f, [&self.head])?; - - if self.groups_should_break(f.context().comments())? { - write!( - f, - [indent(&format_args!( - hard_line_break(), - format_with(|f| { - f.join_with(hard_line_break()) - .entries(self.tail.iter()) - .finish() - }) - ))] - ) - } else { - write!(f, [self.tail]) + let has_comments = self.has_comments(f.comments()); + + let format_one_line = format_with(|f| { + let mut joiner = f.join(); + + joiner.entry(&self.head); + joiner.entries(self.tail.iter()); + + joiner.finish() + }); + + if self.tail.len() <= 1 && !has_comments { + return if is_long_curried_call(&self.root) { + write!(f, [format_one_line]) + } else { + write!(f, [group(&format_one_line)]) + }; } - } -} -pub(crate) fn get_member_chain( - call_expression: &JsCallExpression, - f: &mut JsFormatter, -) -> SyntaxResult { - let mut chain_members = vec![]; - let parent_is_expression_statement = - call_expression.syntax().parent().map_or(false, |parent| { - JsExpressionStatement::can_cast(parent.kind()) + let has_empty_line = match self.tail.members().next() { + Some(member) => member.needs_empty_line_before(), + None => false, + }; + + let format_tail = format_with(|f| { + if !has_empty_line { + write!(f, [hard_line_break()])?; + } + + f.join_with(hard_line_break()) + .entries(self.tail.iter()) + .finish() }); - let root = flatten_member_chain( - &mut chain_members, - call_expression.clone().into(), - f.context().comments(), - true, - )?; + let format_expanded = format_with(|f| write!(f, [self.head, indent(&group(&format_tail))])); - chain_members.push(root); + let format_content = format_with(|f| { + if self.groups_should_break(f)? { + write!(f, [group(&format_expanded)]) + } else { + if has_empty_line || self.last_group().will_break(f)? { + write!(f, [expand_parent()])?; + } - // Count the number of CallExpression in the chain, - // will be used later to decide on how to format it - let calls_count = chain_members - .iter() - .filter(|item| item.is_loose_call_expression()) - .count(); - - // as explained before, the first group is particular, so we calculate it - let index_to_split_at = compute_first_group_index(&chain_members); - - // we have the index where we want to take the first group - let remaining_groups = chain_members.split_off(index_to_split_at); - let first_group = chain_members; - - let mut head_group = MemberChainGroup::from(first_group); - - // `flattened_items` now contains only the nodes that should have a sequence of - // `[ StaticMemberExpression -> AnyNode + JsCallExpression ]` - let mut rest_of_groups = compute_groups( - remaining_groups.into_iter(), - parent_is_expression_statement, - f, - ); - - // Here we check if the first element of Groups::groups can be moved inside the head. - // If so, then we extract it and concatenate it together with the head. - if let Some(group_to_merge) = - rest_of_groups.should_merge_with_first_group(&head_group, f.comments()) - { - let group_to_merge = group_to_merge - .into_iter() - .flat_map(|group| group.into_members()); - head_group.expand_group(group_to_merge); - } + write!(f, [best_fitting!(format_one_line, format_expanded)]) + } + }); - Ok(MemberChain { - calls_count, - head: head_group, - tail: rest_of_groups, - }) + write!( + f, + [labelled(LabelId::of::(), &format_content)] + ) + } } -/// Retrieves the index where we want to calculate the first group. -/// The first group gathers inside it all those nodes that are not a sequence of something like: -/// `[ StaticMemberExpression -> AnyNode + JsCallExpression ]` -fn compute_first_group_index(flatten_items: &[ChainMember]) -> usize { - flatten_items +/// Splits the members into two groups: +/// * The head group that contains all notes that are not a sequence of: `[ StaticMemberExpression -> AnyNode + JsCallExpression ]` +/// * The remaining members +fn split_members_into_head_and_remaining_groups( + mut members: Vec, +) -> (MemberChainGroup, Vec) { + // This where we apply the first two points explained in the description of the main public function. + // We want to keep iterating over the items until we have call expressions + // - `something()()()()` + // - `something[1][2][4]` + // - `something[1]()[3]()` + // - `something()[2].something.else[0]` + let non_call_or_array_member_access_start = members .iter() .enumerate() - // the first element will always be part of the first group, so we skip it + // The first member is always part of the first group .skip(1) - // we now find the index, all items before this index will belong to the first group - .find_map(|(index, item)| { - let should_skip = match item { - // This where we apply the first two points explained in the description of the main public function. - // We want to keep iterating over the items until we have call expressions or computed expressions: - // - `something()()()()` - // - `something[1][2][4]` - // - `something[1]()[3]()` - // - `something()[2].something.else[0]` - ChainMember::CallExpression { .. } | ChainMember::ComputedMember { .. } => true, - - // SAFETY: The check `flatten_items[index + 1]` will never panic at runtime because - // 1. The array will always have at least two items - // 2. The last element of the array is always a CallExpression - // - // Something like `a()` produces these flatten times: - // ``` - // [ - // Token("a", 0..1), - // CallExpression: [Empty, Empty, Group(List [Token("(", 5..6), Token(")", 2..7)])], - // ] - // ``` - // - // Hence, it will never enter the branch of this `match`. - // - // When we have something like `a.b.c()`, the flatten items produced are: - // - // ``` - // [ - // Token("a", 0..1), - // StaticMember: [Token(".", 1..2), Token("b", 2..3)], - // StaticMember: [Token(".", 3..4), Token("c", 4..5)], - // CallExpression: [Empty, Empty, Group(List [Token("(", 5..6), Token(")", 6..7)])], - // ] - // ``` - // - // The loop will match against `StaticMember: [Token(".", 3..4), Token("c", 4..5)],` - // and the next one is a call expression... the `matches!` fails and the loop is stopped. - // - // The last element of the array is always a `CallExpression`, which allows us to avoid the overflow of the array. - ChainMember::StaticMember { .. } => { - let next_flatten_item = &flatten_items[index + 1]; - matches!( - next_flatten_item, - ChainMember::StaticMember { .. } | ChainMember::ComputedMember { .. } - ) + .find_map(|(index, member)| match member { + ChainMember::CallExpression { .. } + | ChainMember::TsNonNullAssertionExpression { .. } => None, + + ChainMember::ComputedMember { expression } => { + if matches!( + expression.member(), + Ok(JsAnyExpression::JsAnyLiteralExpression( + JsAnyLiteralExpression::JsNumberLiteralExpression(_), + )) + ) { + None + } else { + Some(index) } - _ => false, - }; - - if should_skip { - None - } else { - Some(index) } + + _ => Some(index), }) - // If the above returns None this means either all items were skipped - // or the list was empty. In either case, this means the first group - // covers the entire list of [FlattenItem] - .unwrap_or(flatten_items.len()) + .unwrap_or(members.len()); + + let first_group_end_index = if !members + .first() + .map_or(false, |member| member.is_call_expression()) + { + // Take as many member access chains as possible + let rest = &members[non_call_or_array_member_access_start..]; + let member_end = rest + .iter() + .enumerate() + .find_map(|(index, member)| match member { + ChainMember::StaticMember { .. } | ChainMember::ComputedMember { .. } => { + let next_is_member = matches!( + rest.get(index + 1), + Some(ChainMember::ComputedMember { .. } | ChainMember::StaticMember { .. }) + ); + + (!next_is_member).then_some(index) + } + _ => Some(index), + }) + .unwrap_or(rest.len()); + + non_call_or_array_member_access_start + member_end + } else { + non_call_or_array_member_access_start + }; + + let remaining = members.split_off(first_group_end_index); + (MemberChainGroup::from(members), remaining) } /// computes groups coming after the first group -fn compute_groups( - flatten_items: impl Iterator, - in_expression_statement: bool, - f: &JsFormatter, -) -> MemberChainGroups { +fn compute_remaining_groups(members: Vec, comments: &JsComments) -> TailChainGroups { let mut has_seen_call_expression = false; - let mut groups_builder = - MemberChainGroupsBuilder::new(in_expression_statement, f.options().tab_width()); - for item in flatten_items { - let has_trailing_comments = f.comments().has_trailing_comments(item.syntax()); + let mut groups_builder = MemberChainGroupsBuilder::default(); - match item { - ChainMember::StaticMember { .. } => { + for member in members { + let has_trailing_comments = comments.has_trailing_comments(member.syntax()); + + match member { + // [0] should be appended at the end of the group instead of the + // beginning of the next one + ChainMember::ComputedMember { .. } if is_computed_array_member_access(&member) => { + groups_builder.start_or_continue_group(member); + } + + ChainMember::StaticMember { .. } | ChainMember::ComputedMember { .. } => { // if we have seen a JsCallExpression, we want to close the group. // The resultant group will be something like: [ . , then, () ]; // `.` and `then` belong to the previous StaticMemberExpression, // and `()` belong to the call expression we just encountered - if has_seen_call_expression { groups_builder.close_group(); - groups_builder.start_or_continue_group(item); + groups_builder.start_group(member); has_seen_call_expression = false; } else { - groups_builder.start_or_continue_group(item); + groups_builder.start_or_continue_group(member); } } + ChainMember::CallExpression { .. } => { - let is_loose_call_expression = item.is_loose_call_expression(); - groups_builder.start_or_continue_group(item); - if is_loose_call_expression { - has_seen_call_expression = true; - } + groups_builder.start_or_continue_group(member); + has_seen_call_expression = true; + } + + ChainMember::TsNonNullAssertionExpression { .. } => { + groups_builder.start_or_continue_group(member); } - ChainMember::ComputedMember { .. } => { - groups_builder.start_or_continue_group(item); + + ChainMember::Node(_) if member.is_call_like_expression() => { + groups_builder.start_or_continue_group(member); + has_seen_call_expression = true; } - ChainMember::Node(_) => groups_builder.continue_group(item), + + ChainMember::Node(_) => groups_builder.continue_group(member), } // Close the group immediately if the node had any trailing comments to @@ -368,77 +524,193 @@ fn compute_groups( // were originally commenting if has_trailing_comments { groups_builder.close_group(); + has_seen_call_expression = false; } } - // closing possible loose groups - groups_builder.close_group(); - groups_builder.finish() } -/// This function tries to flatten the AST. It stores nodes and its formatted version -/// inside an vector of [FlattenItem]. The first element of the vector is the last one. -fn flatten_member_chain( - queue: &mut Vec, - node: JsAnyExpression, +fn is_computed_array_member_access(member: &ChainMember) -> bool { + if let ChainMember::ComputedMember { expression } = member { + matches!( + expression.member(), + Ok(JsAnyExpression::JsAnyLiteralExpression( + JsAnyLiteralExpression::JsNumberLiteralExpression(_) + )) + ) + } else { + false + } +} + +fn has_arrow_or_function_expression_arg(call: &JsCallExpression) -> bool { + call.arguments().map_or(false, |arguments| { + arguments.args().iter().any(|argument| { + matches!( + argument, + Ok(JsAnyCallArgument::JsAnyExpression( + JsAnyExpression::JsArrowFunctionExpression(_) + | JsAnyExpression::JsFunctionExpression(_) + )) + ) + }) + }) +} + +fn has_simple_arguments(call: &JsCallExpression) -> bool { + call.arguments().map_or(false, |arguments| { + arguments.args().iter().all(|argument| { + argument.map_or(false, |argument| SimpleArgument::new(argument).is_simple()) + }) + }) +} + +/// In order to detect those cases, we use an heuristic: if the first +/// node is an identifier with the name starting with a capital +/// letter or just a sequence of _$. The rationale is that they are +/// likely to be factories. +fn is_factory(token: &JsSyntaxToken) -> bool { + let text = token.text_trimmed(); + + let mut chars = text.chars(); + + match text.chars().next() { + // Any sequence of '$' or '_' characters + Some('_') | Some('$') => chars.all(|c| matches!(c, '_' | '$')), + Some(c) => c.is_uppercase(), + _ => false, + } +} + +/// Here we check if the length of the groups exceeds the cutoff or there are comments +/// This function is the inverse of the prettier function +/// [Prettier applies]: https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/member-chain.js#L342 +pub fn is_member_call_chain( + expression: JsCallExpression, comments: &JsComments, + tab_width: TabWidth, +) -> SyntaxResult { + let chain = MemberChain::from_call_expression(expression, comments, tab_width)?; + + Ok(chain.tail.is_member_call_chain(comments)) +} + +/// Tests if expression is a long curried call +/// +/// ```javascript +/// `connect(a, b, c)(d)` +/// ``` +fn is_long_curried_call(expression: &JsCallExpression) -> bool { + if let Some(parent_call) = expression.parent::() { + match (expression.arguments(), parent_call.arguments()) { + (Ok(arguments), Ok(parent_arguments)) => { + is_callee(expression.syntax(), parent_call.syntax()) + && arguments.args().len() > parent_arguments.args().len() + && !parent_arguments.args().is_empty() + } + _ => false, + } + } else { + false + } +} + +fn has_short_name(identifier: &JsIdentifierExpression, tab_width: TabWidth) -> bool { + identifier + .name() + .and_then(|name| name.value_token()) + .map_or(false, |name| { + name.text_trimmed().len() <= u8::from(tab_width) as usize + }) +} + +struct ChainMembersIterator<'a> { + next: Option, + comments: &'a JsComments, root: bool, -) -> SyntaxResult { - use JsAnyExpression::*; +} - if comments.is_suppressed(node.syntax()) { - return Ok(ChainMember::Node(node.into_syntax())); +impl<'a> ChainMembersIterator<'a> { + fn new(root: JsAnyExpression, comments: &'a JsComments) -> Self { + Self { + next: Some(root), + comments, + root: true, + } } +} - let member = match node { - JsCallExpression(call_expression) => { - let callee = call_expression.callee()?; - let left = flatten_member_chain(queue, callee, comments, false)?; - queue.push(left); +impl Iterator for ChainMembersIterator<'_> { + type Item = ChainMember; - ChainMember::CallExpression { - expression: call_expression, - root, - } + fn next(&mut self) -> Option { + use JsAnyExpression::*; + + let expression = self.next.take()?; + + if self.comments.is_suppressed(expression.syntax()) { + return Some(ChainMember::Node(expression.into_syntax())); } - JsStaticMemberExpression(static_member) => { - let object = static_member.object()?; - let left = flatten_member_chain(queue, object, comments, false)?; - queue.push(left); + let member = match expression { + JsCallExpression(call_expression) => { + let callee = call_expression.callee().ok(); - ChainMember::StaticMember { - expression: static_member, - root, + let is_chain = matches!( + callee, + Some( + JsStaticMemberExpression(_) + | JsComputedMemberExpression(_) + | JsCallExpression(_) + ) + ); + + if is_chain { + self.next = callee; + } + + let position = if self.root { + CallExpressionPosition::End + } else if !is_chain { + CallExpressionPosition::Start + } else { + CallExpressionPosition::Middle + }; + + ChainMember::CallExpression { + expression: call_expression, + position, + } } - } - JsComputedMemberExpression(computed_expression) => { - let object = computed_expression.object()?; + JsStaticMemberExpression(static_member) => { + self.next = static_member.object().ok(); + ChainMember::StaticMember { + expression: static_member, + } + } - let left = flatten_member_chain(queue, object, comments, false)?; - queue.push(left); + JsComputedMemberExpression(computed_expression) => { + self.next = computed_expression.object().ok(); - ChainMember::ComputedMember { - expression: computed_expression, - root, + ChainMember::ComputedMember { + expression: computed_expression, + } } - } - expression => ChainMember::Node(expression.into_syntax()), - }; - Ok(member) -} + TsNonNullAssertionExpression(expression) => { + self.next = expression.expression().ok(); + ChainMember::TsNonNullAssertionExpression { expression } + } -/// Here we check if the length of the groups exceeds the cutoff or there are comments -/// This function is the inverse of the prettier function -/// [Prettier applies]: https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/member-chain.js#L342 -pub fn is_member_call_chain( - expression: &JsCallExpression, - f: &mut JsFormatter, -) -> SyntaxResult { - let chain = get_member_chain(expression, f)?; + expression => ChainMember::Node(expression.into_syntax()), + }; + + self.root = false; - Ok(chain.tail.is_member_call_chain(f.context().comments())) + Some(member) + } } + +impl FusedIterator for ChainMembersIterator<'_> {} diff --git a/crates/rome_js_formatter/src/utils/member_chain/simple_argument.rs b/crates/rome_js_formatter/src/utils/member_chain/simple_argument.rs index c0dd0001076..0ace9ad2eca 100644 --- a/crates/rome_js_formatter/src/utils/member_chain/simple_argument.rs +++ b/crates/rome_js_formatter/src/utils/member_chain/simple_argument.rs @@ -38,8 +38,6 @@ use rome_rowan::{AstSeparatedList, SyntaxResult}; pub(crate) enum SimpleArgument { Expression(JsAnyExpression), Name(JsAnyName), - Member(JsAnyObjectMember), - ArrayElement(JsAnyArrayElement), Spread, } @@ -51,7 +49,11 @@ impl SimpleArgument { } } - pub fn is_simple(&self, depth: u8) -> bool { + pub fn is_simple(&self) -> bool { + self.is_simple_impl(0) + } + + fn is_simple_impl(&self, depth: u8) -> bool { if depth >= 2 { return false; } @@ -81,12 +83,12 @@ impl SimpleArgument { let arguments = match any_expression { JsAnyExpression::JsNewExpression(expr) => { let callee = expr.callee()?; - is_simple_callee = SimpleArgument::from(callee).is_simple(depth); + is_simple_callee = SimpleArgument::from(callee).is_simple_impl(depth); expr.arguments() } JsAnyExpression::JsCallExpression(expr) => { let callee = expr.callee()?; - is_simple_callee = SimpleArgument::from(callee).is_simple(depth); + is_simple_callee = SimpleArgument::from(callee).is_simple_impl(depth); expr.arguments().ok() } JsAnyExpression::JsImportCallExpression(expr) => { @@ -99,7 +101,7 @@ impl SimpleArgument { let simple_arguments = if let Some(arguments) = arguments { arguments.args().iter().all(|argument| { argument.map_or(true, |argument| { - SimpleArgument::from(argument).is_simple(depth + 1) + SimpleArgument::from(argument).is_simple_impl(depth + 1) }) }) } else { @@ -125,8 +127,8 @@ impl SimpleArgument { let JsStaticMemberExpressionFields { member, object, .. } = static_expression.as_fields(); - Ok(SimpleArgument::from(member?).is_simple(depth) - && SimpleArgument::from(object?).is_simple(depth)) + Ok(SimpleArgument::from(member?).is_simple_impl(depth) + && SimpleArgument::from(object?).is_simple_impl(depth)) } else { Ok(false) } @@ -137,7 +139,7 @@ impl SimpleArgument { assertion, )) = self { - Ok(SimpleArgument::from(assertion.expression()?).is_simple(depth)) + Ok(SimpleArgument::from(assertion.expression()?).is_simple_impl(depth)) } else { Ok(false) } @@ -151,7 +153,7 @@ impl SimpleArgument { unary_expression.operator()?, JsUnaryOperator::LogicalNot | JsUnaryOperator::Minus ) { - Ok(SimpleArgument::from(unary_expression.argument()?).is_simple(depth)) + Ok(SimpleArgument::from(unary_expression.argument()?).is_simple_impl(depth)) } else { Ok(false) } @@ -168,7 +170,12 @@ impl SimpleArgument { .elements() .iter() .filter_map(|element| element.ok()) - .all(|element| SimpleArgument::from(element).is_simple(depth + 1)) + .all(|element| match element { + JsAnyArrayElement::JsAnyExpression(expression) => { + SimpleArgument::from(expression).is_simple_impl(depth + 1) + } + _ => false, + }) } else { false } @@ -182,20 +189,20 @@ impl SimpleArgument { } } - fn is_simple_literal(&self) -> bool { - match self { - SimpleArgument::Expression(expression) => { - matches!( - expression, - JsAnyExpression::JsAnyLiteralExpression(_) - | JsAnyExpression::JsThisExpression(_) - | JsAnyExpression::JsIdentifierExpression(_) - | JsAnyExpression::JsSuperExpression(_) - ) - } - SimpleArgument::Name(JsAnyName::JsPrivateName(_)) => true, - _ => false, + const fn is_simple_literal(&self) -> bool { + if let SimpleArgument::Name(JsAnyName::JsPrivateName(_)) = self { + return true; } + + matches!( + self, + SimpleArgument::Expression( + JsAnyExpression::JsAnyLiteralExpression(_) + | JsAnyExpression::JsThisExpression(_) + | JsAnyExpression::JsIdentifierExpression(_) + | JsAnyExpression::JsSuperExpression(_), + ) + ) } fn is_simple_object_expression(&self, depth: u8) -> bool { @@ -207,22 +214,24 @@ impl SimpleArgument { .iter() .filter_map(|member| member.ok()) .all(|member| { - let is_shorthand_property = matches!( - member, - JsAnyObjectMember::JsShorthandPropertyObjectMember(_) - ); - let is_computed_property = - if let JsAnyObjectMember::JsPropertyObjectMember(property) = &member { - matches!( + use JsAnyObjectMember::*; + + match member { + JsShorthandPropertyObjectMember(_) => true, + JsPropertyObjectMember(property) => { + let is_computed = matches!( property.name(), Ok(JsAnyObjectMemberName::JsComputedMemberName(_)) - ) - } else { - false - }; - let is_simple = SimpleArgument::from(member).is_simple(depth + 1); + ); - !is_computed_property && (is_shorthand_property || is_simple) + let is_simple = property.value().map_or(false, |value| { + SimpleArgument::from(value).is_simple_impl(depth + 1) + }); + + !is_computed && is_simple + } + _ => false, + } }) } else { false @@ -242,18 +251,6 @@ impl From for SimpleArgument { } } -impl From for SimpleArgument { - fn from(member: JsAnyObjectMember) -> Self { - Self::Member(member) - } -} - -impl From for SimpleArgument { - fn from(element: JsAnyArrayElement) -> Self { - Self::ArrayElement(element) - } -} - impl From for SimpleArgument { fn from(_: JsSpread) -> Self { Self::Spread @@ -284,7 +281,7 @@ pub fn is_simple_template_literal(template: &JsTemplate, depth: u8) -> SyntaxRes } JsAnyTemplateElement::JsTemplateElement(element) => { let expression = element.expression()?; - if !(SimpleArgument::from(expression).is_simple(depth)) { + if !(SimpleArgument::from(expression).is_simple_impl(depth)) { return Ok(false); } } diff --git a/crates/rome_js_formatter/src/utils/mod.rs b/crates/rome_js_formatter/src/utils/mod.rs index 480e32d912d..71f406a33a8 100644 --- a/crates/rome_js_formatter/src/utils/mod.rs +++ b/crates/rome_js_formatter/src/utils/mod.rs @@ -6,7 +6,7 @@ pub mod string_utils; pub(crate) mod format_class; pub mod jsx; -mod member_chain; +pub(crate) mod member_chain; mod object; mod object_like; mod object_pattern_like; @@ -23,7 +23,6 @@ pub(crate) use binary_like_expression::{ needs_binary_like_parentheses, JsAnyBinaryLikeExpression, JsAnyBinaryLikeLeftExpression, }; pub(crate) use conditional::{ConditionalJsxChain, JsAnyConditional}; -pub(crate) use member_chain::get_member_chain; pub(crate) use object_like::JsObjectLike; pub(crate) use object_pattern_like::JsObjectPatternLike; use rome_formatter::{format_args, write, Buffer}; diff --git a/crates/rome_js_formatter/tests/specs/js/module/declarations/variable_declaration.js.snap b/crates/rome_js_formatter/tests/specs/js/module/declarations/variable_declaration.js.snap index f7e95fbf442..7447764ca60 100644 --- a/crates/rome_js_formatter/tests/specs/js/module/declarations/variable_declaration.js.snap +++ b/crates/rome_js_formatter/tests/specs/js/module/declarations/variable_declaration.js.snap @@ -426,13 +426,13 @@ let loooooooooooooooooooooooooong2 = /\wwwwwwwwwwwwwwwwww+/gi, ).ewqeqewqweqweqweqweqweqweqw; let loooooooooooooooooooooooooong3 = - objdddddddddectobjdddddddddect( - /\wwwwwwwwwwwwwwwwww+/gi, - )[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; + objdddddddddectobjdddddddddect(/\wwwwwwwwwwwwwwwwww+/gi)[ + dsadsadsadsadsadsadsa + ]().ewqoewqoeiowqieopwqie; let loooooooooooooooooooooooooong3 = - objdddddddddectobjdddddddddect( - /\wwwwwwwwwwwwwwwwww+/gi, - )[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; + objdddddddddectobjdddddddddect(/\wwwwwwwwwwwwwwwwww+/gi)[ + dsadsadsadsadsadsadsa + ]().ewqoewqoeiowqieopwqie; //JsTemplate argument var loooooooooooooooooooooooooong1 = @@ -444,13 +444,13 @@ let loooooooooooooooooooooooooong2 = `111111111111111111`, ).ewqeqewqweqweqweqweqweqweqw; let loooooooooooooooooooooooooong3 = - objdddddddddectobjddsadsaddddddddect( - `111111111111111111`, - )[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; + objdddddddddectobjddsadsaddddddddect(`111111111111111111`)[ + dsadsadsadsadsadsadsa + ]().ewqoewqoeiowqieopwqie; let loooooooooooooooooooooooooong3 = - objdddddddddectobjdddsadaddddddddect( - `111111111111111111`, - )[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; + objdddddddddectobjdddsadaddddddddect(`111111111111111111`)[ + dsadsadsadsadsadsadsa + ]().ewqoewqoeiowqieopwqie; // rest JsAnyLiteralExpression var loooooooooooooooooooooooooong1 = @@ -630,18 +630,14 @@ let loooooooooooooooooooooooooong3 = objdddddddddectobjddsadsaddddddddect( // has new line var loooooooooooooooooooooooooong1 = - fnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfn( - `123123 - dsa`, - ); -let loooooooooooooooooooooooooong2 = objdddddddddectobjdddsadsadddddddect( - `123123 -dsa`, -).ewqeqewqweqweqweqweqweqweqw; -let loooooooooooooooooooooooooong3 = objdddddddddectobjddsadsaddddddddect( - `123123 - dsa`, -)[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; + fnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfnfn(`123123 + dsa`); +let loooooooooooooooooooooooooong2 = + objdddddddddectobjdddsadsadddddddect(`123123 +dsa`).ewqeqewqweqweqweqweqweqweqw; +let loooooooooooooooooooooooooong3 = + objdddddddddectobjddsadsaddddddddect(`123123 + dsa`)[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; //JsThisExpression var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = @@ -702,20 +698,14 @@ let looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo // has new line var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - this( - `123123 - dsa`, - ); + this(`123123 + dsa`); let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - this( - `123123 -dsa`, - ).ewqeqewqweqweqweqweqweqweqw; + this(`123123 +dsa`).ewqeqewqweqweqweqweqweqweqw; let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - this( - `123123 - dsa`, - )[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; + this(`123123 + dsa`)[dsadsadsadsadsadsadsa]().ewqoewqoeiowqieopwqie; //lone short argument JsUnaryExpression argument with comment var loooooooooooooooooooooooooong1 = @@ -775,30 +765,30 @@ const a 251: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = 253: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = 255: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = - 367: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 369: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 371: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 375: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 377: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 379: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 381: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = - 385: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 387: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 389: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 391: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = - 395: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 397: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 399: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 402: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = - 407: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 409: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 411: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 416: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 418: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 420: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 424: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 429: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = - 434: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = - 450: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = - 452: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 363: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 365: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 367: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 371: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 373: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 375: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 377: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = + 381: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 383: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 385: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 387: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = + 391: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 393: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 395: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 398: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong4 = + 403: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 405: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 407: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 412: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 414: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 416: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 420: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 423: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = + 426: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong3 = + 440: var loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1 = + 442: let loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong2 = diff --git a/crates/rome_js_formatter/tests/specs/js/module/expression/member-chain/computed.js.snap b/crates/rome_js_formatter/tests/specs/js/module/expression/member-chain/computed.js.snap index c9b5c26d37c..63fd7e5a589 100644 --- a/crates/rome_js_formatter/tests/specs/js/module/expression/member-chain/computed.js.snap +++ b/crates/rome_js_formatter/tests/specs/js/module/expression/member-chain/computed.js.snap @@ -19,7 +19,8 @@ Quote style: Double Quotes Quote properties: As needed ----- nock(/test/) - .matchHeader("Accept", "application/json")[httpMethodNock(method)]("/foo") + .matchHeader("Accept", "application/json") + [httpMethodNock(method)]("/foo") .reply(200, { foo: "bar", }); diff --git a/crates/rome_js_formatter/tests/specs/js/module/expression/static_member_expression.js.snap b/crates/rome_js_formatter/tests/specs/js/module/expression/static_member_expression.js.snap index 40b67388204..9eb4fe55db7 100644 --- a/crates/rome_js_formatter/tests/specs/js/module/expression/static_member_expression.js.snap +++ b/crates/rome_js_formatter/tests/specs/js/module/expression/static_member_expression.js.snap @@ -41,19 +41,27 @@ a?.b.#c; a?.#b.c().d; lorem.ipsum(); -lorem.ipsum().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong(); -lorem()[0]().ipsum().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong(); +lorem + .ipsum() + .looooooooooooooooooooooooooong() + .looooooooooooooooooooooooooong() + .looooooooooooooooooooooooooong(); +lorem()[0]() + .ipsum() + .looooooooooooooooooooooooooong() + .looooooooooooooooooooooooooong() + .looooooooooooooooooooooooooong(); -something()[1]()[3]().items.item.what_else[3]().something().something().then().catcht().else().what_the_hell(); +something()[1]()[3]() + .items.item.what_else[3]() + .something() + .something() + .then() + .catcht() + .else() + .what_the_hell(); some.member.with. // rome-ignore format: Verify that formatting calls into right.format() rather.hard.to.test.because.name.doesnt.format.being.ignored; - -## Lines exceeding width of 80 characters - - 9: lorem.ipsum().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong(); - 10: lorem()[0]().ipsum().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong().looooooooooooooooooooooooooong(); - 12: something()[1]()[3]().items.item.what_else[3]().something().something().then().catcht().else().what_the_hell(); - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/assignment/call-with-template.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/assignment/call-with-template.js.snap deleted file mode 100644 index 78cb353c58b..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/assignment/call-with-template.js.snap +++ /dev/null @@ -1,56 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const result = template(` - if (SOME_VAR === "") {} -`)({ - SOME_VAR: value, -}); - -const output = - template(`function f() %%A%%`)({ - A: t.blockStatement([]), - }); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,6 +1,8 @@ --const result = template(` -+const result = template( -+ ` - if (SOME_VAR === "") {} --`)({ -+`, -+)({ - SOME_VAR: value, - }); - -``` - -# Output - -```js -const result = template( - ` - if (SOME_VAR === "") {} -`, -)({ - SOME_VAR: value, -}); - -const output = template(`function f() %%A%%`)({ - A: t.blockStatement([]), -}); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/assignment/lone-arg.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/assignment/lone-arg.js.snap deleted file mode 100644 index 9598c1f063b..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/assignment/lone-arg.js.snap +++ /dev/null @@ -1,77 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: js/assignment/lone-arg.js ---- - -# Input - -```js -let vgChannel = pointPositionDefaultRef({ - model, - defaultPos, - channel, -})() - -let vgChannel2 = pointPositionDefaultRef({ model, - defaultPos, - channel, -})() - -const bifornCringerMoshedPerplexSawderGlyphsHa = - someBigFunctionName("foo")("bar"); - -if (true) { - node.id = this.flowParseTypeAnnotatableIdentifier(/*allowPrimitiveOverride*/ true); -} - -const bifornCringerMoshedPerplexSawderGlyphsHb = someBigFunctionName(`foo -`)("bar"); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -15,5 +15,7 @@ - ); - } - --const bifornCringerMoshedPerplexSawderGlyphsHb = someBigFunctionName(`foo --`)("bar"); -+const bifornCringerMoshedPerplexSawderGlyphsHb = someBigFunctionName( -+ `foo -+`, -+)("bar"); -``` - -# Output - -```js -let vgChannel = pointPositionDefaultRef({ - model, - defaultPos, - channel, -})(); - -let vgChannel2 = pointPositionDefaultRef({ model, defaultPos, channel })(); - -const bifornCringerMoshedPerplexSawderGlyphsHa = - someBigFunctionName("foo")("bar"); - -if (true) { - node.id = this.flowParseTypeAnnotatableIdentifier( - /*allowPrimitiveOverride*/ true, - ); -} - -const bifornCringerMoshedPerplexSawderGlyphsHb = someBigFunctionName( - `foo -`, -)("bar"); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/closure-compiler-type-cast.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/closure-compiler-type-cast.js.snap deleted file mode 100644 index 33463b4d748..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/closure-compiler-type-cast.js.snap +++ /dev/null @@ -1,190 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: js/comments-closure-typecast/closure-compiler-type-cast.js ---- - -# Input - -```js -// test to make sure comments are attached correctly -let inlineComment = /* some comment */ ( - someReallyLongFunctionCall(withLots, ofArguments)); - -let object = { - key: /* some comment */ (someReallyLongFunctionCall(withLots, ofArguments)) -}; - -// preserve parens only for type casts -let assignment = /** @type {string} */ (getValue()); -let value = /** @type {string} */ (this.members[0]).functionCall(); - -functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({})); - -function returnValue() { - return /** @type {!Array.} */ (['hello', 'you']); -} - -// Only numberOrString is typecast -var newArray = /** @type {array} */ (numberOrString).map(x => x); -var newArray = /** @type {array} */ ((numberOrString)).map(x => x); -var newArray = test(/** @type {array} */ (numberOrString).map(x => x)); -var newArray = test(/** @type {array} */ ((numberOrString)).map(x => x)); - -// The numberOrString.map CallExpression is typecast -var newArray = /** @type {array} */ (numberOrString.map(x => x)); -var newArray = /** @type {array} */ ((numberOrString).map(x => x)); -var newArray = test(/** @type {array} */ (numberOrString.map(x => x))); -var newArray = test(/** @type {array} */ ((numberOrString).map(x => x))); - -test(/** @type {number} */(num) + 1); -test(/** @type {!Array} */(arrOrString).length + 1); -test(/** @type {!Array} */((arrOrString)).length + 1); - -const data = functionCall( - arg1, - arg2, - /** @type {{height: number, width: number}} */ (arg3)); - -const style = /** @type {{ - width: number, - height: number, - marginTop: number, - marginLeft: number, - marginRight: number, - marginBottom: number, -}} */ ({ - width, - height, - ...margins, -}); - -const style2 =/** - * @type {{ - * width: number, - * }} -*/({ - width, -}); - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -10,7 +10,8 @@ - - // preserve parens only for type casts - let assignment = /** @type {string} */ (getValue()); --let value = /** @type {string} */ (this.members[0]).functionCall(); -+let value = /** @type {string} */ (this.members[0]) -+ .functionCall(); - - functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({})); - -@@ -19,10 +20,18 @@ - } - - // Only numberOrString is typecast --var newArray = /** @type {array} */ (numberOrString).map((x) => x); --var newArray = /** @type {array} */ (numberOrString).map((x) => x); --var newArray = test(/** @type {array} */ (numberOrString).map((x) => x)); --var newArray = test(/** @type {array} */ (numberOrString).map((x) => x)); -+var newArray = /** @type {array} */ (numberOrString) -+ .map((x) => x); -+var newArray = /** @type {array} */ (numberOrString) -+ .map((x) => x); -+var newArray = test( -+ /** @type {array} */ (numberOrString) -+ .map((x) => x), -+); -+var newArray = test( -+ /** @type {array} */ (numberOrString) -+ .map((x) => x), -+); - - // The numberOrString.map CallExpression is typecast - var newArray = /** @type {array} */ (numberOrString.map((x) => x)); -``` - -# Output - -```js -// test to make sure comments are attached correctly -let inlineComment = /* some comment */ someReallyLongFunctionCall( - withLots, - ofArguments, -); - -let object = { - key: /* some comment */ someReallyLongFunctionCall(withLots, ofArguments), -}; - -// preserve parens only for type casts -let assignment = /** @type {string} */ (getValue()); -let value = /** @type {string} */ (this.members[0]) - .functionCall(); - -functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({})); - -function returnValue() { - return /** @type {!Array.} */ (["hello", "you"]); -} - -// Only numberOrString is typecast -var newArray = /** @type {array} */ (numberOrString) - .map((x) => x); -var newArray = /** @type {array} */ (numberOrString) - .map((x) => x); -var newArray = test( - /** @type {array} */ (numberOrString) - .map((x) => x), -); -var newArray = test( - /** @type {array} */ (numberOrString) - .map((x) => x), -); - -// The numberOrString.map CallExpression is typecast -var newArray = /** @type {array} */ (numberOrString.map((x) => x)); -var newArray = /** @type {array} */ (numberOrString.map((x) => x)); -var newArray = test(/** @type {array} */ (numberOrString.map((x) => x))); -var newArray = test(/** @type {array} */ (numberOrString.map((x) => x))); - -test(/** @type {number} */ (num) + 1); -test(/** @type {!Array} */ (arrOrString).length + 1); -test(/** @type {!Array} */ (arrOrString).length + 1); - -const data = functionCall( - arg1, - arg2, - /** @type {{height: number, width: number}} */ (arg3), -); - -const style = /** @type {{ - width: number, - height: number, - marginTop: number, - marginLeft: number, - marginRight: number, - marginBottom: number, -}} */ ({ - width, - height, - ...margins, -}); - -const style2 = /** - * @type {{ - * width: number, - * }} - */ ({ - width, -}); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/comment-in-the-middle.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/comment-in-the-middle.js.snap deleted file mode 100644 index a5f7b1a5923..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/comments-closure-typecast/comment-in-the-middle.js.snap +++ /dev/null @@ -1,57 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: js/comments-closure-typecast/comment-in-the-middle.js ---- - -# Input - -```js -var a = -/** - * bla bla bla - * @type {string | - * number - * } -* bla bla bla - */ -//2 - ((window['s'])).toString(); -console.log(a.foo()); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -7,5 +7,6 @@ - * bla bla bla - */ - //2 -- (window["s"]).toString(); -+ (window["s"]) -+ .toString(); - console.log(a.foo()); -``` - -# Output - -```js -var a = - /** - * bla bla bla - * @type {string | - * number - * } - * bla bla bla - */ - //2 - (window["s"]) - .toString(); -console.log(a.foo()); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/functional_compose.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/functional_compose.js.snap index 0d3409439a6..bd79c48bdf7 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/functional_compose.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/functional_compose.js.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: js/functional-composition/functional_compose.js --- # Input @@ -57,7 +59,7 @@ this.subscriptions.add( ```diff --- Prettier +++ Rome -@@ -1,51 +1,27 @@ +@@ -1,46 +1,21 @@ -compose( - sortBy((x) => x), - flatten, @@ -111,15 +113,6 @@ this.subscriptions.add( } } - this.subscriptions.add( -- this.componentUpdates -- .pipe(startWith(this.props), distinctUntilChanged(isEqual)) -- .subscribe((props) => {}), -+ this.componentUpdates.pipe( -+ startWith(this.props), -+ distinctUntilChanged(isEqual), -+ ).subscribe((props) => {}), - ); ``` # Output @@ -147,10 +140,9 @@ class A extends B { } this.subscriptions.add( - this.componentUpdates.pipe( - startWith(this.props), - distinctUntilChanged(isEqual), - ).subscribe((props) => {}), + this.componentUpdates + .pipe(startWith(this.props), distinctUntilChanged(isEqual)) + .subscribe((props) => {}), ); ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/rxjs_pipe.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/rxjs_pipe.js.snap deleted file mode 100644 index c56eccb195f..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/functional-composition/rxjs_pipe.js.snap +++ /dev/null @@ -1,61 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -import { range } from 'rxjs/observable/range'; -import { map, filter, scan } from 'rxjs/operators'; - -const source$ = range(0, 10); - -source$.pipe( - filter(x => x % 2 === 0), - map(x => x + x), - scan((acc, x) => acc + x, 0) -) -.subscribe(x => console.log(x)) -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -3,10 +3,8 @@ - - const source$ = range(0, 10); - --source$ -- .pipe( -- filter((x) => x % 2 === 0), -- map((x) => x + x), -- scan((acc, x) => acc + x, 0), -- ) -- .subscribe((x) => console.log(x)); -+source$.pipe( -+ filter((x) => x % 2 === 0), -+ map((x) => x + x), -+ scan((acc, x) => acc + x, 0), -+).subscribe((x) => console.log(x)); -``` - -# Output - -```js -import { range } from "rxjs/observable/range"; -import { map, filter, scan } from "rxjs/operators"; - -const source$ = range(0, 10); - -source$.pipe( - filter((x) => x % 2 === 0), - map((x) => x + x), - scan((acc, x) => acc + x, 0), -).subscribe((x) => console.log(x)); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/member/expand.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/member/expand.js.snap deleted file mode 100644 index db88499a1dd..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/member/expand.js.snap +++ /dev/null @@ -1,117 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const veryVeryVeryVeryVeryVeryVeryLong = doc.expandedStates[doc.expandedStates.length - 1]; -const small = doc.expandedStates[doc.expandedStates.length - 1]; - -const promises = [ - promise.resolve().then(console.log).catch(err => { - console.log(err) - return null - }), - redis.fetch(), - other.fetch(), -]; - -const promises2 = [ - promise.resolve().veryLongFunctionCall().veryLongFunctionCall().then(console.log).catch(err => { - console.log(err) - return null - }), - redis.fetch(), - other.fetch(), -]; - -window.FooClient.setVars({ - locale: getFooLocale({ page }), - authorizationToken: data.token -}).initVerify("foo_container"); - -window.something.FooClient.setVars({ - locale: getFooLocale({ page }), - authorizationToken: data.token -}).initVerify("foo_container"); - -window.FooClient.something.setVars({ - locale: getFooLocale({ page }), - authorizationToken: data.token -}).initVerify("foo_container"); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -38,9 +38,7 @@ - authorizationToken: data.token, - }).initVerify("foo_container"); - --window.FooClient.something -- .setVars({ -- locale: getFooLocale({ page }), -- authorizationToken: data.token, -- }) -- .initVerify("foo_container"); -+window.FooClient.something.setVars({ -+ locale: getFooLocale({ page }), -+ authorizationToken: data.token, -+}).initVerify("foo_container"); -``` - -# Output - -```js -const veryVeryVeryVeryVeryVeryVeryLong = - doc.expandedStates[doc.expandedStates.length - 1]; -const small = doc.expandedStates[doc.expandedStates.length - 1]; - -const promises = [ - promise - .resolve() - .then(console.log) - .catch((err) => { - console.log(err); - return null; - }), - redis.fetch(), - other.fetch(), -]; - -const promises2 = [ - promise - .resolve() - .veryLongFunctionCall() - .veryLongFunctionCall() - .then(console.log) - .catch((err) => { - console.log(err); - return null; - }), - redis.fetch(), - other.fetch(), -]; - -window.FooClient.setVars({ - locale: getFooLocale({ page }), - authorizationToken: data.token, -}).initVerify("foo_container"); - -window.something.FooClient.setVars({ - locale: getFooLocale({ page }), - authorizationToken: data.token, -}).initVerify("foo_container"); - -window.FooClient.something.setVars({ - locale: getFooLocale({ page }), - authorizationToken: data.token, -}).initVerify("foo_container"); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/13018.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/13018.js.snap deleted file mode 100644 index d3a5c2b1867..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/13018.js.snap +++ /dev/null @@ -1,69 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: js/method-chain/13018.js ---- - -# Input - -```js -foo(_a).bar().leet(); -foo(-a).bar().leet(); -foo(+a).bar().leet(); -foo(~a).bar().leet(); -foo(++a).bar().leet(); -foo(--a).bar().leet(); -foo(a++).bar().leet(); -foo(a--).bar().leet(); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,20 +1,8 @@ - foo(_a).bar().leet(); - foo(-a).bar().leet(); --foo(+a) -- .bar() -- .leet(); --foo(~a) -- .bar() -- .leet(); --foo(++a) -- .bar() -- .leet(); --foo(--a) -- .bar() -- .leet(); --foo(a++) -- .bar() -- .leet(); --foo(a--) -- .bar() -- .leet(); -+foo(+a).bar().leet(); -+foo(~a).bar().leet(); -+foo(++a).bar().leet(); -+foo(--a).bar().leet(); -+foo(a++).bar().leet(); -+foo(a--).bar().leet(); -``` - -# Output - -```js -foo(_a).bar().leet(); -foo(-a).bar().leet(); -foo(+a).bar().leet(); -foo(~a).bar().leet(); -foo(++a).bar().leet(); -foo(--a).bar().leet(); -foo(a++).bar().leet(); -foo(a--).bar().leet(); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/bracket_0-1.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/bracket_0-1.js.snap deleted file mode 100644 index 0495cddb7fc..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/bracket_0-1.js.snap +++ /dev/null @@ -1,34 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const thingamabobMetaAlias = -path.scope.getProgramParent().path.get("body")[0].node; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,3 +1,2 @@ --const thingamabobMetaAlias = path.scope -- .getProgramParent() -- .path.get("body")[0].node; -+const thingamabobMetaAlias = path.scope.getProgramParent().path.get("body")[0] -+ .node; -``` - -# Output - -```js -const thingamabobMetaAlias = path.scope.getProgramParent().path.get("body")[0] - .node; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/comment.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/comment.js.snap deleted file mode 100644 index 79f10844abd..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/comment.js.snap +++ /dev/null @@ -1,160 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: js/method-chain/comment.js ---- - -# Input - -```js -function f() { - return observableFromSubscribeFunction() - // Debounce manually rather than using editor.onDidStopChanging so that the debounce time is - // configurable. - .debounceTime(debounceInterval); -} - -_.a(a) - /* very very very very very very very long such that it is longer than 80 columns */ - .a() - -_.a( - a -)/* very very very very very very very long such that it is longer than 80 columns */ -.a(); - -_.a( - a -) /* very very very very very very very long such that it is longer than 80 columns */.a(); - -Something - // $FlowFixMe(>=0.41.0) - .getInstance(this.props.dao) - .getters() - -// Warm-up first -measure() - .then(() => { - SomethingLong(); - }); - -measure() // Warm-up first - .then(() => { - SomethingLong(); - }); - -const configModel = this.baseConfigurationService.getCache().consolidated // global/default values (do NOT modify) - .merge(this.cachedWorkspaceConfig); - -this.doWriteConfiguration(target, value, options) // queue up writes to prevent race conditions - .then(() => null, - error => { - return options.donotNotifyError ? TPromise.wrapError(error) : this.onError(error, target, value); - }); - -ret = __DEV__ ? - // $FlowFixMe: this type differs according to the env -vm.runInContext(source, ctx) -: a - -angular.module('AngularAppModule') - // Hello, I am comment. - .constant('API_URL', 'http://localhost:8080/api'); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -53,7 +53,8 @@ - - ret = __DEV__ - ? // $FlowFixMe: this type differs according to the env -- vm.runInContext(source, ctx) -+ vm -+ .runInContext(source, ctx) - : a; - - angular -``` - -# Output - -```js -function f() { - return ( - observableFromSubscribeFunction() - // Debounce manually rather than using editor.onDidStopChanging so that the debounce time is - // configurable. - .debounceTime(debounceInterval) - ); -} - -_.a(a) - /* very very very very very very very long such that it is longer than 80 columns */ - .a(); - -_.a( - a, -) /* very very very very very very very long such that it is longer than 80 columns */ - .a(); - -_.a( - a, -) /* very very very very very very very long such that it is longer than 80 columns */ - .a(); - -Something - // $FlowFixMe(>=0.41.0) - .getInstance(this.props.dao) - .getters(); - -// Warm-up first -measure().then(() => { - SomethingLong(); -}); - -measure() // Warm-up first - .then(() => { - SomethingLong(); - }); - -const configModel = this.baseConfigurationService - .getCache() - .consolidated // global/default values (do NOT modify) - .merge(this.cachedWorkspaceConfig); - -this.doWriteConfiguration(target, value, options) // queue up writes to prevent race conditions - .then( - () => null, - (error) => { - return options.donotNotifyError - ? TPromise.wrapError(error) - : this.onError(error, target, value); - }, - ); - -ret = __DEV__ - ? // $FlowFixMe: this type differs according to the env - vm - .runInContext(source, ctx) - : a; - -angular - .module("AngularAppModule") - // Hello, I am comment. - .constant("API_URL", "http://localhost:8080/api"); -``` - - -# Lines exceeding max width of 80 characters -``` - 4: // Debounce manually rather than using editor.onDidStopChanging so that the debounce time is - 11: /* very very very very very very very long such that it is longer than 80 columns */ - 16: ) /* very very very very very very very long such that it is longer than 80 columns */ - 21: ) /* very very very very very very very long such that it is longer than 80 columns */ - 44: this.doWriteConfiguration(target, value, options) // queue up writes to prevent race conditions -``` - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed-merge.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed-merge.js.snap deleted file mode 100644 index 7f7700d2c63..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed-merge.js.snap +++ /dev/null @@ -1,65 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -[].forEach(key => { - data[key]('foo') - .then(() => console.log('bar')) - .catch(() => console.log('baz')); -}); - -[].forEach(key => { - data('foo') - [key]('bar') - .then(() => console.log('bar')) - .catch(() => console.log('baz')); -}); - -window.Data[key]("foo") - .then(() => a) - .catch(() => b); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -5,8 +5,7 @@ - }); - - [].forEach((key) => { -- data("foo") -- [key]("bar") -+ data("foo")[key]("bar") - .then(() => console.log("bar")) - .catch(() => console.log("baz")); - }); -``` - -# Output - -```js -[].forEach((key) => { - data[key]("foo") - .then(() => console.log("bar")) - .catch(() => console.log("baz")); -}); - -[].forEach((key) => { - data("foo")[key]("bar") - .then(() => console.log("bar")) - .catch(() => console.log("baz")); -}); - -window.Data[key]("foo") - .then(() => a) - .catch(() => b); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed.js.snap deleted file mode 100644 index f35739c27ef..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/computed.js.snap +++ /dev/null @@ -1,43 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -nock(/test/) - .matchHeader('Accept', 'application/json') - [httpMethodNock(method)]('/foo') - .reply(200, { - foo: 'bar', - }); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,6 +1,5 @@ - nock(/test/) -- .matchHeader("Accept", "application/json") -- [httpMethodNock(method)]("/foo") -+ .matchHeader("Accept", "application/json")[httpMethodNock(method)]("/foo") - .reply(200, { - foo: "bar", - }); -``` - -# Output - -```js -nock(/test/) - .matchHeader("Accept", "application/json")[httpMethodNock(method)]("/foo") - .reply(200, { - foo: "bar", - }); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/conditional.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/conditional.js.snap deleted file mode 100644 index 1da233ef2f1..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/conditional.js.snap +++ /dev/null @@ -1,95 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -(a ? b : c).d(); - -(a ? b : c).d().e(); - -(a ? b : c).d().e().f(); - -(valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(this.defaultUser)) -.map(); - -(valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(this.defaultUser)) -.map().filter(); - -(valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(defaultUser)) -.map(); - -object[valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(defaultUser)] -.map(); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -12,17 +12,13 @@ - (valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(this.defaultUser) --) -- .map() -- .filter(); -+).map().filter(); - - (valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(defaultUser) - ).map(); - --object[ -- valid -- ? helper.responseBody(this.currentUser) -- : helper.responseBody(defaultUser) --].map(); -+object[valid -+ ? helper.responseBody(this.currentUser) -+ : helper.responseBody(defaultUser)].map(); -``` - -# Output - -```js -(a ? b : c).d(); - -(a ? b : c).d().e(); - -(a ? b : c).d().e().f(); - -(valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(this.defaultUser) -).map(); - -(valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(this.defaultUser) -).map().filter(); - -(valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(defaultUser) -).map(); - -object[valid - ? helper.responseBody(this.currentUser) - : helper.responseBody(defaultUser)].map(); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/d3.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/d3.js.snap deleted file mode 100644 index d0a59b84fdf..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/d3.js.snap +++ /dev/null @@ -1,87 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -d3.select('body') - .append('circle') - .at({ width: 30, fill: '#f0f' }) - .st({ fontWeight: 600 }) - -const myScale = d3.scaleLinear() - .domain([1950, 1980]) - .range([0, width]) - -not.d3.select('body') - .append('circle') - .at({ width: 30, fill: '#f0f' }) - .st({ fontWeight: 600 }) - -not.d3.scaleLinear() - .domain([1950, 1980]) - .range([0, width]) -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,9 +1,13 @@ --d3.select("body") -+d3 -+ .select("body") - .append("circle") - .at({ width: 30, fill: "#f0f" }) - .st({ fontWeight: 600 }); - --const myScale = d3.scaleLinear().domain([1950, 1980]).range([0, width]); -+const myScale = d3 -+ .scaleLinear() -+ .domain([1950, 1980]) -+ .range([0, width]); - - not.d3 - .select("body") -@@ -11,4 +15,7 @@ - .at({ width: 30, fill: "#f0f" }) - .st({ fontWeight: 600 }); - --not.d3.scaleLinear().domain([1950, 1980]).range([0, width]); -+not.d3 -+ .scaleLinear() -+ .domain([1950, 1980]) -+ .range([0, width]); -``` - -# Output - -```js -d3 - .select("body") - .append("circle") - .at({ width: 30, fill: "#f0f" }) - .st({ fontWeight: 600 }); - -const myScale = d3 - .scaleLinear() - .domain([1950, 1980]) - .range([0, width]); - -not.d3 - .select("body") - .append("circle") - .at({ width: 30, fill: "#f0f" }) - .st({ fontWeight: 600 }); - -not.d3 - .scaleLinear() - .domain([1950, 1980]) - .range([0, width]); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/first_long.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/first_long.js.snap index 770e9ad34c2..b271e047198 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/first_long.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/first_long.js.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: js/method-chain/first_long.js --- # Input @@ -79,34 +81,6 @@ function f() { ); } -@@ -19,15 +20,16 @@ - return this._getWorker(workerOptions)({ - filePath, - hasteImplModulePath: this._options.hasteImplModulePath, -- }).then((metadata) => { -- // `1` for truthy values instead of `true` to save cache space. -- fileMetadata[H.VISITED] = 1; -- const metadataId = metadata.id; -- const metadataModule = metadata.module; -- if (metadataId && metadataModule) { -- fileMetadata[H.ID] = metadataId; -- setModule(metadataId, metadataModule); -- } -- fileMetadata[H.DEPENDENCIES] = metadata.dependencies || []; -- }); -+ }) -+ .then((metadata) => { -+ // `1` for truthy values instead of `true` to save cache space. -+ fileMetadata[H.VISITED] = 1; -+ const metadataId = metadata.id; -+ const metadataModule = metadata.module; -+ if (metadataId && metadataModule) { -+ fileMetadata[H.ID] = metadataId; -+ setModule(metadataId, metadataModule); -+ } -+ fileMetadata[H.DEPENDENCIES] = metadata.dependencies || []; -+ }); - } ``` # Output @@ -134,18 +108,17 @@ function f() { return this._getWorker(workerOptions)({ filePath, hasteImplModulePath: this._options.hasteImplModulePath, - }) - .then((metadata) => { - // `1` for truthy values instead of `true` to save cache space. - fileMetadata[H.VISITED] = 1; - const metadataId = metadata.id; - const metadataModule = metadata.module; - if (metadataId && metadataModule) { - fileMetadata[H.ID] = metadataId; - setModule(metadataId, metadataModule); - } - fileMetadata[H.DEPENDENCIES] = metadata.dependencies || []; - }); + }).then((metadata) => { + // `1` for truthy values instead of `true` to save cache space. + fileMetadata[H.VISITED] = 1; + const metadataId = metadata.id; + const metadataModule = metadata.module; + if (metadataId && metadataModule) { + fileMetadata[H.ID] = metadataId; + setModule(metadataId, metadataModule); + } + fileMetadata[H.DEPENDENCIES] = metadata.dependencies || []; + }); } ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/fluent-configuration.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/fluent-configuration.js.snap deleted file mode 100644 index 7eaadce662d..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/fluent-configuration.js.snap +++ /dev/null @@ -1,63 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -domain - .concept('Page') - .val('title', 'string') - .vals('widgets', 'Widget') -domain - .concept('Widget') - .val('title', 'string') - .val('color', 'Color') - .val('foo', 'Foo') - .val('bar', 'Bar') -domain - .concept('Widget') - .val('title', 'string') - .val('color', 'Color') -domain - .concept(CONCEPT_NAME) - .val('title') - .vals() -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,9 +1,7 @@ - domain.concept("Page").val("title", "string").vals("widgets", "Widget"); --domain -- .concept("Widget") -- .val("title", "string") -- .val("color", "Color") -- .val("foo", "Foo") -- .val("bar", "Bar"); -+domain.concept("Widget").val("title", "string").val("color", "Color").val( -+ "foo", -+ "Foo", -+).val("bar", "Bar"); - domain.concept("Widget").val("title", "string").val("color", "Color"); - domain.concept(CONCEPT_NAME).val("title").vals(); -``` - -# Output - -```js -domain.concept("Page").val("title", "string").vals("widgets", "Widget"); -domain.concept("Widget").val("title", "string").val("color", "Color").val( - "foo", - "Foo", -).val("bar", "Bar"); -domain.concept("Widget").val("title", "string").val("color", "Color"); -domain.concept(CONCEPT_NAME).val("title").vals(); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-3594.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-3594.js.snap deleted file mode 100644 index f4e05bbeb23..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-3594.js.snap +++ /dev/null @@ -1,53 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const fetched = fetch("/foo"); -fetched - .then(response => response.json()) - .then(json => processThings(json.data.things)); - -let column = new Column(null, conn) - .table(data.table) - .json(data.column); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,6 +1,8 @@ - const fetched = fetch("/foo"); --fetched -- .then((response) => response.json()) -- .then((json) => processThings(json.data.things)); -+fetched.then((response) => response.json()).then( -+ (json) => processThings(json.data.things), -+); - --let column = new Column(null, conn).table(data.table).json(data.column); -+let column = new Column(null, conn) -+ .table(data.table) -+ .json(data.column); -``` - -# Output - -```js -const fetched = fetch("/foo"); -fetched.then((response) => response.json()).then( - (json) => processThings(json.data.things), -); - -let column = new Column(null, conn) - .table(data.table) - .json(data.column); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-4125.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-4125.js.snap index f568ae0a27d..642f3bb8987 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-4125.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/issue-4125.js.snap @@ -164,63 +164,7 @@ var l = base ```diff --- Prettier +++ Rome -@@ -44,7 +44,8 @@ - - // examples from https://github.com/prettier/prettier/issues/1565 - --d3.select("body") -+d3 -+ .select("body") - .selectAll("p") - .data([1, 2, 3]) - .enter() -@@ -67,7 +68,10 @@ - - db.branch( - db.table("users").filter({ email }).count(), -- db.table("users").filter({ email: "a@b.com" }).count(), -+ db -+ .table("users") -+ .filter({ email: "a@b.com" }) -+ .count(), - db.table("users").insert({ email }), - db.table("users").filter({ email }), - ); -@@ -90,39 +94,39 @@ - authorizationToken: data.token, - }).initVerify("foo_container"); - -- fejax -- .ajax({ -- url: "/verification/", -- dataType: "json", -- }) -- .then( -- (data) => { -- this.setState({ isLoading: false }); -- this.initWidget(data); -- }, -- (data) => { -- this.logImpression("foo_fetch_error", data); -- Flash.error(I18n.t("offline_identity.foo_issue")); -- }, -- ); -+ fejax.ajax({ -+ url: "/verification/", -+ dataType: "json", -+ }).then( -+ (data) => { -+ this.setState({ isLoading: false }); -+ this.initWidget(data); -+ }, -+ (data) => { -+ this.logImpression("foo_fetch_error", data); -+ Flash.error(I18n.t("offline_identity.foo_issue")); -+ }, -+ ); - } - - action$ +@@ -111,18 +111,20 @@ .ofType(ActionTypes.SEARCHED_USERS) .map((action) => action.payload.query) .filter((q) => !!q) @@ -252,7 +196,7 @@ var l = base ); window.FooClient.setVars({ -@@ -138,21 +142,32 @@ +@@ -138,10 +140,18 @@ const a1 = x.a(true).b(null).c(123); const a2 = x.d("").e(``).f(g); const a3 = x.d("").e(`${123}`).f(g); @@ -273,24 +217,7 @@ var l = base } } - // should break when call expressions get complex --x.a() -+x -+ .a() - .b([c, [d, [e]]]) - .f(); --x.a() -+x -+ .a() - .b(c(d(e()))) - .f(); --x.a() -+x -+ .a() - .b(`${c(d())}`) - .f(); - -@@ -161,7 +176,4 @@ +@@ -161,7 +171,4 @@ .b() .c(a(a(b(c(d().p).p).p).p)); @@ -350,8 +277,7 @@ function palindrome(a, b) { // examples from https://github.com/prettier/prettier/issues/1565 -d3 - .select("body") +d3.select("body") .selectAll("p") .data([1, 2, 3]) .enter() @@ -374,10 +300,7 @@ something() db.branch( db.table("users").filter({ email }).count(), - db - .table("users") - .filter({ email: "a@b.com" }) - .count(), + db.table("users").filter({ email: "a@b.com" }).count(), db.table("users").insert({ email }), db.table("users").filter({ email }), ); @@ -400,19 +323,21 @@ function HelloWorld() { authorizationToken: data.token, }).initVerify("foo_container"); - fejax.ajax({ - url: "/verification/", - dataType: "json", - }).then( - (data) => { - this.setState({ isLoading: false }); - this.initWidget(data); - }, - (data) => { - this.logImpression("foo_fetch_error", data); - Flash.error(I18n.t("offline_identity.foo_issue")); - }, - ); + fejax + .ajax({ + url: "/verification/", + dataType: "json", + }) + .then( + (data) => { + this.setState({ isLoading: false }); + this.initWidget(data); + }, + (data) => { + this.logImpression("foo_fetch_error", data); + Flash.error(I18n.t("offline_identity.foo_issue")); + }, + ); } action$ @@ -464,16 +389,13 @@ class X { } // should break when call expressions get complex -x - .a() +x.a() .b([c, [d, [e]]]) .f(); -x - .a() +x.a() .b(c(d(e()))) .f(); -x - .a() +x.a() .b(`${c(d())}`) .f(); diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/logical.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/logical.js.snap index a487a31ffa5..7a97dc8e1d5 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/logical.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/logical.js.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: js/method-chain/logical.js --- # Input @@ -30,7 +32,7 @@ const someLongVariableName = (idx( ```diff --- Prettier +++ Rome -@@ -2,13 +2,13 @@ +@@ -2,8 +2,8 @@ idx(this.props, (props) => props.someLongPropertyName) || [] ).map((edge) => edge.node); @@ -40,25 +42,7 @@ const someLongVariableName = (idx( + (tickets) => TicketRecord.createFromSomeLongString(), ); --(veryLongVeryLongVeryLong || e) -- .map((tickets) => TicketRecord.createFromSomeLongString()) -- .filter((obj) => !!obj); -+(veryLongVeryLongVeryLong || e).map( -+ (tickets) => TicketRecord.createFromSomeLongString(), -+).filter((obj) => !!obj); - - ( - veryLongVeryLongVeryLong || -@@ -20,6 +20,6 @@ - veryLongVeryLongVeryLong || - anotherVeryLongVeryLongVeryLong || - veryVeryVeryLongError --) -- .map((tickets) => TicketRecord.createFromSomeLongString()) -- .filter((obj) => !!obj); -+).map((tickets) => TicketRecord.createFromSomeLongString()).filter( -+ (obj) => !!obj, -+); + (veryLongVeryLongVeryLong || e) ``` # Output @@ -72,9 +56,9 @@ const someLongVariableName = ( (tickets) => TicketRecord.createFromSomeLongString(), ); -(veryLongVeryLongVeryLong || e).map( - (tickets) => TicketRecord.createFromSomeLongString(), -).filter((obj) => !!obj); +(veryLongVeryLongVeryLong || e) + .map((tickets) => TicketRecord.createFromSomeLongString()) + .filter((obj) => !!obj); ( veryLongVeryLongVeryLong || @@ -86,9 +70,9 @@ const someLongVariableName = ( veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError -).map((tickets) => TicketRecord.createFromSomeLongString()).filter( - (obj) => !!obj, -); +) + .map((tickets) => TicketRecord.createFromSomeLongString()) + .filter((obj) => !!obj); ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/multiple-members.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/multiple-members.js.snap deleted file mode 100644 index 51a1dc784ae..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/multiple-members.js.snap +++ /dev/null @@ -1,133 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -if (testConfig.ENABLE_ONLINE_TESTS === "true") { - describe("POST /users/me/pet", function() { - it("saves pet", function() { - function assert(pet) { - expect(pet).to.have.property("OwnerAddress").that.deep.equals({ - AddressLine1: "Alexanderstrasse", - AddressLine2: "", - PostalCode: "10999", - Region: "Berlin", - City: "Berlin", - Country: "DE" - }); - } - }); - }); -} - -wrapper.find('SomewhatLongNodeName').prop('longPropFunctionName')().then(function() { - doSomething(); -}); - -wrapper.find('SomewhatLongNodeName').prop('longPropFunctionName')('argument').then(function() { - doSomething(); -}); - -wrapper.find('SomewhatLongNodeName').prop('longPropFunctionName', 'second argument that pushes this group past 80 characters')('argument').then(function() { - doSomething(); -}); - -wrapper.find('SomewhatLongNodeName').prop('longPropFunctionName')('argument', 'second argument that pushes this group past 80 characters').then(function() { - doSomething(); -}); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -2,14 +2,16 @@ - describe("POST /users/me/pet", function () { - it("saves pet", function () { - function assert(pet) { -- expect(pet).to.have.property("OwnerAddress").that.deep.equals({ -- AddressLine1: "Alexanderstrasse", -- AddressLine2: "", -- PostalCode: "10999", -- Region: "Berlin", -- City: "Berlin", -- Country: "DE", -- }); -+ expect(pet).to.have -+ .property("OwnerAddress") -+ .that.deep.equals({ -+ AddressLine1: "Alexanderstrasse", -+ AddressLine2: "", -+ PostalCode: "10999", -+ Region: "Berlin", -+ City: "Berlin", -+ Country: "DE", -+ }); - } - }); - }); -``` - -# Output - -```js -if (testConfig.ENABLE_ONLINE_TESTS === "true") { - describe("POST /users/me/pet", function () { - it("saves pet", function () { - function assert(pet) { - expect(pet).to.have - .property("OwnerAddress") - .that.deep.equals({ - AddressLine1: "Alexanderstrasse", - AddressLine2: "", - PostalCode: "10999", - Region: "Berlin", - City: "Berlin", - Country: "DE", - }); - } - }); - }); -} - -wrapper - .find("SomewhatLongNodeName") - .prop("longPropFunctionName")() - .then(function () { - doSomething(); - }); - -wrapper - .find("SomewhatLongNodeName") - .prop("longPropFunctionName")("argument") - .then(function () { - doSomething(); - }); - -wrapper - .find("SomewhatLongNodeName") - .prop( - "longPropFunctionName", - "second argument that pushes this group past 80 characters", - )("argument") - .then(function () { - doSomething(); - }); - -wrapper - .find("SomewhatLongNodeName") - .prop("longPropFunctionName")( - "argument", - "second argument that pushes this group past 80 characters", - ) - .then(function () { - doSomething(); - }); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/square_0.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/square_0.js.snap deleted file mode 100644 index 6bf85f30612..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/square_0.js.snap +++ /dev/null @@ -1,52 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const version = someLongString - .split('jest version =') - .pop() - .split(EOL)[0] - .trim(); - -const component = find('.org-lclp-edit-copy-url-banner__link')[0] - .getAttribute('href') - .indexOf(this.landingPageLink); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,8 +1,6 @@ --const version = someLongString -- .split("jest version =") -- .pop() -- .split(EOL)[0] -- .trim(); -+const version = someLongString.split("jest version =").pop().split( -+ EOL, -+)[0].trim(); - - const component = find(".org-lclp-edit-copy-url-banner__link")[0] - .getAttribute("href") -``` - -# Output - -```js -const version = someLongString.split("jest version =").pop().split( - EOL, -)[0].trim(); - -const component = find(".org-lclp-edit-copy-url-banner__link")[0] - .getAttribute("href") - .indexOf(this.landingPageLink); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/test.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/test.js.snap index f62128a3728..4b8c0f72f45 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/test.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/test.js.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: js/method-chain/test.js --- # Input @@ -19,12 +21,9 @@ method().then(x => x) ```diff --- Prettier +++ Rome -@@ -1,7 +1,5 @@ - method() -- .then((x) => x) -- ["abc"]((x) => x) -- [abc]((x) => x); -+ .then((x) => x)["abc"]((x) => x)[abc]((x) => x); +@@ -3,5 +3,5 @@ + ["abc"]((x) => x) + [abc]((x) => x); -({}.a().b()); -({}.a().b()); @@ -36,7 +35,9 @@ method().then(x => x) ```js method() - .then((x) => x)["abc"]((x) => x)[abc]((x) => x); + .then((x) => x) + ["abc"]((x) => x) + [abc]((x) => x); ({}).a().b(); ({}).a().b(); diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/this.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/this.js.snap deleted file mode 100644 index 36200454a39..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/method-chain/this.js.snap +++ /dev/null @@ -1,37 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const sel = this.connections - .concat(this.activities.concat(this.operators)) - .filter(x => x.selected); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,3 +1,3 @@ --const sel = this.connections -- .concat(this.activities.concat(this.operators)) -- .filter((x) => x.selected); -+const sel = this.connections.concat( -+ this.activities.concat(this.operators), -+).filter((x) => x.selected); -``` - -# Output - -```js -const sel = this.connections.concat( - this.activities.concat(this.operators), -).filter((x) => x.selected); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/multiparser-css/issue-11797.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/multiparser-css/issue-11797.js.snap index 3133be540b8..90d40d9b454 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/multiparser-css/issue-11797.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/multiparser-css/issue-11797.js.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: js/multiparser-css/issue-11797.js --- # Input @@ -25,12 +27,14 @@ const paragraph3 = css` ```diff --- Prettier +++ Rome -@@ -1,7 +1,6 @@ +@@ -1,7 +1,8 @@ const paragraph1 = css` font-size: 12px; - transform: ${vert ? "translateY" : "translateX"} - (${translation + handleOffset}px); -+ transform: ${vert ? "translateY" : "translateX"}(${translation + handleOffset}px); ++ transform: ${vert ? "translateY" : "translateX"}(${ ++ translation + handleOffset ++}px); `; const paragraph2 = css` @@ -41,7 +45,9 @@ const paragraph3 = css` ```js const paragraph1 = css` font-size: 12px; - transform: ${vert ? "translateY" : "translateX"}(${translation + handleOffset}px); + transform: ${vert ? "translateY" : "translateX"}(${ + translation + handleOffset +}px); `; const paragraph2 = css` @@ -54,8 +60,4 @@ const paragraph3 = css` ``` -# Lines exceeding max width of 80 characters -``` - 3: transform: ${vert ? "translateY" : "translateX"}(${translation + handleOffset}px); -``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/optional-chaining/comments.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/optional-chaining/comments.js.snap deleted file mode 100644 index cee76a51803..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/optional-chaining/comments.js.snap +++ /dev/null @@ -1,148 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: js/optional-chaining/comments.js ---- - -# Input - -```js -function foo() { - return a - .b() - .c() - // Comment - ?.d() -} - -fooBar - .doSomething("Hello World") - .doAnotherThing("Foo", { foo: bar }) - - // App configuration. - .doOneMoreThing(config) - - ?.run(() => console.log("Bar")); - -bigDeal - - .doSomething("Hello World") - - // Hello world - ?.doAnotherThing("Foo", { foo: bar }) - - // App configuration. - .doOneMoreThing(config) - - ?.run(() => console.log("Bar")); - -foo.bar.baz - - ?.doSomething("Hello World") - - // Hello world - .foo.bar.doAnotherThing("Foo", { foo: bar }) - - .doOneMoreThing(config) - ?.bar.run(() => console.log("Bar")); - -(somethingGood ? thisIsIt : maybeNot) - -// Hello world -.doSomething("Hello World") - - ?.doAnotherThing("Foo", { foo: bar }) // Run this - .run(() => console.log("Bar")); // Do this -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -11,38 +11,27 @@ - fooBar - .doSomething("Hello World") - .doAnotherThing("Foo", { foo: bar }) -- - // App configuration. - .doOneMoreThing(config) -- - ?.run(() => console.log("Bar")); - - bigDeal -- - .doSomething("Hello World") -- - // Hello world - ?.doAnotherThing("Foo", { foo: bar }) -- - // App configuration. - .doOneMoreThing(config) -- - ?.run(() => console.log("Bar")); - - foo.bar.baz -- - ?.doSomething("Hello World") -- - // Hello world - .foo.bar.doAnotherThing("Foo", { foo: bar }) -- - .doOneMoreThing(config) - ?.bar.run(() => console.log("Bar")); - - (somethingGood ? thisIsIt : maybeNot) -- - // Hello world - .doSomething("Hello World") -- - ?.doAnotherThing("Foo", { foo: bar }) // Run this - .run(() => console.log("Bar")); // Do this -``` - -# Output - -```js -function foo() { - return ( - a - .b() - .c() - // Comment - ?.d() - ); -} - -fooBar - .doSomething("Hello World") - .doAnotherThing("Foo", { foo: bar }) - // App configuration. - .doOneMoreThing(config) - ?.run(() => console.log("Bar")); - -bigDeal - .doSomething("Hello World") - // Hello world - ?.doAnotherThing("Foo", { foo: bar }) - // App configuration. - .doOneMoreThing(config) - ?.run(() => console.log("Bar")); - -foo.bar.baz - ?.doSomething("Hello World") - // Hello world - .foo.bar.doAnotherThing("Foo", { foo: bar }) - .doOneMoreThing(config) - ?.bar.run(() => console.log("Bar")); - -(somethingGood ? thisIsIt : maybeNot) - // Hello world - .doSomething("Hello World") - ?.doAnotherThing("Foo", { foo: bar }) // Run this - .run(() => console.log("Bar")); // Do this -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/preserve-line/member-chain.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/preserve-line/member-chain.js.snap deleted file mode 100644 index 2f0a975237c..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/preserve-line/member-chain.js.snap +++ /dev/null @@ -1,191 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -fooBar.doSomething('Hello World').doAnotherThing('Foo', { foo: bar }) - - // App configuration. - .doOneMoreThing(config) - - .run(() => console.log('Bar')); - -bigDeal - - .doSomething('Hello World') - - // Hello world - .doAnotherThing('Foo', { foo: bar }) - - // App configuration. - .doOneMoreThing(config) - - .run(() => console.log('Bar')); - - -foo.bar.baz - - .doSomething('Hello World') - - // Hello world - .foo.bar.doAnotherThing('Foo', { foo: bar }) - - .doOneMoreThing(config) - .bar.run(() => console.log('Bar')); - -( - somethingGood ? thisIsIt : maybeNot -) - - // Hello world - .doSomething('Hello World') - - .doAnotherThing('Foo', { foo: bar }) // Run this - .run(() => console.log('Bar')); // Do this - -helloWorld - - .text() - - .then(t => t); - -(veryLongVeryLongVeryLong || - anotherVeryLongVeryLongVeryLong || - veryVeryVeryLongError -) - - .map(tickets => TicketRecord.createFromSomeLongString()) - - .filter(obj => !!obj); - -const sel = this.connections - - .concat(this.activities.concat(this.operators)) - .filter(x => x.selected); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,59 +1,41 @@ - fooBar - .doSomething("Hello World") - .doAnotherThing("Foo", { foo: bar }) -- - // App configuration. - .doOneMoreThing(config) -- - .run(() => console.log("Bar")); - - bigDeal -- - .doSomething("Hello World") -- - // Hello world - .doAnotherThing("Foo", { foo: bar }) -- - // App configuration. - .doOneMoreThing(config) -- - .run(() => console.log("Bar")); - - foo.bar.baz -- - .doSomething("Hello World") -- - // Hello world - .foo.bar.doAnotherThing("Foo", { foo: bar }) -- - .doOneMoreThing(config) - .bar.run(() => console.log("Bar")); - - (somethingGood ? thisIsIt : maybeNot) -- - // Hello world - .doSomething("Hello World") -- - .doAnotherThing("Foo", { foo: bar }) // Run this - .run(() => console.log("Bar")); // Do this - --helloWorld -- -- .text() -- -- .then((t) => t); -+helloWorld.text().then((t) => t); - - ( - veryLongVeryLongVeryLong || - anotherVeryLongVeryLongVeryLong || - veryVeryVeryLongError --) -+).map((tickets) => TicketRecord.createFromSomeLongString()).filter( -+ (obj) => !!obj, -+); - -- .map((tickets) => TicketRecord.createFromSomeLongString()) -- -- .filter((obj) => !!obj); -- --const sel = this.connections -- -- .concat(this.activities.concat(this.operators)) -- .filter((x) => x.selected); -+const sel = this.connections.concat( -+ this.activities.concat(this.operators), -+).filter((x) => x.selected); -``` - -# Output - -```js -fooBar - .doSomething("Hello World") - .doAnotherThing("Foo", { foo: bar }) - // App configuration. - .doOneMoreThing(config) - .run(() => console.log("Bar")); - -bigDeal - .doSomething("Hello World") - // Hello world - .doAnotherThing("Foo", { foo: bar }) - // App configuration. - .doOneMoreThing(config) - .run(() => console.log("Bar")); - -foo.bar.baz - .doSomething("Hello World") - // Hello world - .foo.bar.doAnotherThing("Foo", { foo: bar }) - .doOneMoreThing(config) - .bar.run(() => console.log("Bar")); - -(somethingGood ? thisIsIt : maybeNot) - // Hello world - .doSomething("Hello World") - .doAnotherThing("Foo", { foo: bar }) // Run this - .run(() => console.log("Bar")); // Do this - -helloWorld.text().then((t) => t); - -( - veryLongVeryLongVeryLong || - anotherVeryLongVeryLongVeryLong || - veryVeryVeryLongError -).map((tickets) => TicketRecord.createFromSomeLongString()).filter( - (obj) => !!obj, -); - -const sel = this.connections.concat( - this.activities.concat(this.operators), -).filter((x) => x.selected); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/require/require.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/require/require.js.snap deleted file mode 100644 index 8e656bc6f83..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/require/require.js.snap +++ /dev/null @@ -1,75 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -const { one, two, three, four, five, six, seven, eight, nine, ten } = require('./my-utils'); -const { one1, two1, three1, four1, five1, six1, seven1, eight1, nine1, ten1, eleven1 } = require('./my-utils'); - -const MyReallyExtrememlyLongModuleName = require('MyReallyExtrememlyLongModuleName'); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,15 +1,6 @@ --const { -- one, -- two, -- three, -- four, -- five, -- six, -- seven, -- eight, -- nine, -- ten, --} = require("./my-utils"); -+const { one, two, three, four, five, six, seven, eight, nine, ten } = require( -+ "./my-utils", -+); - const { - one1, - two1, -@@ -24,4 +15,6 @@ - eleven1, - } = require("./my-utils"); - --const MyReallyExtrememlyLongModuleName = require("MyReallyExtrememlyLongModuleName"); -+const MyReallyExtrememlyLongModuleName = require( -+ "MyReallyExtrememlyLongModuleName", -+); -``` - -# Output - -```js -const { one, two, three, four, five, six, seven, eight, nine, ten } = require( - "./my-utils", -); -const { - one1, - two1, - three1, - four1, - five1, - six1, - seven1, - eight1, - nine1, - ten1, - eleven1, -} = require("./my-utils"); - -const MyReallyExtrememlyLongModuleName = require( - "MyReallyExtrememlyLongModuleName", -); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/template-literals/styled-jsx-with-expressions.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/template-literals/styled-jsx-with-expressions.js.snap index cd5d8e7ba17..03b07841923 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/js/template-literals/styled-jsx-with-expressions.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/js/template-literals/styled-jsx-with-expressions.js.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: js/template-literals/styled-jsx-with-expressions.js --- # Input @@ -96,7 +98,7 @@ source: crates/rome_js_formatter/tests/prettier_tests.rs } @font-face { ${expr} -@@ -30,13 +30,12 @@ +@@ -30,13 +30,13 @@ ; ``` @@ -155,14 +158,11 @@ source: crates/rome_js_formatter/tests/prettier_tests.rs ; ``` -# Lines exceeding max width of 80 characters -``` - 39: animation: 3s ease-in 1s ${(foo) => foo.getIterations()} reverse both paused slidein; -``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/template/call.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/template/call.js.snap deleted file mode 100644 index fa5cde20fe2..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/template/call.js.snap +++ /dev/null @@ -1,73 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -insertRule(`*, *:before, *:after { - box-sizing: inherit; -}`); - -insertRule`*, *:before, *:after { - box-sizing: inherit; -}`; - -new Error(formatErrorMessage` - This a really bad error. - Which has more than one line. -`); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,12 +1,16 @@ --insertRule(`*, *:before, *:after { -+insertRule( -+ `*, *:before, *:after { - box-sizing: inherit; --}`); -+}`, -+); - - insertRule`*, *:before, *:after { - box-sizing: inherit; - }`; - --new Error(formatErrorMessage` -+new Error( -+ formatErrorMessage` - This a really bad error. - Which has more than one line. --`); -+`, -+); -``` - -# Output - -```js -insertRule( - `*, *:before, *:after { - box-sizing: inherit; -}`, -); - -insertRule`*, *:before, *:after { - box-sizing: inherit; -}`; - -new Error( - formatErrorMessage` - This a really bad error. - Which has more than one line. -`, -); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/template/inline.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/template/inline.js.snap deleted file mode 100644 index 5199d4b49c9..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/template/inline.js.snap +++ /dev/null @@ -1,99 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -this._pipe.write(`\n\n Pattern matches ${total} ${pluralizeTest}`); -this._pipe.write( - `\n\n Pattern matches ${total} ${pluralizeTest}` -); -this._pipe - .write( - `\n\n Pattern matches ${total} ${pluralizeTest}` - ); - -this._pipe.write(`\n\n Pattern matches ${total} ${pluralizeTest} but that's long`); - -this._pipe.write( - `\n\n Pattern matches ${total} ${pluralizeTest} but that's long` -); - -this._pipe.write(` - \n\n Pattern matches ${total} ${pluralizeTest} but that's long -`); - - -() => ` - a -`; - -() => - ` - a - `; - - -// https://github.com/prettier/prettier/issues/5529 -editTitle += `${iconHTML({ class: "reply-to-glyph" })}`; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -10,9 +10,11 @@ - `\n\n Pattern matches ${total} ${pluralizeTest} but that's long`, - ); - --this._pipe.write(` -+this._pipe.write( -+ ` - \n\n Pattern matches ${total} ${pluralizeTest} but that's long --`); -+`, -+); - - () => ` - a -``` - -# Output - -```js -this._pipe.write(`\n\n Pattern matches ${total} ${pluralizeTest}`); -this._pipe.write(`\n\n Pattern matches ${total} ${pluralizeTest}`); -this._pipe.write(`\n\n Pattern matches ${total} ${pluralizeTest}`); - -this._pipe.write( - `\n\n Pattern matches ${total} ${pluralizeTest} but that's long`, -); - -this._pipe.write( - `\n\n Pattern matches ${total} ${pluralizeTest} but that's long`, -); - -this._pipe.write( - ` - \n\n Pattern matches ${total} ${pluralizeTest} but that's long -`, -); - -() => ` - a -`; - -() => - ` - a - `; - -// https://github.com/prettier/prettier/issues/5529 -editTitle += `${iconHTML({ class: "reply-to-glyph" })}`; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/js/ternaries/indent-after-paren.js.snap b/crates/rome_js_formatter/tests/specs/prettier/js/ternaries/indent-after-paren.js.snap deleted file mode 100644 index 5117448408d..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/js/ternaries/indent-after-paren.js.snap +++ /dev/null @@ -1,675 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -foo7 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)[Fooooooooooo]; - -foo8 = (condition ? firstValue : secondValue)[SomeType]; - -const foo9 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)[Fooooooooooo]; - -function foo10() { - return (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)[Fooooooooooo]; -} - -function foo11() { - throw (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)[Fooooooooooo]; -} - -function foo12() { - void (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)[Fooooooooooo]; -} - -foo13 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -).Fooooooooooo.Fooooooooooo; - -foo14 = (condition ? firstValue : secondValue)[SomeType]; - -const foo15 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -).Fooooooooooo.Fooooooooooo; - -function foo16() { - return (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; -} - -function foo17() { - throw (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; -} - -function foo18() { - void (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; -} - -foo19 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)(Fooooooooooo.Fooooooooooo); - -foo20 = (condition ? firstValue : secondValue)[SomeType]; - -const foo21 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)(Fooooooooooo.Fooooooooooo); - -function foo22() { - return (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)(Fooooooooooo.Fooooooooooo); -} - -function foo23() { - throw (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)(Fooooooooooo.Fooooooooooo); -} - -function foo24() { - void (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)(Fooooooooooo.Fooooooooooo); -} - -foo25 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.(Fooooooooooo.Fooooooooooo); - -foo26 = (condition ? firstValue : secondValue)[SomeType]; - -const foo27 = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.(Fooooooooooo.Fooooooooooo); - -function foo28() { - return (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.(Fooooooooooo.Fooooooooooo); -} - -function foo29() { - throw (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.(Fooooooooooo.Fooooooooooo); -} - -function foo30() { - void (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.(Fooooooooooo.Fooooooooooo); -} - -function* foo31() { - yield (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.(Fooooooooooo.Fooooooooooo); - yield (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)(Fooooooooooo.Fooooooooooo); - yield (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz).Fooooooooooo.Fooooooooooo; - yield (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)[Fooooooooooo.Fooooooooooo]; -} - -const foo32 = new (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)(Fooooooooooo.Fooooooooooo); - -function foo33() { - return new (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -function foo34() { - throw new (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -function foo35() { - void new (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -foo36 = new (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)(Fooooooooooo.Fooooooooooo); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - ((glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)[AnnularCooeedSplicesWalksWayWay]); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - ((glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)[AnnularCooeedSplicesWalksWayWay]); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - ((glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol).Fooooooooooo.Fooooooooooo); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - ((glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol).Fooooooooooo.Fooooooooooo); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - ((glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)(Fooooooooooo.Fooooooooooo)); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - ((glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)(Fooooooooooo.Fooooooooooo)); - -bifornCringerMoshedPerplexSawder = ( - glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).annularCooeedSplicesWalksWayWay - .annularCooeedSplicesWalksWayWay(annularCooeedSplicesWalksWayWay) - .annularCooeedSplicesWalksWayWay(); - -foo = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)?.()?.()?.(); - -foo = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)()()(); - -foo = - foo.bar.baz[ - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ]; - -const decorated = (arg, ignoreRequestError) => { - return ( - typeof arg === "string" || - (arg && arg.valueOf && typeof arg.valueOf() === "string") - ? $delegate(arg, ignoreRequestError) - : handleAsyncOperations(arg, ignoreRequestError) - ).foo(); -}; - -bifornCringerMoshedPerplexSawder = fn( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -); - -fn( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -) - -bifornCringerMoshedPerplexSawder = fn?.( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -); - -fn?.( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -) - -bifornCringerMoshedPerplexSawder = - fn[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop - ]; - -fn[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -]; - -bifornCringerMoshedPerplexSawder = - fn?.[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop - ]; - -fn?.[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -]; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -255,9 +255,9 @@ - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol --).annularCooeedSplicesWalksWayWay -- .annularCooeedSplicesWalksWayWay(annularCooeedSplicesWalksWayWay) -- .annularCooeedSplicesWalksWayWay(); -+).annularCooeedSplicesWalksWayWay.annularCooeedSplicesWalksWayWay( -+ annularCooeedSplicesWalksWayWay, -+).annularCooeedSplicesWalksWayWay(); - - foo = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond -``` - -# Output - -```js -foo7 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)[Fooooooooooo]; - -foo8 = (condition ? firstValue : secondValue)[SomeType]; - -const foo9 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)[Fooooooooooo]; - -function foo10() { - return ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )[Fooooooooooo]; -} - -function foo11() { - throw ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )[Fooooooooooo]; -} - -function foo12() { - void ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )[Fooooooooooo]; -} - -foo13 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -).Fooooooooooo.Fooooooooooo; - -foo14 = (condition ? firstValue : secondValue)[SomeType]; - -const foo15 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -).Fooooooooooo.Fooooooooooo; - -function foo16() { - return ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; -} - -function foo17() { - throw ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; -} - -function foo18() { - void ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; -} - -foo19 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)(Fooooooooooo.Fooooooooooo); - -foo20 = (condition ? firstValue : secondValue)[SomeType]; - -const foo21 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)(Fooooooooooo.Fooooooooooo); - -function foo22() { - return ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -function foo23() { - throw ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -function foo24() { - void ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -foo25 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)?.(Fooooooooooo.Fooooooooooo); - -foo26 = (condition ? firstValue : secondValue)[SomeType]; - -const foo27 = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)?.(Fooooooooooo.Fooooooooooo); - -function foo28() { - return ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )?.(Fooooooooooo.Fooooooooooo); -} - -function foo29() { - throw ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )?.(Fooooooooooo.Fooooooooooo); -} - -function foo30() { - void ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )?.(Fooooooooooo.Fooooooooooo); -} - -function* foo31() { - yield ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )?.(Fooooooooooo.Fooooooooooo); - yield ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); - yield ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ).Fooooooooooo.Fooooooooooo; - yield ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )[Fooooooooooo.Fooooooooooo]; -} - -const foo32 = new ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)(Fooooooooooo.Fooooooooooo); - -function foo33() { - return new ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -function foo34() { - throw new ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -function foo35() { - void new ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - )(Fooooooooooo.Fooooooooooo); -} - -foo36 = new ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)(Fooooooooooo.Fooooooooooo); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)[AnnularCooeedSplicesWalksWayWay]; - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)[AnnularCooeedSplicesWalksWayWay]; - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).Fooooooooooo.Fooooooooooo; - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).Fooooooooooo.Fooooooooooo; - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)(Fooooooooooo.Fooooooooooo); - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol)(Fooooooooooo.Fooooooooooo); - -bifornCringerMoshedPerplexSawder = ( - glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol -).annularCooeedSplicesWalksWayWay.annularCooeedSplicesWalksWayWay( - annularCooeedSplicesWalksWayWay, -).annularCooeedSplicesWalksWayWay(); - -foo = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)?.()?.()?.(); - -foo = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)()()(); - -foo = - foo.bar.baz[ - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz - ]; - -const decorated = (arg, ignoreRequestError) => { - return ( - typeof arg === "string" || - (arg && arg.valueOf && typeof arg.valueOf() === "string") - ? $delegate(arg, ignoreRequestError) - : handleAsyncOperations(arg, ignoreRequestError) - ).foo(); -}; - -bifornCringerMoshedPerplexSawder = fn( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop, -); - -fn( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop, -); - -bifornCringerMoshedPerplexSawder = fn?.( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop, -); - -fn?.( - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop, -); - -bifornCringerMoshedPerplexSawder = - fn[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop - ]; - -fn[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -]; - -bifornCringerMoshedPerplexSawder = - fn?.[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop - ]; - -fn?.[ - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).prop -]; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/cast/generic-cast.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/cast/generic-cast.ts.snap deleted file mode 100644 index 88a3c075048..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/cast/generic-cast.ts.snap +++ /dev/null @@ -1,321 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: typescript/cast/generic-cast.ts ---- - -# Input - -```js -// https://github.com/prettier/prettier/issues/4171 -function y() { - - const fits = >fits(); - const fitsObjLiteral = >{ a: "test" }; - const fitsArrayLiteral = >["test", "test2"] - - const breakAfterCast = >someExistingConfigMap.mergeDeep(fallbackOpts); - - const stillTooLong = >someExistingConfigMap.mergeDeep(fallbackOptions); - - const stillTooLong2 = | undefined>someExistingConfigMap.mergeDeep(fallbackOptions); - - const stillTooLong3 = >someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2)); - - const stillTooLong4 = | undefined>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2)); - - const testObjLiteral = >{ property1: "myPropertyVal" }; - - const testObjLiteral2 = >{ property1: "myPropertyVal" }; - - const testArrayLiteral = >["first", "second", "third"]; - - const testArrayLiteral2 = >["first", "second", "third"]; - - const insideFuncCall = myFunc(param1, >param2, param3) -} - -// https://github.com/prettier/prettier/issues/4168 -function x() { - const fits = | undefined>(permissions)[type]; - const fitsObjLiteral = | undefined>{ a: "test" }; - const fitsArrayLiteral = | undefined>["t1", "t2"]; - - const breakAfterCast = | undefined>(permissions)[receiverType]; - - const stillTooLong = | undefined | number | string | boolean>(permissions)[receiverType]; - - const stillTooLong2 = | undefined | number | string | boolean | null | never>(permissions)[receiverType]; - - const stillTooLong3 = | undefined>(permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName]; - - const stillTooLong4 = | undefined | number | string | boolean | null | never>(permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName]; - - const testObjLiteral = | undefined>{ prop1: "myPropVal" }; - - const testObjLiteral2 = | undefined | number | string | boolean | null | never | object>{ prop1: "myPropVal" }; - - const testArrayLiteral = | undefined>["first", "second", "third"]; - - const testArrayLiteral2 = | undefined | number | string | boolean | null | never | object>["first", "second", "third"]; - - const insideFuncCall = myFunc(param1, | undefined>param2, param3) -} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -4,9 +4,9 @@ - const fitsObjLiteral = >{ a: "test" }; - const fitsArrayLiteral = >["test", "test2"]; - -- const breakAfterCast = >( -- someExistingConfigMap.mergeDeep(fallbackOpts) -- ); -+ const breakAfterCast = < -+ Immutable.Map -+ >someExistingConfigMap.mergeDeep(fallbackOpts); - - const stillTooLong = < - Immutable.Map< -@@ -37,10 +37,8 @@ - | undefined - >someExistingConfigMap.mergeDeep(fallbackOptions); - -- const stillTooLong3 = >( -- someExistingConfigMap.mergeDeep( -- fallbackOptions.someMethodWithLongName(param1, param2), -- ) -+ const stillTooLong3 = >someExistingConfigMap.mergeDeep( -+ fallbackOptions.someMethodWithLongName(param1, param2), - ); - - const stillTooLong4 = < -@@ -111,9 +109,9 @@ - const fitsObjLiteral = | undefined>{ a: "test" }; - const fitsArrayLiteral = | undefined>["t1", "t2"]; - -- const breakAfterCast = | undefined>( -- (permissions)[receiverType] -- ); -+ const breakAfterCast = | undefined>(< -+ any -+ >permissions)[receiverType]; - - const stillTooLong = < - PermissionsChecker | undefined | number | string | boolean -@@ -129,11 +127,11 @@ - | never - >(permissions)[receiverType]; - -- const stillTooLong3 = | undefined>( -- (permissions.someMethodWithLongName(parameter1, parameter2))[ -- receiverTypeLongName -- ] -- ); -+ const stillTooLong3 = | undefined>(< -+ any -+ >permissions.someMethodWithLongName(parameter1, parameter2))[ -+ receiverTypeLongName -+ ]; - - const stillTooLong4 = < - | PermissionsChecker -``` - -# Output - -```js -// https://github.com/prettier/prettier/issues/4171 -function y() { - const fits = >fits(); - const fitsObjLiteral = >{ a: "test" }; - const fitsArrayLiteral = >["test", "test2"]; - - const breakAfterCast = < - Immutable.Map - >someExistingConfigMap.mergeDeep(fallbackOpts); - - const stillTooLong = < - Immutable.Map< - string, - boolean, - number, - object, - null, - undefined, - any, - void, - never - > - >someExistingConfigMap.mergeDeep(fallbackOptions); - - const stillTooLong2 = < - | Immutable.Map< - string, - boolean, - number, - object, - null, - undefined, - any, - void, - never - > - | undefined - >someExistingConfigMap.mergeDeep(fallbackOptions); - - const stillTooLong3 = >someExistingConfigMap.mergeDeep( - fallbackOptions.someMethodWithLongName(param1, param2), - ); - - const stillTooLong4 = < - | Immutable.Map< - string, - boolean, - number, - object, - null, - undefined, - any, - void, - never - > - | undefined - >someExistingConfigMap.mergeDeep( - fallbackOptions.someMethodWithLongName(param1, param2), - ); - - const testObjLiteral = >{ - property1: "myPropertyVal", - }; - - const testObjLiteral2 = < - Immutable.Map< - string, - any, - number, - boolean, - object, - null, - undefined, - never, - "extra long" - > - >{ property1: "myPropertyVal" }; - - const testArrayLiteral = >[ - "first", - "second", - "third", - ]; - - const testArrayLiteral2 = < - Immutable.Map< - string, - any, - number, - boolean, - object, - null, - undefined, - never, - "extra long" - > - >["first", "second", "third"]; - - const insideFuncCall = myFunc( - param1, - >param2, - param3, - ); -} - -// https://github.com/prettier/prettier/issues/4168 -function x() { - const fits = | undefined>(permissions)[type]; - const fitsObjLiteral = | undefined>{ a: "test" }; - const fitsArrayLiteral = | undefined>["t1", "t2"]; - - const breakAfterCast = | undefined>(< - any - >permissions)[receiverType]; - - const stillTooLong = < - PermissionsChecker | undefined | number | string | boolean - >(permissions)[receiverType]; - - const stillTooLong2 = < - | PermissionsChecker - | undefined - | number - | string - | boolean - | null - | never - >(permissions)[receiverType]; - - const stillTooLong3 = | undefined>(< - any - >permissions.someMethodWithLongName(parameter1, parameter2))[ - receiverTypeLongName - ]; - - const stillTooLong4 = < - | PermissionsChecker - | undefined - | number - | string - | boolean - | null - | never - >(permissions.someMethodWithLongName(parameter1, parameter2))[ - receiverTypeLongName - ]; - - const testObjLiteral = | undefined>{ - prop1: "myPropVal", - }; - - const testObjLiteral2 = < - | PermissionsChecker - | undefined - | number - | string - | boolean - | null - | never - | object - >{ prop1: "myPropVal" }; - - const testArrayLiteral = | undefined>[ - "first", - "second", - "third", - ]; - - const testArrayLiteral2 = < - | PermissionsChecker - | undefined - | number - | string - | boolean - | null - | never - | object - >["first", "second", "third"]; - - const insideFuncCall = myFunc( - param1, - | undefined>param2, - param3, - ); -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap deleted file mode 100644 index 57957fc60a4..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap +++ /dev/null @@ -1,87 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: typescript/custom/typeParameters/variables.ts ---- - -# Input - -```js -const foo: SomeThing = func(); -const bar: SomeThing = func(); -const fooo: SomeThing<{ [P in "x" | "y"]: number }> = func(); -const baar: SomeThing = func(); -const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaaaaaaaar: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaar: SomeThing<{ [P in "x" | "y"]: number }> = looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaaar: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const isAnySuccessfulAttempt$: Observable = this._quizService.isAnySuccessfulAttempt$().pipe( - tap((isAnySuccessfulAttempt: boolean) => { - this.isAnySuccessfulAttempt = isAnySuccessfulAttempt; - }), -); -const isAnySuccessfulAttempt2$: Observable = this._someMethodWithLongName(); -const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -10,9 +10,8 @@ - looooooooooooooooooooooooooooooongNameFunc(); - const baaaaaaaaaaaaaaaar: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); --const isAnySuccessfulAttempt$: Observable = this._quizService -- .isAnySuccessfulAttempt$() -- .pipe( -+const isAnySuccessfulAttempt$: Observable = -+ this._quizService.isAnySuccessfulAttempt$().pipe( - tap((isAnySuccessfulAttempt: boolean) => { - this.isAnySuccessfulAttempt = isAnySuccessfulAttempt; - }), -``` - -# Output - -```js -const foo: SomeThing = func(); -const bar: SomeThing = func(); -const fooo: SomeThing<{ [P in "x" | "y"]: number }> = func(); -const baar: SomeThing = func(); -const fooooooooooooooo: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaaaaaaaar: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaar: SomeThing<{ [P in "x" | "y"]: number }> = - looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaaar: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const isAnySuccessfulAttempt$: Observable = - this._quizService.isAnySuccessfulAttempt$().pipe( - tap((isAnySuccessfulAttempt: boolean) => { - this.isAnySuccessfulAttempt = isAnySuccessfulAttempt; - }), - ); -const isAnySuccessfulAttempt2$: Observable = - this._someMethodWithLongName(); -const fooooooooooooooo: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -const fooooooooooooooo: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/ternaries/indent.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/ternaries/indent.ts.snap deleted file mode 100644 index a448b013054..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/ternaries/indent.ts.snap +++ /dev/null @@ -1,160 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -foo = (callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression; - -foo = (callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression; - -bifornCringerMoshedPerplexSawder = (glimseGlyphsHazardNoopsTieTie === 0 && -kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol -).annularCooeedSplicesWalksWayWay - .annularCooeedSplicesWalksWayWay(annularCooeedSplicesWalksWayWay)! - .annularCooeedSplicesWalksWayWay(); - -foo = (callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression!; - -foo = (callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression!; - -bifornCringerMoshedPerplexSawder = (glimseGlyphsHazardNoopsTieTie === 0 && -kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol -).annularCooeedSplicesWalksWayWay - .annularCooeedSplicesWalksWayWay(annularCooeedSplicesWalksWayWay)! - .annularCooeedSplicesWalksWayWay()!; - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).Foo!.foo; - -foo = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)!; - -foo = (coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz)!!!!!; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -15,9 +15,9 @@ - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol --).annularCooeedSplicesWalksWayWay -- .annularCooeedSplicesWalksWayWay(annularCooeedSplicesWalksWayWay)! -- .annularCooeedSplicesWalksWayWay(); -+).annularCooeedSplicesWalksWayWay.annularCooeedSplicesWalksWayWay( -+ annularCooeedSplicesWalksWayWay, -+)!.annularCooeedSplicesWalksWayWay(); - - foo = ( - callNode.parent?.type === AST_NODE_TYPES.ChainExpression -@@ -36,9 +36,9 @@ - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol --).annularCooeedSplicesWalksWayWay -- .annularCooeedSplicesWalksWayWay(annularCooeedSplicesWalksWayWay)! -- .annularCooeedSplicesWalksWayWay()!; -+).annularCooeedSplicesWalksWayWay.annularCooeedSplicesWalksWayWay( -+ annularCooeedSplicesWalksWayWay, -+)!.annularCooeedSplicesWalksWayWay()!; - - bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + -``` - -# Output - -```js -foo = ( - callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression; - -foo = ( - callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression; - -bifornCringerMoshedPerplexSawder = ( - glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol -).annularCooeedSplicesWalksWayWay.annularCooeedSplicesWalksWayWay( - annularCooeedSplicesWalksWayWay, -)!.annularCooeedSplicesWalksWayWay(); - -foo = ( - callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression!; - -foo = ( - callNode.parent?.type === AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent -).TSESTree!.BinaryExpression!; - -bifornCringerMoshedPerplexSawder = ( - glimseGlyphsHazardNoopsTieTie === 0 && - kochabCooieGameOnOboleUnweave === Math.PI - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol -).annularCooeedSplicesWalksWayWay.annularCooeedSplicesWalksWayWay( - annularCooeedSplicesWalksWayWay, -)!.annularCooeedSplicesWalksWayWay()!; - -bifornCringerMoshedPerplexSawder = - askTrovenaBeenaDependsRowans + - (glimseGlyphsHazardNoopsTieTie === 0 - ? averredBathersBoxroomBuggyNurl - : anodyneCondosMalateOverateRetinol - ).Foo!.foo; - -foo = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)!; - -foo = ( - coooooooooooooooooooooooooooooooooooooooooooooooooooond - ? baaaaaaaaaaaaaaaaaaaaar - : baaaaaaaaaaaaaaaaaaaaaz -)!!!!!; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/typeparams/class-method.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/typeparams/class-method.ts.snap index a98f975cc32..67d479287b2 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/typeparams/class-method.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/typeparams/class-method.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/typeparams/class-method.ts --- # Input @@ -110,21 +112,7 @@ const appIDs = createSelector( ```diff --- Prettier +++ Rome -@@ -54,15 +54,19 @@ - export class Thing8 implements OtherThing { - do: (type: Type) => Provider = memoize( - (type: ObjectType) => -- >( -- type.doSomething(withArgs, soIt, does, not, fit).extraCall() -- ), -+ >type.doSomething( -+ withArgs, -+ soIt, -+ does, -+ not, -+ fit, -+ ).extraCall(), - ); +@@ -61,8 +61,8 @@ } export class Thing9 implements OtherThing { @@ -135,23 +123,6 @@ const appIDs = createSelector( ); } -@@ -143,9 +147,13 @@ - - export class Thing19 implements OtherThing { - do: (type: Type) => Provider = memoize(function (type: ObjectType) { -- return >( -- type.doSomething(withArgs, soIt, does, not, fit).extraCall() -- ); -+ return >type.doSomething( -+ withArgs, -+ soIt, -+ does, -+ not, -+ fit, -+ ).extraCall(); - }); - } - ``` # Output @@ -213,13 +184,9 @@ export class Thing7 implements OtherThing { export class Thing8 implements OtherThing { do: (type: Type) => Provider = memoize( (type: ObjectType) => - >type.doSomething( - withArgs, - soIt, - does, - not, - fit, - ).extraCall(), + >( + type.doSomething(withArgs, soIt, does, not, fit).extraCall() + ), ); } @@ -306,13 +273,9 @@ export class Thing18 implements OtherThing { export class Thing19 implements OtherThing { do: (type: Type) => Provider = memoize(function (type: ObjectType) { - return >type.doSomething( - withArgs, - soIt, - does, - not, - fit, - ).extraCall(); + return >( + type.doSomething(withArgs, soIt, does, not, fit).extraCall() + ); }); } diff --git a/editors/vscode/src/commands/syntaxTree.ts b/editors/vscode/src/commands/syntaxTree.ts index 17763a1cc2f..0931af91b55 100644 --- a/editors/vscode/src/commands/syntaxTree.ts +++ b/editors/vscode/src/commands/syntaxTree.ts @@ -92,16 +92,14 @@ class SyntaxTreeProvider }; // send request to the server and store its content in the cache if successful - return this.session.client.sendRequest( - syntaxTreeRequest, - params, - token, - ).then((result) => { - const document = new SyntaxTreeDocument(uri, result); - this.documents.set(documentUri, document); - - return document.value; - }); + return this.session.client + .sendRequest(syntaxTreeRequest, params, token) + .then((result) => { + const document = new SyntaxTreeDocument(uri, result); + this.documents.set(documentUri, document); + + return document.value; + }); } dispose(): any { diff --git a/npm/backend-jsonrpc/src/command.ts b/npm/backend-jsonrpc/src/command.ts index 06b1edeb735..bc45faf27f7 100644 --- a/npm/backend-jsonrpc/src/command.ts +++ b/npm/backend-jsonrpc/src/command.ts @@ -1,6 +1,6 @@ /** * Gets the path of the Rome binary for the current platform - * + * * @returns Filesystem path to the binary, or null if no prebuilt distribution exists for the current platform */ export function getCommand(): string | null { diff --git a/npm/backend-jsonrpc/src/index.ts b/npm/backend-jsonrpc/src/index.ts index fa10aa17c4b..891221669d2 100644 --- a/npm/backend-jsonrpc/src/index.ts +++ b/npm/backend-jsonrpc/src/index.ts @@ -1,12 +1,16 @@ import { getCommand } from "./command"; import { createSocket } from "./socket"; import { Transport } from "./transport"; -import { createWorkspace as wrapTransport, type Workspace, type RomePath } from "./workspace"; +import { + createWorkspace as wrapTransport, + type Workspace, + type RomePath, +} from "./workspace"; /** * Create an instance of the Workspace client connected to a remote daemon * instance through the JSON-RPC protocol - * + * * @returns A Workspace client, or null if the underlying platform is not supported */ export async function createWorkspace(): Promise { @@ -22,7 +26,7 @@ export async function createWorkspace(): Promise { * Create an instance of the Workspace client connected to a remote daemon * instance through the JSON-RPC protocol, using the provided command to spawn * the daemon if necessary - * + * * @param command Path to the Rome binary distribution * @returns A Workspace client, or null if the underlying platform is not supported */ diff --git a/npm/backend-jsonrpc/src/socket.ts b/npm/backend-jsonrpc/src/socket.ts index b5204d5cf7e..b5081619ae3 100644 --- a/npm/backend-jsonrpc/src/socket.ts +++ b/npm/backend-jsonrpc/src/socket.ts @@ -18,7 +18,11 @@ function getSocket(command: string): Promise { if (code === 0) { resolve(pipeName.trimEnd()); } else { - reject(new Error(`Command '${command} __print_socket' exited with code ${code}`)); + reject( + new Error( + `Command '${command} __print_socket' exited with code ${code}`, + ), + ); } }); }); diff --git a/npm/backend-jsonrpc/src/transport.ts b/npm/backend-jsonrpc/src/transport.ts index 69bd8c09128..c1f070d5f22 100644 --- a/npm/backend-jsonrpc/src/transport.ts +++ b/npm/backend-jsonrpc/src/transport.ts @@ -59,15 +59,15 @@ function isJsonRpcNotification( type JsonRpcResponse = | { - jsonrpc: "2.0"; - id: number; - result: any; - } + jsonrpc: "2.0"; + id: number; + result: any; + } | { - jsonrpc: "2.0"; - id: number; - error: any; - }; + jsonrpc: "2.0"; + id: number; + error: any; + }; function isJsonRpcResponse( message: JsonRpcMessage, @@ -118,7 +118,7 @@ export class Transport { /** * Send a request to the remote server - * + * * @param method Name of the remote method to call * @param params Parameters object the remote method should be called with * @return Promise resolving with the value returned by the remote method, or rejecting with an RPC error if the remote call failed @@ -138,7 +138,7 @@ export class Transport { /** * Send a notification message to the remote server - * + * * @param method Name of the remote method to call * @param params Parameters object the remote method should be called with */ diff --git a/npm/backend-jsonrpc/tests/transport.test.mjs b/npm/backend-jsonrpc/tests/transport.test.mjs index 2776cda3bdd..69ccbb8f675 100644 --- a/npm/backend-jsonrpc/tests/transport.test.mjs +++ b/npm/backend-jsonrpc/tests/transport.test.mjs @@ -6,9 +6,9 @@ function makeMessage(body) { const content = JSON.stringify(body); return Buffer.from( `Content-Length: ${content.length}\r\n` + - `Content-Type: application/vscode-jsonrpc;charset=utf-8\r\n` + - `\r\n` + - content + `Content-Type: application/vscode-jsonrpc;charset=utf-8\r\n` + + `\r\n` + + content, ); } @@ -17,7 +17,7 @@ describe("Transport Layer", () => { let onData = null; const socket = { on(event, fn) { - expect(event).toBe('data'); + expect(event).toBe("data"); onData = fn; }, write: vi.fn(), @@ -26,20 +26,24 @@ describe("Transport Layer", () => { const transport = new Transport(socket); - const result = transport.request('method', "params"); - - expect(socket.write).toHaveBeenCalledWith(makeMessage({ - jsonrpc: "2.0", - id: 0, - method: "method", - params: "params", - })); - - onData(makeMessage({ - jsonrpc: "2.0", - id: 0, - result: "result", - })); + const result = transport.request("method", "params"); + + expect(socket.write).toHaveBeenCalledWith( + makeMessage({ + jsonrpc: "2.0", + id: 0, + method: "method", + params: "params", + }), + ); + + onData( + makeMessage({ + jsonrpc: "2.0", + id: 0, + result: "result", + }), + ); const response = await result; expect(response).toMatchObject({}); @@ -52,7 +56,7 @@ describe("Transport Layer", () => { let onData = null; const socket = { on(event, fn) { - expect(event).toBe('data'); + expect(event).toBe("data"); onData = fn; }, write: vi.fn(), @@ -61,7 +65,9 @@ describe("Transport Layer", () => { const transport = new Transport(socket); - expect(() => onData(Buffer.from(`\r\n`))).toThrowError('incoming message from the remote workspace is missing the Content-Length header'); + expect(() => onData(Buffer.from(`\r\n`))).toThrowError( + "incoming message from the remote workspace is missing the Content-Length header", + ); transport.destroy(); expect(socket.destroy).toHaveBeenCalledOnce(); @@ -71,7 +77,7 @@ describe("Transport Layer", () => { let onData = null; const socket = { on(event, fn) { - expect(event).toBe('data'); + expect(event).toBe("data"); onData = fn; }, write: vi.fn(), @@ -80,7 +86,9 @@ describe("Transport Layer", () => { const transport = new Transport(socket); - expect(() => onData(Buffer.from(`Content-Length\r\n`))).toThrowError('could not find colon token in "Content-Length\r\n"'); + expect(() => onData(Buffer.from(`Content-Length\r\n`))).toThrowError( + 'could not find colon token in "Content-Length\r\n"', + ); transport.destroy(); expect(socket.destroy).toHaveBeenCalledOnce(); @@ -90,7 +98,7 @@ describe("Transport Layer", () => { let onData = null; const socket = { on(event, fn) { - expect(event).toBe('data'); + expect(event).toBe("data"); onData = fn; }, write: vi.fn(), @@ -99,7 +107,11 @@ describe("Transport Layer", () => { const transport = new Transport(socket); - expect(() => onData(Buffer.from(`Content-Type: text/plain\r\n`))).toThrowError('invalid value for Content-Type expected "application/vscode-jsonrpc", got "text/plain"'); + expect( + () => onData(Buffer.from(`Content-Type: text/plain\r\n`)), + ).toThrowError( + 'invalid value for Content-Type expected "application/vscode-jsonrpc", got "text/plain"', + ); transport.destroy(); expect(socket.destroy).toHaveBeenCalledOnce(); @@ -109,7 +121,7 @@ describe("Transport Layer", () => { let onData = null; const socket = { on(event, fn) { - expect(event).toBe('data'); + expect(event).toBe("data"); onData = fn; }, write: vi.fn(), @@ -118,7 +130,11 @@ describe("Transport Layer", () => { const transport = new Transport(socket); - expect(() => onData(makeMessage({ jsonrpc: "2.0", id: 0, result: "result" }))).toThrowError('could not find any pending request matching RPC response ID 0'); + expect( + () => onData(makeMessage({ jsonrpc: "2.0", id: 0, result: "result" })), + ).toThrowError( + "could not find any pending request matching RPC response ID 0", + ); transport.destroy(); expect(socket.destroy).toHaveBeenCalledOnce(); @@ -128,7 +144,7 @@ describe("Transport Layer", () => { let onData = null; const socket = { on(event, fn) { - expect(event).toBe('data'); + expect(event).toBe("data"); onData = fn; }, write: vi.fn(), @@ -137,7 +153,9 @@ describe("Transport Layer", () => { const transport = new Transport(socket); - expect(() => onData(makeMessage({}))).toThrowError('failed to deserialize incoming message from remote workspace, "{}" is not a valid JSON-RPC message body'); + expect(() => onData(makeMessage({}))).toThrowError( + 'failed to deserialize incoming message from remote workspace, "{}" is not a valid JSON-RPC message body', + ); transport.destroy(); expect(socket.destroy).toHaveBeenCalledOnce(); diff --git a/npm/backend-jsonrpc/tests/workspace.test.mjs b/npm/backend-jsonrpc/tests/workspace.test.mjs index 15b829abd6f..77f7bdf7582 100644 --- a/npm/backend-jsonrpc/tests/workspace.test.mjs +++ b/npm/backend-jsonrpc/tests/workspace.test.mjs @@ -12,9 +12,9 @@ describe("Workspace API", () => { "../../../..", `target/release/rome${extension}`, ); - + const workspace = await createWorkspaceWithBinary(command); - + await workspace.openFile({ path: { path: "test.js", @@ -23,7 +23,7 @@ describe("Workspace API", () => { content: "statement()", version: 0, }); - + const printed = await workspace.formatFile({ path: { path: "test.js", @@ -32,14 +32,14 @@ describe("Workspace API", () => { }); expect(printed.code).toBe("statement();\n"); - + await workspace.closeFile({ path: { path: "test.js", id: 0, }, }); - + workspace.destroy(); }); }); diff --git a/website/.eleventy.js b/website/.eleventy.js index 3b0a02b3000..34eb5e2b12e 100644 --- a/website/.eleventy.js +++ b/website/.eleventy.js @@ -60,10 +60,11 @@ module.exports = function (eleventyConfig) { permalinkAttrs: (slug) => ({ "aria-label": slug }), slugify: (title) => { return encodeURIComponent( - String(title).trim().toLowerCase().replace( - /[^a-zA-Z\s0-9]/g, - "", - ).replace(/\s+/g, "-"), + String(title) + .trim() + .toLowerCase() + .replace(/[^a-zA-Z\s0-9]/g, "") + .replace(/\s+/g, "-"), ); }, }); @@ -171,9 +172,11 @@ module.exports = function (eleventyConfig) { eleventyConfig.addFilter("blogSummary", (val) => { const lines = val.split("")[0].split("\n"); - return lines.filter((line) => { - return line.startsWith("

"); - }).join("\n"); + return lines + .filter((line) => { + return line.startsWith("

"); + }) + .join("\n"); }); eleventyConfig.addFilter("dateFormat", function (value) {