Skip to content

Commit 4c2ba65

Browse files
authored
Merge pull request #92 from PHPCSStandards/feature/squiz-nonexecutablecode-various-tweaks
Squiz/NonExecutableCode: simplify + improve handling of comments and closures
2 parents 76ebdef + 632600b commit 4c2ba65

File tree

4 files changed

+42
-33
lines changed

4 files changed

+42
-33
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ The file documents changes to the PHP_CodeSniffer project.
9090
- Thanks to Dan Wallis (@fredden) for the patch
9191
- Squiz.PHP.InnerFunctions sniff no longer reports on OO methods for OO structures declared within a function or closure
9292
- Thanks to @Daimona for the patch
93+
- Squiz.PHP.NonExecutableCode will now also flag redundant return statements just before a closure close brace
94+
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
9395
- Runtime performance improvement for PHPCS CLI users. The improvement should be most noticeable for users on Windows.
9496
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
9597
- The -e (explain) command will now list sniffs in natural order
@@ -175,6 +177,8 @@ The file documents changes to the PHP_CodeSniffer project.
175177
- Thanks to @simonsan for the patch
176178
- Fixed bug #3893 : Generic/DocComment : the SpacingAfterTagGroup fixer could accidentally remove ignore annotations
177179
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
180+
- Fixed bug #3898 : Squiz/NonExecutableCode : the sniff could get confused over comments in unexpected places
181+
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
178182
- Fixed bug #3904 : Squiz/FunctionSpacing : prevent potential fixer conflict
179183
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
180184
- Fixed bug #3906 : Tokenizer/CSS: fixed a bug related to the unsupported slash comment syntax

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

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -94,35 +94,29 @@ public function process(File $phpcsFile, $stackPtr)
9494
}
9595
}//end if
9696

97-
// Check if this token is actually part of a one-line IF or ELSE statement.
98-
for ($i = ($stackPtr - 1); $i > 0; $i--) {
99-
if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
100-
$i = $tokens[$i]['parenthesis_opener'];
101-
continue;
102-
} else if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) {
103-
continue;
104-
}
105-
106-
break;
107-
}
108-
109-
if ($tokens[$i]['code'] === T_IF
110-
|| $tokens[$i]['code'] === T_ELSE
111-
|| $tokens[$i]['code'] === T_ELSEIF
97+
// This token may be part of an inline condition.
98+
// If we find a closing parenthesis that belongs to a condition,
99+
// or an "else", we should ignore this token.
100+
if ($tokens[$prev]['code'] === T_ELSE
101+
|| (isset($tokens[$prev]['parenthesis_owner']) === true
102+
&& ($tokens[$tokens[$prev]['parenthesis_owner']]['code'] === T_IF
103+
|| $tokens[$tokens[$prev]['parenthesis_owner']]['code'] === T_ELSEIF))
112104
) {
113105
return;
114106
}
115107

116108
if ($tokens[$stackPtr]['code'] === T_RETURN) {
117-
$next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
109+
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
118110
if ($tokens[$next]['code'] === T_SEMICOLON) {
119-
$next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true);
111+
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true);
120112
if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
121113
// If this is the closing brace of a function
122114
// then this return statement doesn't return anything
123115
// and is not required anyway.
124116
$owner = $tokens[$next]['scope_condition'];
125-
if ($tokens[$owner]['code'] === T_FUNCTION) {
117+
if ($tokens[$owner]['code'] === T_FUNCTION
118+
|| $tokens[$owner]['code'] === T_CLOSURE
119+
) {
126120
$warning = 'Empty return statement not required here';
127121
$phpcsFile->addWarning($warning, $stackPtr, 'ReturnNotRequired');
128122
return;
@@ -174,21 +168,6 @@ public function process(File $phpcsFile, $stackPtr)
174168
}//end if
175169
}//end if
176170

177-
// This token may be part of an inline condition.
178-
// If we find a closing parenthesis that belongs to a condition
179-
// we should ignore this token.
180-
if (isset($tokens[$prev]['parenthesis_owner']) === true) {
181-
$owner = $tokens[$prev]['parenthesis_owner'];
182-
$ignore = [
183-
T_IF => true,
184-
T_ELSE => true,
185-
T_ELSEIF => true,
186-
];
187-
if (isset($ignore[$tokens[$owner]['code']]) === true) {
188-
return;
189-
}
190-
}
191-
192171
$ourConditions = array_keys($tokens[$stackPtr]['conditions']);
193172

194173
if (empty($ourConditions) === false) {

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,5 +396,28 @@ function executionStoppingThrowExpressionsE() {
396396
echo 'non-executable';
397397
}
398398

399+
function returnNotRequiredIgnoreCommentsA()
400+
{
401+
if ($something === TRUE) {
402+
return /*comment*/;
403+
}
404+
405+
echo 'foo';
406+
return /*comment*/;
407+
}
408+
409+
function returnNotRequiredIgnoreCommentsB()
410+
{
411+
echo 'foo';
412+
return;
413+
/*comment*/
414+
}
415+
416+
$closure = function ()
417+
{
418+
echo 'foo';
419+
return; // This return should be flagged as not required.
420+
};
421+
399422
// Intentional syntax error.
400423
return array_map(

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public function getWarningList($testFile='')
8282
386 => 1,
8383
391 => 1,
8484
396 => 1,
85+
406 => 1,
86+
412 => 1,
87+
419 => 1,
8588
];
8689

8790
case 'NonExecutableCodeUnitTest.2.inc':

0 commit comments

Comments
 (0)