Skip to content

Commit

Permalink
Squiz/NonExecutableCode: fix false positives when code goes in and ou…
Browse files Browse the repository at this point in the history
…t of PHP/HTML (#3770)

Ignore HTML whitespace and PHP re-open tags when determining whether code should be flagged as non executable.
  • Loading branch information
fredden authored and jrfnl committed Oct 12, 2023
1 parent 1cdb2a1 commit 0b5db14
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 3 deletions.
16 changes: 13 additions & 3 deletions src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ public function process(File $phpcsFile, $stackPtr)
$end = ($phpcsFile->numTokens - 1);
}//end if

// Find the semicolon that ends this statement, skipping
// nested statements like FOR loops and closures.
// Find the semicolon or closing PHP tag that ends this statement,
// skipping nested statements like FOR loops and closures.
for ($start = ($stackPtr + 1); $start < $phpcsFile->numTokens; $start++) {
if ($start === $end) {
break;
Expand All @@ -262,7 +262,7 @@ public function process(File $phpcsFile, $stackPtr)
continue;
}

if ($tokens[$start]['code'] === T_SEMICOLON) {
if ($tokens[$start]['code'] === T_SEMICOLON || $tokens[$start]['code'] === T_CLOSE_TAG) {
break;
}
}//end for
Expand Down Expand Up @@ -295,6 +295,16 @@ public function process(File $phpcsFile, $stackPtr)
continue;
}

// Skip HTML whitespace.
if ($tokens[$i]['code'] === T_INLINE_HTML && \trim($tokens[$i]['content']) === '') {
continue;
}

// Skip PHP re-open tag (eg, after inline HTML).
if ($tokens[$i]['code'] === T_OPEN_TAG) {
continue;
}

$line = $tokens[$i]['line'];
if ($line > $lastLine) {
$type = substr($tokens[$stackPtr]['type'], 2);
Expand Down
12 changes: 12 additions & 0 deletions src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,16 @@ $a = new class {
}
};

// Multiple statements are still one line of unreachable code, so should get
// only one complaint from this sniff. (Well, technically two here since there
// are two 'exit()' statements above, so one complaint from each of those. So,
// two here, but not six.)
echo 'one'; echo 'two'; echo 'three';

// A single statement split across multiple lines. Here we get complaints for
// each line, even though they're all part of one statement.
echo 'one' . 'two'
. 'three' . 'four'
. 'five' . 'six';

interface MyInterface {
64 changes: 64 additions & 0 deletions src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.3.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<!-- no problem here -->
<?php if (true): ?>
<?php foreach ([] as $item): ?>
<?php continue; ?>
<?php endforeach; ?>
<?php endif; ?>

<!-- no problem here -->
<?php if (true) { ?>
<?php foreach ([] as $item) { ?>
<?php continue; ?>
<?php } ?>
<?php } ?>

<!-- no problem here -->
<?php if (true) { ?>
<?php foreach ([] as $item) { ?>
<!-- note missing semicolon on next line -->
<?php continue ?>
<?php } ?>
<?php } ?>

<!-- should detect an error here -->
<?php if (true): ?>
<?php foreach ([] as $item): ?>
<?php continue; ?>
<div>non-executable</div>
<?php endforeach; ?>
<?php endif; ?>

<!-- should detect an error here -->
<?php if (true): ?>
<?php foreach ([] as $item): ?>
<!-- note missing semicolon on next line -->
<?php continue ?>
<div>non-executable</div>
<?php endforeach; ?>
<?php endif; ?>

<!-- should detect an error here -->
<?php if (true): ?>
<?php foreach ([] as $item): ?>
<?php continue; ?>

<div>non-executable</div>

<?php endforeach; ?>
<?php endif; ?>

<!-- should detect an error here -->
<?php if (true): ?>
<?php foreach ([] as $item): ?>
<?php continue; ?>
<?= 'unreachable - no semicolon' ?>
<?php endforeach; ?>
<?php endif; ?>

<!-- should detect an error here -->
<?php if (true): ?>
<?php foreach ([] as $item): ?>
<?php continue; ?>
<?= 'unreachable - with semicolon'; ?>
<?php endforeach; ?>
<?php endif; ?>
12 changes: 12 additions & 0 deletions src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,20 @@ public function getWarningList($testFile='')
10 => 2,
14 => 1,
54 => 2,
65 => 2,
69 => 2,
70 => 2,
71 => 2,
];
break;
case 'NonExecutableCodeUnitTest.3.inc':
return [
27 => 1,
36 => 1,
45 => 1,
54 => 1,
62 => 1,
];
default:
return [];
break;
Expand Down

0 comments on commit 0b5db14

Please sign in to comment.