@@ -5,6 +5,7 @@ use oxc_span::GetSpan;
55
66use crate :: formatter:: prelude:: { FormatElements , format_once, line_suffix_boundary} ;
77use crate :: formatter:: { BufferExtensions , VecBuffer } ;
8+ use crate :: utils:: member_chain:: is_member_call_chain;
89use crate :: write:: BinaryLikeExpression ;
910use crate :: write:: { FormatJsArrowFunctionExpression , FormatJsArrowFunctionExpressionOptions } ;
1011use crate :: {
@@ -208,7 +209,9 @@ impl<'a> AssignmentLike<'a, '_> {
208209 return layout;
209210 }
210211
211- if let Some ( Expression :: CallExpression ( call_expression) ) = & right_expression {
212+ if let Some ( Expression :: CallExpression ( call_expression) ) =
213+ & right_expression. map ( AsRef :: as_ref)
214+ {
212215 if call_expression
213216 . callee
214217 . get_identifier_reference ( )
@@ -236,14 +239,15 @@ impl<'a> AssignmentLike<'a, '_> {
236239 // !"123" -> "123"
237240 // void "123" -> "123"
238241 // !!"string"! -> "string"
239- let right_expression = iter:: successors ( right_expression, |expression| match expression {
240- Expression :: UnaryExpression ( unary) => Some ( & unary. argument ) ,
241- Expression :: TSNonNullExpression ( assertion) => Some ( & assertion. expression ) ,
242- _ => None ,
243- } )
244- . last ( ) ;
245-
246- if matches ! ( right_expression, Some ( Expression :: StringLiteral ( _) ) ) {
242+ let right_expression =
243+ iter:: successors ( right_expression, |expression| match expression. as_ast_nodes ( ) {
244+ AstNodes :: UnaryExpression ( unary) => Some ( unary. argument ( ) ) ,
245+ AstNodes :: TSNonNullExpression ( assertion) => Some ( assertion. expression ( ) ) ,
246+ _ => None ,
247+ } )
248+ . last ( ) ;
249+
250+ if matches ! ( right_expression. map( AsRef :: as_ref) , Some ( Expression :: StringLiteral ( _) ) ) {
247251 return AssignmentLikeLayout :: BreakAfterOperator ;
248252 }
249253
@@ -258,7 +262,7 @@ impl<'a> AssignmentLike<'a, '_> {
258262
259263 if !left_may_break
260264 && matches ! (
261- right_expression,
265+ right_expression. map ( AsRef :: as_ref ) ,
262266 Some (
263267 Expression :: ClassExpression ( _)
264268 | Expression :: TemplateLiteral ( _)
@@ -273,12 +277,10 @@ impl<'a> AssignmentLike<'a, '_> {
273277 AssignmentLikeLayout :: Fluid
274278 }
275279
276- fn get_right_expression ( & self ) -> Option < & Expression < ' a > > {
280+ fn get_right_expression ( & self ) -> Option < & AstNode < ' a , Expression < ' a > > > {
277281 match self {
278- AssignmentLike :: VariableDeclarator ( variable_decorator) => {
279- variable_decorator. init . as_ref ( )
280- }
281- AssignmentLike :: AssignmentExpression ( assignment) => Some ( & assignment. right ) ,
282+ AssignmentLike :: VariableDeclarator ( variable_decorator) => variable_decorator. init ( ) ,
283+ AssignmentLike :: AssignmentExpression ( assignment) => Some ( assignment. right ( ) ) ,
282284 }
283285 }
284286
@@ -389,7 +391,7 @@ impl<'a> AssignmentLike<'a, '_> {
389391 /// for nodes that belong to TypeScript too.
390392 fn should_break_after_operator (
391393 & self ,
392- right_expression : Option < & Expression < ' a > > ,
394+ right_expression : Option < & AstNode < ' a , Expression < ' a > > > ,
393395 f : & Formatter < ' _ , ' a > ,
394396 ) -> bool {
395397 let comments = f. context ( ) . comments ( ) ;
@@ -454,14 +456,17 @@ impl<'a> AssignmentLike<'a, '_> {
454456}
455457
456458/// Checks if the function is entitled to be printed with layout [AssignmentLikeLayout::BreakAfterOperator]
457- fn should_break_after_operator ( right : & Expression , f : & Formatter < ' _ , ' _ > ) -> bool {
459+ fn should_break_after_operator < ' a > (
460+ right : & AstNode < ' a , Expression < ' a > > ,
461+ f : & Formatter < ' _ , ' a > ,
462+ ) -> bool {
458463 if f. comments ( ) . has_leading_own_line_comments ( right. span ( ) . start )
459- && !matches ! ( right, Expression :: JSXElement ( _) | Expression :: JSXFragment ( _) )
464+ && !matches ! ( right. as_ref ( ) , Expression :: JSXElement ( _) | Expression :: JSXFragment ( _) )
460465 {
461466 return true ;
462467 }
463468
464- match right {
469+ match right. as_ref ( ) {
465470 // head is a long chain, meaning that right -> right are both assignment expressions
466471 Expression :: AssignmentExpression ( assignment) => {
467472 matches ! ( assignment. right, Expression :: AssignmentExpression ( _) )
@@ -476,14 +481,15 @@ fn should_break_after_operator(right: &Expression, f: &Formatter<'_, '_>) -> boo
476481 Expression :: ClassExpression ( class) => !class. decorators . is_empty ( ) ,
477482
478483 _ => {
479- let argument = match right {
480- Expression :: AwaitExpression ( expression) => Some ( & expression. argument ) ,
481- Expression :: YieldExpression ( expression) => expression. argument . as_ref ( ) ,
482- Expression :: UnaryExpression ( expression) => {
483- match get_last_non_unary_argument ( expression) {
484- Expression :: AwaitExpression ( expression) => Some ( & expression. argument ) ,
485- Expression :: YieldExpression ( expression) => expression. argument . as_ref ( ) ,
486- argument => Some ( argument) ,
484+ let argument = match right. as_ast_nodes ( ) {
485+ AstNodes :: AwaitExpression ( expression) => Some ( expression. argument ( ) ) ,
486+ AstNodes :: YieldExpression ( expression) => expression. argument ( ) ,
487+ AstNodes :: UnaryExpression ( expression) => {
488+ let argument = get_last_non_unary_argument ( expression) ;
489+ match argument. as_ast_nodes ( ) {
490+ AstNodes :: AwaitExpression ( expression) => Some ( expression. argument ( ) ) ,
491+ AstNodes :: YieldExpression ( expression) => expression. argument ( ) ,
492+ _ => Some ( argument) ,
487493 }
488494 }
489495 _ => None ,
@@ -499,12 +505,12 @@ fn should_break_after_operator(right: &Expression, f: &Formatter<'_, '_>) -> boo
499505/// Iterate over unary expression arguments to get last non-unary
500506/// Example: void !!(await test()) -> returns await as last argument
501507fn get_last_non_unary_argument < ' a , ' b > (
502- unary_expression : & ' b UnaryExpression < ' a > ,
503- ) -> & ' b Expression < ' a > {
504- let mut argument = & unary_expression. argument ;
508+ unary_expression : & ' b AstNode < ' a , UnaryExpression < ' a > > ,
509+ ) -> & ' b AstNode < ' a , Expression < ' a > > {
510+ let mut argument = unary_expression. argument ( ) ;
505511
506- while let Expression :: UnaryExpression ( unary) = argument {
507- argument = & unary. argument ;
512+ while let AstNodes :: UnaryExpression ( unary) = argument. as_ast_nodes ( ) {
513+ argument = unary. argument ( ) ;
508514 }
509515
510516 argument
@@ -641,9 +647,9 @@ impl<'a> Format<'a> for WithAssignmentLayout<'a, '_> {
641647/// A chain that has no calls at all or all of whose calls have no arguments
642648/// or have only one which [is_short_argument], except for member call chains
643649/// [Prettier applies]: <https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/assignment.js#L329>
644- fn is_poorly_breakable_member_or_call_chain (
645- expression : & Expression ,
646- f : & Formatter < ' _ , ' _ > ,
650+ fn is_poorly_breakable_member_or_call_chain < ' a > (
651+ expression : & AstNode < ' a , Expression < ' a > > ,
652+ f : & Formatter < ' _ , ' a > ,
647653) -> bool {
648654 let threshold = f. options ( ) . line_width . value ( ) / 4 ;
649655
@@ -662,23 +668,23 @@ fn is_poorly_breakable_member_or_call_chain(
662668 let mut expression = expression;
663669
664670 loop {
665- expression = match expression {
666- Expression :: TSNonNullExpression ( assertion) => & assertion. expression ,
667- Expression :: CallExpression ( call_expression) => {
671+ expression = match expression. as_ast_nodes ( ) {
672+ AstNodes :: TSNonNullExpression ( assertion) => assertion. expression ( ) ,
673+ AstNodes :: CallExpression ( call_expression) => {
668674 is_chain = true ;
669- let callee = & call_expression. callee ;
675+ let callee = & call_expression. callee ( ) ;
670676 call_expressions. push ( call_expression) ;
671677 callee
672678 }
673- Expression :: StaticMemberExpression ( node) => {
679+ AstNodes :: StaticMemberExpression ( node) => {
674680 is_chain = true ;
675- & node. object
681+ node. object ( )
676682 }
677- Expression :: ComputedMemberExpression ( node) => {
683+ AstNodes :: ComputedMemberExpression ( node) => {
678684 is_chain = true ;
679- & node. object
685+ node. object ( )
680686 }
681- Expression :: Identifier ( _) | Expression :: ThisExpression ( _) => {
687+ AstNodes :: IdentifierReference ( _) | AstNodes :: ThisExpression ( _) => {
682688 is_chain_head_simple = true ;
683689 break ;
684690 }
@@ -692,16 +698,15 @@ fn is_poorly_breakable_member_or_call_chain(
692698 return false ;
693699 }
694700
695- for call_expression in call_expressions {
696- // if is_member_call_chain(call_expression.clone(), f.comments(), f.options().tab_width())? {
697- // return Ok(false);
698- // }
699- // TODO: It looks like `is_member_call_chain` is used for checking comments,
700- // but not sure if the following code is equivalent to the above check.
701- if f. comments ( ) . has_comments_in_span ( call_expression. span ) {
702- return false ;
703- }
701+ if call_expressions. is_empty ( ) {
702+ return true ;
703+ }
704+
705+ if f. comments ( ) . has_comments_in_span ( call_expressions[ 0 ] . span ) {
706+ return false ;
707+ }
704708
709+ for call_expression in & call_expressions {
705710 let args = & call_expression. arguments ;
706711
707712 let is_breakable_call = match args. len ( ) {
@@ -727,7 +732,7 @@ fn is_poorly_breakable_member_or_call_chain(
727732 }
728733 }
729734
730- true
735+ ! is_member_call_chain ( call_expressions [ 0 ] , f )
731736}
732737
733738/// This function checks if `JsAnyCallArgument` is short
0 commit comments