mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 21:01:48 +07:00
TypeParameter inferred types check unification
This commit is contained in:
+17
-41
@@ -27,6 +27,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
@@ -59,49 +60,24 @@ public class GenericsHighlightUtil {
|
||||
public static HighlightInfo checkInferredTypeArguments(PsiMethod genericMethod,
|
||||
PsiMethodCallExpression call,
|
||||
PsiSubstitutor substitutor) {
|
||||
PsiTypeParameter[] typeParameters = genericMethod.getTypeParameters();
|
||||
for (PsiTypeParameter typeParameter : typeParameters) {
|
||||
PsiType substituted = substitutor.substitute(typeParameter);
|
||||
if (substituted == null) return null;
|
||||
substituted = PsiUtil.captureToplevelWildcards(substituted, call);
|
||||
PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes();
|
||||
for (PsiClassType type : extendsTypes) {
|
||||
PsiType extendsType = substitutor.substitute(type);
|
||||
if (substituted instanceof PsiWildcardType) {
|
||||
if (((PsiWildcardType)substituted).isSuper()) {
|
||||
continue;
|
||||
}
|
||||
final PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
|
||||
if (TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(extendsBound))) {
|
||||
if (extendsBound instanceof PsiClassType) {
|
||||
PsiType[] parameters = ((PsiClassType)extendsBound).getParameters();
|
||||
if (parameters.length == 1) {
|
||||
PsiType argType = parameters[0];
|
||||
if (argType instanceof PsiCapturedWildcardType) {
|
||||
argType = ((PsiCapturedWildcardType)argType).getWildcard();
|
||||
}
|
||||
if (argType instanceof PsiWildcardType && !((PsiWildcardType)argType).isBounded()) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TypeConversionUtil.isAssignable(extendsType, substituted, false)) {
|
||||
PsiClass boundClass = extendsType instanceof PsiClassType ? ((PsiClassType)extendsType).resolve() : null;
|
||||
final Pair<PsiTypeParameter, PsiType> inferredTypeArgument =
|
||||
GenericsUtil.findTypeParameterWithBoundError(genericMethod.getTypeParameters(), substitutor, call, false);
|
||||
if (inferredTypeArgument != null) {
|
||||
final PsiType extendsType = inferredTypeArgument.second;
|
||||
final PsiTypeParameter typeParameter = inferredTypeArgument.first;
|
||||
PsiClass boundClass = extendsType instanceof PsiClassType ? ((PsiClassType)extendsType).resolve() : null;
|
||||
|
||||
@NonNls String messageKey = boundClass == null || typeParameter.isInterface() == boundClass.isInterface()
|
||||
? "generics.inferred.type.for.type.parameter.is.not.within.its.bound.extend"
|
||||
: "generics.inferred.type.for.type.parameter.is.not.within.its.bound.implement";
|
||||
@NonNls String messageKey = boundClass == null || typeParameter.isInterface() == boundClass.isInterface()
|
||||
? "generics.inferred.type.for.type.parameter.is.not.within.its.bound.extend"
|
||||
: "generics.inferred.type.for.type.parameter.is.not.within.its.bound.implement";
|
||||
|
||||
String description = JavaErrorMessages.message(
|
||||
messageKey,
|
||||
HighlightUtil.formatClass(typeParameter),
|
||||
JavaHighlightUtil.formatType(extendsType),
|
||||
JavaHighlightUtil.formatType(substituted)
|
||||
);
|
||||
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(call).descriptionAndTooltip(description).create();
|
||||
}
|
||||
}
|
||||
String description = JavaErrorMessages.message(
|
||||
messageKey,
|
||||
HighlightUtil.formatClass(typeParameter),
|
||||
JavaHighlightUtil.formatType(extendsType),
|
||||
JavaHighlightUtil.formatType(substitutor.substitute(typeParameter))
|
||||
);
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(call).descriptionAndTooltip(description).create();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -249,10 +249,17 @@ public class GenericsUtil {
|
||||
final PsiSubstitutor substitutor,
|
||||
final PsiElement context,
|
||||
final boolean allowUncheckedConversion) {
|
||||
return findTypeParameterWithBoundError(typeParams, substitutor, context, allowUncheckedConversion) == null;
|
||||
}
|
||||
|
||||
public static Pair<PsiTypeParameter, PsiType> findTypeParameterWithBoundError(final PsiTypeParameter[] typeParams,
|
||||
final PsiSubstitutor substitutor,
|
||||
final PsiElement context,
|
||||
final boolean allowUncheckedConversion) {
|
||||
nextTypeParam:
|
||||
for (PsiTypeParameter typeParameter : typeParams) {
|
||||
PsiType substituted = substitutor.substitute(typeParameter);
|
||||
if (substituted == null) return true;
|
||||
if (substituted == null) return null;
|
||||
substituted = PsiUtil.captureToplevelWildcards(substituted, context);
|
||||
|
||||
PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes();
|
||||
@@ -263,7 +270,7 @@ public class GenericsUtil {
|
||||
continue;
|
||||
}
|
||||
final PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
|
||||
if (TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(extendsBound))) {
|
||||
if (Comparing.equal(TypeConversionUtil.erasure(extendsType), TypeConversionUtil.erasure(extendsBound))) {
|
||||
if (extendsBound instanceof PsiClassType) {
|
||||
if (acceptExtendsBound((PsiClassType)extendsBound, 0)) continue;
|
||||
} else if (extendsBound instanceof PsiIntersectionType) {
|
||||
@@ -275,12 +282,12 @@ public class GenericsUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TypeConversionUtil.isAssignable(extendsType, substituted, allowUncheckedConversion)) {
|
||||
return false;
|
||||
if (extendsType != null && !TypeConversionUtil.isAssignable(extendsType, substituted, allowUncheckedConversion)) {
|
||||
return Pair.create(typeParameter, extendsType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean acceptExtendsBound(PsiClassType extendsBound, int depth) {
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ class SortTest<R extends Comparable<R>> implements Comparable<SortTest<R>> {
|
||||
list.add(t1);
|
||||
SortTest<?> t2 = new SortTest<Integer>(0);
|
||||
list.add(t2);
|
||||
<error descr="Inferred type 'SortTest<capture<?>>' for type parameter 'T' is not within its bound; should implement 'java.lang.Comparable<? super SortTest<?>>'">Collections.sort(list)</error>;
|
||||
<error descr="Inferred type 'SortTest<?>' for type parameter 'T' is not within its bound; should implement 'java.lang.Comparable<? super SortTest<?>>'">Collections.sort(list)</error>;
|
||||
t1.compareTo<error descr="'compareTo(SortTest<capture<? extends java.lang.Comparable<capture<?>>>>)' in 'SortTest' cannot be applied to '(SortTest<capture<?>>)'">(t2)</error>;
|
||||
|
||||
//this should be OK
|
||||
|
||||
Reference in New Issue
Block a user