Lines 21-27
Link Here
|
21 |
} |
21 |
} |
22 |
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { |
22 |
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { |
23 |
MethodBinding sub = computeSubstituteMethod(two, one); |
23 |
MethodBinding sub = computeSubstituteMethod(two, one); |
24 |
return sub != null && doesSubstituteMethodOverride(one, sub) && areReturnTypesCompatible(one, sub); |
24 |
return sub != null && isSubstituteParameterSubsignature(one, sub) && areReturnTypesCompatible(one, sub); |
25 |
} |
25 |
} |
26 |
boolean areParametersEqual(MethodBinding one, MethodBinding two) { |
26 |
boolean areParametersEqual(MethodBinding one, MethodBinding two) { |
27 |
TypeBinding[] oneArgs = one.parameters; |
27 |
TypeBinding[] oneArgs = one.parameters; |
Lines 224-230
Link Here
|
224 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
224 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
225 |
for (int m = 0, n = methods.length; m < n; m++) { |
225 |
for (int m = 0, n = methods.length; m < n; m++) { |
226 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
226 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
227 |
if (substitute != null && !doesSubstituteMethodOverride(currentMethod, substitute) && detectNameClash(currentMethod, substitute)) |
227 |
if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute)) |
228 |
return; |
228 |
return; |
229 |
} |
229 |
} |
230 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
230 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
Lines 252-258
Link Here
|
252 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
252 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
253 |
for (int m = 0, n = methods.length; m < n; m++){ |
253 |
for (int m = 0, n = methods.length; m < n; m++){ |
254 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
254 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
255 |
if (substitute != null && !doesSubstituteMethodOverride(currentMethod, substitute) && detectNameClash(currentMethod, substitute)) |
255 |
if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute)) |
256 |
return; |
256 |
return; |
257 |
} |
257 |
} |
258 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
258 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
Lines 424-430
Link Here
|
424 |
for (int j = 0, length2 = inherited.length; j < length2; j++) { |
424 |
for (int j = 0, length2 = inherited.length; j < length2; j++) { |
425 |
MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod); |
425 |
MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod); |
426 |
if (inheritedMethod != null) { |
426 |
if (inheritedMethod != null) { |
427 |
if (foundMatch[j] == 0 && doesSubstituteMethodOverride(currentMethod, inheritedMethod)) { |
427 |
if (foundMatch[j] == 0 && isSubstituteParameterSubsignature(currentMethod, inheritedMethod)) { |
428 |
matchingInherited[++index] = inheritedMethod; |
428 |
matchingInherited[++index] = inheritedMethod; |
429 |
foundMatch[j] = 1; // cannot null out inherited methods |
429 |
foundMatch[j] = 1; // cannot null out inherited methods |
430 |
} else { |
430 |
} else { |
Lines 454-460
Link Here
|
454 |
otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); |
454 |
otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); |
455 |
if (otherInheritedMethod != null) { |
455 |
if (otherInheritedMethod != null) { |
456 |
if (inheritedMethod.declaringClass != otherInheritedMethod.declaringClass |
456 |
if (inheritedMethod.declaringClass != otherInheritedMethod.declaringClass |
457 |
&& doesSubstituteMethodOverride(inheritedMethod, otherInheritedMethod)) { |
457 |
&& isSubstituteParameterSubsignature(inheritedMethod, otherInheritedMethod)) { |
458 |
matchingInherited[++index] = otherInheritedMethod; |
458 |
matchingInherited[++index] = otherInheritedMethod; |
459 |
foundMatch[j] = 1; // cannot null out inherited methods |
459 |
foundMatch[j] = 1; // cannot null out inherited methods |
460 |
} else { |
460 |
} else { |
Lines 491-497
Link Here
|
491 |
if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) |
491 |
if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) |
492 |
continue; |
492 |
continue; |
493 |
otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); |
493 |
otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); |
494 |
if (otherInheritedMethod != null && doesSubstituteMethodOverride(inheritedMethod, otherInheritedMethod)) { |
494 |
if (otherInheritedMethod != null && isSubstituteParameterSubsignature(inheritedMethod, otherInheritedMethod)) { |
495 |
matchingInherited[++index] = otherInheritedMethod; |
495 |
matchingInherited[++index] = otherInheritedMethod; |
496 |
inherited[j] = null; // do not want to find it again |
496 |
inherited[j] = null; // do not want to find it again |
497 |
} |
497 |
} |
Lines 586-614
Link Here
|
586 |
return true; |
586 |
return true; |
587 |
} |
587 |
} |
588 |
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
588 |
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
589 |
MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method); |
589 |
if (!couldMethodOverride(method, inheritedMethod)) |
590 |
return substitute != null && doesSubstituteMethodOverride(method, substitute); |
|
|
591 |
} |
592 |
// if method "overrides" substituteMethod then we can skip over substituteMethod while resolving a message send |
593 |
// if it does not then a name clash error is likely |
594 |
boolean doesSubstituteMethodOverride(MethodBinding method, MethodBinding substituteMethod) { |
595 |
if (!areParametersEqual(method, substituteMethod)) { |
596 |
// method can still override substituteMethod in cases like : |
597 |
// <U extends Number> void c(U u) {} |
598 |
// @Override void c(Number n) {} |
599 |
// but method cannot have a "generic-enabled" parameter type |
600 |
if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod)) |
601 |
return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method); |
602 |
return false; |
590 |
return false; |
603 |
} |
|
|
604 |
|
591 |
|
605 |
if (substituteMethod instanceof ParameterizedGenericMethodBinding) { |
592 |
inheritedMethod = inheritedMethod.original(); |
606 |
// since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does |
593 |
TypeBinding match = method.declaringClass.findSuperTypeOriginatingFrom(inheritedMethod.declaringClass); |
607 |
return ! (hasGenericParameter(method) && method.typeVariables == Binding.NO_TYPE_VARIABLES); |
594 |
if (!(match instanceof ReferenceBinding)) |
|
|
595 |
return false; // method's declaringClass does not inherit from inheritedMethod's |
596 |
|
597 |
if (match != inheritedMethod.declaringClass) { |
598 |
MethodBinding[] superMethods = ((ReferenceBinding) match).getMethods(inheritedMethod.selector); |
599 |
for (int i = 0, length = superMethods.length; i < length; i++) |
600 |
if (superMethods[i].original() == inheritedMethod) |
601 |
return isParameterSubsignature(method, superMethods[i]); |
608 |
} |
602 |
} |
609 |
|
603 |
|
610 |
// if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() |
604 |
return isParameterSubsignature(method, inheritedMethod); |
611 |
return method.typeVariables == Binding.NO_TYPE_VARIABLES; |
|
|
612 |
} |
605 |
} |
613 |
boolean hasGenericParameter(MethodBinding method) { |
606 |
boolean hasGenericParameter(MethodBinding method) { |
614 |
if (method.genericSignature() == null) return false; |
607 |
if (method.genericSignature() == null) return false; |
Lines 708-713
Link Here
|
708 |
&& inheritedMethod.returnType == existingMethod.returnType // keep around to produce bridge methods |
701 |
&& inheritedMethod.returnType == existingMethod.returnType // keep around to produce bridge methods |
709 |
&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType); |
702 |
&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType); |
710 |
} |
703 |
} |
|
|
704 |
public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) { |
705 |
if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) |
706 |
return false; |
707 |
|
708 |
inheritedMethod = inheritedMethod.original(); |
709 |
TypeBinding match = method.declaringClass.findSuperTypeOriginatingFrom(inheritedMethod.declaringClass); |
710 |
if ((match instanceof ReferenceBinding) && match != inheritedMethod.declaringClass) { |
711 |
MethodBinding[] superMethods = ((ReferenceBinding) match).getMethods(inheritedMethod.selector); |
712 |
for (int i = 0, length = superMethods.length; i < length; i++) |
713 |
if (superMethods[i].original() == inheritedMethod) |
714 |
return isParameterSubsignature(method, superMethods[i]); |
715 |
} |
716 |
|
717 |
return isParameterSubsignature(method, inheritedMethod); |
718 |
} |
719 |
boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { |
720 |
MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method); |
721 |
return substitute != null && isSubstituteParameterSubsignature(method, substitute); |
722 |
} |
723 |
// if method "overrides" substituteMethod then we can skip over substituteMethod while resolving a message send |
724 |
// if it does not then a name clash error is likely |
725 |
boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) { |
726 |
if (!areParametersEqual(method, substituteMethod)) { |
727 |
// method can still override substituteMethod in cases like : |
728 |
// <U extends Number> void c(U u) {} |
729 |
// @Override void c(Number n) {} |
730 |
// but method cannot have a "generic-enabled" parameter type |
731 |
if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod)) |
732 |
return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method); |
733 |
return false; |
734 |
} |
735 |
|
736 |
if (substituteMethod instanceof ParameterizedGenericMethodBinding) { |
737 |
// since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does |
738 |
return ! (hasGenericParameter(method) && method.typeVariables == Binding.NO_TYPE_VARIABLES); |
739 |
} |
740 |
|
741 |
// if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() |
742 |
return method.typeVariables == Binding.NO_TYPE_VARIABLES; |
743 |
} |
711 |
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
744 |
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
712 |
// JLS 3 §8.4.5: more are accepted, with an unchecked conversion |
745 |
// JLS 3 §8.4.5: more are accepted, with an unchecked conversion |
713 |
if (currentMethod.returnType == inheritedMethod.returnType.erasure()) { |
746 |
if (currentMethod.returnType == inheritedMethod.returnType.erasure()) { |