@@ -44,7 +44,7 @@ public static function getIntOrNull($value)
4444 public static function findContainingOpeningSquareBracket (File $ phpcsFile , $ stackPtr )
4545 {
4646 $ previousStatementPtr = self ::getPreviousStatementPtr ($ phpcsFile , $ stackPtr );
47- return self ::getIntOrNull ($ phpcsFile ->findPrevious ([T_OPEN_SHORT_ARRAY ], $ stackPtr - 1 , $ previousStatementPtr ));
47+ return self ::getIntOrNull ($ phpcsFile ->findPrevious ([T_OPEN_SHORT_ARRAY , T_OPEN_SQUARE_BRACKET ], $ stackPtr - 1 , $ previousStatementPtr ));
4848 }
4949
5050 /**
@@ -654,7 +654,70 @@ public static function getArrowFunctionOpenClose(File $phpcsFile, $stackPtr)
654654 }
655655
656656 /**
657- * Return a list of indices for variables assigned within a list assignment
657+ * Determine if a token is a list opener for list assignment/destructuring.
658+ *
659+ * The index provided can be either the opening square brace of a short list
660+ * assignment like the first character of `[$a] = $b;` or the `list` token of
661+ * an expression like `list($a) = $b;` or the opening parenthesis of that
662+ * expression.
663+ *
664+ * @param File $phpcsFile
665+ * @param int $listOpenerIndex
666+ *
667+ * @return bool
668+ */
669+ private static function isListAssignment (File $ phpcsFile , $ listOpenerIndex )
670+ {
671+ $ tokens = $ phpcsFile ->getTokens ();
672+ // Match `[$a] = $b;` except for when the previous token is a parenthesis.
673+ if ($ tokens [$ listOpenerIndex ]['code ' ] === T_OPEN_SHORT_ARRAY ) {
674+ return true ;
675+ }
676+ // Match `list($a) = $b;`
677+ if ($ tokens [$ listOpenerIndex ]['code ' ] === T_LIST ) {
678+ return true ;
679+ }
680+
681+ // If $listOpenerIndex is the open parenthesis of `list($a) = $b;`, then
682+ // match that too.
683+ if ($ tokens [$ listOpenerIndex ]['code ' ] === T_OPEN_PARENTHESIS ) {
684+ $ previousTokenPtr = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , $ listOpenerIndex - 1 , null , true );
685+ if (
686+ isset ($ tokens [$ previousTokenPtr ])
687+ && $ tokens [$ previousTokenPtr ]['code ' ] === T_LIST
688+ ) {
689+ return true ;
690+ }
691+ return true ;
692+ }
693+
694+ // If the list opener token is a square bracket that is preceeded by a
695+ // close parenthesis that has an owner which is a scope opener, then this
696+ // is a list assignment and not an array access.
697+ //
698+ // Match `if (true) [$a] = $b;`
699+ if ($ tokens [$ listOpenerIndex ]['code ' ] === T_OPEN_SQUARE_BRACKET ) {
700+ $ previousTokenPtr = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , $ listOpenerIndex - 1 , null , true );
701+ if (
702+ isset ($ tokens [$ previousTokenPtr ])
703+ && $ tokens [$ previousTokenPtr ]['code ' ] === T_CLOSE_PARENTHESIS
704+ && isset ($ tokens [$ previousTokenPtr ]['parenthesis_owner ' ])
705+ && isset (Tokens::$ scopeOpeners [$ tokens [$ tokens [$ previousTokenPtr ]['parenthesis_owner ' ]]['code ' ]])
706+ ) {
707+ return true ;
708+ }
709+ }
710+
711+ return false ;
712+ }
713+
714+ /**
715+ * Return a list of indices for variables assigned within a list assignment.
716+ *
717+ * The index provided can be either the opening square brace of a short list
718+ * assignment like the first character of `[$a] = $b;` or the `list` token of
719+ * an expression like `list($a) = $b;` or the opening parenthesis of that
720+ * expression.
658721 *
659722 * @param File $phpcsFile
660723 * @param int $listOpenerIndex
@@ -719,6 +782,10 @@ public static function getListAssignments(File $phpcsFile, $listOpenerIndex)
719782 ++$ currentPtr ;
720783 }
721784
785+ if (! self ::isListAssignment ($ phpcsFile , $ listOpenerIndex )) {
786+ return null ;
787+ }
788+
722789 return $ variablePtrs ;
723790 }
724791
0 commit comments