Skip to content

Commit 7fc2e87

Browse files
committed
Squiz/NonExecutableCode: only ignore inline statements when PHP allows them
Aside from `T_EXIT`, PHP (prior to PHP 8.0) does not allow for the inline use of the other tokens this sniff registers. While using those tokens inline would result in a parse error, that is not the concern of this sniff. By ignoring these, the sniff causes false negatives. This commit makes the sniff more selective and only ignores inline statements for tokens which are allowed in inline statements. Includes unit test.
1 parent 272aa59 commit 7fc2e87

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
class NonExecutableCodeSniff implements Sniff
1717
{
1818

19+
/**
20+
* Tokens for terminating expressions, which can be used inline.
21+
*
22+
* This is in contrast to terminating statements, which cannot be used inline
23+
* and would result in a parse error (which is not the concern of this sniff).
24+
*
25+
* @var array
26+
*/
27+
private $expressionTokens = [T_EXIT => T_EXIT];
28+
1929

2030
/**
2131
* Returns an array of tokens this test wants to listen for.
@@ -49,11 +59,15 @@ public function process(File $phpcsFile, $stackPtr)
4959
{
5060
$tokens = $phpcsFile->getTokens();
5161

52-
// If this token is preceded with an "or", it only relates to one line
53-
// and should be ignored. For example: fopen() or die().
5462
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true);
55-
if ($tokens[$prev]['code'] === T_LOGICAL_OR || $tokens[$prev]['code'] === T_BOOLEAN_OR) {
56-
return;
63+
64+
// Tokens which can be used in inline expressions need special handling.
65+
if (isset($this->expressionTokens[$tokens[$stackPtr]['code']]) === true) {
66+
// If this token is preceded with an "or", it only relates to one line
67+
// and should be ignored. For example: fopen() or die().
68+
if ($tokens[$prev]['code'] === T_LOGICAL_OR || $tokens[$prev]['code'] === T_BOOLEAN_OR) {
69+
return;
70+
}
5771
}
5872

5973
// Check if this token is actually part of a one-line IF or ELSE statement.

src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,5 +297,16 @@ class TestAlternativeControlStructures {
297297
$var_after_class_in_global_space = 1;
298298
do_something_else();
299299

300+
// These are parse errors, but that's not the concern of the sniff.
301+
function parseError1() {
302+
defined('FOO') or return 'foo';
303+
echo 'unreachable';
304+
}
305+
306+
function parseError2() {
307+
defined('FOO') || continue;
308+
echo 'unreachable';
309+
}
310+
300311
// Intentional syntax error.
301312
return array_map(

src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public function getWarningList($testFile='')
7474
252 => 1,
7575
253 => 1,
7676
254 => 2,
77+
303 => 1,
78+
308 => 1,
7779
];
7880
break;
7981
case 'NonExecutableCodeUnitTest.2.inc':

0 commit comments

Comments
 (0)