[java-inspection] IDEA-352587 Support JEP 455: Improve conversion from if to switch

- add more tests
- fix corner cases with doubled values

GitOrigin-RevId: 205a03a05a25282f41dad199a31fcba9c8141433
This commit is contained in:
Mikhail Pyltsin
2024-05-27 11:27:15 +00:00
committed by intellij-monorepo-bot
parent 588a63565f
commit 0dad9dd658
13 changed files with 173 additions and 11 deletions
@@ -216,14 +216,14 @@ public final class SwitchUtils {
if (existingCaseValues != null && existingCaseValues.contains(o)) {
return false;
}
if (existingCaseValues != null) {
existingCaseValues.add(o);
}
PsiType selectorType = selector.getType();
PsiType valueType = value.getType();
if (selectorType == null || valueType == null) return false;
PsiPrimitiveType unwrapped = PsiPrimitiveType.getOptionallyUnboxedType(selectorType);
if (unwrapped != null && (PsiTypes.longType().equals(unwrapped) ||
PsiTypes.doubleType().equals(unwrapped) ||
PsiTypes.floatType().equals(unwrapped) ||
PsiTypes.booleanType().equals(unwrapped))) {
if (unwrapped != null && (isExtendedPrimitives(unwrapped))) {
return unwrapped.equals(valueType);
}
return TypeConversionUtil.isAssignable(selectorType, valueType);
@@ -374,8 +374,11 @@ public final class SwitchUtils {
if (JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS.isSufficient(languageLevel) &&
expression instanceof PsiBinaryExpression psiBinaryExpression) {
IElementType operationTokenType = psiBinaryExpression.getOperationTokenType();
if (operationTokenType.equals(JavaTokenType.OROR) || operationTokenType.equals(JavaTokenType.ANDAND) ||
operationTokenType.equals(JavaTokenType.OR) || operationTokenType.equals(JavaTokenType.AND)) {
if (!operationTokenType.equals(JavaTokenType.EQEQ) &&
!operationTokenType.equals(JavaTokenType.GT) &&
!operationTokenType.equals(JavaTokenType.GE) &&
!operationTokenType.equals(JavaTokenType.LT) &&
!operationTokenType.equals(JavaTokenType.LE)) {
return null;
}
final PsiExpression left = psiBinaryExpression.getLOperand();
@@ -617,11 +620,10 @@ public final class SwitchUtils {
PsiExpression switchSelector = null;
for (PsiBinaryExpression binaryExpression : binaryExpressions) {
IElementType binaryExpressionOperationTokenType = binaryExpression.getOperationTokenType();
if (!JavaTokenType.EQEQ.equals(binaryExpressionOperationTokenType) &&
!JavaTokenType.OROR.equals(binaryExpressionOperationTokenType) &&
!JavaTokenType.ANDAND.equals(binaryExpressionOperationTokenType) &&
!JavaTokenType.OR.equals(binaryExpressionOperationTokenType) &&
!JavaTokenType.AND.equals(binaryExpressionOperationTokenType)) {
if (JavaTokenType.LE.equals(binaryExpressionOperationTokenType) ||
JavaTokenType.LT.equals(binaryExpressionOperationTokenType) ||
JavaTokenType.GE.equals(binaryExpressionOperationTokenType) ||
JavaTokenType.GT.equals(binaryExpressionOperationTokenType)) {
PsiExpression lOperand = binaryExpression.getLOperand();
PsiExpression rOperand = binaryExpression.getROperand();
EquivalenceChecker equivalence = EquivalenceChecker.getCanonicalPsiEquivalence();
@@ -0,0 +1,17 @@
import org.jetbrains.annotations.NotNull;
class Test {
void test(Number code) {
i<caret>f (code == 100) {
return "Continue";
} else if (code == 200) {
return "OK";
} else if (code == 301) {
return "Moved permanently";
} else if (code > 502 && code < 600) {
return "Server error";
} else {
return "unknown code";
}
}
}
@@ -0,0 +1,17 @@
import org.jetbrains.annotations.NotNull;
class Test {
void test(@NotNull Integer code) {
i<caret>f (code == 100) {
return "Continue";
} else if (code == 100) {
return "OK";
} else if (301 == code) {
return "Moved permanently";
} else if (502 > code) {
return "Server error";
} else {
return "unknown code";
}
}
}
@@ -0,0 +1,17 @@
import org.jetbrains.annotations.NotNull;
class Test {
void test(@NotNull Integer code) {
i<caret>f (code instanceof Integer) {
return "Continue";
} else if (code == 100) {
return "OK";
} else if (301 == code) {
return "Moved permanently";
} else if (502 > code) {
return "Server error";
} else {
return "unknown code";
}
}
}
@@ -0,0 +1,11 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
<caret>switch (l) {
case int j when j > 1 -> System.out.println("3");
case int j when j < 0 -> System.out.println("1");
case Integer i -> System.out.println("2");
}
}
}
@@ -0,0 +1,13 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
i<caret>f (l > 1) {
System.out.println("3");
} else if (l < 0) {
System.out.println("1");
} else if (l instanceof Integer) {
System.out.println("2");
}
}
}
@@ -0,0 +1,11 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
<caret>switch (l) {
case 1 -> System.out.println("3");
case 0 -> System.out.println("1");
case Integer i -> System.out.println("2");
}
}
}
@@ -0,0 +1,13 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
i<caret>f (1 == l) {
System.out.println("3");
} else if (0 == l) {
System.out.println("1");
} else if (l instanceof Integer) {
System.out.println("2");
}
}
}
@@ -0,0 +1,11 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
<caret>switch (l) {
case int j when 1 > j -> System.out.println("3");
case int j when 0 < j -> System.out.println("1");
case Integer i -> System.out.println("2");
}
}
}
@@ -0,0 +1,13 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
i<caret>f (1 > l) {
System.out.println("3");
} else if (0 < l) {
System.out.println("1");
} else if (l instanceof Integer) {
System.out.println("2");
}
}
}
@@ -0,0 +1,14 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
int a = 1;
i<caret>f (l > 1) {
System.out.println("3");
} else if (a < 0) {
System.out.println("1");
} else if (l instanceof Integer) {
System.out.println("2");
}
}
}
@@ -0,0 +1,14 @@
import org.jetbrains.annotations.Nullable;
class Test {
void test(int l) {
int a = 1;
i<caret>f (l > 1) {
System.out.println("3");
} else if (0 < a) {
System.out.println("1");
} else if (l instanceof Integer) {
System.out.println("2");
}
}
}
@@ -31,6 +31,11 @@ public class IfCanBePrimitivePatternSwitchFixTest extends IGQuickFixesTestCase {
}
public void testPrimitiveIntType() { doTest(); }
public void testPrimitiveIntTypeWithDifferent() { assertQuickfixNotAvailable(); }
public void testPrimitiveIntTypeWithDifferentRevert() { assertQuickfixNotAvailable(); }
public void testPrimitiveIntTypeRevert() { doTest(); }
public void testPrimitiveIntTypeRevertComparison() { doTest(); }
public void testPrimitiveIntTypeComparison() { doTest(); }
public void testPrimitiveLongIntType() { assertQuickfixNotAvailable(); }
public void testPrimitiveLongType() { doTest(); }
public void testPrimitiveLongType2() { doTest(); }
@@ -53,4 +58,8 @@ public class IfCanBePrimitivePatternSwitchFixTest extends IGQuickFixesTestCase {
public void testComparisonWithPrimitives1() { doTest(); }
public void testComparisonWithPrimitives2() { doTest(); }
public void testComparisonWithPrimitives3() { doTest(); }
public void testComparisonNonPrimitive() { assertQuickfixNotAvailable(); }
public void testDoubleComparison() { assertQuickfixNotAvailable(); }
public void testPrimitiveDominates() { assertQuickfixNotAvailable(); }
}