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 47cc4115b7ac..c70bf120bc66 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 @@ -1298,13 +1298,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState { final int idPlain = varPlain.getID(); final int idNegated = varNegated == null ? -1 : varNegated.getID(); - if(isNull(varPlain) || isNotNull(varPlain)) { - DfaVariableState state = myVariableStates.get(varPlain); - if (state != null) { - setVariableState(varPlain, state.withoutFact(DfaFactType.CAN_BE_NULL)); - } - } - int[] classes = myIdToEqClassesIndices.get(idPlain); int[] negatedClasses = myIdToEqClassesIndices.get(idNegated); int[] result = ArrayUtil diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java index 7df042704c05..0f8932dd6ecf 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java @@ -665,6 +665,10 @@ class StateMerger { @Override void removeFromState(@NotNull DfaMemoryStateImpl state) { + if(!myPositive && state.isNotNull(myVar) && state.isNull(myArg)) { + // merging "x == null" and "x != null" should be possible with marking "x" as nullable + state.forceVariableFact(myVar, CAN_BE_NULL, true); + } state.removeEquivalenceRelations(myVar); } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java b/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java new file mode 100644 index 000000000000..25dbaf2f37c1 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java @@ -0,0 +1,31 @@ +import org.jetbrains.annotations.*; + +class NullabilityBasics { + + void test2() { + String x = getNullable(); + if (x == null) { + System.out.println("x is null!"); + } + if (isEmpty(x) && Math.random() > 0.5) { + return; + } + System.out.println(x.trim()); + } + + @Nullable String getNullable() { + return Math.random() > 0.5 ? null : ""; + } + + @Contract(value = "null -> true",pure = true) + static boolean isEmpty(@Nullable String s) { + return s == null || s.isEmpty(); + } + + void test(String x) { + if (x == null) { + System.out.println("x is null!"); + } + System.out.println(x.trim()); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index 76cf4cd7774b..bcd2171cecb1 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -582,4 +582,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testPrimitiveNull() { doTest(); } public void testLessThanRelations() { doTest(); } public void testAdvancedArrayAccess() { doTest(); } + public void testNullabilityBasics() { doTest(); } }