mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
[java-psi] Disable nullity processing during upper bound capturing
We rely on PsiCapturedWildcardType identity when creating recursive types (the upper bound of a PsiCapturedWildcardType may refer to the same type). However, when we are under NullMarked annotation, the PsiCapturedWildcardType instance could be recreated, which prevents us from creating a proper PsiType object. Fixes IDEA-378142 Regress issue with resolve type of returned generics value (cherry picked from commit 4fb3c306e302715ab8de93f606397cd2a3dcb864) IJ-CR-174927 GitOrigin-RevId: 37ff78949e58209010a5a493be537b6265052e34
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a34483fe06
commit
50bbd0efa5
@@ -53,7 +53,7 @@ public final class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
PsiType originalBound = !wildcardType.isSuper() ? wildcardType.getBound() : null;
|
||||
PsiType glb = originalBound;
|
||||
for (PsiType boundType : boundTypes) {
|
||||
final PsiType substitutedBoundType = captureSubstitutor.substitute(boundType);
|
||||
final PsiType substitutedBoundType = captureSubstitutor.substituteIgnoringNullability(boundType);
|
||||
//glb for array types is not specified yet
|
||||
if (originalBound instanceof PsiArrayType &&
|
||||
substitutedBoundType instanceof PsiArrayType &&
|
||||
|
||||
@@ -51,6 +51,19 @@ public interface PsiSubstitutor {
|
||||
@Contract(pure = true, value = "null -> null")
|
||||
PsiType substitute(@Nullable PsiType type);
|
||||
|
||||
/**
|
||||
* Substitutes type parameters occurring in {@code type} with their values.
|
||||
* If value for type parameter is {@code null}, appropriate erasure is returned.
|
||||
* The nullability of the original type
|
||||
*
|
||||
* @param type the type to substitute the type parameters for.siT
|
||||
* @return the result of the substitution.
|
||||
*/
|
||||
@Contract(pure = true, value = "null -> null")
|
||||
default PsiType substituteIgnoringNullability(@Nullable PsiType type) {
|
||||
return substitute(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this substitutor has at least one raw substitution
|
||||
*/
|
||||
|
||||
@@ -46,7 +46,6 @@ public final class PsiSubstitutorImpl implements PsiSubstitutor {
|
||||
private static final UnmodifiableHashMap<PsiTypeParameter, PsiType> EMPTY_MAP = UnmodifiableHashMap.empty(PSI_EQUIVALENCE);
|
||||
|
||||
private final @NotNull UnmodifiableHashMap<PsiTypeParameter, PsiType> mySubstitutionMap;
|
||||
private final SubstitutionVisitor mySimpleSubstitutionVisitor = new SubstitutionVisitor();
|
||||
|
||||
PsiSubstitutorImpl(@NotNull Map<? extends PsiTypeParameter, ? extends PsiType> map) {
|
||||
mySubstitutionMap = UnmodifiableHashMap.fromMap(PSI_EQUIVALENCE, map);
|
||||
@@ -78,7 +77,7 @@ public final class PsiSubstitutorImpl implements PsiSubstitutor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type mapped to type parameter; null if type parameter is mapped to null; or PsiType.VOID if no mapping exists
|
||||
* @return type mapped to type parameter; null if the type parameter is mapped to null; or PsiType.VOID if no mapping exists
|
||||
*/
|
||||
private PsiType getFromMap(@NotNull PsiTypeParameter typeParameter) {
|
||||
if (typeParameter instanceof LightTypeParameter && ((LightTypeParameter)typeParameter).useDelegateToSubstitute()) {
|
||||
@@ -88,12 +87,19 @@ public final class PsiSubstitutorImpl implements PsiSubstitutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType substitute(PsiType type) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
public PsiType substitute(@Nullable PsiType type) {
|
||||
return doSubstitute(type, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType substituteIgnoringNullability(@Nullable PsiType type) {
|
||||
return doSubstitute(type, true);
|
||||
}
|
||||
|
||||
private @Nullable PsiType doSubstitute(@Nullable PsiType type, boolean ignoreNullity) {
|
||||
if (type == null) return null;
|
||||
PsiUtil.ensureValidType(type);
|
||||
PsiType substituted = type.accept(mySimpleSubstitutionVisitor);
|
||||
PsiType substituted = type.accept(new SubstitutionVisitor(ignoreNullity));
|
||||
return correctExternalSubstitution(substituted, type);
|
||||
}
|
||||
|
||||
@@ -151,6 +157,11 @@ public final class PsiSubstitutorImpl implements PsiSubstitutor {
|
||||
}
|
||||
|
||||
private class SubstitutionVisitor extends PsiTypeMapper {
|
||||
private final boolean ignoreNullity;
|
||||
|
||||
private SubstitutionVisitor(boolean ignoreNullity) {
|
||||
this.ignoreNullity = ignoreNullity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitType(@NotNull PsiType type) {
|
||||
@@ -210,8 +221,10 @@ public final class PsiSubstitutorImpl implements PsiSubstitutor {
|
||||
// TODO: remove once nullability works better than annotations
|
||||
result = result.annotate(getMergedProvider(classType, result));
|
||||
}
|
||||
TypeNullability origNullability = classType.getNullability();
|
||||
result = origNullability.equals(TypeNullability.UNKNOWN) ? result : result.withNullability(origNullability.instantiatedWith(result.getNullability()));
|
||||
if (!ignoreNullity) {
|
||||
TypeNullability origNullability = classType.getNullability();
|
||||
result = origNullability.equals(TypeNullability.UNKNOWN) ? result : result.withNullability(origNullability.instantiatedWith(result.getNullability()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -377,4 +377,30 @@ public final class PsiTypeNullabilityTest extends LightJavaCodeInsightFixtureTes
|
||||
TypeNullability typeNullability = info.toTypeNullability();
|
||||
assertEquals("NOT_NULL (@NotNullByDefault on package foo)", typeNullability.toString());
|
||||
}
|
||||
|
||||
public void testFBoundResolveUnderNotNull() {
|
||||
myFixture.configureByText("Test.java", """
|
||||
import org.jetbrains.annotations.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
interface RestClient2 {
|
||||
default void test(RequestHeadersUriSpec<?> spec2) {
|
||||
spec2.uri().attributes().retrieve();
|
||||
}
|
||||
|
||||
interface UriSpec<S extends RequestHeadersSpec<?>> {
|
||||
S uri();
|
||||
}
|
||||
|
||||
interface RequestHeadersSpec<S extends RequestHeadersSpec<S>> {
|
||||
S attributes();
|
||||
Object retrieve();
|
||||
}
|
||||
|
||||
interface RequestHeadersUriSpec<S extends RequestHeadersSpec<S>> extends UriSpec<S>, RequestHeadersSpec<S> {
|
||||
}
|
||||
}
|
||||
""");
|
||||
myFixture.checkHighlighting();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user