Lines 165-181
Link Here
|
165 |
} |
165 |
} |
166 |
|
166 |
|
167 |
if (this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()) != null) { |
167 |
if (this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()) != null) { |
168 |
for (int i = 0, l = allInheritedMethods.length; i < l; i++) { |
168 |
for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) { |
169 |
MethodBinding otherInheritedMethod = allInheritedMethods[i]; |
169 |
if (allInheritedMethods[i] != null && detectInheritedNameClash(originalInherited, allInheritedMethods[i].original())) |
170 |
MethodBinding otherOriginal = otherInheritedMethod.original(); |
|
|
171 |
// only check inherited methods that are different & come from separate inheritance paths |
172 |
if (otherOriginal == originalInherited || otherOriginal == otherInheritedMethod) continue; |
173 |
if (inheritedMethod.areParametersEqual(otherInheritedMethod)) continue; |
174 |
// skip it if otherInheritedMethod is defined by a subtype of inheritedMethod's declaringClass |
175 |
if (otherInheritedMethod.declaringClass.erasure() != inheritedMethod.declaringClass.erasure()) |
176 |
if (otherInheritedMethod.declaringClass.findSuperTypeOriginatingFrom(inheritedMethod.declaringClass) != null) |
177 |
continue; |
178 |
if (detectInheritedNameClash(originalInherited, otherOriginal)) |
179 |
return; |
170 |
return; |
180 |
} |
171 |
} |
181 |
} |
172 |
} |
Lines 295-303
Link Here
|
295 |
problemReporter().duplicateInheritedMethods(this.type, inheritedMethod, otherInheritedMethod); |
286 |
problemReporter().duplicateInheritedMethods(this.type, inheritedMethod, otherInheritedMethod); |
296 |
return; |
287 |
return; |
297 |
} |
288 |
} |
298 |
} else if (inheritedMethod.declaringClass.findSuperTypeOriginatingFrom(otherInheritedMethod.declaringClass) != null) { |
|
|
299 |
// skip it if inheritedMethod is defined by a subtype of otherInheritedMethod declaringClass |
300 |
return; |
301 |
} |
289 |
} |
302 |
|
290 |
|
303 |
// the 2 inherited methods clash because of a parameterized type overrides a raw type |
291 |
// the 2 inherited methods clash because of a parameterized type overrides a raw type |
Lines 437-455
Link Here
|
437 |
} |
425 |
} |
438 |
|
426 |
|
439 |
int index = -1; |
427 |
int index = -1; |
|
|
428 |
int inheritedLength = inherited.length; |
440 |
MethodBinding[] matchingInherited = new MethodBinding[inherited.length]; |
429 |
MethodBinding[] matchingInherited = new MethodBinding[inherited.length]; |
441 |
byte[] foundMatch = new byte[inherited.length]; |
430 |
MethodBinding[] foundMatch = new MethodBinding[inherited.length]; // null is no match, otherwise value is matching currentMethod |
442 |
if (current != null) { |
431 |
if (current != null) { |
443 |
for (int i = 0, length1 = current.length; i < length1; i++) { |
432 |
for (int i = 0, length1 = current.length; i < length1; i++) { |
444 |
MethodBinding currentMethod = current[i]; |
433 |
MethodBinding currentMethod = current[i]; |
445 |
for (int j = 0, length2 = inherited.length; j < length2; j++) { |
434 |
MethodBinding[] nonMatchingInherited = null; |
|
|
435 |
for (int j = 0; j < inheritedLength; j++) { |
446 |
MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod); |
436 |
MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod); |
447 |
if (inheritedMethod != null) { |
437 |
if (inheritedMethod != null) { |
448 |
if (foundMatch[j] == 0 && isSubstituteParameterSubsignature(currentMethod, inheritedMethod)) { |
438 |
if (foundMatch[j] == null && isSubstituteParameterSubsignature(currentMethod, inheritedMethod)) { |
449 |
matchingInherited[++index] = inheritedMethod; |
439 |
matchingInherited[++index] = inheritedMethod; |
450 |
foundMatch[j] = 1; // cannot null out inherited methods |
440 |
foundMatch[j] = currentMethod; |
451 |
} else { |
441 |
} else { |
|
|
442 |
// best place to check each currentMethod against each non-matching inheritedMethod |
452 |
checkForNameClash(currentMethod, inheritedMethod); |
443 |
checkForNameClash(currentMethod, inheritedMethod); |
|
|
444 |
if (inheritedLength > 1) { |
445 |
if (nonMatchingInherited == null) |
446 |
nonMatchingInherited = new MethodBinding[inheritedLength]; |
447 |
nonMatchingInherited[j] = inheritedMethod; |
448 |
} |
453 |
} |
449 |
} |
454 |
} |
450 |
} |
455 |
} |
451 |
} |
Lines 457-484
Link Here
|
457 |
// see addtional comments in https://bugs.eclipse.org/bugs/show_bug.cgi?id=122881 |
453 |
// see addtional comments in https://bugs.eclipse.org/bugs/show_bug.cgi?id=122881 |
458 |
// if (index > 0 && currentMethod.declaringClass.isInterface()) // only check when inherited methods are from interfaces |
454 |
// if (index > 0 && currentMethod.declaringClass.isInterface()) // only check when inherited methods are from interfaces |
459 |
// checkInheritedReturnTypes(matchingInherited, index + 1); |
455 |
// checkInheritedReturnTypes(matchingInherited, index + 1); |
460 |
checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1, inherited); // pass in the length of matching |
456 |
checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1, nonMatchingInherited); // pass in the length of matching |
461 |
while (index >= 0) matchingInherited[index--] = null; // clear the contents of the matching methods |
457 |
while (index >= 0) matchingInherited[index--] = null; // clear the contents of the matching methods |
462 |
} |
458 |
} |
463 |
} |
459 |
} |
464 |
} |
460 |
} |
465 |
|
461 |
|
466 |
for (int i = 0, length = inherited.length; i < length; i++) { |
462 |
// skip tracks which inherited methods have matched other inherited methods |
467 |
if (foundMatch[i] == 1) continue; |
463 |
// either because they match the same currentMethod or match each other |
468 |
|
464 |
boolean[] skip = new boolean[inheritedLength]; |
|
|
465 |
for (int i = 0; i < inheritedLength; i++) { |
466 |
if (skip[i]) continue; |
469 |
MethodBinding inheritedMethod = inherited[i]; |
467 |
MethodBinding inheritedMethod = inherited[i]; |
470 |
matchingInherited[++index] = inheritedMethod; |
468 |
MethodBinding matchMethod = foundMatch[i]; |
471 |
for (int j = i + 1; j < length; j++) { |
469 |
if (matchMethod == null) |
|
|
470 |
matchingInherited[++index] = inheritedMethod; |
471 |
for (int j = i + 1; j < inheritedLength; j++) { |
472 |
MethodBinding otherInheritedMethod = inherited[j]; |
472 |
MethodBinding otherInheritedMethod = inherited[j]; |
473 |
if (foundMatch[j] == 1 || canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) |
473 |
if (matchMethod == foundMatch[j] && matchMethod != null) |
|
|
474 |
continue; // both inherited methods matched the same currentMethod |
475 |
if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) |
474 |
continue; |
476 |
continue; |
475 |
otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); |
477 |
otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); |
476 |
if (otherInheritedMethod != null) { |
478 |
if (otherInheritedMethod != null) { |
477 |
if (inheritedMethod.declaringClass != otherInheritedMethod.declaringClass |
479 |
if (inheritedMethod.declaringClass != otherInheritedMethod.declaringClass |
478 |
&& isSubstituteParameterSubsignature(inheritedMethod, otherInheritedMethod)) { |
480 |
&& isSubstituteParameterSubsignature(inheritedMethod, otherInheritedMethod)) { |
|
|
481 |
if (index == -1) |
482 |
matchingInherited[++index] = inheritedMethod; |
479 |
matchingInherited[++index] = otherInheritedMethod; |
483 |
matchingInherited[++index] = otherInheritedMethod; |
480 |
foundMatch[j] = 1; // cannot null out inherited methods |
484 |
skip[j] = true; |
481 |
} else { |
485 |
} else if (matchMethod == null && foundMatch[j] == null) { |
482 |
checkInheritedMethods(inheritedMethod, otherInheritedMethod); |
486 |
checkInheritedMethods(inheritedMethod, otherInheritedMethod); |
483 |
} |
487 |
} |
484 |
} |
488 |
} |
Lines 487-493
Link Here
|
487 |
|
491 |
|
488 |
if (index > 0) |
492 |
if (index > 0) |
489 |
checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching |
493 |
checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching |
490 |
else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract()) |
494 |
else if (mustImplementAbstractMethods && matchingInherited[0].isAbstract()) |
491 |
checkAbstractMethod(matchingInherited[0]); |
495 |
checkAbstractMethod(matchingInherited[0]); |
492 |
while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods |
496 |
while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods |
493 |
} |
497 |
} |
Lines 593-609
Link Here
|
593 |
return substitute; |
597 |
return substitute; |
594 |
} |
598 |
} |
595 |
boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) { |
599 |
boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) { |
596 |
if (!inherited.areParameterErasuresEqual(otherInherited) || inherited.returnType.erasure() != otherInherited.returnType.erasure()) return false; |
600 |
if (!inherited.areParameterErasuresEqual(otherInherited) || inherited.returnType.erasure() != otherInherited.returnType.erasure()) |
|
|
601 |
return false; |
602 |
// skip it if otherInherited is defined by a subtype of inherited's declaringClass |
603 |
if (inherited.declaringClass.erasure() != otherInherited.declaringClass.erasure()) |
604 |
if (inherited.declaringClass.findSuperTypeOriginatingFrom(otherInherited.declaringClass) != null) |
605 |
return false; |
597 |
|
606 |
|
598 |
problemReporter().inheritedMethodsHaveNameClash(this.type, inherited, otherInherited); |
607 |
problemReporter().inheritedMethodsHaveNameClash(this.type, inherited, otherInherited); |
599 |
return true; |
608 |
return true; |
600 |
} |
609 |
} |
601 |
boolean detectNameClash(MethodBinding current, MethodBinding inherited) { |
610 |
boolean detectNameClash(MethodBinding current, MethodBinding inherited) { |
602 |
MethodBinding original = inherited.original(); // can be the same as inherited |
611 |
MethodBinding original = inherited.original(); // can be the same as inherited |
603 |
if (!current.areParameterErasuresEqual(original) || current.returnType.erasure() != original.returnType.erasure()) return false; |
612 |
if (!current.areParameterErasuresEqual(original) || current.returnType.erasure() != original.returnType.erasure()) |
|
|
613 |
return false; |
604 |
|
614 |
|
605 |
problemReporter(current).methodNameClash(current, |
615 |
problemReporter(current).methodNameClash(current, inherited.declaringClass.isRawType() ? inherited : original); |
606 |
inherited.declaringClass.isRawType() ? inherited : original); |
|
|
607 |
return true; |
616 |
return true; |
608 |
} |
617 |
} |
609 |
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
618 |
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
Lines 744-751
Link Here
|
744 |
} |
753 |
} |
745 |
|
754 |
|
746 |
if (substituteMethod instanceof ParameterizedGenericMethodBinding) { |
755 |
if (substituteMethod instanceof ParameterizedGenericMethodBinding) { |
|
|
756 |
if (method.typeVariables != Binding.NO_TYPE_VARIABLES) |
757 |
return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw; |
747 |
// since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does |
758 |
// since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does |
748 |
return ! (hasGenericParameter(method) && method.typeVariables == Binding.NO_TYPE_VARIABLES); |
759 |
return !hasGenericParameter(method); |
749 |
} |
760 |
} |
750 |
|
761 |
|
751 |
// if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() |
762 |
// if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() |