Skip to content

Commit

Permalink
Fixed bug #2895 : PSR2.Methods.FunctionCallSignature.MultipleArgument…
Browse files Browse the repository at this point in the history
…s false positive with arrow function argument
  • Loading branch information
gsherwood committed Mar 12, 2020
1 parent 1dbc333 commit 2914011
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 5 deletions.
1 change: 1 addition & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
- Fixed bug #2865 : Double arrow tokenized as T_STRING when placed after function named "fn"
- Fixed bug #2868 : phpcs:ignore annotation doesnt work inside a docblock
- Fixed bug #2878 : PSR12.Files.FileHeader conflicts with Generic.Files.LineEndings
- Fixed bug #2895 : PSR2.Methods.FunctionCallSignature.MultipleArguments false positive with arrow function argument
</notes>
<contents>
<dir name="/">
Expand Down
4 changes: 2 additions & 2 deletions src/Files/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -2333,7 +2333,6 @@ public function findEndOfStatement($start, $ignore=null)
}

$lastNotEmpty = $start;

for ($i = $start; $i < $this->numTokens; $i++) {
if ($i !== $start && isset($endTokens[$this->tokens[$i]['code']]) === true) {
// Found the end of the statement.
Expand All @@ -2356,7 +2355,8 @@ public function findEndOfStatement($start, $ignore=null)
|| $i === $this->tokens[$i]['scope_condition'])
) {
if ($this->tokens[$i]['code'] === T_FN) {
$i = ($this->tokens[$i]['scope_closer'] - 1);
$lastNotEmpty = $this->tokens[$i]['scope_closer'];
$i = ($this->tokens[$i]['scope_closer'] - 1);
continue;
}

Expand Down
20 changes: 17 additions & 3 deletions src/Tokenizers/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -1851,10 +1851,18 @@ protected function processAdditional()
T_CLOSE_TAG => true,
];

$inTernary = false;
$inTernary = false;
$lastEndToken = null;

for ($scopeCloser = ($arrow + 1); $scopeCloser < $numTokens; $scopeCloser++) {
if (isset($endTokens[$this->tokens[$scopeCloser]['code']]) === true) {
if ($lastEndToken !== null
&& $this->tokens[$scopeCloser]['code'] === T_CLOSE_PARENTHESIS
&& $this->tokens[$scopeCloser]['parenthesis_opener'] < $arrow
) {
$scopeCloser = $lastEndToken;
}

break;
}

Expand All @@ -1867,12 +1875,14 @@ protected function processAdditional()
}

if (isset($this->tokens[$scopeCloser]['parenthesis_closer']) === true) {
$scopeCloser = $this->tokens[$scopeCloser]['parenthesis_closer'];
$scopeCloser = $this->tokens[$scopeCloser]['parenthesis_closer'];
$lastEndToken = $scopeCloser;
continue;
}

if (isset($this->tokens[$scopeCloser]['bracket_closer']) === true) {
$scopeCloser = $this->tokens[$scopeCloser]['bracket_closer'];
$scopeCloser = $this->tokens[$scopeCloser]['bracket_closer'];
$lastEndToken = $scopeCloser;
continue;
}

Expand All @@ -1895,6 +1905,10 @@ protected function processAdditional()
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$line = $this->tokens[$i]['line'];
echo "\t=> token $i on line $line processed as arrow function".PHP_EOL;
echo "\t\t* scope opener set to $arrow *".PHP_EOL;
echo "\t\t* scope closer set to $scopeCloser *".PHP_EOL;
echo "\t\t* parenthesis opener set to $x *".PHP_EOL;
echo "\t\t* parenthesis closer set to $closer *".PHP_EOL;
}

$this->tokens[$i]['code'] = T_FN;
Expand Down
10 changes: 10 additions & 0 deletions tests/Core/File/FindEndOfStatementTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,14 @@ static fn ($a) => $a;
/* testArrowFunctionReturnValue */
fn(): array => [a($a, $b)];

/* testArrowFunctionAsArgument */
$foo = foo(
fn() => bar()
);

/* testArrowFunctionWithArrayAsArgument */
$foo = foo(
fn() => [$row[0], $row[3]]
);

return 0;
32 changes: 32 additions & 0 deletions tests/Core/File/FindEndOfStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,36 @@ public function testArrowFunctionReturnValue()
}//end testArrowFunctionReturnValue()


/**
* Test arrow function used as a function argument.
*
* @return void
*/
public function testArrowFunctionAsArgument()
{
$start = (self::$phpcsFile->findNext(T_COMMENT, 0, null, false, '/* testArrowFunctionAsArgument */') + 10);
$found = self::$phpcsFile->findEndOfStatement($start);

$tokens = self::$phpcsFile->getTokens();
$this->assertSame($tokens[($start + 8)], $tokens[$found]);

}//end testArrowFunctionAsArgument()


/**
* Test arrow function with arrays used as a function argument.
*
* @return void
*/
public function testArrowFunctionWithArrayAsArgument()
{
$start = (self::$phpcsFile->findNext(T_COMMENT, 0, null, false, '/* testArrowFunctionWithArrayAsArgument */') + 10);
$found = self::$phpcsFile->findEndOfStatement($start);

$tokens = self::$phpcsFile->getTokens();
$this->assertSame($tokens[($start + 17)], $tokens[$found]);

}//end testArrowFunctionWithArrayAsArgument()


}//end class

0 comments on commit 2914011

Please sign in to comment.