diff --git a/Tests/VariableAnalysisSniff/fixtures/ArrowFunctionFixture.php b/Tests/VariableAnalysisSniff/fixtures/ArrowFunctionFixture.php index 9a16dc4..f3f48e8 100644 --- a/Tests/VariableAnalysisSniff/fixtures/ArrowFunctionFixture.php +++ b/Tests/VariableAnalysisSniff/fixtures/ArrowFunctionFixture.php @@ -166,3 +166,12 @@ function arrowFunctionWithQuotes($allowedReferrers) { && $permissionName !== CustomPermission::ALL_CONFIG ); } + +function arrowFunctionWithNestedArrowFunction() { + $fn = fn($outerArrowArg) => [ + $outerArrowArg, + fn($insideArg) => $insideArg, + $outerArrowArg, + ]; + $fn(); +} diff --git a/VariableAnalysis/Lib/Helpers.php b/VariableAnalysis/Lib/Helpers.php index dfcdc38..6af1b22 100644 --- a/VariableAnalysis/Lib/Helpers.php +++ b/VariableAnalysis/Lib/Helpers.php @@ -608,6 +608,17 @@ private static function getPreviousArrowFunctionIndex(File $phpcsFile, $stackPtr if ($token['content'] === 'fn' && self::isArrowFunction($phpcsFile, $index)) { return $index; } + // If we find a token that would close an arrow function scope before we + // find a token that would open an arrow function scope, then we've found + // a nested arrow function and we should ignore it, move back before THAT + // arrow function's scope, and continue to search. + $arrowFunctionStartIndex = $phpcsFile->findPrevious([T_FN], $index, $enclosingScopeIndex); + if (is_int($arrowFunctionStartIndex)) { + $openClose = self::getArrowFunctionOpenClose($phpcsFile, $arrowFunctionStartIndex); + if ($openClose && $openClose['scope_closer'] === $index) { + $index = $openClose['scope_opener']; + } + } } return null; } @@ -646,6 +657,15 @@ public static function isArrowFunction(File $phpcsFile, $stackPtr) } /** + * Find the opening and closing scope positions for an arrow function if the + * given position is the start of the arrow function (the `fn` keyword + * token). + * + * Returns null if the passed token is not an arrow function keyword. + * + * If the token is an arrow function keyword, the scope opener is returned as + * the provided position. + * * @param File $phpcsFile * @param int $stackPtr *