diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 889f308fd8b1..c3e51a45218d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1050,10 +1050,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor { PsiType exprType = expression.getType(); if (TypeConversionUtil.isPrimitiveAndNotNull(expectedType) && TypeConversionUtil.isPrimitiveWrapper(exprType)) { - addInstruction(new MethodCallInstruction(expression, MethodCallInstruction.MethodType.UNBOXING)); + addInstruction(new MethodCallInstruction(expression, MethodCallInstruction.MethodType.UNBOXING, expectedType)); } else if (TypeConversionUtil.isPrimitiveWrapper(expectedType) && TypeConversionUtil.isPrimitiveAndNotNull(exprType)) { - addInstruction(new MethodCallInstruction(expression, MethodCallInstruction.MethodType.BOXING)); + addInstruction(new MethodCallInstruction(expression, MethodCallInstruction.MethodType.BOXING, expectedType)); } else if (exprType != expectedType && TypeConversionUtil.isPrimitiveAndNotNull(exprType) && diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 54df852bfbab..14bffccec716 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -229,17 +229,14 @@ public class StandardInstructionVisitor extends InstructionVisitor { final PsiType type = instruction.getResultType(); final MethodCallInstruction.MethodType methodType = instruction.getMethodType(); - if (type != null && (type instanceof PsiClassType || type.getArrayDimensions() > 0)) { - return factory.createTypeValueWithNullability(type, myReturnTypeNullability.get(instruction)); - } - + if (methodType == MethodCallInstruction.MethodType.UNBOXING) { return factory.getBoxedFactory().createUnboxed(qualifierValue); } if (methodType == MethodCallInstruction.MethodType.BOXING) { DfaValue boxed = factory.getBoxedFactory().createBoxed(qualifierValue); - return boxed == null ? DfaUnknownValue.getInstance() : boxed; + return boxed == null ? factory.getNotNullFactory().create(type) : boxed; } if (methodType == MethodCallInstruction.MethodType.CAST) { @@ -248,6 +245,10 @@ public class StandardInstructionVisitor extends InstructionVisitor { } return qualifierValue; } + + if (type != null && (type instanceof PsiClassType || type.getArrayDimensions() > 0)) { + return factory.createTypeValueWithNullability(type, myReturnTypeNullability.get(instruction)); + } return DfaUnknownValue.getInstance(); } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java index 22f98623447d..a46abb680cd6 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java @@ -36,40 +36,35 @@ import org.jetbrains.annotations.Nullable; public class MethodCallInstruction extends Instruction { @Nullable private final PsiCallExpression myCall; - @Nullable private PsiType myType; + @Nullable private final PsiType myType; @NotNull private final PsiExpression[] myArgs; - private boolean myShouldFlushFields; + private final boolean myShouldFlushFields; @NotNull private final PsiExpression myContext; private final MethodType myMethodType; - @Nullable private DfaValue myPrecalculatedReturnValue; + @Nullable private final DfaValue myPrecalculatedReturnValue; public enum MethodType { BOXING, UNBOXING, REGULAR_METHOD_CALL, CAST } - public MethodCallInstruction(@NotNull PsiCallExpression callExpression, @Nullable DfaValue precalculatedReturnValue) { - this(callExpression, MethodType.REGULAR_METHOD_CALL); - myPrecalculatedReturnValue = precalculatedReturnValue; - } - public MethodCallInstruction(@NotNull PsiExpression context, MethodType methodType, @Nullable PsiType resultType) { - this(context, methodType); - myType = resultType; - myShouldFlushFields = false; - } - - public MethodCallInstruction(@NotNull PsiExpression context, MethodType methodType) { myContext = context; myMethodType = methodType; - myCall = methodType == MethodType.REGULAR_METHOD_CALL && context instanceof PsiCallExpression ? (PsiCallExpression)context : null; - final PsiExpressionList argList = myCall == null ? null : myCall.getArgumentList(); + myCall = null; + myArgs = PsiExpression.EMPTY_ARRAY; + myType = resultType; + myShouldFlushFields = false; + myPrecalculatedReturnValue = null; + } + + public MethodCallInstruction(@NotNull PsiCallExpression context, @Nullable DfaValue precalculatedReturnValue) { + myContext = context; + myMethodType = MethodType.REGULAR_METHOD_CALL; + myCall = context; + final PsiExpressionList argList = context.getArgumentList(); myArgs = argList != null ? argList.getExpressions() : PsiExpression.EMPTY_ARRAY; - - myType = myCall == null ? null : myCall.getType(); - - myShouldFlushFields = true; - if (myCall instanceof PsiNewExpression && myType != null && myType.getArrayDimensions() > 0) { - myShouldFlushFields = false; - } + myType = myCall.getType(); + myShouldFlushFields = !(myCall instanceof PsiNewExpression && myType != null && myType.getArrayDimensions() > 0); + myPrecalculatedReturnValue = precalculatedReturnValue; } @Nullable diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NotNullPrimitive.java b/java/java-tests/testData/inspection/dataFlow/fixture/NotNullPrimitive.java new file mode 100644 index 000000000000..d76f214bba62 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NotNullPrimitive.java @@ -0,0 +1,24 @@ +import org.jetbrains.annotations.NotNull; + +class Foo { + public int getValue() { + return 5; + } + + public void nullcheck() { + Integer x = getValue(); + System.out.println(x == null ? "NULL" : Integer.toHexString(x)); + } +} + +class Bar { + @NotNull + public Integer getValue() { + return 5; + } + + public void nullcheck() { + Integer x = getValue(); + System.out.println(x == null ? "NULL" : Integer.toHexString(x)); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index a9cfa16baf1f..36060cac29b6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -69,6 +69,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testComparingToNotNullShouldNotAffectNullity() throws Throwable { doTest(); } public void testStringTernaryAlwaysTrue() throws Throwable { doTest(); } + public void testNotNullPrimitive() throws Throwable { doTest(); } public void testBoxing128() throws Throwable { doTest(); } public void testFinalFieldsInitializedByAnnotatedParameters() throws Throwable { doTest(); } public void testMultiCatch() throws Throwable { doTest(); }