Skip to content

Commit

Permalink
Properly detect variables used in quotes inside arrow functions (#222)
Browse files Browse the repository at this point in the history
* Add test for variables used in arrow functions within quotes

* Allow passing a different varName to findVariableScope

* Pass normalized varName to scope detection in processVariableInString

* Replace null coalescing operator
  • Loading branch information
sirbrillig authored Dec 30, 2020
1 parent df30329 commit 6a0b28f
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
6 changes: 6 additions & 0 deletions Tests/VariableAnalysisSniff/fixtures/ArrowFunctionFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ function arrowFunctionAsExpressionWithUnusedVariableOutsideArrow($subject) { //u
echo $post; // undefined variable $post;
}

function arrowFunctionWithVariableUsedInsideQuotes($allowed_extensions) {
$data = array_map( fn($extension) => '.' . $extension, $allowed_extensions );
$data = array_map( fn($extension) => ".$extension", $allowed_extensions );
$data = array_map( fn($extension) => ".{$extension}", $allowed_extensions );
return $data;
}
10 changes: 7 additions & 3 deletions VariableAnalysis/Lib/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,14 @@ public static function normalizeVarName($varName) {
/**
* @param File $phpcsFile
* @param int $stackPtr
* @param string $varName (optional) if it differs from the normalized 'content' of the token at $stackPtr
*
* @return ?int
*/
public static function findVariableScope(File $phpcsFile, $stackPtr) {
public static function findVariableScope(File $phpcsFile, $stackPtr, $varName = null) {
$tokens = $phpcsFile->getTokens();
$token = $tokens[$stackPtr];
$varName = isset($varName) ? $varName : self::normalizeVarName($token['content']);

$arrowFunctionIndex = self::getContainingArrowFunctionIndex($phpcsFile, $stackPtr);
$isTokenInsideArrowFunctionBody = is_int($arrowFunctionIndex);
Expand All @@ -319,7 +321,8 @@ public static function findVariableScope(File $phpcsFile, $stackPtr) {
// otherwise, it uses the enclosing scope.
if ($arrowFunctionIndex) {
$variableNames = self::getVariablesDefinedByArrowFunction($phpcsFile, $arrowFunctionIndex);
if (in_array($token['content'], $variableNames, true)) {
self::debug('findVariableScope: looking for', $varName, 'in arrow function variables', $variableNames);
if (in_array($varName, $variableNames, true)) {
return $arrowFunctionIndex;
}
}
Expand Down Expand Up @@ -654,9 +657,10 @@ public static function getVariablesDefinedByArrowFunction(File $phpcsFile, $stac
for ($index = $arrowFunctionToken['parenthesis_opener']; $index < $arrowFunctionToken['parenthesis_closer']; $index++) {
$token = $tokens[$index];
if ($token['code'] === T_VARIABLE) {
$variableNames[] = $token['content'];
$variableNames[] = self::normalizeVarName($token['content']);
}
}
self::debug('found these variables in arrow function token', $variableNames);
return $variableNames;
}

Expand Down
10 changes: 6 additions & 4 deletions VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -1528,12 +1528,9 @@ protected function processVariableInString(File $phpcsFile, $stackPtr) {
}
Helpers::debug("examining token for variable in string", $token);

$currScope = Helpers::findVariableScope($phpcsFile, $stackPtr);
if ($currScope === null) {
return;
}
foreach ($matches[1] as $varName) {
$varName = Helpers::normalizeVarName($varName);

// Are we $this within a class?
if ($this->processVariableAsThisWithinClass($phpcsFile, $stackPtr, $varName)) {
continue;
Expand All @@ -1548,6 +1545,11 @@ protected function processVariableInString(File $phpcsFile, $stackPtr) {
continue;
}

$currScope = Helpers::findVariableScope($phpcsFile, $stackPtr, $varName);
if ($currScope === null) {
continue;
}

$this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $stackPtr, $currScope);
}
}
Expand Down

0 comments on commit 6a0b28f

Please sign in to comment.