Skip to content

Commit

Permalink
PHP Tokenizer: fix "undefined offset" notice during live coding / arr…
Browse files Browse the repository at this point in the history
…ow functions

Defensive coding for the arrow functions backfill. This fixes a number of "undefined index" PHP notices when arrow functions are being declared during live coding.

```
Notice: Undefined offset: 561 in /path/to/PHP_CodeSniffer/src/Tokenizers/PHP.php on line 1807
Notice: Undefined offset: 561 in /path/to/PHP_CodeSniffer/src/Tokenizers/PHP.php on line 1808
Notice: Undefined offset: 561 in /path/to/PHP_CodeSniffer/src/Tokenizers/PHP.php on line 1815
```

It also fixes a bug where an inner for loop was using the wrong variable for the condition part.

Includes adjusted unit test + additional unit test covering all changes.

Includes minor documentation fix.
  • Loading branch information
jrfnl committed Jan 10, 2020
1 parent c2494e3 commit 332e094
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
6 changes: 3 additions & 3 deletions src/Tokenizers/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -1801,9 +1801,9 @@ protected function processAdditional()
}//end if

continue;
} else if ($this->tokens[$i]['code'] === T_FN) {
} else if ($this->tokens[$i]['code'] === T_FN && isset($this->tokens[($i + 1)]) === true) {
// Possible arrow function.
for ($x = ($i + 1); $i < $numTokens; $x++) {
for ($x = ($i + 1); $x < $numTokens; $x++) {
if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false
&& $this->tokens[$x]['code'] !== T_BITWISE_AND
) {
Expand All @@ -1812,7 +1812,7 @@ protected function processAdditional()
}
}

if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) {
if (isset($this->tokens[$x]) === true && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) {
$ignore = Util\Tokens::$emptyTokens;
$ignore += [
T_STRING => T_STRING,
Expand Down
4 changes: 4 additions & 0 deletions tests/Core/Tokenizer/BackfillFnTokenTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,7 @@ fn(callable $a) : callable => $a;

/* testTernary */
$fn = fn($a) => $a ? /* testTernaryThen */ fn() : string => 'a' : /* testTernaryElse */ fn() : string => 'b';

/* testLiveCoding */
// Intentional parse error. This has to be the last test in the file.
$fn = fn
26 changes: 25 additions & 1 deletion tests/Core/Tokenizer/BackfillFnTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,31 @@ public function testTernary()


/**
* Test that anonymous class tokens without parenthesis do not get assigned a parenthesis owner.
* Test that the backfill presumes T_FN during live coding, but doesn't set the additional index keys.
*
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
*
* @return void
*/
public function testLiveCoding()
{
$tokens = self::$phpcsFile->getTokens();

$token = $this->getTargetToken('/* testLiveCoding */', [T_STRING, T_FN]);
$this->assertSame($tokens[$token]['code'], T_FN, 'Token not tokenized as T_FN');

$this->assertArrayNotHasKey('scope_condition', $tokens[$token], 'Scope condition is set');
$this->assertArrayNotHasKey('scope_opener', $tokens[$token], 'Scope opener is set');
$this->assertArrayNotHasKey('scope_closer', $tokens[$token], 'Scope closer is set');
$this->assertArrayNotHasKey('parenthesis_owner', $tokens[$token], 'Parenthesis owner is set');
$this->assertArrayNotHasKey('parenthesis_opener', $tokens[$token], 'Parenthesis opener is set');
$this->assertArrayNotHasKey('parenthesis_closer', $tokens[$token], 'Parenthesis closer is set');

}//end testLiveCoding()


/**
* Helper function to check that all token keys are correctly set for T_FN tokens.
*
* @param string $token The T_FN token to check.
*
Expand Down

0 comments on commit 332e094

Please sign in to comment.