highlight type parameter extends list errors: check once for all refs in refList not to repeat ourselves

This commit is contained in:
Anna Kozlova
2015-10-14 11:12:30 +02:00
parent 0554dd2c04
commit f29517700f
5 changed files with 27 additions and 9 deletions
@@ -333,12 +333,6 @@ public class GenericsHighlightUtil {
JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(extendFrom, resolveResult.getSubstitutor());
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createExtendsListFix(aClass, type, false), null);
}
if (errorResult == null && languageLevel.isAtLeast(LanguageLevel.JDK_1_7) &&
referenceElements.length > 1) {
//todo suppress erased methods which come from the same class
final Collection<HighlightInfo> result = checkOverrideEquivalentMethods(aClass);
return result != null && !result.isEmpty() ? result.iterator().next() : null;
}
return errorResult;
}
@@ -1412,5 +1406,19 @@ public class GenericsHighlightUtil {
}
return null;
}
public static HighlightInfo checkTypeParameterOverrideEquivalentMethods(PsiClass aClass, LanguageLevel level) {
if (aClass instanceof PsiTypeParameter && level.isAtLeast(LanguageLevel.JDK_1_7)) {
final PsiReferenceList extendsList = aClass.getExtendsList();
if (extendsList != null && extendsList.getReferenceElements().length > 1) {
//todo suppress erased methods which come from the same class
final Collection<HighlightInfo> result = GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass);
if (result != null && !result.isEmpty()) {
return result.iterator().next();
}
}
}
return null;
}
}
@@ -396,6 +396,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass, myJavaSdkVersion));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassAndPackageConflict(aClass));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkPublicClassInRightFile(aClass));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterOverrideEquivalentMethods(aClass, myLanguageLevel));
}
@Override
@@ -58,8 +58,17 @@ public class MethodSignatureUtil {
}
};
/**
* def: (8.4.2 Method Signature) Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
*
* erasure (erasure) = erasure, so we would check if erasures are equal and then check if the number of type parameters agree:
* if signature(m1)=signature(m2), then m1.typeParams=m2.typeParams
* if (erasure(signature(m1))=signature(m2), then m2.typeParams.length=0 and vise versa
*/
public static boolean areOverrideEquivalent(PsiMethod method1, PsiMethod method2) {
return method1.getTypeParameters().length == method2.getTypeParameters().length &&
final int typeParamsLength1 = method1.getTypeParameters().length;
final int typeParamsLength2 = method2.getTypeParameters().length;
return (typeParamsLength1 == typeParamsLength2 || typeParamsLength1 == 0 || typeParamsLength2 == 0) &&
areErasedParametersEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY));
}
@@ -10,6 +10,6 @@ interface IB{
}
class C {
<<error descr="'foo(A<T>)' in 'pck.IB' clashes with 'foo(A<?>)' in 'pck.IA'; both methods have same erasure, yet neither overrides the other"></error>T extends IA & IB> void bar(T x, A<String> y){
x.foo<error descr="Ambiguous method call: both 'IA.foo(A<?>)' and 'IB.foo(A<String>)' match">(y)</error>;
x.foo(y);
}
}
@@ -3,5 +3,5 @@ import java.util.List;
interface A
{
<<error descr="'add(E)' in 'java.util.List' clashes with 'add(E)' in 'java.util.Collection'; both methods have same erasure, yet neither overrides the other"></error><error descr="'add(E)' in 'java.util.List' clashes with 'add(E)' in 'java.util.Collection'; both methods have same erasure, yet neither overrides the other"></error>T extends List<?> & Collection<? extends Cloneable>> void foo(T x);
<<error descr="'java.util.Collection' cannot be inherited with different type arguments: 'capture<?>' and 'capture<? extends java.lang.Cloneable>'"></error>T extends List<?> & Collection<? extends Cloneable>> void foo(T x);
}