From af07f88aef6608544b4921a8c6ccc830debbe746 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 12 Oct 2015 13:25:17 +0200 Subject: [PATCH] IDEA-146122 Wrong 'can produce NPE' after comparing with enum constant --- .../dataFlow/DfaMemoryStateImpl.java | 10 ++++++++- .../fixture/CompareToEnumConstant.java | 21 +++++++++++++++++++ .../DataFlowInspectionTest.java | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/CompareToEnumConstant.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index e9f9d49eb3e5..b015f5bfa80d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UnorderedPair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.JavaTokenType; +import com.intellij.psi.PsiEnumConstant; import com.intellij.psi.PsiPrimitiveType; import com.intellij.psi.PsiType; import com.intellij.psi.util.TypeConversionUtil; @@ -833,7 +834,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState { for (long encodedPair : myDistinctClasses.toArray()) { EqClass c1 = myEqClasses.get(low(encodedPair)); EqClass c2 = myEqClasses.get(high(encodedPair)); - if (c1.findConstant(false) != null && c2.findConstant(false) != null) { + DfaConstValue const1 = (DfaConstValue)c1.findConstant(false); + DfaConstValue const2 = (DfaConstValue)c2.findConstant(false); + if (const1 != null && const2 != null && !preserveConstantDistinction(const1.getValue(), const2.getValue())) { myDistinctClasses.remove(encodedPair); } } @@ -851,6 +854,11 @@ public class DfaMemoryStateImpl implements DfaMemoryState { return true; } + private static boolean preserveConstantDistinction(final Object c1, final Object c2) { + return c1 == null && c2 instanceof PsiEnumConstant || + c2 == null && c1 instanceof PsiEnumConstant; + } + private boolean areCompatibleConstants(int i1, int i2) { Double dv1 = getDoubleValue(i1); return dv1 != null && dv1.equals(getDoubleValue(i2)); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CompareToEnumConstant.java b/java/java-tests/testData/inspection/dataFlow/fixture/CompareToEnumConstant.java new file mode 100644 index 000000000000..db5c5197a5ef --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/CompareToEnumConstant.java @@ -0,0 +1,21 @@ +import org.jetbrains.annotations.Nullable; + +enum MyEnum { + ITEM, + ANOTHER_ITEM, + LOL_ITEM; +} + +@SuppressWarnings({"UseOfSystemOutOrSystemErr", "unused"}) +class Main { + void foo(@Nullable MyEnum myEnum) { + if (myEnum == null) return; + switch (myEnum) { + case ITEM: + case ANOTHER_ITEM: + System.out.println(myEnum == MyEnum.ITEM ? "item" : "another"); + myEnum.name(); + default: + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index b08a702b883b..fdcb1a6d2c10 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -94,6 +94,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testEqualsEnumConstant() throws Throwable { doTest(); } public void testSwitchEnumConstant() { doTest(); } public void testEnumConstantNotNull() throws Throwable { doTest(); } + public void testCompareToEnumConstant() throws Throwable { doTest(); } public void testEqualsConstant() throws Throwable { doTest(); } public void testDontSaveTypeValue() { doTest(); } public void testFinalLoopVariableInstanceof() throws Throwable { doTest(); }