diff --git a/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties b/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties index 78bf308b8246..83db9a808ba6 100644 --- a/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties +++ b/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties @@ -77,6 +77,7 @@ dataflow.message.return.nullable.from.notnull=Expression #ref might dataflow.message.return.nullable.from.notnullable=Expression #ref might evaluate to null but is returned by the method which is not declared as @{0} dataflow.message.storing.array.null=null is stored to an array of @NotNull elements dataflow.message.storing.array.nullable=Expression #ref 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 NullPointerException dataflow.message.unboxing.method.reference=Use of #ref #loc would need unboxing which may produce NullPointerException dataflow.message.unboxing=Unboxing of #ref #loc may produce NullPointerException dataflow.message.unreachable.switch.label=Switch label #ref #loc is unreachable diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 196020e24dc9..d39a3a66f3e9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -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); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblemKind.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblemKind.java index f40cc562d74d..0c1b3e6a7223 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblemKind.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblemKind.java @@ -88,6 +88,8 @@ public final class NullabilityProblemKind { public static final NullabilityProblemKind passingToNotNullParameter = new NullabilityProblemKind<>(RE, "passingToNotNullParameter", "dataflow.message.passing.null.argument", "dataflow.message.passing.nullable.argument"); + public static final NullabilityProblemKind unboxingMethodRefParameter = + new NullabilityProblemKind<>(NPE, "unboxingMethodRefParameter", "dataflow.message.passing.nullable.argument.methodref"); public static final NullabilityProblemKind passingToNotNullMethodRefParameter = new NullabilityProblemKind<>(RE, "passingToNotNullMethodRefParameter", "dataflow.message.passing.nullable.argument.methodref"); public static final NullabilityProblemKind passingToNonAnnotatedParameter = 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 a0f1299630fc..c8d6f2ca5929 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 @@ -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()); } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ImplicitUnboxingInMethodReference.java b/java/java-tests/testData/inspection/dataFlow/fixture/ImplicitUnboxingInMethodReference.java new file mode 100644 index 000000000000..0d6d96c84a4e --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ImplicitUnboxingInMethodReference.java @@ -0,0 +1,23 @@ +import org.jetbrains.annotations.*; +import java.util.stream.*; + +// IDEA-250913 +class Test { + void main() { + print(parse("1")); + + Stream.of("1", "2") + .map(this::parse) + .forEach(this::print); + + } + + @Nullable + Long parse(String s) { + return null; + } + + private void print(long s) { + System.out.println(s); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java index 549ffcecdedb..24c47c63d12a 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -296,4 +296,7 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { setupTypeUseAnnotations("typeUse", myFixture); doTest(); } + public void testImplicitUnboxingInMethodReference() { + doTest(); + } } \ No newline at end of file