diff --git a/src/Tokenizers/PHP.php b/src/Tokenizers/PHP.php index 9c6c11e4c3..c6b8e29065 100644 --- a/src/Tokenizers/PHP.php +++ b/src/Tokenizers/PHP.php @@ -2817,7 +2817,10 @@ protected function processAdditional() } } - if (isset($this->tokens[$x]) === true && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + if (isset($this->tokens[$x]) === true + && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + && isset($this->tokens[$x]['parenthesis_closer']) === true + ) { $ignore = Tokens::$emptyTokens; $ignore += [ T_ARRAY => T_ARRAY, @@ -2995,7 +2998,7 @@ protected function processAdditional() }//end if }//end if - // If after all that, the extra tokens are not set, this is not an arrow function. + // If after all that, the extra tokens are not set, this is not a (valid) arrow function. if (isset($this->tokens[$i]['scope_closer']) === false) { if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; diff --git a/tests/Core/Tokenizers/PHP/BackfillFnTokenParseErrorTest.inc b/tests/Core/Tokenizers/PHP/BackfillFnTokenParseErrorTest.inc new file mode 100644 index 0000000000..ce247e991b --- /dev/null +++ b/tests/Core/Tokenizers/PHP/BackfillFnTokenParseErrorTest.inc @@ -0,0 +1,5 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class BackfillFnTokenParseErrorTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that un unfinished arrow function during live coding doesn't cause a "Undefined array key "parenthesis_closer"" error. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnfinishedArrowFunction() + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testLiveCoding */', [T_STRING, T_FN], 'fn'); + $tokenArray = $tokens[$token]; + + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testUnfinishedArrowFunction() + + +}//end class