@@ -84,20 +84,20 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, IdentifierReference<'a>> {
8484 matches ! ( self . parent, AstNodes :: ForOfStatement ( stmt) if !stmt. r#await && stmt. left. span( ) . contains_inclusive( self . span) )
8585 }
8686 "let" => {
87- let mut parent = self . parent ;
88- loop {
87+ // Walk up ancestors to find the relevant context for `let` keyword
88+ for parent in self . ancestors ( ) {
8989 match parent {
90- AstNodes :: Program ( _ ) | AstNodes :: ExpressionStatement ( _) => return false ,
90+ AstNodes :: ExpressionStatement ( _) => return false ,
9191 AstNodes :: ForOfStatement ( stmt) => {
9292 return stmt. left . span ( ) . contains_inclusive ( self . span ) ;
9393 }
9494 AstNodes :: TSSatisfiesExpression ( expr) => {
9595 return expr. expression . span ( ) == self . span ( ) ;
9696 }
97- _ => parent = parent . parent ( ) ,
97+ _ => { }
9898 }
9999 }
100- unreachable ! ( )
100+ false
101101 }
102102 name => {
103103 // <https://github.com/prettier/prettier/blob/7584432401a47a26943dd7a9ca9a8e032ead7285/src/language-js/needs-parens.js#L123-L133>
@@ -131,7 +131,7 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, IdentifierReference<'a>> {
131131 matches ! (
132132 parent, AstNodes :: ExpressionStatement ( stmt) if
133133 !matches!(
134- stmt. parent . parent ( ) , AstNodes :: ArrowFunctionExpression ( arrow)
134+ stmt. grand_parent ( ) , AstNodes :: ArrowFunctionExpression ( arrow)
135135 if arrow. expression( )
136136 )
137137 )
@@ -392,8 +392,9 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, BinaryExpression<'a>> {
392392
393393/// Add parentheses if the `in` is inside of a `for` initializer (see tests).
394394fn is_in_for_initializer ( expr : & AstNode < ' _ , BinaryExpression < ' _ > > ) -> bool {
395- let mut parent = expr. parent ;
396- loop {
395+ let mut ancestors = expr. ancestors ( ) ;
396+
397+ while let Some ( parent) = ancestors. next ( ) {
397398 match parent {
398399 AstNodes :: ExpressionStatement ( stmt) => {
399400 let grand_parent = parent. parent ( ) ;
@@ -404,7 +405,13 @@ fn is_in_for_initializer(expr: &AstNode<'_, BinaryExpression<'_>>) -> bool {
404405 grand_grand_parent,
405406 AstNodes :: ArrowFunctionExpression ( arrow) if arrow. expression( )
406407 ) {
407- parent = grand_grand_parent;
408+ // Skip ahead to grand_grand_parent by consuming ancestors
409+ // until we reach it
410+ for ancestor in ancestors. by_ref ( ) {
411+ if core:: ptr:: eq ( ancestor, grand_grand_parent) {
412+ break ;
413+ }
414+ }
408415 continue ;
409416 }
410417 }
@@ -423,11 +430,11 @@ fn is_in_for_initializer(expr: &AstNode<'_, BinaryExpression<'_>>) -> bool {
423430 AstNodes :: Program ( _) => {
424431 return false ;
425432 }
426- _ => {
427- parent = parent. parent ( ) ;
428- }
433+ _ => { }
429434 }
430435 }
436+
437+ false
431438}
432439
433440impl < ' a > NeedsParentheses < ' a > for AstNode < ' a , PrivateInExpression < ' a > > {
@@ -546,25 +553,20 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, AssignmentExpression<'a>> {
546553 // - `a = 1, b = 2` in for loops don't need parens
547554 // - `(a = 1, b = 2)` elsewhere usually need parens
548555 AstNodes :: SequenceExpression ( sequence) => {
549- let mut current_parent = self . parent ;
550- loop {
551- match current_parent {
552- AstNodes :: SequenceExpression ( _) | AstNodes :: ParenthesizedExpression ( _) => {
553- current_parent = current_parent. parent ( ) ;
554- }
555- AstNodes :: ForStatement ( for_stmt) => {
556- let is_initializer = for_stmt
557- . init
558- . as_ref ( )
559- . is_some_and ( |init| init. span ( ) . contains_inclusive ( self . span ( ) ) ) ;
560- let is_update = for_stmt. update . as_ref ( ) . is_some_and ( |update| {
561- update. span ( ) . contains_inclusive ( self . span ( ) )
562- } ) ;
563- return !( is_initializer || is_update) ;
564- }
565- _ => break ,
556+ // Skip through SequenceExpression and ParenthesizedExpression ancestors
557+ if let Some ( ancestor) = self . ancestors ( ) . find ( |p| {
558+ !matches ! ( p, AstNodes :: SequenceExpression ( _) | AstNodes :: ParenthesizedExpression ( _) )
559+ } ) && let AstNodes :: ForStatement ( for_stmt) = ancestor {
560+ let is_initializer = for_stmt
561+ . init
562+ . as_ref ( )
563+ . is_some_and ( |init| init. span ( ) . contains_inclusive ( self . span ( ) ) ) ;
564+ let is_update = for_stmt. update . as_ref ( ) . is_some_and ( |update| {
565+ update. span ( ) . contains_inclusive ( self . span ( ) )
566+ } ) ;
567+ return !( is_initializer || is_update) ;
566568 }
567- }
569+
568570 true
569571 }
570572 // `interface { [a = 1]; }` and `class { [a = 1]; }` not need parens
@@ -620,8 +622,8 @@ impl<'a> NeedsParentheses<'a> for AstNode<'a, SequenceExpression<'a>> {
620622 }
621623}
622624
623- impl < ' a > NeedsParentheses < ' a > for AstNode < ' a , AwaitExpression < ' a > > {
624- fn needs_parentheses ( & self , f : & Formatter < ' _ , ' a > ) -> bool {
625+ impl NeedsParentheses < ' _ > for AstNode < ' _ , AwaitExpression < ' _ > > {
626+ fn needs_parentheses ( & self , f : & Formatter < ' _ , ' _ > ) -> bool {
625627 if f. comments ( ) . is_type_cast_node ( self ) {
626628 return false ;
627629 }
@@ -977,14 +979,15 @@ pub enum FirstInStatementMode {
977979/// the left most node or reached a statement.
978980fn is_first_in_statement (
979981 mut current_span : Span ,
980- mut parent : & AstNodes < ' _ > ,
982+ parent : & AstNodes < ' _ > ,
981983 mode : FirstInStatementMode ,
982984) -> bool {
983- let mut is_not_first_iteration = false ;
984- loop {
985- match parent {
985+ for ( index, ancestor) in parent. ancestors ( ) . enumerate ( ) {
986+ let is_not_first_iteration = index > 0 ;
987+
988+ match ancestor {
986989 AstNodes :: ExpressionStatement ( stmt) => {
987- if matches ! ( stmt. parent . parent ( ) , AstNodes :: ArrowFunctionExpression ( arrow) if arrow. expression)
990+ if matches ! ( stmt. grand_parent ( ) , AstNodes :: ArrowFunctionExpression ( arrow) if arrow. expression)
988991 {
989992 if mode == FirstInStatementMode :: ExpressionStatementOrArrow {
990993 if is_not_first_iteration
@@ -1051,9 +1054,7 @@ fn is_first_in_statement(
10511054 }
10521055 _ => break ,
10531056 }
1054- current_span = parent. span ( ) ;
1055- parent = parent. parent ( ) ;
1056- is_not_first_iteration = true ;
1057+ current_span = ancestor. span ( ) ;
10571058 }
10581059
10591060 false
0 commit comments