diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 0217b819ce3b..be70ba0e4328 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -31,6 +31,10 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.intellij.psi.JavaTokenType.*; +import static com.intellij.psi.JavaTokenType.EQEQ; +import static com.intellij.psi.JavaTokenType.NE; + /** * @author peter */ @@ -184,7 +188,7 @@ public class StandardInstructionVisitor extends InstructionVisitor { DfaValue dfaExpr = factory.createValue(instruction.getCasted()); if (dfaExpr != null) { DfaTypeValue dfaType = (DfaTypeValue)factory.createTypeValue(instruction.getCastTo(), Nullness.UNKNOWN); - DfaRelationValue dfaInstanceof = factory.getRelationFactory().createRelation(dfaExpr, dfaType, JavaTokenType.INSTANCEOF_KEYWORD, false); + DfaRelationValue dfaInstanceof = factory.getRelationFactory().createRelation(dfaExpr, dfaType, INSTANCEOF_KEYWORD, false); if (dfaInstanceof != null && !memState.applyInstanceofOrNull(dfaInstanceof)) { onInstructionProducesCCE(instruction); } @@ -289,7 +293,12 @@ public class StandardInstructionVisitor extends InstructionVisitor { protected boolean checkNotNullable(DfaMemoryState state, DfaValue value, NullabilityProblem problem, PsiElement anchor) { - return state.checkNotNullable(value); + boolean notNullable = state.checkNotNullable(value); + if (notNullable && problem != NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter) { + DfaValueFactory factory = ((DfaMemoryStateImpl)state).getFactory(); + state.applyCondition(factory.getRelationFactory().createRelation(value, factory.getConstFactory().getNull(), NE, false)); + } + return notNullable; } @Override @@ -309,7 +318,7 @@ public class StandardInstructionVisitor extends InstructionVisitor { return states; } - if (JavaTokenType.PLUS == opSign) { + if (PLUS == opSign) { memState.push(instruction.getNonNullStringValue(runner.getFactory())); } else { @@ -415,12 +424,12 @@ public class StandardInstructionVisitor extends InstructionVisitor { DfaValue dfaRight, DfaValue dfaLeft) { final IElementType opSign = instruction.getOperationSign(); - if (JavaTokenType.EQEQ != opSign && JavaTokenType.NE != opSign || + if (EQEQ != opSign && NE != opSign || !(dfaLeft instanceof DfaConstValue) || !(dfaRight instanceof DfaConstValue)) { return null; } - boolean negated = (JavaTokenType.NE == opSign) ^ (DfaMemoryStateImpl.isNaN(dfaLeft) || DfaMemoryStateImpl.isNaN(dfaRight)); + boolean negated = (NE == opSign) ^ (DfaMemoryStateImpl.isNaN(dfaLeft) || DfaMemoryStateImpl.isNaN(dfaRight)); if (dfaLeft == dfaRight ^ negated) { memState.push(runner.getFactory().getConstFactory().getTrue()); instruction.setTrueReachable(); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ComparingToNotNullShouldNotAffectNullity.java b/java/java-tests/testData/inspection/dataFlow/fixture/ComparingToNotNullShouldNotAffectNullity.java index fed3d1b79015..98c26df45721 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ComparingToNotNullShouldNotAffectNullity.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ComparingToNotNullShouldNotAffectNullity.java @@ -18,6 +18,27 @@ class Bar3 { if (first == getObj() || collection.size() > 0) { System.out.println(first.hashCode()); } + if (first == null) { + System.out.println(first.hashCode()); + } + } + } + + void foo2(Collection collection) { + if (!collection.isEmpty()) { + Object first = collection.iterator().next(); + if (first != getObj() || collection.size() > 0) { + first.hashCode(); + } + } + } + + void foo3(Collection collection) { + if (!collection.isEmpty()) { + Object first = collection.iterator().next(); + if (first == getObj() || collection.size() > 2) { + System.out.println(first.hashCode()); + } if (first == null) { System.out.println(first.hashCode()); } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NotNullAfterDereference.java b/java/java-tests/testData/inspection/dataFlow/fixture/NotNullAfterDereference.java new file mode 100644 index 000000000000..5c6dc81fe339 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NotNullAfterDereference.java @@ -0,0 +1,9 @@ +class Foo { + + private void someMethod(String someArg) { + someArg.getClass(); + if (someArg == null) { + System.err.println("Wrong argument"); + } + } +} \ 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 ddec53269a1c..80b6e028db00 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -309,6 +309,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testUnusedCallDoesNotMakeUnknown() { doTest(); } public void testGettersAndPureNoFlushing() { doTest(); } + + public void testNotNullAfterDereference() { doTest(); } public void testSameComparisonTwice() { doTest(); }