Skip to content

Commit a58b8b2

Browse files
authored
Ensure case always has a space before the label in IfElseIfConstructToSwitch (#1071)
Guarantee a single space between `case` and the pattern label when the label prefix is empty and the type expression has no leading whitespace, so the printed switch is always well-formed (e.g. `case Type name` rather than `caseType name`). See openrewrite/rewrite#7458
1 parent eac4344 commit a58b8b2

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

src/main/java/org/openrewrite/java/migrate/lang/IfElseIfConstructToSwitch.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.openrewrite.java.tree.JRightPadded;
3131
import org.openrewrite.java.tree.Space;
3232
import org.openrewrite.java.tree.Statement;
33+
import org.openrewrite.java.tree.TypeTree;
3334
import org.openrewrite.marker.Markers;
3435
import org.openrewrite.staticanalysis.groovy.GroovyFileChecker;
3536
import org.openrewrite.staticanalysis.kotlin.KotlinFileChecker;
@@ -264,15 +265,31 @@ private J.Switch fixTypeAttribution(J.Switch switch_) {
264265
var0.withType( originalPattern.getType() )
265266
.withName( var0.getName().withType( originalPattern.getType() ) ) ) );
266267
}
267-
return case_.withCaseLabels( singletonList( varDecl.withPrefix( label.getPrefix() ) ) );
268+
return case_.withCaseLabels( singletonList( varDecl.withPrefix( ensureLeadingSpace( label.getPrefix(), varDecl.getTypeExpression() ) ) ) );
268269
}
269270
// JavaTemplate couldn't resolve the type, so no VariableDeclarations was produced.
270271
// Reconstruct one from the original instanceof pattern.
271272
return case_.withCaseLabels( singletonList(
272-
buildVariableDeclarations( instanceOf, label.getPrefix() ) ) );
273+
buildVariableDeclarations( instanceOf, ensureLeadingSpace( label.getPrefix(), null ) ) ) );
273274
})));
274275
}
275276

277+
/**
278+
* The label prefix carries the space after {@code case}. If it is empty and the
279+
* type expression also has no leading space, the printed output would collapse
280+
* {@code case} into the type name (e.g. {@code caseType name}). Guarantee a
281+
* single space so the emitted switch case is always well-formed.
282+
*/
283+
private Space ensureLeadingSpace(Space labelPrefix, @Nullable TypeTree typeExpression) {
284+
if (!labelPrefix.getWhitespace().isEmpty()) {
285+
return labelPrefix;
286+
}
287+
if (typeExpression != null && !typeExpression.getPrefix().getWhitespace().isEmpty()) {
288+
return labelPrefix;
289+
}
290+
return Space.SINGLE_SPACE;
291+
}
292+
276293
@SuppressWarnings("deprecation")
277294
private J.VariableDeclarations buildVariableDeclarations(J.InstanceOf instanceOf, Space prefix) {
278295
J.Identifier pattern = (J.Identifier) instanceOf.getPattern();

src/test/java/org/openrewrite/java/migrate/lang/IfElseIfConstructToSwitchTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.openrewrite.staticanalysis.InstanceOfPatternMatch;
2222
import org.openrewrite.test.RecipeSpec;
2323
import org.openrewrite.test.RewriteTest;
24+
import org.openrewrite.test.TypeValidation;
2425

2526
import static org.openrewrite.java.Assertions.java;
2627
import static org.openrewrite.java.Assertions.version;
@@ -935,6 +936,51 @@ else if (obj instanceof Long l) {
935936
}
936937
}
937938

939+
@Test
940+
void unresolvableTypesKeepCaseSpacing() {
941+
// https://github.com/openrewrite/rewrite/issues/7458
942+
rewriteRun(
943+
spec -> spec.typeValidationOptions(TypeValidation.none()),
944+
//language=java
945+
java(
946+
"""
947+
package com.example;
948+
import com.example.missing.Http2Frame;
949+
import com.example.missing.Http2ResetFrame;
950+
import com.example.missing.Http2GoAwayFrame;
951+
class Test {
952+
protected void incrementCounter(Http2Frame frame) {
953+
long errorCode;
954+
if (frame instanceof Http2ResetFrame resetFrame) {
955+
errorCode = resetFrame.errorCode();
956+
} else if (frame instanceof Http2GoAwayFrame goAwayFrame) {
957+
errorCode = goAwayFrame.errorCode();
958+
} else {
959+
errorCode = -1;
960+
}
961+
}
962+
}
963+
""",
964+
"""
965+
package com.example;
966+
import com.example.missing.Http2Frame;
967+
import com.example.missing.Http2ResetFrame;
968+
import com.example.missing.Http2GoAwayFrame;
969+
class Test {
970+
protected void incrementCounter(Http2Frame frame) {
971+
long errorCode;
972+
switch (frame) {
973+
case Http2ResetFrame resetFrame -> errorCode = resetFrame.errorCode();
974+
case Http2GoAwayFrame goAwayFrame -> errorCode = goAwayFrame.errorCode();
975+
case null, default -> errorCode = -1;
976+
}
977+
}
978+
}
979+
"""
980+
)
981+
);
982+
}
983+
938984
@Nested
939985
class AddLabels {
940986
@Test

0 commit comments

Comments
 (0)