@@ -107,13 +107,13 @@ public function process(File $phpcsFile, $stackPtr)
107
107
}
108
108
}
109
109
110
- $ next = $ phpcsFile -> findNext ( T_WHITESPACE , ( $ opener + 1 ), null , true );
111
- if ($ tokens [$ next ]['line ' ] === $ tokens [ $ opener ][ ' line ' ]
112
- && ( $ tokens [$ next ]['code ' ] === T_COMMENT
113
- || isset (Tokens:: $ phpcsCommentTokens [ $ tokens [$ next ]['code ' ]]) === true )
114
- ) {
115
- // Skip comments on the same line.
116
- $ next = $ phpcsFile -> findNext ( T_WHITESPACE , ( $ next + 1 ), null , true );
110
+ for ( $ next = ( $ opener + 1 ); $ next < $ nextCloser ; $ next ++) {
111
+ if (isset (Tokens:: $ emptyTokens [ $ tokens [$ next ]['code ' ]]) === false
112
+ || ( isset (Tokens:: $ commentTokens [ $ tokens [$ next ]['code ' ]]) === true
113
+ && $ tokens [$ next ]['line ' ] !== $ tokens [ $ opener ][ ' line ' ] )
114
+ ) {
115
+ break ;
116
+ }
117
117
}
118
118
119
119
if ($ tokens [$ next ]['line ' ] !== ($ tokens [$ opener ]['line ' ] + 1 )) {
@@ -126,17 +126,21 @@ public function process(File $phpcsFile, $stackPtr)
126
126
} else {
127
127
$ phpcsFile ->fixer ->beginChangeset ();
128
128
for ($ i = ($ opener + 1 ); $ i < $ next ; $ i ++) {
129
+ if ($ tokens [$ i ]['line ' ] === $ tokens [$ opener ]['line ' ]) {
130
+ // Ignore trailing comments.
131
+ continue ;
132
+ }
133
+
129
134
if ($ tokens [$ i ]['line ' ] === $ tokens [$ next ]['line ' ]) {
130
135
break ;
131
136
}
132
137
133
138
$ phpcsFile ->fixer ->replaceToken ($ i , '' );
134
139
}
135
140
136
- $ phpcsFile ->fixer ->addNewLineBefore ($ i );
137
141
$ phpcsFile ->fixer ->endChangeset ();
138
142
}
139
- }
143
+ }//end if
140
144
}//end if
141
145
142
146
if ($ tokens [$ nextCloser ]['scope_condition ' ] === $ nextCase ) {
@@ -250,22 +254,25 @@ private function findNestedTerminator($phpcsFile, $stackPtr, $end)
250
254
251
255
if ($ tokens [$ lastToken ]['code ' ] === T_CLOSE_CURLY_BRACKET ) {
252
256
// 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
257
+ // belongs to a SWITCH, IF, ELSEIF or ELSE, TRY, CATCH OR FINALLY clause.
258
+ // If yes, we continue searching for a terminating statement within that
255
259
// block. Note that we have to make sure that every block of
256
260
// the entire if/else/switch statement has a terminating statement.
261
+ // For a try/catch/finally statement, either the finally block has
262
+ // to have a terminating statement or every try/catch block has to have one.
257
263
$ currentCloser = $ lastToken ;
258
264
$ hasElseBlock = false ;
265
+ $ hasCatchWithoutTerminator = false ;
259
266
do {
260
267
$ scopeOpener = $ tokens [$ currentCloser ]['scope_opener ' ];
261
268
$ scopeCloser = $ tokens [$ currentCloser ]['scope_closer ' ];
262
269
263
- $ prevToken = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ scopeOpener - 1 ), $ stackPtr , true );
270
+ $ prevToken = $ phpcsFile ->findPrevious (Tokens:: $ emptyTokens , ($ scopeOpener - 1 ), $ stackPtr , true );
264
271
if ($ prevToken === false ) {
265
272
return false ;
266
273
}
267
274
268
- // SWITCH, IF and ELSEIF clauses possess a condition we have to account for.
275
+ // SWITCH, IF, ELSEIF, CATCH clauses possess a condition we have to account for.
269
276
if ($ tokens [$ prevToken ]['code ' ] === T_CLOSE_PARENTHESIS ) {
270
277
$ prevToken = $ tokens [$ prevToken ]['parenthesis_owner ' ];
271
278
}
@@ -288,10 +295,39 @@ private function findNestedTerminator($phpcsFile, $stackPtr, $end)
288
295
return false ;
289
296
}
290
297
291
- $ currentCloser = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ prevToken - 1 ), $ stackPtr , true );
298
+ $ currentCloser = $ phpcsFile ->findPrevious (Tokens:: $ emptyTokens , ($ prevToken - 1 ), $ stackPtr , true );
292
299
if ($ tokens [$ prevToken ]['code ' ] === T_ELSE ) {
293
300
$ hasElseBlock = true ;
294
301
}
302
+ } else if ($ tokens [$ prevToken ]['code ' ] === T_FINALLY ) {
303
+ // If we find a terminating statement within this block,
304
+ // the whole try/catch/finally statement is covered.
305
+ $ hasTerminator = $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
306
+ if ($ hasTerminator !== false ) {
307
+ return $ hasTerminator ;
308
+ }
309
+
310
+ // Otherwise, we continue with the previous TRY or CATCH clause.
311
+ $ currentCloser = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , ($ prevToken - 1 ), $ stackPtr , true );
312
+ } else if ($ tokens [$ prevToken ]['code ' ] === T_TRY ) {
313
+ // If we've seen CATCH blocks without terminator statement and
314
+ // have not seen a FINALLY *with* a terminator statement, we
315
+ // don't even need to bother checking the TRY.
316
+ if ($ hasCatchWithoutTerminator === true ) {
317
+ return false ;
318
+ }
319
+
320
+ return $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
321
+ } else if ($ tokens [$ prevToken ]['code ' ] === T_CATCH ) {
322
+ // Keep track of seen catch statements without terminating statement,
323
+ // but don't bow out yet as there may still be a FINALLY clause
324
+ // with a terminating statement before the CATCH.
325
+ $ hasTerminator = $ this ->findNestedTerminator ($ phpcsFile , ($ scopeOpener + 1 ), $ scopeCloser );
326
+ if ($ hasTerminator === false ) {
327
+ $ hasCatchWithoutTerminator = true ;
328
+ }
329
+
330
+ $ currentCloser = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , ($ prevToken - 1 ), $ stackPtr , true );
295
331
} else if ($ tokens [$ prevToken ]['code ' ] === T_SWITCH ) {
296
332
$ hasDefaultBlock = false ;
297
333
$ endOfSwitch = $ tokens [$ prevToken ]['scope_closer ' ];
@@ -305,7 +341,7 @@ private function findNestedTerminator($phpcsFile, $stackPtr, $end)
305
341
306
342
$ opener = $ tokens [$ nextCase ]['scope_opener ' ];
307
343
308
- $ nextCode = $ phpcsFile ->findNext (T_WHITESPACE , ($ opener + 1 ), $ endOfSwitch , true );
344
+ $ nextCode = $ phpcsFile ->findNext (Tokens:: $ emptyTokens , ($ opener + 1 ), $ endOfSwitch , true );
309
345
if ($ tokens [$ nextCode ]['code ' ] === T_CASE || $ tokens [$ nextCode ]['code ' ] === T_DEFAULT ) {
310
346
// This case statement has no content, so skip it.
311
347
continue ;
@@ -339,15 +375,15 @@ private function findNestedTerminator($phpcsFile, $stackPtr, $end)
339
375
// We found the last statement of the CASE. Now we want to
340
376
// check whether it is a terminating one.
341
377
$ terminators = [
342
- T_RETURN ,
343
- T_BREAK ,
344
- T_CONTINUE ,
345
- T_THROW ,
346
- T_EXIT ,
378
+ T_RETURN => T_RETURN ,
379
+ T_BREAK => T_BREAK ,
380
+ T_CONTINUE => T_CONTINUE ,
381
+ T_THROW => T_THROW ,
382
+ T_EXIT => T_EXIT ,
347
383
];
348
384
349
385
$ terminator = $ phpcsFile ->findStartOfStatement (($ lastToken - 1 ));
350
- if (in_array ( $ tokens [$ terminator ]['code ' ], $ terminators , true ) === true ) {
386
+ if (isset ( $ terminators [ $ tokens [$ terminator ]['code ' ]] ) === true ) {
351
387
return $ terminator ;
352
388
}
353
389
}//end if
0 commit comments