mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
resolve member/type annotation nullable/notnull conflict (IDEA-174042)
This commit is contained in:
@@ -245,11 +245,35 @@ public abstract class NullableNotNullManager {
|
||||
private PsiAnnotation findPlainNullabilityAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases) {
|
||||
Set<String> qNames = ContainerUtil.newHashSet(getNullablesWithNickNames());
|
||||
qNames.addAll(getNotNullsWithNickNames());
|
||||
return checkBases && owner instanceof PsiMethod
|
||||
? AnnotationUtil.findAnnotationInHierarchy(owner, qNames)
|
||||
: AnnotationUtil.findAnnotation(owner, qNames);
|
||||
PsiAnnotation memberAnno = checkBases && owner instanceof PsiMethod
|
||||
? AnnotationUtil.findAnnotationInHierarchy(owner, qNames)
|
||||
: AnnotationUtil.findAnnotation(owner, qNames);
|
||||
if (memberAnno != null) {
|
||||
if (owner instanceof PsiMethod) {
|
||||
return preferTypeAnnotation(memberAnno, ((PsiMethod)owner).getReturnType());
|
||||
}
|
||||
if (owner instanceof PsiVariable) {
|
||||
return preferTypeAnnotation(memberAnno, ((PsiVariable)owner).getType());
|
||||
}
|
||||
}
|
||||
return memberAnno;
|
||||
}
|
||||
|
||||
private static PsiAnnotation preferTypeAnnotation(@NotNull PsiAnnotation memberAnno, @Nullable PsiType type) {
|
||||
if (type != null) {
|
||||
for (PsiAnnotation typeAnno : type.getApplicableAnnotations()) {
|
||||
if (areDifferentNullityAnnotations(memberAnno, typeAnno)) {
|
||||
return typeAnno;
|
||||
}
|
||||
}
|
||||
}
|
||||
return memberAnno;
|
||||
}
|
||||
|
||||
private static boolean areDifferentNullityAnnotations(@NotNull PsiAnnotation memberAnno, PsiAnnotation typeAnno) {
|
||||
return isNullableAnnotation(typeAnno) && isNotNullAnnotation(memberAnno) ||
|
||||
isNullableAnnotation(memberAnno) && isNotNullAnnotation(typeAnno);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected List<String> getNullablesWithNickNames() {
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import withTypeUse.NotNull;
|
||||
import withTypeUse.Nullable;
|
||||
|
||||
interface Foo {
|
||||
@Nullable Object @NotNull [] getNotNullArrayOfNullableObjects();
|
||||
@NotNull Object @Nullable [] getNullableArrayOfNotNullObjects();
|
||||
}
|
||||
|
||||
class FooImpl implements Foo {
|
||||
|
||||
@Override
|
||||
public @Nullable Object @NotNull [] getNotNullArrayOfNullableObjects() {
|
||||
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Object @Nullable [] getNullableArrayOfNotNullObjects() {
|
||||
if (Math.random() > 0.5) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return new Object[]{null, new Object()};
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-2
@@ -133,8 +133,12 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
|
||||
}
|
||||
|
||||
static void setupTypeUseAnnotations(String pkg, JavaCodeInsightTestFixture fixture) {
|
||||
fixture.addClass("package " + pkg + ";\n\nimport java.lang.annotation.*;\n\n@Target({ElementType.TYPE_USE}) public @interface Nullable { }");
|
||||
fixture.addClass("package " + pkg + ";\n\nimport java.lang.annotation.*;\n\n@Target({ElementType.TYPE_USE}) public @interface NotNull { }");
|
||||
setupCustomAnnotations(pkg, "{ElementType.TYPE_USE}", fixture);
|
||||
}
|
||||
|
||||
private static void setupCustomAnnotations(String pkg, String target, JavaCodeInsightTestFixture fixture) {
|
||||
fixture.addClass("package " + pkg + ";\n\nimport java.lang.annotation.*;\n\n@Target(" + target + ") public @interface Nullable { }");
|
||||
fixture.addClass("package " + pkg + ";\n\nimport java.lang.annotation.*;\n\n@Target(" + target + ") public @interface NotNull { }");
|
||||
setCustomAnnotations(fixture.getProject(), fixture.getTestRootDisposable(), pkg + ".NotNull", pkg + ".Nullable");
|
||||
}
|
||||
|
||||
@@ -151,4 +155,9 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
|
||||
public void testCapturedWildcardNotNull() { doTest(); }
|
||||
public void testVarargNotNull() { doTestWithCustomAnnotations(); }
|
||||
|
||||
public void testArrayComponentAndMethodAnnotationConflict() {
|
||||
setupCustomAnnotations("withTypeUse", "{ElementType.METHOD, ElementType.TYPE_USE}", myFixture);
|
||||
doTest();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user