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();