From 0dad9dd6580acb6e4028462229077fb7bb9190f6 Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Mon, 27 May 2024 11:12:34 +0200 Subject: [PATCH] [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 --- .../com/siyeh/ig/psiutils/SwitchUtils.java | 24 ++++++++++--------- .../ComparisonNonPrimitive.java | 17 +++++++++++++ .../if_can_be_switch/DoubleComparison.java | 17 +++++++++++++ .../if_can_be_switch/PrimitiveDominates.java | 17 +++++++++++++ .../PrimitiveIntTypeComparison.after.java | 11 +++++++++ .../PrimitiveIntTypeComparison.java | 13 ++++++++++ .../PrimitiveIntTypeRevert.after.java | 11 +++++++++ .../PrimitiveIntTypeRevert.java | 13 ++++++++++ ...rimitiveIntTypeRevertComparison.after.java | 11 +++++++++ .../PrimitiveIntTypeRevertComparison.java | 13 ++++++++++ .../PrimitiveIntTypeWithDifferent.java | 14 +++++++++++ .../PrimitiveIntTypeWithDifferentRevert.java | 14 +++++++++++ .../IfCanBePrimitivePatternSwitchFixTest.java | 9 +++++++ 13 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/ComparisonNonPrimitive.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/DoubleComparison.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveDominates.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.after.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.after.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.after.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferent.java create mode 100644 java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferentRevert.java diff --git a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java index 1edceca68590..61838450811c 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java @@ -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(); diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/ComparisonNonPrimitive.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/ComparisonNonPrimitive.java new file mode 100644 index 000000000000..b111f43250de --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/ComparisonNonPrimitive.java @@ -0,0 +1,17 @@ +import org.jetbrains.annotations.NotNull; + +class Test { + void test(Number code) { + if (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"; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/DoubleComparison.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/DoubleComparison.java new file mode 100644 index 000000000000..8827f03ea8f1 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/DoubleComparison.java @@ -0,0 +1,17 @@ +import org.jetbrains.annotations.NotNull; + +class Test { + void test(@NotNull Integer code) { + if (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"; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveDominates.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveDominates.java new file mode 100644 index 000000000000..b3b8ad688923 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveDominates.java @@ -0,0 +1,17 @@ +import org.jetbrains.annotations.NotNull; + +class Test { + void test(@NotNull Integer code) { + if (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"; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.after.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.after.java new file mode 100644 index 000000000000..cfa8a31be152 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.after.java @@ -0,0 +1,11 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + 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"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.java new file mode 100644 index 000000000000..de4d88281741 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeComparison.java @@ -0,0 +1,13 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + if (l > 1) { + System.out.println("3"); + } else if (l < 0) { + System.out.println("1"); + } else if (l instanceof Integer) { + System.out.println("2"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.after.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.after.java new file mode 100644 index 000000000000..839062bda02c --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.after.java @@ -0,0 +1,11 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + switch (l) { + case 1 -> System.out.println("3"); + case 0 -> System.out.println("1"); + case Integer i -> System.out.println("2"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.java new file mode 100644 index 000000000000..28c14879b192 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevert.java @@ -0,0 +1,13 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + if (1 == l) { + System.out.println("3"); + } else if (0 == l) { + System.out.println("1"); + } else if (l instanceof Integer) { + System.out.println("2"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.after.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.after.java new file mode 100644 index 000000000000..9bc196b0d9e0 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.after.java @@ -0,0 +1,11 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + 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"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.java new file mode 100644 index 000000000000..27a16fd8129b --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeRevertComparison.java @@ -0,0 +1,13 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + if (1 > l) { + System.out.println("3"); + } else if (0 < l) { + System.out.println("1"); + } else if (l instanceof Integer) { + System.out.println("2"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferent.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferent.java new file mode 100644 index 000000000000..7f3521406782 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferent.java @@ -0,0 +1,14 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + int a = 1; + if (l > 1) { + System.out.println("3"); + } else if (a < 0) { + System.out.println("1"); + } else if (l instanceof Integer) { + System.out.println("2"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferentRevert.java b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferentRevert.java new file mode 100644 index 000000000000..e93c0f5be7a1 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igfixes/migration/if_can_be_switch/PrimitiveIntTypeWithDifferentRevert.java @@ -0,0 +1,14 @@ +import org.jetbrains.annotations.Nullable; + +class Test { + void test(int l) { + int a = 1; + if (l > 1) { + System.out.println("3"); + } else if (0 < a) { + System.out.println("1"); + } else if (l instanceof Integer) { + System.out.println("2"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/siyeh/ig/fixes/migration/IfCanBePrimitivePatternSwitchFixTest.java b/java/java-tests/testSrc/com/siyeh/ig/fixes/migration/IfCanBePrimitivePatternSwitchFixTest.java index c8019086a4b4..2fe9b6ea38c1 100644 --- a/java/java-tests/testSrc/com/siyeh/ig/fixes/migration/IfCanBePrimitivePatternSwitchFixTest.java +++ b/java/java-tests/testSrc/com/siyeh/ig/fixes/migration/IfCanBePrimitivePatternSwitchFixTest.java @@ -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(); } }