[java-dfa] Report implicit unboxing of nullable method reference argument

Fixes IDEA-250913 Inspection "Constant conditions and exceptions" does not catch "Unboxing may produce NullPointerException" in stream operations

GitOrigin-RevId: 536668db2e1b3bb5307cccff710f3212d07bce2e
This commit is contained in:
Tagir Valeev
2020-09-21 09:44:52 +00:00
committed by intellij-monorepo-bot
parent 095fb1bd79
commit 742ad45a22
6 changed files with 36 additions and 0 deletions
@@ -77,6 +77,7 @@ dataflow.message.return.nullable.from.notnull=Expression <code>#ref</code> might
dataflow.message.return.nullable.from.notnullable=Expression <code>#ref</code> might evaluate to null but is returned by the method which is not declared as @{0}
dataflow.message.storing.array.null=<code>null</code> is stored to an array of @NotNull elements
dataflow.message.storing.array.nullable=Expression <code>#ref</code> might evaluate to null but is stored to an array of @NotNull elements
dataflow.message.unboxing.nullable.argument.methodref=Passing an argument to the method reference requires unboxing which may produce <code>NullPointerException</code>
dataflow.message.unboxing.method.reference=Use of <code>#ref</code> #loc would need unboxing which may produce <code>NullPointerException</code>
dataflow.message.unboxing=Unboxing of <code>#ref</code> #loc may produce <code>NullPointerException</code>
dataflow.message.unreachable.switch.label=Switch label <code>#ref</code> #loc is unreachable
@@ -588,6 +588,10 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
LocalQuickFix[] fixes = createMethodReferenceNPEFixes(methodRef, reporter.isOnTheFly()).toArray(LocalQuickFix.EMPTY_ARRAY);
reporter.registerProblem(methodRef, JavaAnalysisBundle.message("dataflow.message.passing.nullable.argument.methodref"), fixes);
});
NullabilityProblemKind.unboxingMethodRefParameter.ifMyProblem(problem, methodRef -> {
LocalQuickFix[] fixes = createMethodReferenceNPEFixes(methodRef, reporter.isOnTheFly()).toArray(LocalQuickFix.EMPTY_ARRAY);
reporter.registerProblem(methodRef, JavaAnalysisBundle.message("dataflow.message.unboxing.nullable.argument.methodref"), fixes);
});
NullabilityProblemKind.arrayAccessNPE.ifMyProblem(problem, arrayAccess -> {
LocalQuickFix[] fixes =
createNPEFixes(arrayAccess.getArrayExpression(), arrayAccess, reporter.isOnTheFly()).toArray(LocalQuickFix.EMPTY_ARRAY);
@@ -88,6 +88,8 @@ public final class NullabilityProblemKind<T extends PsiElement> {
public static final NullabilityProblemKind<PsiExpression> passingToNotNullParameter =
new NullabilityProblemKind<>(RE, "passingToNotNullParameter", "dataflow.message.passing.null.argument",
"dataflow.message.passing.nullable.argument");
public static final NullabilityProblemKind<PsiMethodReferenceExpression> unboxingMethodRefParameter =
new NullabilityProblemKind<>(NPE, "unboxingMethodRefParameter", "dataflow.message.passing.nullable.argument.methodref");
public static final NullabilityProblemKind<PsiMethodReferenceExpression> passingToNotNullMethodRefParameter =
new NullabilityProblemKind<>(RE, "passingToNotNullMethodRefParameter", "dataflow.message.passing.nullable.argument.methodref");
public static final NullabilityProblemKind<PsiExpression> passingToNonAnnotatedParameter =
@@ -439,6 +439,9 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (paramList != null) {
PsiParameter parameter = paramList.getParameter(paramIndex);
if (parameter != null) {
if (TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
arg = dereference(memState, arg, NullabilityProblemKind.unboxingMethodRefParameter.problem(methodRef, null));
}
arg = DfaUtil.boxUnbox(arg, parameter.getType());
}
}
@@ -0,0 +1,23 @@
import org.jetbrains.annotations.*;
import java.util.stream.*;
// IDEA-250913
class Test {
void main() {
print(<warning descr="Unboxing of 'parse(\"1\")' may produce 'NullPointerException'">parse("1")</warning>);
Stream.of("1", "2")
.map(this::parse)
.forEach(<warning descr="Passing an argument to the method reference requires unboxing which may produce 'NullPointerException'">this::print</warning>);
}
@Nullable
Long parse(String s) {
return null;
}
private void print(long s) {
System.out.println(s);
}
}
@@ -296,4 +296,7 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
setupTypeUseAnnotations("typeUse", myFixture);
doTest();
}
public void testImplicitUnboxingInMethodReference() {
doTest();
}
}