17
17
18
18
import lombok .EqualsAndHashCode ;
19
19
import lombok .Value ;
20
+ import org .openrewrite .Cursor ;
20
21
import org .openrewrite .Tree ;
21
22
import org .openrewrite .internal .ListUtils ;
22
23
import org .openrewrite .java .JavaIsoVisitor ;
@@ -54,7 +55,7 @@ public J.Case visitCase(J.Case case_, P p) {
54
55
if (getCursor ().firstEnclosing (J .Switch .class ) != null ) {
55
56
J .Switch switch_ = getCursor ().dropParentUntil (J .Switch .class ::isInstance ).getValue ();
56
57
if (Boolean .TRUE .equals (style .getCheckLastCaseGroup ()) || !isLastCase (case_ , switch_ )) {
57
- if (FindLastLineBreaksOrFallsThroughComments .find (switch_ , c ).isEmpty () && FindGuaranteedReturns .find (switch_ , c ).isEmpty ()) {
58
+ if (FindLastLineBreaksOrFallsThroughComments .find (switch_ , c ).isEmpty () && FindGuaranteedReturns .find (getCursor (), switch_ , c ).isEmpty ()) {
58
59
c = (J .Case ) new AddBreak <>(c ).visitNonNull (c , p , getCursor ().getParentOrThrow ());
59
60
}
60
61
}
@@ -232,30 +233,32 @@ private FindGuaranteedReturns() {
232
233
* @param scope the {@link J.Case} to use as a target.
233
234
* @return A set representing whether the case contains any guaranteed {@link J.Return} statements.
234
235
*/
235
- private static Set <J > find (J .Switch enclosingSwitch , J .Case scope ) {
236
+ private static Set <J > find (Cursor cursor , J .Switch enclosingSwitch , J .Case scope ) {
236
237
Set <J > references = new HashSet <>();
237
- new FindGuaranteedReturnsVisitor (scope ).visit (enclosingSwitch , references );
238
+ new FindGuaranteedReturnsVisitor (cursor , scope ).visit (enclosingSwitch , references );
238
239
return references ;
239
240
}
240
241
241
242
private static class FindGuaranteedReturnsVisitor extends JavaIsoVisitor <Set <J >> {
243
+ private Cursor cursor ;
242
244
private final J .Case scope ;
243
245
244
- public FindGuaranteedReturnsVisitor (J .Case scope ) {
246
+ public FindGuaranteedReturnsVisitor (Cursor cursor , J .Case scope ) {
247
+ this .cursor = cursor ;
245
248
this .scope = scope ;
246
249
}
247
250
248
251
249
- private static boolean hasGuaranteedReturn (List <? extends Statement > trees ) {
252
+ private boolean hasGuaranteedReturn (List <? extends Statement > trees ) {
250
253
return trees .stream ()
251
254
.anyMatch (s -> returns (s ));
252
255
}
253
256
254
- private static boolean returns (Statement s ) {
257
+ private boolean returns (Statement s ) {
255
258
if (s instanceof J .ForLoop ) {
256
259
J .ForLoop forLoop = (J .ForLoop ) s ;
257
260
Expression condition = forLoop .getControl ().getCondition ();
258
- if (condition == null || condition instanceof J .Empty || (condition instanceof J .Literal && ((J .Literal ) condition ).getValue () == Boolean .TRUE )) {
261
+ if (condition == null || condition instanceof J .Empty || (condition instanceof J .Literal && ((J .Literal ) condition ).getValue () == Boolean .TRUE ) || isFinalTrue ( condition ) ) {
259
262
Statement body = forLoop .getBody ();
260
263
if (body instanceof J .Block ) {
261
264
return !hasBreak (((J .Block ) body ).getStatements ()) && hasGuaranteedReturn (((J .Block ) body ).getStatements ());
@@ -265,30 +268,71 @@ private static boolean returns(Statement s) {
265
268
}
266
269
} else if (s instanceof J .WhileLoop ) {
267
270
J .WhileLoop whileLoop = (J .WhileLoop ) s ;
268
- Expression condition = whileLoop .getCondition ();
269
- if (((J .ControlParentheses <?>) condition ).getTree () instanceof J .Literal ) {
270
- J .Literal value = (J .Literal ) ((J .ControlParentheses <?>) condition ).getTree ();
271
- if (value .getValue () == Boolean .TRUE ) {
272
- Statement body = whileLoop .getBody ();
273
- if (body instanceof J .Block ) {
274
- return !hasBreak (((J .Block ) body ).getStatements ()) && hasGuaranteedReturn (((J .Block ) body ).getStatements ());
275
- } else {
276
- return hasGuaranteedReturn (Collections .singletonList (whileLoop .getBody ()));
277
- }
271
+ Expression condition = whileLoop .getCondition ().getTree ();
272
+ if (condition instanceof J .Literal && ((J .Literal ) condition ).getValue () == Boolean .TRUE || isFinalTrue (condition )) {
273
+ Statement body = whileLoop .getBody ();
274
+ if (body instanceof J .Block ) {
275
+ return !hasBreak (((J .Block ) body ).getStatements ()) && hasGuaranteedReturn (((J .Block ) body ).getStatements ());
276
+ } else {
277
+ return hasGuaranteedReturn (Collections .singletonList (whileLoop .getBody ()));
278
278
}
279
279
}
280
280
}
281
281
return s instanceof J .Return ;
282
282
}
283
283
284
+ private boolean isFinalTrue (Expression condition ) {
285
+ if (condition instanceof J .Identifier && ((J .Identifier ) condition ).getFieldType () != null && ((J .Identifier ) condition ).getFieldType ().hasFlags (Flag .Final )) {
286
+ J .Identifier id = (J .Identifier ) condition ;
287
+ J .VariableDeclarations .NamedVariable declaration = null ;
288
+ while (declaration == null ) {
289
+ J value = cursor .getValue ();
290
+ if (value instanceof J .Case ) {
291
+ List <Statement > statements = ((J .Case ) value ).getStatements ();
292
+ declaration = finalVariableDeclaration (statements , id );
293
+ } else if (value instanceof J .MethodDeclaration ) {
294
+ List <Statement > statements = ((J .MethodDeclaration ) value ).getBody ().getStatements ();
295
+ declaration = finalVariableDeclaration (statements , id );
296
+ } else if (value instanceof J .ClassDeclaration ) {
297
+ List <Statement > statements = ((J .ClassDeclaration ) value ).getBody ().getStatements ();
298
+ declaration = finalVariableDeclaration (statements , id );
299
+ }
300
+ cursor = cursor .getParentTreeCursor ();
301
+ if (cursor .isRoot ()) {
302
+ break ;
303
+ }
304
+ }
305
+ if (declaration != null ) {
306
+ return declaration .getInitializer () instanceof J .Literal && ((J .Literal ) declaration .getInitializer ()).getValue () == Boolean .TRUE ;
307
+ }
308
+ }
309
+ return false ;
310
+ }
311
+
312
+ private J .VariableDeclarations .NamedVariable finalVariableDeclaration (List <Statement > statements , J .Identifier id ) {
313
+ for (Statement s : statements ) {
314
+ if (s instanceof J .VariableDeclarations ) {
315
+ J .VariableDeclarations vd = (J .VariableDeclarations ) s ;
316
+ if (TypeUtils .isAssignableTo ("boolean" , vd .getType ()) && vd .hasModifier (J .Modifier .Type .Final )) {
317
+ for (J .VariableDeclarations .NamedVariable v : vd .getVariables ()) {
318
+ if (v .getSimpleName ().equals (id .getSimpleName ())) {
319
+ return v ;
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
325
+ return null ;
326
+ }
327
+
284
328
private static boolean hasBreak (List <Statement > statements ) {
285
329
for (Statement s : statements ) {
286
330
if (s instanceof J .Break ) {
287
331
return true ;
288
332
} else if (s instanceof J .If ) {
289
333
J .If if_ = (J .If ) s ;
290
334
Statement body = if_ .getThenPart ();
291
- boolean hasBreak = false ;
335
+ boolean hasBreak ;
292
336
if (body instanceof J .Block ) {
293
337
hasBreak = hasBreak (((J .Block ) body ).getStatements ());
294
338
} else {
0 commit comments