Lines 1-5
Link Here
|
1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2000, 2009 IBM Corporation and others. |
2 |
* Copyright (c) 2000, 2010 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
5 |
* which accompanies this distribution, and is available at |
Lines 550-557
Link Here
|
550 |
*/ |
550 |
*/ |
551 |
void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
551 |
void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
552 |
// only want to remember inheritedMethods that can have an impact on the current type |
552 |
// only want to remember inheritedMethods that can have an impact on the current type |
553 |
// if an inheritedMethod has been 'replaced' by a supertype's method then skip it |
553 |
// if an inheritedMethod has been 'replaced' by a supertype's method then skip it, however |
554 |
|
554 |
// see usage of canOverridingMethodDifferInErasure below. |
555 |
this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type |
555 |
this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type |
556 |
ReferenceBinding[] interfacesToVisit = null; |
556 |
ReferenceBinding[] interfacesToVisit = null; |
557 |
int nextPosition = 0; |
557 |
int nextPosition = 0; |
Lines 563-592
Link Here
|
563 |
|
563 |
|
564 |
ReferenceBinding superType = superclass; |
564 |
ReferenceBinding superType = superclass; |
565 |
HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods |
565 |
HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods |
566 |
boolean allSuperclassesAreAbstract = true; |
|
|
567 |
|
566 |
|
568 |
while (superType != null && superType.isValidBinding()) { |
567 |
while (superType != null && superType.isValidBinding()) { |
569 |
if (allSuperclassesAreAbstract) { |
568 |
// We used to only include superinterfaces if immediate superclasses are abstract |
570 |
if (superType.isAbstract()) { |
569 |
// but that is problematic. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358 |
571 |
// only need to include superinterfaces if immediate superclasses are abstract |
570 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
572 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
571 |
if (interfacesToVisit == null) { |
573 |
if (interfacesToVisit == null) { |
572 |
interfacesToVisit = itsInterfaces; |
574 |
interfacesToVisit = itsInterfaces; |
573 |
nextPosition = interfacesToVisit.length; |
575 |
nextPosition = interfacesToVisit.length; |
|
|
576 |
} else { |
577 |
int itsLength = itsInterfaces.length; |
578 |
if (nextPosition + itsLength >= interfacesToVisit.length) |
579 |
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); |
580 |
nextInterface : for (int a = 0; a < itsLength; a++) { |
581 |
ReferenceBinding next = itsInterfaces[a]; |
582 |
for (int b = 0; b < nextPosition; b++) |
583 |
if (next == interfacesToVisit[b]) continue nextInterface; |
584 |
interfacesToVisit[nextPosition++] = next; |
585 |
} |
586 |
} |
587 |
} |
588 |
} else { |
574 |
} else { |
589 |
allSuperclassesAreAbstract = false; |
575 |
int itsLength = itsInterfaces.length; |
|
|
576 |
if (nextPosition + itsLength >= interfacesToVisit.length) |
577 |
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); |
578 |
nextInterface : for (int a = 0; a < itsLength; a++) { |
579 |
ReferenceBinding next = itsInterfaces[a]; |
580 |
for (int b = 0; b < nextPosition; b++) |
581 |
if (next == interfacesToVisit[b]) continue nextInterface; |
582 |
interfacesToVisit[nextPosition++] = next; |
583 |
} |
590 |
} |
584 |
} |
591 |
} |
585 |
} |
592 |
|
586 |
|
Lines 599-605
Link Here
|
599 |
if (existingMethods != null) { |
593 |
if (existingMethods != null) { |
600 |
existing : for (int i = 0, length = existingMethods.length; i < length; i++) { |
594 |
existing : for (int i = 0, length = existingMethods.length; i < length; i++) { |
601 |
MethodBinding existingMethod = existingMethods[i]; |
595 |
MethodBinding existingMethod = existingMethods[i]; |
602 |
if (existingMethod.declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethod, inheritedMethod)) { |
596 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358, skip inherited method only if any overriding version |
|
|
597 |
// in a subclass is guaranteed to have the same erasure as an existing method. |
598 |
if (existingMethod.declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethod, inheritedMethod) && !canOverridingMethodDifferInErasure(existingMethod, inheritedMethod)) { |
603 |
if (inheritedMethod.isDefault()) { |
599 |
if (inheritedMethod.isDefault()) { |
604 |
if (inheritedMethod.isAbstract()) { |
600 |
if (inheritedMethod.isAbstract()) { |
605 |
checkPackagePrivateAbstractMethod(inheritedMethod); |
601 |
checkPackagePrivateAbstractMethod(inheritedMethod); |
Lines 681-688
Link Here
|
681 |
} else { |
677 |
} else { |
682 |
int length = existingMethods.length; |
678 |
int length = existingMethods.length; |
683 |
// look to see if any of the existingMethods implement this inheritedMethod |
679 |
// look to see if any of the existingMethods implement this inheritedMethod |
|
|
680 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358, skip inherited method only if any overriding version |
681 |
// in a subclass is guaranteed to have the same erasure as an existing method. |
684 |
for (int e = 0; e < length; e++) |
682 |
for (int e = 0; e < length; e++) |
685 |
if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType)) |
683 |
if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType) && !canOverridingMethodDifferInErasure(existingMethods[e], inheritedMethod)) |
686 |
continue nextMethod; // skip interface method with the same signature if visible to its declaringClass |
684 |
continue nextMethod; // skip interface method with the same signature if visible to its declaringClass |
687 |
System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length); |
685 |
System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length); |
688 |
existingMethods[length] = inheritedMethod; |
686 |
existingMethods[length] = inheritedMethod; |
Lines 692-698
Link Here
|
692 |
} |
690 |
} |
693 |
} |
691 |
} |
694 |
} |
692 |
} |
695 |
|
693 |
// Given `overridingMethod' which overrides `inheritedMethod' answer whether some subclass method that |
|
|
694 |
// differs in erasure from overridingMethod could override `inheritedMethod' |
695 |
protected boolean canOverridingMethodDifferInErasure(MethodBinding overridingMethod, MethodBinding inheritedMethod) { |
696 |
return false; // the case for <= 1.4 (cannot differ) |
697 |
} |
696 |
void computeMethods() { |
698 |
void computeMethods() { |
697 |
MethodBinding[] methods = this.type.methods(); |
699 |
MethodBinding[] methods = this.type.methods(); |
698 |
int size = methods.length; |
700 |
int size = methods.length; |