Skip to content

Commit 78f099a

Browse files
committed
Process every variable in compact separately
1 parent 99e3049 commit 78f099a

File tree

2 files changed

+68
-60
lines changed

2 files changed

+68
-60
lines changed

VariableAnalysis/Lib/Helpers.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,64 @@ public static function findVariableScope(File $phpcsFile, $stackPtr, $varName =
445445
return self::findVariableScopeExceptArrowFunctions($phpcsFile, $stackPtr);
446446
}
447447

448+
/**
449+
* Return the variable names of each variable targetted by a `compact()` call.
450+
*
451+
* @param File $phpcsFile
452+
* @param int $stackPtr
453+
* @param array<int, array<int>> $arguments The stack pointers of each argument; see findFunctionCallArguments
454+
*
455+
* @return string[]
456+
*/
457+
public static function getVariableNamesFromCompact(File $phpcsFile, $stackPtr, $arguments)
458+
{
459+
$tokens = $phpcsFile->getTokens();
460+
$variableNames = [];
461+
462+
foreach ($arguments as $argumentPtrs) {
463+
$argumentPtrs = array_values(array_filter($argumentPtrs, function ($argumentPtr) use ($tokens) {
464+
return isset(Tokens::$emptyTokens[$tokens[$argumentPtr]['code']]) === false;
465+
}));
466+
if (empty($argumentPtrs)) {
467+
continue;
468+
}
469+
if (!isset($tokens[$argumentPtrs[0]])) {
470+
continue;
471+
}
472+
$argumentFirstToken = $tokens[$argumentPtrs[0]];
473+
if ($argumentFirstToken['code'] === T_ARRAY) {
474+
// It's an array argument, recurse.
475+
$arrayArguments = Helpers::findFunctionCallArguments($phpcsFile, $argumentPtrs[0]);
476+
$variableNames = array_merge($variableNames, self::getVariableNamesFromCompact($phpcsFile, $stackPtr, $arrayArguments));
477+
continue;
478+
}
479+
if (count($argumentPtrs) > 1) {
480+
// Complex argument, we can't handle it, ignore.
481+
continue;
482+
}
483+
if ($argumentFirstToken['code'] === T_CONSTANT_ENCAPSED_STRING) {
484+
// Single-quoted string literal, ie compact('whatever').
485+
// Substr is to strip the enclosing single-quotes.
486+
$varName = substr($argumentFirstToken['content'], 1, -1);
487+
$variableNames[] = $varName;
488+
continue;
489+
}
490+
if ($argumentFirstToken['code'] === T_DOUBLE_QUOTED_STRING) {
491+
// Double-quoted string literal.
492+
$regexp = Constants::getDoubleQuotedVarRegexp();
493+
if (! empty($regexp) && preg_match($regexp, $argumentFirstToken['content'])) {
494+
// Bail if the string needs variable expansion, that's runtime stuff.
495+
continue;
496+
}
497+
// Substr is to strip the enclosing double-quotes.
498+
$varName = substr($argumentFirstToken['content'], 1, -1);
499+
$variableNames[] = $varName;
500+
continue;
501+
}
502+
}
503+
return $variableNames;
504+
}
505+
448506
/**
449507
* Return the token index of the scope start for a token
450508
*

VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,61 +1869,6 @@ protected function processVariableInString(File $phpcsFile, $stackPtr)
18691869
}
18701870
}
18711871

1872-
/**
1873-
* @param File $phpcsFile
1874-
* @param int $stackPtr
1875-
* @param array<int, array<int>> $arguments The stack pointers of each argument
1876-
* @param int $currScope
1877-
*
1878-
* @return void
1879-
*/
1880-
protected function processCompactArguments(File $phpcsFile, $stackPtr, $arguments, $currScope)
1881-
{
1882-
$tokens = $phpcsFile->getTokens();
1883-
1884-
foreach ($arguments as $argumentPtrs) {
1885-
$argumentPtrs = array_values(array_filter($argumentPtrs, function ($argumentPtr) use ($tokens) {
1886-
return isset(Tokens::$emptyTokens[$tokens[$argumentPtr]['code']]) === false;
1887-
}));
1888-
if (empty($argumentPtrs)) {
1889-
continue;
1890-
}
1891-
if (!isset($tokens[$argumentPtrs[0]])) {
1892-
continue;
1893-
}
1894-
$argumentFirstToken = $tokens[$argumentPtrs[0]];
1895-
if ($argumentFirstToken['code'] === T_ARRAY) {
1896-
// It's an array argument, recurse.
1897-
$arrayArguments = Helpers::findFunctionCallArguments($phpcsFile, $argumentPtrs[0]);
1898-
$this->processCompactArguments($phpcsFile, $stackPtr, $arrayArguments, $currScope);
1899-
continue;
1900-
}
1901-
if (count($argumentPtrs) > 1) {
1902-
// Complex argument, we can't handle it, ignore.
1903-
continue;
1904-
}
1905-
if ($argumentFirstToken['code'] === T_CONSTANT_ENCAPSED_STRING) {
1906-
// Single-quoted string literal, ie compact('whatever').
1907-
// Substr is to strip the enclosing single-quotes.
1908-
$varName = substr($argumentFirstToken['content'], 1, -1);
1909-
$this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $argumentPtrs[0], $currScope);
1910-
continue;
1911-
}
1912-
if ($argumentFirstToken['code'] === T_DOUBLE_QUOTED_STRING) {
1913-
// Double-quoted string literal.
1914-
$regexp = Constants::getDoubleQuotedVarRegexp();
1915-
if (! empty($regexp) && preg_match($regexp, $argumentFirstToken['content'])) {
1916-
// Bail if the string needs variable expansion, that's runtime stuff.
1917-
continue;
1918-
}
1919-
// Substr is to strip the enclosing double-quotes.
1920-
$varName = substr($argumentFirstToken['content'], 1, -1);
1921-
$this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $argumentPtrs[0], $currScope);
1922-
continue;
1923-
}
1924-
}
1925-
}
1926-
19271872
/**
19281873
* Called to process variables named in a call to compact().
19291874
*
@@ -1934,13 +1879,18 @@ protected function processCompactArguments(File $phpcsFile, $stackPtr, $argument
19341879
*/
19351880
protected function processCompact(File $phpcsFile, $stackPtr)
19361881
{
1937-
$currScope = Helpers::findVariableScope($phpcsFile, $stackPtr);
1938-
if ($currScope === null) {
1939-
return;
1940-
}
1882+
Helpers::debug("processCompact at {$stackPtr}");
19411883

19421884
$arguments = Helpers::findFunctionCallArguments($phpcsFile, $stackPtr);
1943-
$this->processCompactArguments($phpcsFile, $stackPtr, $arguments, $currScope);
1885+
$variableNames = Helpers::getVariableNamesFromCompact($phpcsFile, $stackPtr, $arguments);
1886+
1887+
foreach ( $variableNames as $variableName ) {
1888+
$currScope = Helpers::findVariableScope($phpcsFile, $stackPtr, $variableName);
1889+
if ($currScope === null) {
1890+
continue;
1891+
}
1892+
$this->markVariableReadAndWarnIfUndefined($phpcsFile, $variableName, $stackPtr, $currScope);
1893+
}
19441894
}
19451895

19461896
/**

0 commit comments

Comments
 (0)