Skip to content

Commit

Permalink
Tokenizer/PHP: prevent an "Undefined array key" notice during live co…
Browse files Browse the repository at this point in the history
…ding

During live coding or for code containing a parse error, it was possible for the tokenizer to run into an `Undefined array key "parenthesis_closer"` error when trying to verify arrow functions.

As this error happens during the tokenization, this resulted in PHPCS silently not scanning the file - without even showing the error notice.

Fixed now.

Includes tests.
  • Loading branch information
jrfnl committed Jan 10, 2025
1 parent b43e1d8 commit 73e8089
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/Tokenizers/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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'];
Expand Down
5 changes: 5 additions & 0 deletions tests/Core/Tokenizers/PHP/BackfillFnTokenParseErrorTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

/* testLiveCoding */
// Intentional parse error. This has to be the only test in the file.
$fn = static fn (string $paramA
44 changes: 44 additions & 0 deletions tests/Core/Tokenizers/PHP/BackfillFnTokenParseErrorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
/**
* Tests the backfilling of the T_FN token to PHP < 7.4 for a specific parse error.
*
* @author Juliette Reinders Folmer <[email protected]>
* @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

0 comments on commit 73e8089

Please sign in to comment.