moreSpecific: check erased signatures when comparing interface methods (IDEA-67519)

This commit is contained in:
Anna Kozlova
2013-08-13 17:06:04 +04:00
parent 215cfff69c
commit 3f49bd2d73
4 changed files with 43 additions and 19 deletions

View File

@@ -58,7 +58,7 @@ public class MethodSignatureUtil {
}
};
private static boolean areErasedParametersEqual(@NotNull MethodSignature method1, @NotNull MethodSignature method2) {
public static boolean areErasedParametersEqual(@NotNull MethodSignature method1, @NotNull MethodSignature method2) {
PsiType[] erased1 = method1 instanceof MethodSignatureBase
? ((MethodSignatureBase)method1).getErasedParameterTypes() : calcErasedParameterTypes(method1);
PsiType[] erased2 = method2 instanceof MethodSignatureBase

View File

@@ -39,6 +39,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.sun.tools.javac.code.Flags.ABSTRACT;
/**
* Created by IntelliJ IDEA.
* User: ik
@@ -309,14 +311,17 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (MethodSignatureUtil.areSignaturesEqual(existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType());
final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType());
if (returnType != null && returnType1 != null && !returnType1.equals(returnType) && TypeConversionUtil.isAssignable(returnType, returnType1, false)) {
if (class1.isInterface() && !existingClass.isInterface()) continue;
conflicts.remove(existing);
} else {
conflicts.remove(i);
if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) {
if (TypeConversionUtil.isAssignable(returnType, returnType1, false)) {
if (class1.isInterface() && !existingClass.isInterface()) continue;
conflicts.remove(existing);
} else {
if (!TypeConversionUtil.isAssignable(returnType1, returnType, false)) continue;
conflicts.remove(i);
}
i--;
break;
}
i--;
break;
}
}
}
@@ -521,33 +526,30 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
}
Specifics isMoreSpecific = null;
if (class1 != class2) {
if (class2.isInheritor(class1, true) || class1.isInterface() && !class2.isInterface()) {
if (MethodSignatureUtil.isSubsignature(method1.getSignature(info1.getSubstitutor()), method2.getSignature(info2.getSubstitutor()))) {
isMoreSpecific = Specifics.SECOND;
return Specifics.SECOND;
}
else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) {
isMoreSpecific = Specifics.SECOND;
return Specifics.SECOND;
}
}
else if (class1.isInheritor(class2, true) || class2.isInterface()) {
if (MethodSignatureUtil.isSubsignature(method2.getSignature(info2.getSubstitutor()), method1.getSignature(info1.getSubstitutor()))) {
isMoreSpecific = Specifics.FIRST;
if (MethodSignatureUtil.areErasedParametersEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY)) &&
MethodSignatureUtil.isSubsignature(method2.getSignature(info2.getSubstitutor()), method1.getSignature(info1.getSubstitutor()))) {
return Specifics.FIRST;
}
else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) {
isMoreSpecific = Specifics.FIRST;
return Specifics.FIRST;
}
}
}
if (isMoreSpecific == null) {
return Specifics.NEITHER;
}
return isMoreSpecific;
return Specifics.NEITHER;
}
private int getLevel(int applicabilityLevel,
private static int getLevel(int applicabilityLevel,
LanguageLevel languageLevel,
PsiMethod method2,
PsiTypeParameter[] typeParameters2,

View File

@@ -0,0 +1,18 @@
package pck;
class A<T extends C<String> & D>
{
void bar(T x)
{
x.foo<error descr="Ambiguous method call: both 'C.foo(String)' and 'D.foo(String)' match">("")</error>;
}
}
interface D
{
abstract void foo(String s);
}
interface C<T>
{
abstract void foo(T s);
}

View File

@@ -211,6 +211,10 @@ public class AdvHighlightingJdk7Test extends DaemonAnalyzerTestCase {
doTestAmbiguous();
}
public void testAmbiguousIDEA67519() throws Exception {
doTestAmbiguous();
}
public void testAmbiguousMethodsFromSameClassAccess() throws Exception {
doTestAmbiguous();
}