Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 8.3 | Tokenizer/PHP + Generic/UnconditionalIfStatement: bug fix #3890

Conversation

jrfnl
Copy link
Contributor

@jrfnl jrfnl commented Sep 20, 2023

Description

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.

Suggested changelog entry

  • Generic/UnconditionalIfStatement: fixed false positive during live coding and prevent PHP 8.3 deprecation notice.
  • Tokenizer/PHP: fix PHP notice when true/false/null is at the end of a file during live coding.

Related issues/external references

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
    • This change is only breaking for integrators, not for external standards or end-users.
  • Documentation improvement

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.
@jrfnl jrfnl changed the title Tokenizer/PHP + Generic/UnconditionalIfStatement: bug fix PHP 8.3 | Tokenizer/PHP + Generic/UnconditionalIfStatement: bug fix Oct 25, 2023
@jrfnl
Copy link
Contributor Author

jrfnl commented Dec 2, 2023

Closing as replaced by PHPCSStandards/PHP_CodeSniffer#90

@jrfnl jrfnl closed this Dec 2, 2023
@jrfnl jrfnl deleted the php-8.3/generic-unconditionalifstatement-tokenizer-php-bugs branch December 2, 2023 02:35
@jrfnl
Copy link
Contributor Author

jrfnl commented Dec 8, 2023

FYI: this fix is included in today's PHP_CodeSniffer 3.8.0 release.

As per #3932, development on PHP_CodeSniffer will continue in the PHPCSStandards/PHP_CodeSniffer repository. If you want to stay informed, you may want to start "watching" that repo (or watching releases from that repo).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants