*/
void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
// only want to remember inheritedMethods that can have an impact on the current type
// if an inheritedMethod has been 'replaced' by a supertype's method then skip it
this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
ReferenceBinding[] itsInterfaces = superInterfaces;
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
nextPosition = itsInterfaces.length;
interfacesToVisit = itsInterfaces;
}
ReferenceBinding superType = superclass;
HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods
boolean allSuperclassesAreAbstract = true;
while (superType != null && superType.isValidBinding()) {
if (allSuperclassesAreAbstract) {
if (superType.isAbstract()) {
// only need to include superinterfaces if immediate superclasses are abstract
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (next == interfacesToVisit[b]) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
} else {
allSuperclassesAreAbstract = false;
}
}
MethodBinding[] methods = superType.unResolvedMethods();
nextMethod : for (int m = methods.length; --m >= 0;) {
MethodBinding inheritedMethod = methods[m];
if (inheritedMethod.isPrivate() || inheritedMethod.isConstructor() || inheritedMethod.isDefaultAbstract())
continue nextMethod;
MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
if (existingMethods != null) {
existing : for (int i = 0, length = existingMethods.length; i < length; i++) {
MethodBinding existingMethod = existingMethods[i];
if (existingMethod.declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethod, inheritedMethod)) {
if (inheritedMethod.isDefault()) {
if (inheritedMethod.isAbstract()) {
checkPackagePrivateAbstractMethod(inheritedMethod);
} else if (existingMethod.declaringClass.fPackage != inheritedMethod.declaringClass.fPackage) {
if (this.type.fPackage == inheritedMethod.declaringClass.fPackage && !areReturnTypesCompatible(inheritedMethod, existingMethod))
continue existing; // may need to record incompatible return type
}
}
continue nextMethod;
}
}
}
if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == this.type.fPackage) {
if (existingMethods == null) {
existingMethods = new MethodBinding[] {inheritedMethod};
} else {
int length = existingMethods.length;
System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
existingMethods[length] = inheritedMethod;
}
this.inheritedMethods.put(inheritedMethod.selector, existingMethods);
} else {
MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector);
if (nonVisible != null)
for (int i = 0, l = nonVisible.length; i < l; i++)
if (areMethodsCompatible(nonVisible[i], inheritedMethod))
continue nextMethod;
if (nonVisible == null) {
nonVisible = new MethodBinding[] {inheritedMethod};
} else {
int length = nonVisible.length;
System.arraycopy(nonVisible, 0, nonVisible = new MethodBinding[length + 1], 0, length);
nonVisible[length] = inheritedMethod;
}
nonVisibleDefaultMethods.put(inheritedMethod.selector, nonVisible);
if (inheritedMethod.isAbstract() && !this.type.isAbstract()) // non visible abstract methods cannot be overridden so the type must be defined abstract
problemReporter().abstractMethodCannotBeOverridden(this.type, inheritedMethod);
MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector);