[java-psi] Substitution fix for nullability

WIP IDEA-372347 Java type inference should respect nullability

GitOrigin-RevId: a059f8847e1b7fb3800db6c10ada606edb023dfa
This commit is contained in:
Tagir Valeev
2025-05-27 16:01:46 +02:00
committed by intellij-monorepo-bot
parent 4c5e1be962
commit cd1f1d9379
3 changed files with 50 additions and 9 deletions

View File

@@ -32,9 +32,11 @@ public final class JavaTypeNullabilityUtil {
PsiElement context = type.getPsiContext();
if (context != null) {
NullableNotNullManager manager = NullableNotNullManager.getInstance(context.getProject());
NullabilityAnnotationInfo typeUseNullability = manager.findDefaultTypeUseNullability(context);
if (typeUseNullability != null) {
return typeUseNullability.toTypeNullability();
if (manager != null) {
NullabilityAnnotationInfo typeUseNullability = manager.findDefaultTypeUseNullability(context);
if (typeUseNullability != null) {
return typeUseNullability.toTypeNullability();
}
}
}
PsiClass target = type.resolve();

View File

@@ -213,7 +213,7 @@ public final class PsiSubstitutorImpl implements PsiSubstitutor {
}
PsiSubstitutor resultSubstitutor = processClass(aClass, resolveResult.getSubstitutor());
return new PsiImmediateClassType(aClass, resultSubstitutor, classType.getLanguageLevel(),
classType.getAnnotationProvider(), classType.getPsiContext());
classType.getAnnotationProvider(), classType.getPsiContext(), classType.getNullability());
}
private @NotNull PsiSubstitutor processClass(@NotNull PsiClass resolve, @NotNull PsiSubstitutor originalSubstitutor) {

View File

@@ -4,12 +4,11 @@ package com.intellij.java.psi;
import com.intellij.codeInsight.Nullability;
import com.intellij.codeInsight.NullabilitySource;
import com.intellij.codeInsight.TypeNullability;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypes;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
public final class PsiTypeNullabilityTest extends LightJavaCodeInsightFixtureTestCase {
public void testPrimitive() {
@@ -29,11 +28,19 @@ public final class PsiTypeNullabilityTest extends LightJavaCodeInsightFixtureTes
assertEquals(NullabilitySource.Standard.NONE, voidTypeNullability.source());
}
private PsiType configureAndGetFieldType(@Language("JAVA") String text) {
private @NotNull PsiType configureAndGetFieldType(@Language("JAVA") String text) {
PsiFile file = myFixture.configureByText("Test.java", text);
return ((PsiJavaFile)file).getClasses()[0].getFields()[0].getType();
}
private @NotNull PsiType configureAndGetExpressionType(@Language("JAVA") String code) {
PsiFile file = myFixture.configureByText("Test.java", code);
PsiExpression expression = PsiTreeUtil.getParentOfType(file.findElementAt(myFixture.getCaretOffset()), PsiExpression.class);
PsiType type = expression.getType();
assertNotNull(type);
return type;
}
public void testSimpleUnknown() {
PsiType type = configureAndGetFieldType("""
class A {
@@ -140,4 +147,36 @@ public final class PsiTypeNullabilityTest extends LightJavaCodeInsightFixtureTes
assertEquals("NULLABLE (@Nullable)", type.getNullability().toString());
assertEquals("NOT_NULL (@NotNull)", type.getDeepComponentType().getNullability().toString());
}
public void testSubstitutorSimple() {
PsiType type = configureAndGetExpressionType("""
import org.jetbrains.annotations.NotNull;
class X<T> {
native T foo();
static void test(X<@NotNull String> x) {
x.foo(<caret>);
}
}
""");
assertEquals("java.lang.String", type.getCanonicalText());
assertEquals("NOT_NULL (@NotNull)", type.getNullability().toString());
}
public void testSubstitutorOuter() {
PsiType type = configureAndGetExpressionType("""
import org.jetbrains.annotations.NotNull;
class X<T> {
native @NotNull X<T> foo();
static void test(X<@NotNull String> x) {
x.foo(<caret>);
}
}
""");
assertEquals("X<java.lang.String>", type.getCanonicalText());
assertEquals("NOT_NULL (@NotNull)", type.getNullability().toString());
}
}