From fb5ddff5cf532d82344ec04bfd6fe527bca9604e Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 17 Feb 2015 15:37:44 +0100 Subject: [PATCH] IDEA-136603 IDEA does not warn if annotated with @Nullable local variable is used for @NotNull parameter method --- .../dataFlow/ControlFlowAnalyzer.java | 6 +----- .../dataFlow/StandardInstructionVisitor.java | 5 +++++ .../dataFlow/instructions/AssignInstruction.java | 6 ++++++ .../fixture/ExplicitlyNullableLocalVar.java | 15 +++++++++++++++ .../codeInspection/DataFlowInspectionTest.java | 2 ++ 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/ExplicitlyNullableLocalVar.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 38d4857c7514..3cde802544c8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1330,11 +1330,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) { startElement(expression); - PsiElement[] children = expression.getChildren(); - for (PsiElement child : children) { - child.accept(this); - } - pushUnknown(); + addInstruction(new PushInstruction(myFactory.createTypeValue(expression.getType(), Nullness.NOT_NULL), expression)); finishElement(expression); } 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 4d8df8da219a..390b0451e082 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 @@ -80,6 +80,11 @@ public class StandardInstructionVisitor extends InstructionVisitor { if (!(psi instanceof PsiField) || !psi.hasModifierProperty(PsiModifier.VOLATILE)) { memState.setVarValue(var, dfaSource); } + if (var.getInherentNullability() == Nullness.NULLABLE && !memState.isNotNull(dfaSource) && instruction.isVariableInitializer()) { + DfaMemoryStateImpl stateImpl = (DfaMemoryStateImpl)memState; + stateImpl.setVariableState(var, stateImpl.getVariableState(var).withNullability(Nullness.NULLABLE)); + } + } else if (dfaDest instanceof DfaTypeValue && ((DfaTypeValue)dfaDest).isNotNull()) { checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression()); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java index a320e5ccf495..90b3796a43fa 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java @@ -30,6 +30,7 @@ import com.intellij.codeInspection.dataFlow.DfaMemoryState; import com.intellij.codeInspection.dataFlow.InstructionVisitor; import com.intellij.codeInspection.dataFlow.value.DfaValue; import com.intellij.psi.PsiExpression; +import com.intellij.psi.PsiVariable; import org.jetbrains.annotations.Nullable; public class AssignInstruction extends Instruction { @@ -46,10 +47,15 @@ public class AssignInstruction extends Instruction { return visitor.visitAssign(this, runner, stateBefore); } + @Nullable public PsiExpression getRExpression() { return myRExpression; } + public boolean isVariableInitializer() { + return myRExpression != null && myRExpression.getParent() instanceof PsiVariable; + } + @Nullable public DfaValue getAssignedValue() { return myAssignedValue; diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ExplicitlyNullableLocalVar.java b/java/java-tests/testData/inspection/dataFlow/fixture/ExplicitlyNullableLocalVar.java new file mode 100644 index 000000000000..f7a0b48d0fdb --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ExplicitlyNullableLocalVar.java @@ -0,0 +1,15 @@ +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.sql.ResultSet; +import java.sql.SQLException; + +abstract class IDEATest { + abstract Object someMethod(@NotNull Object someParam); + abstract Object someObject(); + + public void testIDEA() { + @Nullable Object obj2 = someObject(); + someMethod(obj2); + } +} \ 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 2d44dcbd70b9..acc64ef5f9a0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -198,6 +198,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testNullCheckDoesntAffectUncheckedCast() { doTest(); } public void testThrowNull() { doTest(); } + public void testExplicitlyNullableLocalVar() { doTest(); } + public void testTryWithResourcesNullability() { doTest(); } public void testTryWithResourcesInstanceOf() { doTest(); } public void testOmnipresentExceptions() { doTest(); }