[java-psi] Support annotations directly on wildcards

Usually, they are not allowed, but let's read them
Part of IDEA-372347 Java type inference should respect nullability

GitOrigin-RevId: 8bb222c158e2e62e185f0a57d6608462b2c89883
This commit is contained in:
Tagir Valeev
2025-06-02 16:58:03 +02:00
committed by intellij-monorepo-bot
parent 04f2c5187a
commit 9565341708
2 changed files with 42 additions and 10 deletions

View File

@@ -9,6 +9,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.JavaTypeNullabilityUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,12 +26,23 @@ public final class PsiWildcardType extends PsiType.Stub implements JvmWildcardTy
private final PsiManager myManager;
private final boolean myIsExtending;
private final PsiType myBound;
private final TypeNullability myBaseNullability;
private PsiWildcardType(@NotNull PsiManager manager, boolean isExtending, @Nullable PsiType bound) {
super(TypeAnnotationProvider.EMPTY);
this(manager, isExtending, bound, TypeAnnotationProvider.EMPTY);
}
private PsiWildcardType(@NotNull PsiManager manager, boolean isExtending, @Nullable PsiType bound, @NotNull TypeAnnotationProvider provider) {
this(manager, isExtending, bound, provider, JavaTypeNullabilityUtil.getNullabilityFromAnnotations(provider.getAnnotations()));
}
private PsiWildcardType(@NotNull PsiManager manager, boolean isExtending, @Nullable PsiType bound,
@NotNull TypeAnnotationProvider provider, @NotNull TypeNullability nullability) {
super(provider);
myManager = manager;
myIsExtending = isExtending;
myBound = bound;
myBaseNullability = nullability;
}
public static @NotNull PsiWildcardType createUnbounded(@NotNull PsiManager manager) {
@@ -49,19 +61,21 @@ public final class PsiWildcardType extends PsiType.Stub implements JvmWildcardTy
@Override
public @NotNull TypeNullability getNullability() {
if (myBound != null && isExtends()) {
return myBound.getNullability();
if (!myBaseNullability.equals(TypeNullability.UNKNOWN)) return myBaseNullability;
if (myBound != null && myIsExtending) {
return myBound.getNullability().inherited();
}
return super.getNullability();
return TypeNullability.UNKNOWN;
}
@Override
public @NotNull PsiWildcardType withNullability(@NotNull TypeNullability nullability) {
if (myBound != null && isExtends()) {
PsiType newBound = myBound.withNullability(nullability);
return newBound == myBound ? this : createExtends(getManager(), newBound);
}
return this;
return new PsiWildcardType(myManager, myIsExtending, myBound, getAnnotationProvider(), nullability);
}
@Override
public @NotNull PsiType annotate(@NotNull TypeAnnotationProvider provider) {
return new PsiWildcardType(myManager, myIsExtending, myBound, provider);
}
@Override