Skip to content

Commit b9ade19

Browse files
committed
Squiz/NonExecutableCode: fix undefined index during live coding reviews
Came across this error when running fixer conflict checks for the various standards. Error encountered: `Undefined index: scope_closer in phpcs/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php on line 238` Error occurred when an unfinished function or OO structure is encountered. While looking at the code, I saw three more minor improvements which I have included in this PR: * Account for modern PHP OO structures. The sniff is designed to skip over declarations, but only accounted for functions, classes and interfaces. This has been updated to include closures, traits and anonymous classes. * Add the semi-colon to the ignore list for reporting. In this context a 'lone' semi-colon is most often encountered at the end of a closure or anonymous class, so this might as well be skipped over. * The sniff can thrown two or more errors on the same line when several "exit" commands have been found above the line. I've adjusted the error message to also report on the line where the "exit" command was encountered to make it easier to fix/debug these type of errors. Includes unit tests. To reproduce/test: take the updated unit test file and just run the original sniff over it.
1 parent be6850f commit b9ade19

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,25 +225,34 @@ public function process(File $phpcsFile, $stackPtr)
225225
for ($i = ($start + 1); $i < $end; $i++) {
226226
if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true
227227
|| isset(Tokens::$bracketTokens[$tokens[$i]['code']]) === true
228+
|| $tokens[$i]['code'] === T_SEMICOLON
228229
) {
229230
continue;
230231
}
231232

232233
// Skip whole functions and classes/interfaces because they are not
233234
// technically executed code, but rather declarations that may be used.
234-
if ($tokens[$i]['code'] === T_FUNCTION
235-
|| $tokens[$i]['code'] === T_CLASS
236-
|| $tokens[$i]['code'] === T_INTERFACE
235+
if (isset(Tokens::$ooScopeTokens[$tokens[$i]['code']]) === true
236+
|| $tokens[$i]['code'] === T_FUNCTION
237+
|| $tokens[$i]['code'] === T_CLOSURE
237238
) {
239+
if (isset($tokens[$i]['scope_closer']) === false) {
240+
// Parse error/Live coding.
241+
return;
242+
}
243+
238244
$i = $tokens[$i]['scope_closer'];
239245
continue;
240246
}
241247

242248
$line = $tokens[$i]['line'];
243249
if ($line > $lastLine) {
244250
$type = substr($tokens[$stackPtr]['type'], 2);
245-
$warning = 'Code after %s statement cannot be executed';
246-
$data = [$type];
251+
$warning = 'Code after %s statement (line %s) cannot be executed';
252+
$data = [
253+
$type,
254+
$tokens[$stackPtr]['line'],
255+
];
247256
$phpcsFile->addWarning($warning, $i, 'Unreachable', $data);
248257
$lastLine = $line;
249258
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,22 @@ class HttpStatus
259259
const CONTINUE = 100;
260260
const SWITCHING_PROTOCOLS = 101;
261261
}
262+
263+
interface ABC {
264+
public function noError($name, $var);
265+
}
266+
267+
trait Something {
268+
function getReturnType() {
269+
echo 'no error';
270+
}
271+
}
272+
273+
$a = new class {
274+
public function log($msg)
275+
{
276+
echo 'no error';
277+
}
278+
};
279+
280+
interface MyInterface {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public function getWarningList()
6969
234 => 1,
7070
235 => 2,
7171
239 => 1,
72+
273 => 2,
7273
];
7374

7475
}//end getWarningList()

0 commit comments

Comments
 (0)