IDEA-341719 [java-analysis] Nullability annotation on type param doesn't apply to uses of type param

GitOrigin-RevId: 6a15d9e40e8d132e01c6a1b0b08a30ac3d33189d
This commit is contained in:
Tagir Valeev
2025-11-20 13:10:22 +00:00
committed by intellij-monorepo-bot
parent d0cfe3767b
commit 4b457ac3e7
6 changed files with 47 additions and 6 deletions
@@ -42,8 +42,10 @@ final class CheckerFrameworkSupport implements AnnotationPackageSupport {
// DefaultQualifier is not applicable to type parameter declarations
if (context instanceof PsiTypeParameter) return false;
// DefaultQualifier is not applicable to type parameter uses
return !(PsiUtil.getTypeByPsiElement(context) instanceof PsiClassType classType) ||
!(classType.resolve() instanceof PsiTypeParameter);
return !(PsiUtil.getTypeByPsiElement(context) instanceof PsiClassType classType &&
classType.resolve() instanceof PsiTypeParameter ||
context instanceof PsiJavaCodeReferenceElement ref &&
ref.resolve() instanceof PsiTypeParameter);
});
}
return ContextNullabilityInfo.EMPTY;
@@ -200,7 +200,7 @@ public abstract class NullableNotNullManager {
for (PsiParameter parameter: superParameters) {
NullabilityAnnotationInfo plain = findPlainAnnotation(parameter, false, annotations);
// Plain not null annotation is not inherited
if (plain != null) return null;
if (plain != null && !plain.isContainer()) return null;
NullabilityAnnotationInfo defaultInfo = findContainerAnnotation(parameter);
if (defaultInfo != null) {
return defaultInfo.getNullability() == Nullability.NOT_NULL ? defaultInfo.withInheritedFrom(parameter) : null;
@@ -259,6 +259,11 @@ public abstract class NullableNotNullManager {
Nullability origNullability = holder.getNullability(annotation);
return nullabilities.contains(origNullability) ? origNullability : null;
}
@Override
public boolean isWantedNullability(@NotNull Nullability nullability) {
return nullabilities.contains(nullability);
}
};
NullabilityAnnotationInfo result = findPlainAnnotation(owner, false, filtered);
return result == null || !nullabilities.contains(result.getNullability()) ? null : result;
@@ -296,7 +301,7 @@ public abstract class NullableNotNullManager {
}
if (type == null || type instanceof PsiPrimitiveType) return null;
NullabilityAnnotationInfo info = type.getNullability().toNullabilityAnnotationInfo();
return info != null && annotations.getNullability(info.getAnnotation().getQualifiedName()) != null ? info : null;
return info != null && annotations.isWantedNullability(info.getNullability()) ? info : null;
}
protected @NotNull Nullability correctNullability(@NotNull Nullability nullability, @NotNull PsiAnnotation annotation) {
@@ -479,6 +484,10 @@ public abstract class NullableNotNullManager {
* @return nullability
*/
@Nullable Nullability getNullability(String annotation);
default boolean isWantedNullability(@NotNull Nullability nullability) {
return true;
}
/**
* @param map from annotation qualified name to nullability
@@ -82,7 +82,12 @@ public final class JavaTypeNullabilityUtil {
PsiElement context = classType.getPsiContext();
return context instanceof PsiJavaCodeReferenceElement &&
context.getParent() instanceof PsiTypeElement &&
context.getParent().getParent() instanceof PsiLocalVariable;
isLocalVariable(context.getParent().getParent());
}
private static boolean isLocalVariable(PsiElement element) {
return element instanceof PsiLocalVariable ||
element instanceof PsiParameter && !(element.getParent() instanceof PsiParameterList);
}
/**
@@ -0,0 +1,21 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.NotNullByDefault;
interface Test<T> {
@NotNull
T test();
}
@NotNullByDefault
class TestImpl<T> implements Test<T> {
final T value;
public TestImpl(final T value) {
this.value = value;
}
@Override
public T test() {
return this.value;
}
}
@@ -144,7 +144,7 @@ public class CheckerNullityTest extends LightJavaCodeInsightFixtureTestCase {
import org.checkerframework.framework.qual.*;
@DefaultQualifier(NonNull.class)
interface Test<X> {
interface Test<X extends @Nullable Object> {
String test(X x);
X test(String x);
}""");
@@ -520,4 +520,8 @@ public class NullableStuffInspectionTest extends LightJavaCodeInsightFixtureTest
addJSpecifyNullMarked(myFixture);
doTest();
}
public void testDefaultNotNullTypeParameterOverrides() {
doTest();
}
}