@@ -229,118 +229,127 @@ private function findNextCase($phpcsFile, $stackPtr, $end)
229229
230230
231231 /**
232- * Returns true if a nested terminating statement is found.
232+ * Returns the position of the nested terminating statement.
233+ *
234+ * Returns false if no terminating statement was found.
233235 *
234236 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
235237 * @param int $stackPtr The position to start looking at.
236238 * @param int $end The position to stop looking at.
237239 *
238- * @return bool
240+ * @return int|false
239241 */
240242 private function findNestedTerminator ($ phpcsFile , $ stackPtr , $ end )
241243 {
242- $ tokens = $ phpcsFile ->getTokens ();
243- $ terminators = [
244- T_RETURN ,
245- T_BREAK ,
246- T_CONTINUE ,
247- T_THROW ,
248- T_EXIT ,
249- ];
244+ $ tokens = $ phpcsFile ->getTokens ();
250245
251246 $ lastToken = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ end - 1 ), $ stackPtr , true );
252- if ($ lastToken !== false ) {
253- if ($ tokens [$ lastToken ]['code ' ] === T_CLOSE_CURLY_BRACKET ) {
254- // We found a closing curly bracket and want to check if its block
255- // belongs to a SWITCH or an IF, ELSEIF or ELSE clause. If yes, we
256- // continue searching for a terminating statement within that
257- // block. Note that we have to make sure that every block of
258- // the entire if/else statement has a terminating statement.
259- $ currentCloser = $ lastToken ;
260- $ hasElseBlock = false ;
261- do {
262- $ scopeOpener = $ tokens [$ currentCloser ]['scope_opener ' ];
263- $ scopeCloser = $ tokens [$ currentCloser ]['scope_closer ' ];
264-
265- $ prevToken = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ scopeOpener - 1 ), $ stackPtr , true );
266- if ($ prevToken === false ) {
247+ if ($ lastToken === false ) {
248+ return false ;
249+ }
250+
251+ if ($ tokens [$ lastToken ]['code ' ] === T_CLOSE_CURLY_BRACKET ) {
252+ // We found a closing curly bracket and want to check if its block
253+ // belongs to a SWITCH, IF, ELSEIF or ELSE clause. If yes, we
254+ // continue searching for a terminating statement within that
255+ // block. Note that we have to make sure that every block of
256+ // the entire if/else/switch statement has a terminating statement.
257+ $ currentCloser = $ lastToken ;
258+ $ hasElseBlock = false ;
259+ do {
260+ $ scopeOpener = $ tokens [$ currentCloser ]['scope_opener ' ];
261+ $ scopeCloser = $ tokens [$ currentCloser ]['scope_closer ' ];
262+
263+ $ prevToken = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ scopeOpener - 1 ), $ stackPtr , true );
264+ if ($ prevToken === false ) {
265+ return false ;
266+ }
267+
268+ // SWITCH, IF and ELSEIF clauses possess a condition we have to account for.
269+ if ($ tokens [$ prevToken ]['code ' ] === T_CLOSE_PARENTHESIS ) {
270+ $ prevToken = $ tokens [$ prevToken ]['parenthesis_owner ' ];
271+ }
272+
273+ if ($ tokens [$ prevToken ]['code ' ] === T_IF ) {
274+ // If we have not encountered an ELSE clause by now, we cannot
275+ // be sure that the whole statement terminates in every case.
276+ if ($ hasElseBlock === false ) {
267277 return false ;
268278 }
269279
270- // SWITCH, IF and ELSEIF clauses possess a condition we have to account for.
271- if ($ tokens [$ prevToken ]['code ' ] === T_CLOSE_PARENTHESIS ) {
272- $ prevToken = $ tokens [$ prevToken ]['parenthesis_owner ' ];
280+ return $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
281+ } else if ($ tokens [$ prevToken ]['code ' ] === T_ELSEIF
282+ || $ tokens [$ prevToken ]['code ' ] === T_ELSE
283+ ) {
284+ // If we find a terminating statement within this block,
285+ // we continue with the previous ELSEIF or IF clause.
286+ $ hasTerminator = $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
287+ if ($ hasTerminator === false ) {
288+ return false ;
273289 }
274290
275- if ($ tokens [$ prevToken ]['code ' ] === T_IF ) {
276- // If we have not encountered an ELSE clause by now, we cannot
277- // be sure that the whole statement terminates in every case.
278- if ($ hasElseBlock === false ) {
279- return false ;
291+ $ currentCloser = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ prevToken - 1 ), $ stackPtr , true );
292+ if ($ tokens [$ prevToken ]['code ' ] === T_ELSE ) {
293+ $ hasElseBlock = true ;
294+ }
295+ } else if ($ tokens [$ prevToken ]['code ' ] === T_SWITCH ) {
296+ $ hasDefaultBlock = false ;
297+ $ endOfSwitch = $ tokens [$ prevToken ]['scope_closer ' ];
298+ $ nextCase = $ prevToken ;
299+
300+ // We look for a terminating statement within every blocks.
301+ while (($ nextCase = $ this ->findNextCase ($ phpcsFile , ($ nextCase + 1 ), $ endOfSwitch )) !== false ) {
302+ if ($ tokens [$ nextCase ]['code ' ] === T_DEFAULT ) {
303+ $ hasDefaultBlock = true ;
280304 }
281305
282- return $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
283- } else if ($ tokens [$ prevToken ]['code ' ] === T_ELSEIF
284- || $ tokens [$ prevToken ]['code ' ] === T_ELSE
285- ) {
286- // If we find a terminating statement within this block,
287- // we continue with the previous ELSEIF or IF clause.
288- $ hasTerminator = $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
289- if ($ hasTerminator === false ) {
290- return false ;
291- }
306+ $ opener = $ tokens [$ nextCase ]['scope_opener ' ];
292307
293- $ currentCloser = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ prevToken - 1 ), $ stackPtr , true );
294- if ($ tokens [$ prevToken ]['code ' ] === T_ELSE ) {
295- $ hasElseBlock = true ;
308+ $ nextCode = $ phpcsFile ->findNext (T_WHITESPACE , ($ opener + 1 ), $ endOfSwitch , true );
309+ if ($ tokens [$ nextCode ]['code ' ] === T_CASE || $ tokens [$ nextCode ]['code ' ] === T_DEFAULT ) {
310+ // This case statement has no content, so skip it.
311+ continue ;
296312 }
297- } else if ($ tokens [$ prevToken ]['code ' ] === T_SWITCH ) {
298- $ hasDefaultBlock = false ;
299- $ endOfSwitch = $ tokens [$ prevToken ]['scope_closer ' ];
300- $ nextCase = $ prevToken ;
301-
302- // We look for a terminating statement within every blocks.
303- while (($ nextCase = $ this ->findNextCase ($ phpcsFile , ($ nextCase + 1 ), $ endOfSwitch )) !== false ) {
304- if ($ tokens [$ nextCase ]['code ' ] === T_DEFAULT ) {
305- $ hasDefaultBlock = true ;
306- }
307313
308- $ opener = $ tokens [$ nextCase ]['scope_opener ' ];
309-
310- $ nextCode = $ phpcsFile ->findNext (T_WHITESPACE , ($ opener + 1 ), $ endOfSwitch , true );
311- if ($ tokens [$ nextCode ]['code ' ] === T_CASE || $ tokens [$ nextCode ]['code ' ] === T_DEFAULT ) {
312- // This case statement has no content. We skip it.
313- continue ;
314- }
315-
316- $ nextCode = $ this ->findNextCase ($ phpcsFile , ($ opener + 1 ), $ endOfSwitch );
317- if ($ nextCode === false ) {
318- $ nextCode = $ endOfSwitch ;
319- }
314+ $ endOfCase = $ this ->findNextCase ($ phpcsFile , ($ opener + 1 ), $ endOfSwitch );
315+ if ($ endOfCase === false ) {
316+ $ endOfCase = $ endOfSwitch ;
317+ }
320318
321- $ hasTerminator = $ this ->findNestedTerminator ($ phpcsFile , ($ opener + 1 ), $ nextCode );
322- if ($ hasTerminator === false ) {
323- return false ;
324- }
325- }//end while
319+ $ hasTerminator = $ this ->findNestedTerminator ($ phpcsFile , ($ opener + 1 ), $ endOfCase );
320+ if ($ hasTerminator === false ) {
321+ return false ;
322+ }
323+ }//end while
326324
327- // If we have not encountered a DEFAULT block by now, we cannot
328- // be sure that the whole statement terminates in every case.
329- return $ hasDefaultBlock ;
330- } else {
325+ // If we have not encountered a DEFAULT block by now, we cannot
326+ // be sure that the whole statement terminates in every case.
327+ if ($ hasDefaultBlock === false ) {
331328 return false ;
332- }//end if
333- } while ($ currentCloser !== false && $ tokens [$ currentCloser ]['code ' ] === T_CLOSE_CURLY_BRACKET );
334-
335- return true ;
336- } else if ($ tokens [$ lastToken ]['code ' ] === T_SEMICOLON ) {
337- // We found the last statement of the CASE. Now we want to
338- // check whether it is a terminating one.
339- $ terminator = $ phpcsFile ->findStartOfStatement (($ lastToken - 1 ));
340- if (in_array ($ tokens [$ terminator ]['code ' ], $ terminators , true ) === true ) {
341- return $ terminator ;
342- }
343- }//end if
329+ }
330+
331+ return $ hasTerminator ;
332+ } else {
333+ return false ;
334+ }//end if
335+ } while ($ currentCloser !== false && $ tokens [$ currentCloser ]['code ' ] === T_CLOSE_CURLY_BRACKET );
336+
337+ return true ;
338+ } else if ($ tokens [$ lastToken ]['code ' ] === T_SEMICOLON ) {
339+ // We found the last statement of the CASE. Now we want to
340+ // check whether it is a terminating one.
341+ $ terminators = [
342+ T_RETURN ,
343+ T_BREAK ,
344+ T_CONTINUE ,
345+ T_THROW ,
346+ T_EXIT ,
347+ ];
348+
349+ $ terminator = $ phpcsFile ->findStartOfStatement (($ lastToken - 1 ));
350+ if (in_array ($ tokens [$ terminator ]['code ' ], $ terminators , true ) === true ) {
351+ return $ terminator ;
352+ }
344353 }//end if
345354
346355 return false ;
0 commit comments