mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
treat type parameter array upper bounds (IDEA-190380)
This commit is contained in:
@@ -60,6 +60,8 @@ public class TypeConversionUtil {
|
||||
}
|
||||
};
|
||||
private static final Key<PsiElement> ORIGINAL_CONTEXT = Key.create("ORIGINAL_CONTEXT");
|
||||
public static final Key<PsiType> LOWER_BOUND = Key.create("LowBound");
|
||||
public static final Key<PsiType> UPPER_BOUND = Key.create("UpperBound");
|
||||
|
||||
static {
|
||||
TYPE_TO_RANK_MAP.put(PsiType.BYTE, BYTE_RANK);
|
||||
@@ -808,7 +810,16 @@ public class TypeConversionUtil {
|
||||
return isAssignable(left, ((PsiDisjunctionType)right).getLeastUpperBound(), allowUncheckedConversion, capture);
|
||||
}
|
||||
|
||||
if (left instanceof PsiArrayType) return false;
|
||||
if (left instanceof PsiArrayType) {
|
||||
if (right instanceof PsiClassType) {
|
||||
PsiClass aClass = ((PsiClassType)right).resolve();
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
PsiType upperBound = getUpperBound(aClass);
|
||||
return upperBound != null && isAssignable(left, upperBound, allowUncheckedConversion, capture);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (right instanceof PsiPrimitiveType) {
|
||||
if (isVoidType(right)) return false;
|
||||
if (!(left instanceof PsiPrimitiveType)) {
|
||||
@@ -1450,6 +1461,14 @@ public class TypeConversionUtil {
|
||||
parameter.putUserData(ORIGINAL_CONTEXT, context);
|
||||
}
|
||||
|
||||
public static PsiType getUpperBound(@NotNull PsiClass psiClass) {
|
||||
return psiClass.getUserData(UPPER_BOUND);
|
||||
}
|
||||
|
||||
public static PsiType getLowerBound(@NotNull PsiClass psiClass) {
|
||||
return psiClass.getUserData(LOWER_BOUND);
|
||||
}
|
||||
|
||||
private interface Caster {
|
||||
@NotNull
|
||||
Object cast(@NotNull Object operand);
|
||||
|
||||
@@ -19,14 +19,10 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceBound;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiSearchScopeUtil;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.JavaClassSupers;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -53,7 +49,7 @@ public class JavaClassSupersImpl extends JavaClassSupers {
|
||||
bounds = ((InferenceVariable)superClass).getBounds(InferenceBound.LOWER);
|
||||
}
|
||||
else if (superClass instanceof PsiTypeParameter) {
|
||||
final PsiType lowerBound = InferenceSession.getLowerBound(superClass);
|
||||
final PsiType lowerBound = TypeConversionUtil.getLowerBound(superClass);
|
||||
if (lowerBound != null) {
|
||||
bounds = Collections.singletonList(lowerBound);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub;
|
||||
import com.intellij.psi.impl.source.ClassInnerStuffCache;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.ElementClassFilter;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
@@ -998,7 +997,7 @@ public class PsiClassImplUtil {
|
||||
if (psiClass.isAnnotationType()) {
|
||||
return new PsiClassType[]{getAnnotationSuperType(psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory())};
|
||||
}
|
||||
PsiType upperBound = InferenceSession.getUpperBound(psiClass);
|
||||
PsiType upperBound = TypeConversionUtil.getUpperBound(psiClass);
|
||||
if (upperBound == null && psiClass instanceof PsiTypeParameter) {
|
||||
upperBound = LambdaUtil.getFunctionalTypeMap().get(psiClass);
|
||||
}
|
||||
@@ -1041,7 +1040,7 @@ public class PsiClassImplUtil {
|
||||
if (psiClass.isAnnotationType()) {
|
||||
return CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION.equals(baseClass.getQualifiedName());
|
||||
}
|
||||
PsiType upperBound = InferenceSession.getUpperBound(psiClass);
|
||||
PsiType upperBound = TypeConversionUtil.getUpperBound(psiClass);
|
||||
if (upperBound == null && psiClass instanceof PsiTypeParameter) {
|
||||
upperBound = LambdaUtil.getFunctionalTypeMap().get(psiClass);
|
||||
}
|
||||
|
||||
+4
-13
@@ -42,8 +42,6 @@ import java.util.*;
|
||||
|
||||
public class InferenceSession {
|
||||
private static final Logger LOG = Logger.getInstance(InferenceSession.class);
|
||||
private static final Key<PsiType> LOWER_BOUND = Key.create("LowBound");
|
||||
private static final Key<PsiType> UPPER_BOUND = Key.create("UpperBound");
|
||||
private static final Key<Boolean> ERASED = Key.create("UNCHECKED_CONVERSION");
|
||||
private static final Function<Pair<PsiType, PsiType>, PsiType> UPPER_BOUND_FUNCTION = pair -> GenericsUtil.getGreatestLowerBound(pair.first, pair.second);
|
||||
|
||||
@@ -133,18 +131,11 @@ public class InferenceSession {
|
||||
initBounds(typeParams);
|
||||
}
|
||||
|
||||
public static PsiType getUpperBound(@NotNull PsiClass psiClass) {
|
||||
return psiClass.getUserData(UPPER_BOUND);
|
||||
}
|
||||
public static PsiType getLowerBound(@NotNull PsiClass psiClass) {
|
||||
return psiClass.getUserData(LOWER_BOUND);
|
||||
}
|
||||
|
||||
public static PsiType createTypeParameterTypeWithUpperBound(PsiType upperBound, PsiElement place) {
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(place.getProject());
|
||||
|
||||
final PsiTypeParameter parameter = elementFactory.createTypeParameterFromText("T", place);
|
||||
parameter.putUserData(UPPER_BOUND, upperBound);
|
||||
parameter.putUserData(TypeConversionUtil.UPPER_BOUND, upperBound);
|
||||
|
||||
return elementFactory.createType(parameter);
|
||||
}
|
||||
@@ -1139,9 +1130,9 @@ public class InferenceSession {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
parameter.putUserData(LOWER_BOUND, lub);
|
||||
parameter.putUserData(TypeConversionUtil.LOWER_BOUND, lub);
|
||||
}
|
||||
parameter.putUserData(UPPER_BOUND,
|
||||
parameter.putUserData(TypeConversionUtil.UPPER_BOUND,
|
||||
composeBound(var, InferenceBound.UPPER, UPPER_BOUND_FUNCTION, ySubstitutor.putAll(substitutor), true));
|
||||
TypeConversionUtil.markAsFreshVariable(parameter, myContext);
|
||||
if (!var.addBound(elementFactory.createType(parameter), InferenceBound.EQ, myIncorporationPhase)) {
|
||||
@@ -1195,7 +1186,7 @@ public class InferenceSession {
|
||||
//restore captured wildcard from method return type when no additional constraints were inferred
|
||||
//to preserve equality of type arguments
|
||||
if (capturedWildcard != null &&
|
||||
capturedWildcard.getUpperBound().equals(getUpperBound(aClass))) {
|
||||
capturedWildcard.getUpperBound().equals(TypeConversionUtil.getUpperBound(aClass))) {
|
||||
eqBound = capturedWildcard;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ public class StrictSubtypingConstraint implements ConstraintFormula {
|
||||
if (myT.equals(conjunct)) return true;
|
||||
}
|
||||
}
|
||||
final PsiType lowerBound = InferenceSession.getLowerBound(CClass);
|
||||
final PsiType lowerBound = TypeConversionUtil.getLowerBound(CClass);
|
||||
if (lowerBound != null) {
|
||||
constraints.add(new StrictSubtypingConstraint(lowerBound, myS, myCapture));
|
||||
return true;
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
|
||||
class Test {
|
||||
|
||||
private static Class<? extends Object[]> test(Class<?> arrayType) {
|
||||
return arrayType.asSubclass(Object[].class);
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -1014,6 +1014,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testArrayTypeUpperBound() { doTest(); }
|
||||
|
||||
public void testNonGenericInnerOfGenericOuter() { doTest(); }
|
||||
|
||||
public void testTypeParameterBoundsWithSubstitutionWhenMethodHierarchyIsChecked() {
|
||||
|
||||
Reference in New Issue
Block a user