check method signatures equality by erasure; do not check method names for constructors.

note that erasure of type parameter is erasure of its left bound (jls), so erasure (T extends A & B) != erasure (T extends B & A)
e.g. IDEA-74409
This commit is contained in:
anna
2011-09-22 19:25:18 +02:00
parent 83931c053e
commit 18b6fe1bd4
6 changed files with 36 additions and 23 deletions

View File

@@ -181,7 +181,7 @@ public class OverrideImplementUtil {
for (final MethodImplementor implementor : getImplementors()) {
for (final PsiMethod method : implementor.getMethodsToImplement(aClass)) {
MethodSignature signature = MethodSignatureUtil.createMethodSignature(method.getName(), method.getParameterList(),
method.getTypeParameterList(), PsiSubstitutor.EMPTY);
method.getTypeParameterList(), PsiSubstitutor.EMPTY, method.isConstructor());
CandidateInfo info = new CandidateInfo(method, PsiSubstitutor.EMPTY);
result.put(signature, info);
}
@@ -679,7 +679,7 @@ public class OverrideImplementUtil {
String name = prevBaseMethod.isConstructor() ? aClass.getName() : prevBaseMethod.getName();
//Happens when aClass instanceof PsiAnonymousClass
if (name != null) {
MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, prevBaseMethod.getParameterList(), prevBaseMethod.getTypeParameterList(), substitutor);
MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, prevBaseMethod.getParameterList(), prevBaseMethod.getTypeParameterList(), substitutor, prevBaseMethod.isConstructor());
PsiMethod prevMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);
if (prevMethod != null){
return prevMethod.getNextSibling();
@@ -692,7 +692,7 @@ public class OverrideImplementUtil {
while(nextBaseMethod != null) {
String name = nextBaseMethod.isConstructor() ? aClass.getName() : nextBaseMethod.getName();
if (name != null) {
MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, nextBaseMethod.getParameterList(), nextBaseMethod.getTypeParameterList(), substitutor);
MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, nextBaseMethod.getParameterList(), nextBaseMethod.getTypeParameterList(), substitutor, nextBaseMethod.isConstructor());
PsiMethod nextMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);
if (nextMethod != null){
return nextMethod;

View File

@@ -62,28 +62,26 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
}
public PsiReference getReference() {
final PsiElement scope = getScope();
final PsiClass scope = getScope();
final PsiElement element = getNameElement();
if (scope == null || element == null) return new MyReference(null);
PsiReference psiReference = getReferenceInScope(scope, element);
if (psiReference != null) return psiReference;
if (scope instanceof PsiClass) {
PsiClass classScope = ((PsiClass)scope);
PsiClass containingClass = classScope.getContainingClass();
while (containingClass != null) {
classScope = containingClass;
psiReference = getReferenceInScope(classScope, element);
if (psiReference != null) return psiReference;
containingClass = classScope.getContainingClass();
}
PsiClass classScope;
PsiClass containingClass = scope.getContainingClass();
while (containingClass != null) {
classScope = containingClass;
psiReference = getReferenceInScope(classScope, element);
if (psiReference != null) return psiReference;
containingClass = classScope.getContainingClass();
}
return new MyReference(null);
}
@Nullable
private PsiReference getReferenceInScope(PsiElement scope, PsiElement element) {
private PsiReference getReferenceInScope(PsiClass scope, PsiElement element) {
final String name = element.getText();
final String[] signature = getSignature();
@@ -108,7 +106,8 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
}
}
methodSignature = MethodSignatureUtil.createMethodSignature(name, types.toArray(new PsiType[types.size()]),
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY,
name.equals(scope.getName()));
}
else {
methodSignature = null;
@@ -187,13 +186,13 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
}
@Nullable
private PsiElement getScope(){
private PsiClass getScope(){
if (getFirstChildNode().getElementType() == ElementType.DOC_REFERENCE_HOLDER) {
final PsiElement firstChildPsi = SourceTreeToPsiMap.treeElementToPsi(getFirstChildNode().getFirstChildNode());
if (firstChildPsi instanceof PsiJavaCodeReferenceElement) {
PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)firstChildPsi;
final PsiElement referencedElement = referenceElement.resolve();
if (referencedElement instanceof PsiClass) return referencedElement;
if (referencedElement instanceof PsiClass) return (PsiClass)referencedElement;
return null;
}
else if (firstChildPsi instanceof PsiKeyword) {

View File

@@ -243,7 +243,8 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor {
MethodSignature oldSignature = method.getSignature(PsiSubstitutor.EMPTY);
MethodSignature newSignature = MethodSignatureUtil.createMethodSignature(newName, oldSignature.getParameterTypes(),
oldSignature.getTypeParameters(),
oldSignature.getSubstitutor());
oldSignature.getSubstitutor(),
method.isConstructor());
for (PsiClass inheritor : inheritors) {
PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, inheritor, PsiSubstitutor.EMPTY);
final PsiMethod[] methodsByName = inheritor.findMethodsByName(newName, false);

View File

@@ -16,9 +16,20 @@
import java.io.*;
class Test {
interface InterfA {
<error descr="'foo(T)' is already defined in 'Test.InterfA'"><T extends Cloneable & Iterable> void foo(T x)</error>;
<T extends Cloneable & Iterable> void foo(T x);
<error descr="'foo(T)' is already defined in 'Test.InterfA'"><T extends Iterable & Cloneable> void foo(T x)</error>;
<T extends Iterable & Cloneable> void foo(T x);
}
class ANotSame {
<T extends Cloneable & Iterable> void foo(T x){}
<T extends Iterable & Cloneable> void foo(T x){}
}
class BNotSame extends ANotSame {
@Override
<T extends Cloneable & Iterable> void foo(T x){}
}
abstract class A<T extends Throwable> {

View File

@@ -45,7 +45,7 @@ public class MethodSignatureUtil {
public static final TObjectHashingStrategy<MethodSignature> METHOD_PARAMETERS_ERASURE_EQUALITY =
new TObjectHashingStrategy<MethodSignature>() {
public int computeHashCode(final MethodSignature signature) {
int result = signature.getName().hashCode();
int result = signature.isConstructor() ? 0 : signature.getName().hashCode();
PsiType[] parameterTypes = signature.getParameterTypes();
result += 37 * parameterTypes.length;
@@ -58,7 +58,8 @@ public class MethodSignatureUtil {
}
public boolean equals(MethodSignature method1, MethodSignature method2) {
if (!method1.getName().equals(method2.getName())) return false;
if (method1.isConstructor() != method2.isConstructor()) return false;
if (!method1.isConstructor() && !method1.getName().equals(method2.getName())) return false;
final PsiType[] parameterTypes1 = method1.getParameterTypes();
final PsiType[] parameterTypes2 = method2.getParameterTypes();
if (parameterTypes1.length != parameterTypes2.length) return false;
@@ -122,6 +123,7 @@ public class MethodSignatureUtil {
final MethodSignature superSignature,
final PsiSubstitutor unifyingSubstitutor) {
if (unifyingSubstitutor == null) return false;
if (!METHOD_PARAMETERS_ERASURE_EQUALITY.equals(subSignature, superSignature)) return false;
final PsiType[] subParameterTypes = subSignature.getParameterTypes();
final PsiType[] superParameterTypes = superSignature.getParameterTypes();

View File

@@ -62,7 +62,7 @@ public class PsiSuperMethodUtil {
PsiClass superClass = containingClass.getSuperClass();
if (superClass != null) {
MethodSignature defConstructor = MethodSignatureUtil.createMethodSignature(superClass.getName(), PsiType.EMPTY_ARRAY,
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, true);
return MethodSignatureUtil.findMethodBySignature(superClass, defConstructor, false);
}
}