From 7427f881fd6c6fcd230f83feea35e4a7ad0113f7 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 25 Jun 2021 15:46:14 +0700 Subject: [PATCH] [java-analysis] NullableNotNullManager: prefer type annotation over inherited annotation Fixes IDEA-272250 False-positive warning when overridden method has a nullability type annotation GitOrigin-RevId: a05ae5bdad95e475ac8a2af7736bcafc0e008364 --- .../codeInsight/NullableNotNullManager.java | 23 +++++++++++-------- .../nullableProblems/InheritAmbiguous.java | 10 ++++++++ .../NullableStuffInspectionTest.java | 6 +++++ 3 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testData/inspection/nullableProblems/InheritAmbiguous.java diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java index 7648b7e93461..25a16e692a21 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java @@ -258,18 +258,21 @@ public abstract class NullableNotNullManager { memberAnno = null; } if (memberAnno != null) { - if (type != null) { - for (PsiAnnotation typeAnno : type.getApplicableAnnotations()) { - if (areDifferentNullityAnnotations(memberAnno.annotation, typeAnno)) { - if (typeAnno != memberAnno.annotation) return null; - Nullability nullability = annotations.getNullability(typeAnno.getQualifiedName()); - if (nullability == null) return null; - return new NullabilityAnnotationInfo(typeAnno, nullability, false); - } - } - } Nullability nullability = annotations.getNullability(memberAnno.annotation.getQualifiedName()); if (nullability == null) return null; + if (type != null) { + for (PsiAnnotation typeAnno : type.getApplicableAnnotations()) { + if (typeAnno == memberAnno.annotation) continue; + Nullability typeNullability = annotations.getNullability(typeAnno.getQualifiedName()); + if (typeNullability == null) continue; + if (typeNullability != nullability) { + return null; + } + // Prefer type annotation over inherited annotation; necessary for Nullable/NotNull inspection + memberAnno = new AnnotationAndOwner(owner, typeAnno); + break; + } + } return new NullabilityAnnotationInfo(memberAnno.annotation, nullability, memberAnno.owner == owner ? null : memberAnno.owner, false); } if (type instanceof PsiPrimitiveType) return null; diff --git a/java/java-tests/testData/inspection/nullableProblems/InheritAmbiguous.java b/java/java-tests/testData/inspection/nullableProblems/InheritAmbiguous.java new file mode 100644 index 000000000000..68bfb6679501 --- /dev/null +++ b/java/java-tests/testData/inspection/nullableProblems/InheritAmbiguous.java @@ -0,0 +1,10 @@ +import typeUse.*; + +abstract class A { + class B {} + + @NotNull abstract A.B get(); +} +abstract class C extends A { + abstract A.@NotNull B get(); +} 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 fe90ecad42a7..031632597d54 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/NullableStuffInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/NullableStuffInspectionTest.java @@ -334,6 +334,12 @@ public class NullableStuffInspectionTest extends LightJavaCodeInsightFixtureTest doTest(); } + public void testInheritAmbiguous() { + myInspection.REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = true; + DataFlowInspection8Test.setupAmbiguousAnnotations("typeUse", myFixture); + doTest(); + } + public void testIncorrectPlacementAmbiguous() { DataFlowInspection8Test.setupAmbiguousAnnotations("typeUse", myFixture); doTest();