@@ -94,7 +94,7 @@ public final class StatementSwitchToExpressionSwitch extends BugChecker
9494 ImmutableSet .of (THROW , EXPRESSION_STATEMENT );
9595 private static final ImmutableSet <Kind > KINDS_RETURN_OR_THROW = ImmutableSet .of (THROW , RETURN );
9696 private static final Pattern FALL_THROUGH_PATTERN =
97- Pattern .compile ("\\ bfalls?.?( through|out) \\ b" , Pattern .CASE_INSENSITIVE );
97+ Pattern .compile ("\\ bfalls?.?through\\ b" , Pattern .CASE_INSENSITIVE );
9898 // Default (negative) result for assignment switch conversion analysis. Note that the value is
9999 // immutable.
100100 private static final AssignmentSwitchAnalysisResult DEFAULT_ASSIGNMENT_SWITCH_ANALYSIS_RESULT =
@@ -325,14 +325,21 @@ private static CaseQualifications analyzeCaseForReturnSwitch(
325325 return previousCaseQualifications ;
326326 }
327327
328- // Statement blocks on the RHS are not currently supported
329- if (!(statements .size () == 1 && KINDS_RETURN_OR_THROW .contains (statements .get (0 ).getKind ()))) {
328+ // Statement blocks on the RHS are not currently supported, except for trivial blocks of
329+ // statements expressions followed by a return or throw
330+ // TODO: handle more complex statement blocks that can be converted using 'yield'
331+ if (statements .isEmpty ()) {
332+ return CaseQualifications .SOME_OR_ALL_CASES_DONT_QUALIFY ;
333+ }
334+ StatementTree lastStatement = getLast (statements );
335+ if (!statements .subList (0 , statements .size () - 1 ).stream ()
336+ .allMatch (statement -> statement .getKind ().equals (EXPRESSION_STATEMENT ))
337+ || !KINDS_RETURN_OR_THROW .contains (lastStatement .getKind ())) {
330338 return CaseQualifications .SOME_OR_ALL_CASES_DONT_QUALIFY ;
331339 }
332340
333- StatementTree onlyStatement = statements .get (0 );
334341 // For this analysis, cases that don't return something can be disregarded
335- if (!onlyStatement .getKind ().equals (RETURN )) {
342+ if (!lastStatement .getKind ().equals (RETURN )) {
336343 return previousCaseQualifications ;
337344 }
338345
@@ -343,7 +350,7 @@ private static CaseQualifications analyzeCaseForReturnSwitch(
343350 }
344351
345352 // This is the first value-returning case that we are examining
346- Type returnType = ASTHelpers .getType (((ReturnTree ) onlyStatement ).getExpression ());
353+ Type returnType = ASTHelpers .getType (((ReturnTree ) lastStatement ).getExpression ());
347354 return returnType == null
348355 // Return of void does not qualify
349356 ? CaseQualifications .SOME_OR_ALL_CASES_DONT_QUALIFY
@@ -1117,21 +1124,30 @@ private static String transformReturnOrThrowBlock(
11171124 CaseTree caseTree , VisitorState state , List <? extends StatementTree > statements ) {
11181125
11191126 StringBuilder transformedBlockBuilder = new StringBuilder ();
1120- int codeBlockStart ;
1121- int codeBlockEnd =
1122- statements .isEmpty ()
1123- ? getBlockEnd (state , caseTree )
1124- : state .getEndPosition (Streams .findLast (statements .stream ()).get ());
1125-
1126- if (statements .size () == 1 && statements .get (0 ).getKind ().equals (RETURN )) {
1127+ int codeBlockEnd = state .getEndPosition (caseTree );
1128+ if (statements .size () > 1 ) {
1129+ transformedBlockBuilder .append ("{\n " );
1130+ int codeBlockStart = extractLhsComments (caseTree , state , transformedBlockBuilder );
1131+ int offset = transformedBlockBuilder .length ();
1132+ transformedBlockBuilder .append (state .getSourceCode (), codeBlockStart , codeBlockEnd );
1133+ transformedBlockBuilder .append ("\n }" );
1134+ ReturnTree returnTree = (ReturnTree ) getLast (statements );
1135+ int start = getStartPosition (returnTree );
1136+ transformedBlockBuilder .replace (
1137+ offset + start - codeBlockStart ,
1138+ offset + start - codeBlockStart + "return" .length (),
1139+ "yield" );
1140+ } else if (statements .size () == 1 && statements .get (0 ).getKind ().equals (RETURN )) {
11271141 // For "return x;", we want to take source starting after the "return"
11281142 int unused = extractLhsComments (caseTree , state , transformedBlockBuilder );
11291143 ReturnTree returnTree = (ReturnTree ) statements .get (0 );
1130- codeBlockStart = getStartPosition (returnTree .getExpression ());
1144+ int codeBlockStart = getStartPosition (returnTree .getExpression ());
1145+ codeBlockEnd = state .getEndPosition (Streams .findLast (statements .stream ()).get ());
1146+ transformedBlockBuilder .append (state .getSourceCode (), codeBlockStart , codeBlockEnd );
11311147 } else {
1132- codeBlockStart = extractLhsComments (caseTree , state , transformedBlockBuilder );
1148+ int codeBlockStart = extractLhsComments (caseTree , state , transformedBlockBuilder );
1149+ transformedBlockBuilder .append (state .getSourceCode (), codeBlockStart , codeBlockEnd );
11331150 }
1134- transformedBlockBuilder .append (state .getSourceCode (), codeBlockStart , codeBlockEnd );
11351151
11361152 return transformedBlockBuilder .toString ();
11371153 }
0 commit comments