[java-inspections] IDEA-380526 Jspecify. False positive. Non-null type argument is expected for Array type

GitOrigin-RevId: 132eab2bc3bc9c4f6995a29796d8596b6e4a3c5c
This commit is contained in:
Mikhail Pyltsin
2025-11-07 03:31:56 +00:00
committed by intellij-monorepo-bot
parent ad6d52df3b
commit 8c3b69c65b
16 changed files with 453 additions and 35 deletions
@@ -475,8 +475,11 @@ public final class GenericsUtil {
}
}
else if (type instanceof PsiArrayType) {
PsiType component = eliminateWildcards(((PsiArrayType)type).getComponentType(), false);
PsiType newArray = type instanceof PsiEllipsisType ? new PsiEllipsisType(component) : new PsiArrayType(component);
PsiArrayType psiArrayType = (PsiArrayType)type;
PsiType component = eliminateWildcards(psiArrayType.getComponentType(), false);
PsiType newArray = type instanceof PsiEllipsisType ?
new PsiEllipsisType(component).withContainerNullability(psiArrayType) :
new PsiArrayType(component).withContainerNullability(psiArrayType);
return newArray.annotate(type.getAnnotationProvider()).withNullability(type.getNullability());
}
else if (type instanceof PsiWildcardType) {
@@ -1,10 +1,14 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi;
import com.intellij.codeInsight.NullabilityAnnotationInfo;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.TypeNullability;
import com.intellij.lang.jvm.types.JvmArrayType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.JavaTypeNullabilityUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -16,26 +20,30 @@ import org.jetbrains.annotations.Nullable;
*/
public class PsiArrayType extends PsiType.Stub implements JvmArrayType {
private final PsiType myComponentType;
private TypeNullability myNullability;
TypeNullability myNullability;
@Nullable
final PsiTypeElementPointer myElementPointer;
public PsiArrayType(@NotNull PsiType componentType) {
this(componentType, TypeAnnotationProvider.EMPTY);
}
public PsiArrayType(@NotNull PsiType componentType, PsiAnnotation @NotNull [] annotations) {
super(annotations);
myComponentType = componentType;
myNullability = null;
this(componentType, TypeAnnotationProvider.Static.create(annotations));
}
public PsiArrayType(@NotNull PsiType componentType, @NotNull TypeAnnotationProvider provider) {
this(componentType, provider, null);
this(componentType, provider, null, null);
}
PsiArrayType(@NotNull PsiType componentType, @NotNull TypeAnnotationProvider provider, @Nullable TypeNullability nullability) {
PsiArrayType(@NotNull PsiType componentType,
@NotNull TypeAnnotationProvider provider,
@Nullable TypeNullability nullability,
@Nullable PsiTypeElementPointer elememtPointer) {
super(provider);
myComponentType = componentType;
myNullability = nullability;
myElementPointer = elememtPointer;
}
@Override
@@ -120,10 +128,60 @@ public class PsiArrayType extends PsiType.Stub implements JvmArrayType {
return myComponentType;
}
/**
* Creates a new array type instance with the specified nullable container nullability.
*
* @param elementPointer the PSI element pointer representing the context, or null if no specific context is required.
* @return a new instance of {@link PsiType} with the specified nullable container nullability.
*/
@ApiStatus.Experimental
@NotNull
public PsiType withContainerNullability(@Nullable PsiTypeElementPointer elementPointer) {
if (elementPointer == null) return this;
if (elementPointer == myElementPointer) return this;
return new PsiArrayType(myComponentType, getAnnotationProvider(), myNullability, elementPointer);
}
@ApiStatus.Experimental
@Nullable
static TypeNullability getContainerNullability(@NotNull PsiTypeElement psiContext) {
Project project = psiContext.getProject();
if (project.isDefault()) return null;
NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
if (manager == null) return null;
NullabilityAnnotationInfo defaultNullability = manager.findDefaultTypeUseNullability(psiContext);
TypeNullability nullability = defaultNullability == null ? null : defaultNullability.toTypeNullability();
return nullability;
}
/**
* Creates a new array type instance with the specified nullable container nullability.
*
* @param arrayType the array type from which container nullability will be taken.
* @return a new instance of {@link PsiType} with the specified nullable container nullability.
*/
@ApiStatus.Experimental
@NotNull
public PsiType withContainerNullability(@Nullable PsiArrayType arrayType) {
if (arrayType == null) return this;
if (arrayType.myElementPointer == myElementPointer) return this;
return new PsiArrayType(myComponentType, getAnnotationProvider(), myNullability, arrayType.myElementPointer);
}
@Override
public @NotNull TypeNullability getNullability() {
if (myNullability == null) {
myNullability = JavaTypeNullabilityUtil.getNullabilityFromAnnotations(getAnnotations());
TypeNullability nullability = JavaTypeNullabilityUtil.getNullabilityFromAnnotations(getAnnotations());
if (nullability == TypeNullability.UNKNOWN && myElementPointer != null) {
PsiTypeElement element = myElementPointer.retrieveElement();
if (element != null) {
TypeNullability containerNullability = getContainerNullability(element);
if (containerNullability != null) {
nullability = containerNullability;
}
}
}
myNullability = nullability;
}
return myNullability;
}
@@ -135,7 +193,7 @@ public class PsiArrayType extends PsiType.Stub implements JvmArrayType {
*/
@Override
public @NotNull PsiArrayType withNullability(@NotNull TypeNullability nullability) {
return new PsiArrayType(getComponentType(), getAnnotationProvider(), nullability);
return new PsiArrayType(getComponentType(), getAnnotationProvider(), nullability, myElementPointer);
}
@Override
@@ -4,6 +4,7 @@ package com.intellij.psi;
import com.intellij.codeInsight.TypeNullability;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents the type of a variable arguments array passed as a method parameter.
@@ -20,9 +21,12 @@ public class PsiEllipsisType extends PsiArrayType {
public PsiEllipsisType(@NotNull PsiType componentType, @NotNull TypeAnnotationProvider provider) {
super(componentType, provider);
}
private PsiEllipsisType(@NotNull PsiType componentType, @NotNull TypeAnnotationProvider provider, @NotNull TypeNullability nullability) {
super(componentType, provider, nullability);
private PsiEllipsisType(@NotNull PsiType componentType,
@NotNull TypeAnnotationProvider provider,
@Nullable TypeNullability nullability,
@Nullable PsiTypeElementPointer typeElementPointer) {
super(componentType, provider, nullability, typeElementPointer);
}
@Override
@@ -46,9 +50,25 @@ public class PsiEllipsisType extends PsiArrayType {
super.equalsToText(text);
}
@NotNull
@Override
public PsiType withContainerNullability(@Nullable PsiTypeElementPointer elementPointer) {
if (elementPointer == null) return this;
if (elementPointer == myElementPointer) return this;
return new PsiEllipsisType(getComponentType(), getAnnotationProvider(), myNullability, elementPointer);
}
@NotNull
@Override
public PsiType withContainerNullability(@Nullable PsiArrayType arrayType) {
if (arrayType == null) return this;
if (arrayType.myElementPointer == myElementPointer) return this;
return new PsiEllipsisType(getComponentType(), getAnnotationProvider(), myNullability, arrayType.myElementPointer);
}
@Override
public @NotNull PsiEllipsisType withNullability(@NotNull TypeNullability nullability) {
return new PsiEllipsisType(getComponentType(), getAnnotationProvider(), nullability);
return new PsiEllipsisType(getComponentType(), getAnnotationProvider(), nullability, this.myElementPointer);
}
/**
@@ -0,0 +1,22 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ApiStatus.Experimental
public interface PsiTypeElementPointer {
@Nullable
PsiTypeElement retrieveElement();
static PsiTypeElementPointer constant(@NotNull PsiTypeElement ref) {
return new PsiTypeElementPointer() {
@Override
public @NotNull PsiTypeElement retrieveElement() {
return ref;
}
};
}
}