Skip to content

Commit

Permalink
PHP 8.3 | Tokenizer/PHP + Generic/UnconditionalIfStatement: bug fix
Browse files Browse the repository at this point in the history
When analyzing code during live coding, a situation could occur where the open parenthesis for an `if` control structure exists, but not a closing parenthesis.
In that case, `$end` would be set to `-1` (via `-- null`) and the `for` loop would never even run, but a warning would still be thrown for the code.

This warning is a false positive and should be avoided.

On top of that, PHP 8.3 deprecates the use of the increment/decrement operators on non-float/non-integer values, which can cause the below warning when running the sniff on PHP 8.3.
```
An error occurred during processing; checking has been aborted. The error message was:
Decrement on type null has no effect, this will change in the next major version of PHP in
path\to\src\Standards\Generic\Sniffs\CodeAnalysis\UnconditionalIfStatementSniff.php on line 72
```

Both the incorrect sniff warning, as well as the PHP 8.3 deprecation warning will now be avoided via the defensive coding added to the sniff.

When debugging the issue on the command line with the added test and using the following command `phpcs -ps ./generic/tests/codeanalysis/UnconditionalIfStatementUnitTest.inc --standard=Generic --sniffs=Generic.CodeAnalysis.UnconditionalIfStatement`, I was not receiving any output at all.

Digging deeper, I discovered two (loosely related) bugs in the Tokenizer/PHP class, which were the cause of that and which could be seen when running the tests:
```
Undefined array key 63

path\to\src\Tokenizers\PHP.php:3074
path\to\src\Tokenizers\Tokenizer.php:103
path\to\src\Files\File.php:577
path\to\src\Files\File.php:331
path\to\src\Files\LocalFile.php:92
path\to\tests\Standards\AbstractSniffUnitTest.php:175
path\to\tests\TestSuite7.php:28
```

This bug is fixed by fixing the incorrect comparison on line 3073.

... which then exposed the next bug:

```
Undefined array key 63

path\to\src\Tokenizers\PHP.php:3080
path\to\src\Tokenizers\Tokenizer.php:103
path\to\src\Files\File.php:577
path\to\src\Files\File.php:331
path\to\src\Files\LocalFile.php:92
path\to\tests\Standards\AbstractSniffUnitTest.php:175
path\to\tests\TestSuite7.php:28
```

... which is fixed by adding some extra defensive coding in the condition.

All three fixes are covered by the one test which was added.
  • Loading branch information
jrfnl committed Nov 11, 2023
1 parent 5ef2b66 commit 8a5be4c
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function process(File $phpcsFile, $stackPtr)
$token = $tokens[$stackPtr];

// Skip if statement without body.
if (isset($token['parenthesis_opener']) === false) {
if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ if (true) {

if (file_exists(__FILE__) === true) {

}
}

// Intentional parse error/live coding.
// This needs to be the last test in the file.
if(true
6 changes: 4 additions & 2 deletions src/Tokenizers/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -3130,14 +3130,16 @@ protected function processAdditional()
|| $this->tokens[$i]['code'] === T_FALSE
|| $this->tokens[$i]['code'] === T_NULL
) {
for ($x = ($i + 1); $i < $numTokens; $x++) {
for ($x = ($i + 1); $x < $numTokens; $x++) {
if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
// Non-whitespace content.
break;
}
}

if (isset($this->tstringContexts[$this->tokens[$x]['code']]) === true) {
if ($x !== $numTokens
&& isset($this->tstringContexts[$this->tokens[$x]['code']]) === true
) {
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$line = $this->tokens[$i]['line'];
$type = $this->tokens[$i]['type'];
Expand Down

0 comments on commit 8a5be4c

Please sign in to comment.