From b5044991da2c8d2cd1402dc114f4710e92017448 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 11 Oct 2019 12:32:12 +0700 Subject: [PATCH] =?UTF-8?q?IDEA-224476=20False=20=E2=80=9CMay=20produce=20?= =?UTF-8?q?NullPointerException=E2=80=9C=20positive=20with=20Contract=20an?= =?UTF-8?q?d=20method=20with=20parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitOrigin-RevId: 0dddc582af0ac00cab70b2a237f11afa706477df --- .../dataFlow/ContractValue.java | 7 +++- .../dataFlow/fixture/ParamContract.java | 32 +++++++++++++++++++ .../DataFlowInspection8Test.java | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/ParamContract.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java index 6d74bc407f4d..8ef9bc2da6e9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java @@ -298,11 +298,16 @@ public abstract class ContractValue { @Override public DfaCallArguments updateArguments(DfaCallArguments arguments, boolean negated) { + DfaNullability targetNullability = DfaNullability.NOT_NULL; int index = getNullCheckedArgument(negated).orElse(-1); + if (index == -1) { + index = getNullCheckedArgument(!negated).orElse(-1); + targetNullability = DfaNullability.NULL; + } if (index >= 0 && index < arguments.myArguments.length) { DfaValue arg = arguments.myArguments[index]; if (arg instanceof DfaFactMapValue) { - DfaValue newArg = ((DfaFactMapValue)arg).withFact(DfaFactType.NULLABILITY, DfaNullability.NOT_NULL); + DfaValue newArg = ((DfaFactMapValue)arg).withFact(DfaFactType.NULLABILITY, targetNullability); if (newArg != arg) { DfaValue[] newArguments = arguments.myArguments.clone(); newArguments[index] = newArg; diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ParamContract.java b/java/java-tests/testData/inspection/dataFlow/fixture/ParamContract.java new file mode 100644 index 000000000000..0bb45a826546 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ParamContract.java @@ -0,0 +1,32 @@ +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class TestCls { + public String broken(@NotNull Getter dowGetter) { + final DayOfWeek dowOrDefault = firstNonNull(dowGetter.getDow(""), DayOfWeek.MONDAY); + return dowOrDefault.name(); + } + + public String correct(@NotNull Getter dowGetter) { + final DayOfWeek dowOrDefault = firstNonNull(dowGetter.getDow(), DayOfWeek.MONDAY); + return dowOrDefault.name(); + } + + @Nullable + @Contract(value = "!null, _ -> param1; null, !null -> param2; null, null -> null", pure = true) + public static T firstNonNull(@Nullable T value1, @Nullable T value2) { + return value1 == null ? value2 : value1; + } + + public interface Getter { + @Nullable + DayOfWeek getDow(); + @Nullable + DayOfWeek getDow(String param); + } + + enum DayOfWeek { + MONDAY + } +} \ 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 faa1dd3c943b..c46dd49a0180 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -251,6 +251,7 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { public void testLambdaWritesArrayInTry() { doTest(); } public void testManyNestedOptionals() { doTest(); } public void testGetClass() { doTest(); } + public void testParamContract() { doTest(); } public void testTypeUseVarArg() { setupTypeUseAnnotations("typeUse", myFixture); doTest();