From dc9c7b84fd5e1536cff86fb98f2b5c339649dcb4 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 16 Dec 2020 17:09:41 +0700 Subject: [PATCH] [java-inspections] IDEA-257106 @NotNull Parameters overriding non-annotated reports false positives for generic methods GitOrigin-RevId: fe24523eaaccfef34a3b394ad29337d065f1d786 --- .../nullable/NullableStuffInspectionBase.java | 19 +++++++++++++++++- .../OverrideGenericMethod.java | 20 +++++++++++++++++++ .../NullableStuffInspectionTest.java | 6 ++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/nullableProblems/OverrideGenericMethod.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java index b2a8dc1acef3..bca339824bf5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java @@ -30,6 +30,8 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.util.*; import com.intellij.util.ArrayUtilRt; import com.intellij.util.containers.ContainerUtil; +import com.siyeh.ig.psiutils.ClassUtils; +import com.siyeh.ig.psiutils.TypeUtils; import org.jdom.Element; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nls; @@ -854,7 +856,22 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection if (!REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED) return false; NullabilityAnnotationInfo info = nullableManager.findOwnNullabilityInfo(parameter); return info != null && info.getNullability() == Nullability.NOT_NULL && !info.isInferred() && - ContainerUtil.exists(superParameters, sp -> !hasNullability(nullableManager, sp)); + ContainerUtil.exists(superParameters, sp -> isSuperNotAnnotated(nullableManager, parameter, sp)); + } + + private static boolean isSuperNotAnnotated(NullableNotNullManager nullableManager, PsiParameter parameter, PsiParameter superParameter) { + if (hasNullability(nullableManager, superParameter)) return false; + PsiType type = superParameter.getType(); + if (TypeUtils.isTypeParameter(type)) { + PsiClass childClass = ClassUtils.getContainingClass(parameter); + PsiClass superClass = ClassUtils.getContainingClass(superParameter); + if (superClass != null && childClass != null) { + PsiType substituted = + TypeConversionUtil.getSuperClassSubstitutor(superClass, childClass, PsiSubstitutor.EMPTY).substitute(type); + return DfaPsiUtil.getTypeNullability(substituted) == Nullability.UNKNOWN; + } + } + return true; } private void checkNullLiteralArgumentOfNotNullParameterUsages(PsiMethod method, diff --git a/java/java-tests/testData/inspection/nullableProblems/OverrideGenericMethod.java b/java/java-tests/testData/inspection/nullableProblems/OverrideGenericMethod.java new file mode 100644 index 000000000000..c301d419e6e8 --- /dev/null +++ b/java/java-tests/testData/inspection/nullableProblems/OverrideGenericMethod.java @@ -0,0 +1,20 @@ +import typeUse.*; + +class X { + static abstract class Base { + abstract void consume(T item); + } + + static class Child extends Base<@NotNull String> { + @Override + void consume(@NotNull String item) { + System.out.println(item); + } + } + + public static void main(String[] args) { + Base<@NotNull String> child = new Child(); + child.consume("this can't be null"); + child.consume(null); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/NullableStuffInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/NullableStuffInspectionTest.java index 4df0ecf7cf25..4be16c533e3e 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/NullableStuffInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/NullableStuffInspectionTest.java @@ -273,6 +273,12 @@ public class NullableStuffInspectionTest extends LightJavaCodeInsightFixtureTest DataFlowInspection8Test.setupTypeUseAnnotations("typeUse", myFixture); doTest(); } + + public void testOverrideGenericMethod() { + myInspection.REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED = true; + DataFlowInspection8Test.setupTypeUseAnnotations("typeUse", myFixture); + doTest(); + } public void testTypeUseNotNullOverriding() { myInspection.REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED = true;