Refactored packagename to net.sourceforge.phpdt.internal.compiler.ast
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / MethodVerifier.java
index 1debb98..cf46cd2 100644 (file)
@@ -1,19 +1,19 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v0.5 
+ * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
+ * http://www.eclipse.org/legal/cpl-v10.html
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
- ******************************************************************************/
+ *******************************************************************************/
 package net.sourceforge.phpdt.internal.compiler.lookup;
 
+import net.sourceforge.phpdt.core.compiler.CharOperation;
 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
-import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
 
 public final class MethodVerifier implements TagBits, TypeConstants {
@@ -22,6 +22,7 @@ public final class MethodVerifier implements TagBits, TypeConstants {
        HashtableOfObject currentMethods;
        ReferenceBinding runtimeException;
        ReferenceBinding errorException;
+       LookupEnvironment environment;
 /*
 Binding creation is responsible for reporting all problems with types:
        - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - abstract/final)
@@ -38,215 +39,25 @@ Binding creation is responsible for reporting all problems with types:
                - shadowing an enclosing type's source name
                - defining a static class or interface inside a non-static nested class
                - defining an interface as a local type (local types can only be classes)
-
-verifyTypeStructure
-
-       | hasHierarchyProblem superclass current names interfaces interfacesByIndentity duplicateExists invalidType |
-
-       (type basicModifiers anyMask: AccModifierProblem | AccAlternateModifierProblem) ifTrue: [
-               self reportModifierProblemsOnType: type].
-
-       type controller isJavaDefaultPackage ifFalse: [
-               (nameEnvironment class doesPackageExistNamed: type javaQualifiedName) ifTrue: [
-                       problemSummary
-                               reportVerificationProblem: #CollidesWithPackage
-                               args: (Array with: type javaQualifiedName)
-                               severity: nil
-                               forType: type]].
-
-       hasHierarchyProblem := false.
-
-       type isJavaClass
-               ifTrue: [
-                       (superclass := self superclassFor: type) ~~ nil ifTrue: [
-                               superclass isBuilderClass ifTrue: [
-                                       superclass := superclass newClass].
-                               superclass isJavaMissing
-                                       ifTrue: [
-                                               hasHierarchyProblem := true.
-                                               type javaSuperclassIsMissing ifTrue: [
-                                                       problemSummary
-                                                               reportVerificationProblem: #MissingSuperclass
-                                                               args: (Array with: superclass javaQualifiedName with: superclass unmatchedDescriptor)
-                                                               severity: nil
-                                                               forType: type].
-                                               type javaSuperclassCreatesCycle ifTrue: [
-                                                       problemSummary
-                                                               reportVerificationProblem: #CyclicSuperclass
-                                                               args: (Array with: superclass javaQualifiedName)
-                                                               severity: nil
-                                                               forType: type].
-                                               type javaSuperclassIsInterface ifTrue: [
-                                                       problemSummary
-                                                               reportVerificationProblem: #ClassCannotExtendAnInterface
-                                                               args: (Array with: superclass javaQualifiedName)
-                                                               severity: nil
-                                                               forType: type]]
-                                       ifFalse: [
-                                               "NOTE:  If type is a Java class and its superclass is
-                                               a valid descriptor then it should NEVER be an interface."
-
-                                               superclass isJavaFinal ifTrue: [
-                                                       problemSummary
-                                                               reportVerificationProblem: #ClassCannotExtendFinalClass
-                                                               args: nil
-                                                               severity: nil
-                                                               forType: type]]]]
-               ifFalse: [
-                       type isJavaLocalType ifTrue: [
-                               problemSummary
-                                       reportVerificationProblem: #CannotDefineLocalInterface
-                                       args: nil
-                                       severity: nil
-                                       forType: type]].
-
-       type isJavaNestedType ifTrue: [
-               (current := type) sourceName notEmpty ifTrue: [
-                       names := Set new.
-                       [(current := current enclosingType) ~~ nil] whileTrue: [
-                               names add: current sourceName].
-
-                       (names includes: type sourceName) ifTrue: [
-                               problemSummary
-                                       reportVerificationProblem: #NestedTypeCannotShadowTypeName
-                                       args: nil
-                                       severity: nil
-                                       forType: type]].
-
-               (type enclosingType isJavaNestedType and: [type enclosingType isJavaClass]) ifTrue: [
-                       type enclosingType isJavaStatic ifFalse: [
-                               type isJavaClass
-                                       ifTrue: [
-                                               type isJavaStatic ifTrue: [
-                                                       problemSummary
-                                                               reportVerificationProblem: #StaticClassCannotExistInNestedClass
-                                                               args: nil
-                                                               severity: nil
-                                                               forType: type]]
-                                       ifFalse: [
-                                               problemSummary
-                                                       reportVerificationProblem: #InterfaceCannotExistInNestedClass
-                                                       args: nil
-                                                       severity: nil
-                                                       forType: type]]]].
-
-       (interfaces := newClass superinterfaces) notEmpty ifTrue: [
-               interfacesByIndentity := interfaces asSet.
-               duplicateExists := interfaces size ~~ interfacesByIndentity size.
-
-               interfacesByIndentity do: [:interface |
-                       duplicateExists ifTrue: [
-                               (interfaces occurrencesOf: interface) > 1 ifTrue: [
-                                       problemSummary
-                                               reportVerificationProblem: #InterfaceIsSpecifiedMoreThanOnce
-                                               args: (Array with: interface javaQualifiedName)
-                                               severity: nil
-                                               forType: type]].
-
-                       interface isJavaMissing ifTrue: [
-                               hasHierarchyProblem := true.
-                               interface basicClass == JavaInterfaceIsClass basicClass
-                                       ifTrue: [
-                                               problemSummary
-                                                       reportVerificationProblem: #UsingClassWhereInterfaceIsRequired
-                                                       args: (Array with: interface javaQualifiedName)
-                                                       severity: nil
-                                                       forType: type]
-                                       ifFalse: [
-                                               interface basicClass == JavaMissingInterface basicClass
-                                                       ifTrue: [
-                                                               problemSummary
-                                                                       reportVerificationProblem: #MissingInterface
-                                                                       args: (Array with: interface javaQualifiedName with: interface unmatchedDescriptor)
-                                                                       severity: nil
-                                                                       forType: type]
-                                                       ifFalse: [
-                                                               problemSummary
-                                                                       reportVerificationProblem: #CyclicSuperinterface
-                                                                       args: (Array with: interface javaQualifiedName)
-                                                                       severity: nil
-                                                                       forType: type]]]]].
-
-       hasHierarchyProblem ifFalse: [
-               "Search up the type's hierarchy for
-                       1. missing superclass,
-                       2. superclass cycle, or
-                       3. superclass is interface."
-               (invalidType := newClass findFirstInvalidSupertypeSkipping: EsIdentitySet new) ~~ nil ifTrue: [
-                       problemSummary
-                               reportVerificationProblem: #HasHierarchyProblem
-                               args: (Array with: invalidType javaReadableName)
-                               severity: nil
-                               forType: type]]
-
-reportModifierProblemsOnType: aType
-
-       (type basicModifiers anyMask: AccAlternateModifierProblem) ifTrue: [
-               (type basicModifiers anyMask: AccModifierProblem)
-                       ifTrue: [
-                               ^problemSummary
-                                       reportVerificationProblem: #OnlyOneVisibilityModifierAllowed
-                                       args: nil
-                                       severity: nil
-                                       forType: aType]
-                       ifFalse: [
-                               ^problemSummary
-                                       reportVerificationProblem: #DuplicateModifier
-                                       args: nil
-                                       severity: nil
-                                       forType: aType]].
-
-       type isJavaInterface ifTrue: [
-               ^problemSummary
-                       reportVerificationProblem: #IllegalModifierForInterface
-                       args: nil
-                       severity: nil
-                       forType: aType].
-
-       (type basicModifiers allMask: AccAbstract | AccFinal) ifTrue: [
-               ^problemSummary
-                       reportVerificationProblem: #IllegalModifierCombinationAbstractFinal
-                       args: nil
-                       severity: nil
-                       forType: aType].
-
-       ^problemSummary
-               reportVerificationProblem: #IllegalModifierForClass
-               args: nil
-               severity: nil
-               forType: aType
-
-void reportModifierProblems() {
-       if (this.type.isAbstract() && this.type.isFinal())
-               this.problemReporter.illegalModifierCombinationAbstractFinal(this.type);
-
-       // Should be able to detect all 3 problems NOT just 1
-       if ((type.modifiers() & Modifiers.AccAlternateModifierProblem) == 0) {
-               if (this.type.isInterface())
-                       this.problemReporter.illegalModifierForInterface(this.type);
-               else
-                       this.problemReporter.illegalModifier(this.type);
-       } else {
-               if ((type.modifiers() & Modifiers.AccModifierProblem) != 0)
-                       this.problemReporter.onlyOneVisibilityModifierAllowed(this.type);
-               else
-                       this.problemReporter.duplicateModifier(this.type);
-       }
-}
 */
 public MethodVerifier(LookupEnvironment environment) {
-       this.type = null;               // Initialized with the public method verify(SourceTypeBinding)
+       this.type = null;  // Initialized with the public method verify(SourceTypeBinding)
        this.inheritedMethods = null;
        this.currentMethods = null;
        this.runtimeException = null;
        this.errorException = null;
+       this.environment = environment;
 }
 private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+       currentMethod.modifiers |= CompilerModifiers.AccOverriding;
        for (int i = length; --i >= 0;) {
                MethodBinding inheritedMethod = methods[i];
+               if (!currentMethod.isAbstract() && inheritedMethod.isAbstract())
+                       currentMethod.modifiers |= CompilerModifiers.AccImplementing;
+
                if (currentMethod.returnType != inheritedMethod.returnType) {
                        this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
-               } else if (currentMethod.isStatic() != inheritedMethod.isStatic())       {      // Cannot override a static method or hide an instance method
+               } else if (currentMethod.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
                        this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
                } else {
                        if (currentMethod.thrownExceptions != NoExceptions)
@@ -255,9 +66,9 @@ private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBin
                                this.problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
                        if (!this.isAsVisible(currentMethod, inheritedMethod))
                                this.problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
-                       if (inheritedMethod.isViewedAsDeprecated())
-                               if (!currentMethod.isViewedAsDeprecated())
-                                       this.problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
+//                     if (inheritedMethod.isViewedAsDeprecated())
+//                             if (!currentMethod.isViewedAsDeprecated() || environment.options.reportDeprecationInsideDeprecatedCode)
+//                                     this.problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
                }
        }
 }
@@ -267,7 +78,6 @@ Verify that newExceptions are all included in inheritedExceptions.
 Assumes all exceptions are valid and throwable.
 Unchecked exceptions (compatible with runtime & error) are ignored (see the spec on pg. 203).
 */
-
 private void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) {
        ReferenceBinding[] newExceptions = newMethod.thrownExceptions;
        ReferenceBinding[] inheritedExceptions = inheritedMethod.thrownExceptions;
@@ -283,33 +93,33 @@ private void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMet
 private void checkInheritedMethods(MethodBinding[] methods, int length) {
        TypeBinding returnType = methods[0].returnType;
        int index = length;
-       while ((--index > 0) && (returnType == methods[index].returnType));
-       if (index > 0) {                // All inherited methods do NOT have the same vmSignature
+       while (--index > 0 && returnType == methods[index].returnType);
+       if (index > 0) {  // All inherited methods do NOT have the same vmSignature
                this.problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
                return;
        }
 
        MethodBinding concreteMethod = null;
-       if (!type.isInterface()){ // ignore concrete methods for interfaces
-               for (int i = length; --i >= 0;)         // Remember that only one of the methods can be non-abstract
+       if (!type.isInterface()) {  // ignore concrete methods for interfaces
+               for (int i = length; --i >= 0;) {  // Remember that only one of the methods can be non-abstract
                        if (!methods[i].isAbstract()) {
                                concreteMethod = methods[i];
                                break;
                        }
+               }
        }
        if (concreteMethod == null) {
                if (this.type.isClass() && !this.type.isAbstract()) {
                        for (int i = length; --i >= 0;)
-                               if (!mustImplementAbstractMethod(methods[i]))
-                                       return;         // in this case, we have already reported problem against the concrete superclass
-
-                               TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
-                               if (typeDeclaration != null) {
-                                       MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
-                                       missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
-                               } else {
-                                       this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
-                               }
+                               if (!mustImplementAbstractMethod(methods[i])) return;  // have already reported problem against the concrete superclass
+
+                       TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+                       if (typeDeclaration != null) {
+                               MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
+                               missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+                       } else {
+                               this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+                       }
                }
                return;
        }
@@ -349,8 +159,7 @@ For each inherited method identifier (message pattern - vm signature minus the r
                                else
                                        complain about missing implementation only if type is NOT an interface or abstract
 */
-
-private void checkMethods() {
+private void checkMethods() { 
        boolean mustImplementAbstractMethods = this.type.isClass() && !this.type.isAbstract();
        char[][] methodSelectors = this.inheritedMethods.keyTable;
        for (int s = methodSelectors.length; --s >= 0;) {
@@ -387,22 +196,42 @@ private void checkMethods() {
                                }
                                if (index > 0) {
                                        this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
-                               } else {
-                                       if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract())
-                                               if (mustImplementAbstractMethod(matchingInherited[0])) {
-                                                       TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
-                                                       if (typeDeclaration != null) {
-                                                               MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(matchingInherited[0]);
-                                                               missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
-                                                       } else {
-                                                               this.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
-                                                       }
+                               } else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract()) {
+                                       if (mustImplementAbstractMethod(matchingInherited[0])) {
+                                               TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+                                               if (typeDeclaration != null) {
+                                                       MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(matchingInherited[0]);
+                                                       missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
+                                               } else {
+                                                       this.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
                                                }
+                                       }
                                }
                        }
                }
        }
 }
+private void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
+       ReferenceBinding superType = this.type.superclass();
+       char[] selector = abstractMethod.selector;
+       do {
+               if (!superType.isValidBinding()) return;
+               if (!superType.isAbstract()) return; // closer non abstract super type will be flagged instead
+
+               MethodBinding[] methods = superType.getMethods(selector);
+               nextMethod : for (int m = methods.length; --m >= 0;) {
+                       MethodBinding method = methods[m];
+                       if (method.returnType != abstractMethod.returnType || !method.areParametersEqual(abstractMethod))
+                               continue nextMethod;
+                       if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
+                               continue nextMethod;
+                       if (superType.fPackage == abstractMethod.declaringClass.fPackage) return; // found concrete implementation of abstract method in same package
+               }
+       } while ((superType = superType.superclass()) != abstractMethod.declaringClass);
+
+       // non visible abstract methods cannot be overridden so the type must be defined abstract
+       this.problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod);
+}
 /*
 Binding creation is responsible for reporting:
        - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations)
@@ -421,12 +250,9 @@ private void computeInheritedMethods() {
        int lastPosition = 0;
        interfacesToVisit[lastPosition] = type.superInterfaces();
 
-       ReferenceBinding superType;
-       if (this.type.isClass()) {
-               superType = this.type.superclass();
-       } else { // check interface methods against Object
-               superType = this.type.scope.getJavaLangObject();
-       }
+       ReferenceBinding superType = this.type.isClass()
+               ? this.type.superclass()
+               : this.type.scope.getJavaLangObject(); // check interface methods against Object
        MethodBinding[] nonVisibleDefaultMethods = null;
        int nonVisibleCount = 0;
 
@@ -444,19 +270,23 @@ private void computeInheritedMethods() {
                                MethodBinding method = methods[m];
                                if (!(method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())) { // look at all methods which are NOT private or constructors or default abstract
                                        MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
-                                       if (existingMethods != null)
-                                               for (int i = 0, length = existingMethods.length; i < length; i++)
-                                                       if (method.returnType == existingMethods[i].returnType)
-                                                               if (method.areParametersEqual(existingMethods[i]))
-                                                                       continue nextMethod;
+                                       if (existingMethods != null) {
+                                               for (int i = 0, length = existingMethods.length; i < length; i++) {
+                                                       if (method.returnType == existingMethods[i].returnType && method.areParametersEqual(existingMethods[i])) {
+                                                               if (method.isDefault() && method.isAbstract() && method.declaringClass.fPackage != type.fPackage)
+                                                                       checkPackagePrivateAbstractMethod(method);
+                                                               continue nextMethod;
+                                                       }
+                                               }
+                                       }
                                        if (nonVisibleDefaultMethods != null)
                                                for (int i = 0; i < nonVisibleCount; i++)
-                                                       if (method.returnType == nonVisibleDefaultMethods[i].returnType)
-                                                               if (CharOperation.equals(method.selector, nonVisibleDefaultMethods[i].selector))
-                                                                       if (method.areParametersEqual(nonVisibleDefaultMethods[i]))
-                                                                               continue nextMethod;
+                                                       if (method.returnType == nonVisibleDefaultMethods[i].returnType
+                                                               && CharOperation.equals(method.selector, nonVisibleDefaultMethods[i].selector)
+                                                               && method.areParametersEqual(nonVisibleDefaultMethods[i])) 
+                                                                       continue nextMethod;
 
-                                       if (!(method.isDefault() && (method.declaringClass.fPackage != type.fPackage))) { // ignore methods which have default visibility and are NOT defined in another package
+                                       if (!(method.isDefault() && method.declaringClass.fPackage != type.fPackage)) { // ignore methods which have default visibility and are NOT defined in another package
                                                if (existingMethods == null)
                                                        existingMethods = new MethodBinding[1];
                                                else
@@ -478,11 +308,9 @@ private void computeInheritedMethods() {
                                                MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(method.selector);
                                                if (current != null) { // non visible methods cannot be overridden so a warning is issued
                                                        foundMatch : for (int i = 0, length = current.length; i < length; i++) {
-                                                               if (method.returnType == current[i].returnType) {
-                                                                       if (method.areParametersEqual(current[i])) {
-                                                                               this.problemReporter().overridesPackageDefaultMethod(current[i], method);
-                                                                               break foundMatch;
-                                                                       }
+                                                               if (method.returnType == current[i].returnType && method.areParametersEqual(current[i])) {
+                                                                       this.problemReporter().overridesPackageDefaultMethod(current[i], method);
+                                                                       break foundMatch;
                                                                }
                                                        }
                                                }
@@ -495,6 +323,9 @@ private void computeInheritedMethods() {
 
        for (int i = 0; i <= lastPosition; i++) {
                ReferenceBinding[] interfaces = interfacesToVisit[i];
+               if (interfaces==null) {
+                       interfaces = new ReferenceBinding[0];
+               }
                for (int j = 0, length = interfaces.length; j < length; j++) {
                        superType = interfaces[j];
                        if ((superType.tagBits & InterfaceVisited) == 0) {
@@ -527,56 +358,18 @@ private void computeInheritedMethods() {
        // bit reinitialization
        for (int i = 0; i <= lastPosition; i++) {
                ReferenceBinding[] interfaces = interfacesToVisit[i];
+               if (interfaces==null) {
+                       interfaces = new ReferenceBinding[0];
+               }
                for (int j = 0, length = interfaces.length; j < length; j++)
                        interfaces[j].tagBits &= ~InterfaceVisited;
        }
 }
-/*
-computeInheritedMethodMembers
-
-       "8.4.6.4"
-       "Compute all of the members for the type that are inherited from its supertypes.
-               This includes:
-                       All of the methods implemented in the supertype hierarchy that are not overridden.
-                       PROBLEM:  Currently we do not remove overridden methods in the interface hierarchy.
-                       This could cause a non-existent exception error to be detected."
-
-       | supertype allSuperinterfaces methodsSeen interfacesSeen |
-       inheritedMethodMembers := LookupTable new: 50.
-       allSuperinterfaces := OrderedCollection new.
-
-       type isJavaClass ifTrue: [
-               supertype := type.
-               methodsSeen := EsIdentitySet new: 20.
-               [(supertype := self superclassFor: supertype) == nil] whileFalse: [
-                       (supertype isBuilderClass or: [supertype isValidDescriptor]) ifTrue: [
-                               allSuperinterfaces addAll: (self superinterfacesFor: supertype).
-                               supertype javaUserDefinedMethodsDo: [:method |
-                                       (method isJavaPrivate or: [method isJavaConstructor]) ifFalse: [
-                                               (method isJavaDefault and: [method declaringClass package symbol ~= type package symbol]) ifFalse: [
-                                                       (methodsSeen includes: method selector) ifFalse: [
-                                                               methodsSeen add: method selector.
-                                                               (inheritedMethodMembers
-                                                                       at: (self methodSignatureFor: method selector)
-                                                                       ifAbsentPut: [OrderedCollection new: 3])
-                                                                               add: method]]]]]]].
-
-       allSuperinterfaces addAll: (self superinterfacesFor: type).
-       interfacesSeen := EsIdentitySet new: allSuperinterfaces size * 2.
-       [allSuperinterfaces notEmpty] whileTrue: [
-               supertype := allSuperinterfaces removeFirst.
-               (interfacesSeen includes: supertype) ifFalse: [
-                       interfacesSeen add: supertype.
-                       (supertype isBuilderClass or: [supertype isValidDescriptor]) ifTrue: [
-                               allSuperinterfaces addAll: (self superinterfacesFor: supertype).
-                               supertype javaUserDefinedMethodsDo: [:method |          "Interface methods are all abstract public."
-                                       (inheritedMethodMembers
-                                               at: (self methodSignatureFor: method selector)
-                                               ifAbsentPut: [OrderedCollection new: 3])
-                                                       add: method]]]]
-*/
 private void computeMethods() {
        MethodBinding[] methods = type.methods();
+       if (methods==null) {
+               methods = new MethodBinding[0];
+       }
        int size = methods.length;
        this.currentMethods = new HashtableOfObject(size == 0 ? 1 : size); // maps method selectors to an array of methods... must search to match paramaters & return type
        for (int m = size; --m >= 0;) {
@@ -624,8 +417,11 @@ private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
                while (superclass.isAbstract() && superclass != declaringClass)
                        superclass = superclass.superclass(); // find the first concrete superclass or the abstract declaringClass
        } else {
-               if (this.type.implementsInterface(declaringClass, false))
-                       return !this.type.isAbstract();
+               if (this.type.implementsInterface(declaringClass, false)) {
+                       if (this.type.isAbstract()) return false; // leave it for the subclasses
+                       if (!superclass.implementsInterface(declaringClass, true)) // only if a superclass does not also implement the interface
+                               return true;
+               }
                while (superclass.isAbstract() && !superclass.implementsInterface(declaringClass, false))
                        superclass = superclass.superclass(); // find the first concrete superclass or the superclass which implements the interface
        }
@@ -651,229 +447,13 @@ public void verify(SourceTypeBinding type) {
        this.computeInheritedMethods();
        this.checkMethods();
 }
-private void zzFieldProblems() {
-}
-/*
-Binding creation is responsible for reporting all problems with fields:
-       - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - final/volatile)
-               - plus invalid modifiers given the context (the verifier did not do this before)
-               - include initializers in the modifier checks even though bindings are not created
-       - collisions... 2 fields with same name
-       - interfaces cannot define initializers
-       - nested types cannot define static fields
-       - with the type of the field:
-               - void is not a valid type (or for an array)
-               - an ambiguous, invisible or missing type
-
-verifyFields
-
-       | toSearch |
-       (toSearch := newClass fields) notEmpty ifTrue: [
-               newClass fromJavaClassFile
-                       ifTrue: [
-                               toSearch do: [:field |
-                                       field isJavaInitializer ifFalse: [
-                                               self verifyFieldType: field]]]
-                       ifFalse: [
-                               toSearch do: [:field |
-                                       field isJavaInitializer
-                                               ifTrue: [self verifyFieldInitializer: field]
-                                               ifFalse: [self verifyField: field]]]]
-
-verifyFieldInitializer: field
-
-       type isJavaInterface
-               ifTrue: [
-                       problemSummary
-                               reportVerificationProblem: #InterfacesCannotHaveInitializers
-                               args: #()
-                               severity: nil
-                               forField: field]
-               ifFalse: [
-                       field isJavaStatic
-                               ifTrue: [
-                                       field modifiers == AccStatic ifFalse: [
-                                               problemSummary
-                                                       reportVerificationProblem: #IllegalModifierForStaticInitializer
-                                                       args: #()
-                                                       severity: nil
-                                                       forField: field]]
-                               ifFalse: [
-                                       field modifiers == 0 ifFalse: [
-                                               problemSummary
-                                                       reportVerificationProblem: #IllegalModifierForInitializer
-                                                       args: #()
-                                                       severity: nil
-                                                       forField: field]]]
-
-verifyField: field
-
-       (field basicModifiers anyMask: AccAlternateModifierProblem | AccModifierProblem) ifTrue: [
-               self reportModifierProblemsOnField: field].
-
-       field isJavaStatic ifTrue: [
-               type isJavaStatic ifFalse: [
-                       (type isJavaNestedType and: [type isJavaClass]) ifTrue: [
-                               problemSummary
-                                       reportVerificationProblem: #NestedClassCannotHaveStaticField
-                                       args: #()
-                                       severity: nil
-                                       forField: field]]].
-
-       self verifyFieldType: field
-
-verifyFieldType: field
-
-       | descriptor fieldType |
-       "8.3 (Class) 9.3 (Interface)"
-       "Optimize the base type case"
-       field typeIsBaseType
-               ifTrue: [
-                       field typeName = 'V' ifTrue: [  "$NON-NLS$"
-                               problemSummary
-                                       reportVerificationProblem: #IllegalTypeForField
-                                       args: (Array with: JavaVoid)
-                                       severity: nil
-                                       forField: field]]
-               ifFalse: [
-                       descriptor := field asDescriptorIn: nameEnvironment.
-                       (fieldType := descriptor type) isValidDescriptor
-                               ifTrue: [
-                                       (fieldType isArrayType and: [fieldType leafComponentType isVoidType]) ifTrue: [
-                                               problemSummary
-                                                       reportVerificationProblem: #InvalidArrayType
-                                                       args: (Array with: fieldType javaReadableName)
-                                                       severity: nil
-                                                       forField: field]]
-                               ifFalse: [
-                                       problemSummary
-                                               reportVerificationProblem: #UnboundTypeForField
-                                               args: (Array with: fieldType javaReadableName with: fieldType leafComponentType)
-                                               severity: nil
-                                               forField: field]].
-
-reportModifierProblemsOnField: field
-
-       (field basicModifiers anyMask: AccAlternateModifierProblem) ifTrue: [
-               (field basicModifiers anyMask: AccModifierProblem)
-                       ifTrue: [
-                               ^problemSummary
-                                       reportVerificationProblem: #OnlyOneVisibilityModifierAllowed
-                                       args: #()
-                                       severity: ErrorInfo::ConflictingModifier
-                                       forField: field]
-                       ifFalse: [
-                               ^problemSummary
-                                       reportVerificationProblem: #DuplicateModifier
-                                       args: #()
-                                       severity: ErrorInfo::ConflictingModifier
-                                       forField: field]].
-
-       type isJavaInterface ifTrue: [
-               ^problemSummary
-                       reportVerificationProblem: #IllegalModifierForInterfaceField
-                       args: #()
-                       severity: nil
-                       forField: field].
-
-       (field basicModifiers allMask: AccFinal |  AccVolatile) ifTrue: [
-               ^problemSummary
-                       reportVerificationProblem: #IllegalModifierCombinationFinalVolatile
-                       args: #()
-                       severity: nil
-                       forField: field].
-
-       ^problemSummary
-               reportVerificationProblem: #IllegalModifierForField
-               args: #()
-               severity: nil
-               forField: field
-
-void reportModifierProblems(FieldBinding field) {
-       if (field.isFinal() && field.isVolatile())
-               this.problemReporter.illegalModifierCombinationFinalVolatile(field);
-
-       // Should be able to detect all 3 problems NOT just 1
-       if ((type.modifiers() & Modifiers.AccAlternateModifierProblem) == 0) {
-               if (this.type.isInterface())
-                       this.problemReporter.illegalModifierForInterfaceField(field);
-               else
-                       this.problemReporter.illegalModifier(field);
-       } else {
-               if ((field.modifiers & Modifiers.AccModifierProblem) != 0)
-                       this.problemReporter.onlyOneVisibilityModifierAllowed(field);
-               else
-                       this.problemReporter.duplicateModifier(field);
-       }
-}
-*/
-private void zzImportProblems() {
-}
-/*
-Binding creation is responsible for reporting all problems with imports:
-       - on demand imports which refer to missing packages
-       - with single type imports:
-               - resolves to an ambiguous, invisible or missing type
-               - conflicts with the type's source name
-               - has the same simple name as another import
-
-Note: VAJ ignored duplicate imports (only one was kept)
-
-verifyImports
-
-       | importsBySimpleName nameEnvClass imports cl first |
-       importsBySimpleName := LookupTable new.
-       nameEnvClass := nameEnvironment class.
-
-       "7.5.2"
-       type imports do: [:import |
-               import isOnDemand
-                       ifTrue: [
-                               (nameEnvClass doesPackageExistNamed: import javaPackageName) ifFalse: [
-                                       (nameEnvClass findJavaClassNamedFrom: import javaPackageName) == nil ifTrue: [
-                                               problemSummary
-                                                       reportVerificationProblem: #OnDemandImportRefersToMissingPackage
-                                                       args: (Array with: import asString)
-                                                       severity: ErrorInfo::ImportVerification
-                                                       forType: type]]]
-                       ifFalse: [
-                               (imports := importsBySimpleName at: import javaSimpleName ifAbsent: []) == nil
-                                       ifTrue: [
-                                               importsBySimpleName at: import javaSimpleName put: (Array with: import)]
-                                       ifFalse: [
-                                               (imports includes: import) ifFalse: [
-                                                       importsBySimpleName at: import javaSimpleName put: imports, (Array with: import)]].
-
-                               "Ignore any imports which are simple names - we will treat these as no-ops."
-
-                               import javaPackageName notEmpty ifTrue: [
-                                       cl := nameEnvClass findJavaClassNamedFrom: import asString.
-
-                                       (cl ~~ nil and: [cl isJavaPublic or: [cl controller symbol == type controller symbol]]) ifFalse: [
-                                               problemSummary
-                                                       reportVerificationProblem: #SingleTypeImportRefersToInvisibleType
-                                                       args: (Array with: import asString)
-                                                       severity: ErrorInfo::ImportVerification
-                                                       forType: type]]]].
-
-       importsBySimpleName notEmpty ifTrue: [
-               importsBySimpleName keysAndValuesDo: [:simpleName :matching |
-                       matching size == 1
-                               ifTrue: [
-                                       simpleName = type sourceName ifTrue: [
-                                               matching first javaReadableName = type javaReadableName ifFalse: [
-                                                       problemSummary
-                                                               reportVerificationProblem: #SingleTypeImportConflictsWithType
-                                                               args: #()
-                                                               severity: nil
-                                                               forType: type]]]
-                               ifFalse: [
-                                       problemSummary
-                                               reportVerificationProblem: #SingleTypeImportsHaveSameSimpleName
-                                               args: (Array with: simpleName)
-                                               severity: nil
-                                               forType: type]]]
-*/
-private void zzTypeProblems() {
+public String toString() {
+       StringBuffer buffer = new StringBuffer(10);
+       buffer.append("MethodVerifier for type: "); //$NON-NLS-1$
+       buffer.append(type.readableName());
+       buffer.append('\n');
+       buffer.append("\t-inherited methods: "); //$NON-NLS-1$
+       buffer.append(this.inheritedMethods);
+       return buffer.toString();
 }
 }