mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
custom nullable annotation on an element should win over package-default not-null (IDEA-138894)
This commit is contained in:
@@ -116,7 +116,7 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
|
||||
|
||||
@Nullable
|
||||
public PsiAnnotation getNullableAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases) {
|
||||
return findNullabilityAnnotation(owner, checkBases, true);
|
||||
return findNullabilityAnnotationWithDefault(owner, checkBases, true);
|
||||
}
|
||||
|
||||
public boolean isContainerAnnotation(@NotNull PsiAnnotation anno) {
|
||||
@@ -136,7 +136,7 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
|
||||
|
||||
@Nullable
|
||||
public PsiAnnotation getNotNullAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases) {
|
||||
return findNullabilityAnnotation(owner, checkBases, false);
|
||||
return findNullabilityAnnotationWithDefault(owner, checkBases, false);
|
||||
}
|
||||
|
||||
public PsiAnnotation copyNotNullAnnotation(PsiModifierListOwner owner) {
|
||||
@@ -168,14 +168,14 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiAnnotation findNullabilityAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases, boolean nullable) {
|
||||
Set<String> qNames = ContainerUtil.newHashSet(nullable ? getNullables() : getNotNulls());
|
||||
PsiAnnotation annotation = checkBases && owner instanceof PsiMethod
|
||||
? AnnotationUtil.findAnnotationInHierarchy(owner, qNames)
|
||||
: AnnotationUtil.findAnnotation(owner, qNames);
|
||||
private PsiAnnotation findNullabilityAnnotationWithDefault(@NotNull PsiModifierListOwner owner, boolean checkBases, boolean nullable) {
|
||||
PsiAnnotation annotation = findPlainNullabilityAnnotation(owner, checkBases, nullable);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
if (findPlainNullabilityAnnotation(owner, checkBases, !nullable) != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiType type = getOwnerType(owner);
|
||||
if (type == null || TypeConversionUtil.isPrimitiveAndNotNull(type)) return null;
|
||||
@@ -192,6 +192,13 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
|
||||
return findNullabilityDefaultInHierarchy(owner, nullable);
|
||||
}
|
||||
|
||||
private PsiAnnotation findPlainNullabilityAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases, boolean nullable) {
|
||||
Set<String> qNames = ContainerUtil.newHashSet(nullable ? getNullables() : getNotNulls());
|
||||
return checkBases && owner instanceof PsiMethod
|
||||
? AnnotationUtil.findAnnotationInHierarchy(owner, qNames)
|
||||
: AnnotationUtil.findAnnotation(owner, qNames);
|
||||
}
|
||||
|
||||
protected boolean hasHardcodedContracts(PsiElement element) {
|
||||
return false;
|
||||
}
|
||||
@@ -204,11 +211,11 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
|
||||
}
|
||||
|
||||
public boolean isNullable(@NotNull PsiModifierListOwner owner, boolean checkBases) {
|
||||
return findNullabilityAnnotation(owner, checkBases, true) != null;
|
||||
return findNullabilityAnnotationWithDefault(owner, checkBases, true) != null;
|
||||
}
|
||||
|
||||
public boolean isNotNull(@NotNull PsiModifierListOwner owner, boolean checkBases) {
|
||||
return findNullabilityAnnotation(owner, checkBases, false) != null;
|
||||
return findNullabilityAnnotationWithDefault(owner, checkBases, false) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -331,7 +338,7 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
|
||||
}
|
||||
|
||||
public static boolean isNullable(@NotNull PsiModifierListOwner owner) {
|
||||
return !isNotNull(owner) && getInstance(owner.getProject()).isNullable(owner, true);
|
||||
return getInstance(owner.getProject()).isNullable(owner, true);
|
||||
}
|
||||
|
||||
public static boolean isNotNull(@NotNull PsiModifierListOwner owner) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package foo;
|
||||
|
||||
import custom.CheckForNull;
|
||||
|
||||
class BaseClass {
|
||||
public void foo() {
|
||||
Object nullable = getNullable();
|
||||
if (nullable != null) {
|
||||
System.out.println(nullable.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@CheckForNull Object getNullable() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class ChildClass extends BaseClass {
|
||||
@CheckForNull
|
||||
@Override
|
||||
Object getNullable() {
|
||||
return super.getNullable();
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,11 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInspection.nullable.NullableStuffInspection;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
|
||||
@@ -112,6 +115,33 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
}
|
||||
|
||||
public void testOverrideCustomDefault() {
|
||||
DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
|
||||
myFixture.addClass("package custom;" +
|
||||
"public @interface CheckForNull {}");
|
||||
|
||||
final NullableNotNullManager nnnManager = NullableNotNullManager.getInstance(getProject());
|
||||
nnnManager.setNullables("custom.CheckForNull");
|
||||
Disposer.register(myTestRootDisposable, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
nnnManager.setNullables();
|
||||
}
|
||||
});
|
||||
|
||||
myFixture.addClass("package foo;" +
|
||||
"import static java.lang.annotation.ElementType.*;" +
|
||||
"@javax.annotation.meta.TypeQualifierDefault(METHOD) " +
|
||||
"@javax.annotation.Nonnull " +
|
||||
"public @interface ReturnValuesAreNonnullByDefault {}");
|
||||
|
||||
myFixture.addFileToProject("foo/package-info.java", "@ReturnValuesAreNonnullByDefault package foo;");
|
||||
|
||||
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
|
||||
myFixture.enableInspections(myInspection);
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
}
|
||||
|
||||
public void testHonorParameterDefaultInSetters() {
|
||||
DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
|
||||
DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
|
||||
|
||||
Reference in New Issue
Block a user