first scanner /parser copied from the jdt java version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / MethodVerifier.java
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/MethodVerifier.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/MethodVerifier.java
new file mode 100644 (file)
index 0000000..1debb98
--- /dev/null
@@ -0,0 +1,879 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+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 {
+       SourceTypeBinding type;
+       HashtableOfObject inheritedMethods;
+       HashtableOfObject currentMethods;
+       ReferenceBinding runtimeException;
+       ReferenceBinding errorException;
+/*
+Binding creation is responsible for reporting all problems with types:
+       - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - abstract/final)
+               - plus invalid modifiers given the context (the verifier did not do this before)
+       - qualified name collisions between a type and a package (types in default packages are excluded)
+       - all type hierarchy problems:
+               - cycles in the superclass or superinterface hierarchy
+               - an ambiguous, invisible or missing superclass or superinterface
+               - extending a final class
+               - extending an interface instead of a class
+               - implementing a class instead of an interface
+               - implementing the same interface more than once (ie. duplicate interfaces)
+       - with nested 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.inheritedMethods = null;
+       this.currentMethods = null;
+       this.runtimeException = null;
+       this.errorException = null;
+}
+private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+       for (int i = length; --i >= 0;) {
+               MethodBinding inheritedMethod = methods[i];
+               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
+                       this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
+               } else {
+                       if (currentMethod.thrownExceptions != NoExceptions)
+                               this.checkExceptions(currentMethod, inheritedMethod);
+                       if (inheritedMethod.isFinal())
+                               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);
+               }
+       }
+}
+/*
+"8.4.4"
+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;
+       for (int i = newExceptions.length; --i >= 0;) {
+               ReferenceBinding newException = newExceptions[i];
+               int j = inheritedExceptions.length;
+               while (--j > -1 && !this.isSameClassOrSubclassOf(newException, inheritedExceptions[j]));
+               if (j == -1)
+                       if (!(newException.isCompatibleWith(this.runtimeException()) || newException.isCompatibleWith(this.errorException())))
+                               this.problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException);
+       }
+}
+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
+               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 (!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]);
+                               }
+               }
+               return;
+       }
+
+       MethodBinding[] abstractMethods = new MethodBinding[length - 1];
+       index = 0;
+       for (int i = length; --i >= 0;)
+               if (methods[i] != concreteMethod)
+                       abstractMethods[index++] = methods[i];
+
+       // Remember that interfaces can only define public instance methods
+       if (concreteMethod.isStatic())
+               // Cannot inherit a static method which is specified as an instance method by an interface
+               this.problemReporter().staticInheritedMethodConflicts(type, concreteMethod, abstractMethods);   
+       if (!concreteMethod.isPublic())
+               // Cannot reduce visibility of a public method specified by an interface
+               this.problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
+       if (concreteMethod.thrownExceptions != NoExceptions)
+               for (int i = abstractMethods.length; --i >= 0;)
+                       this.checkExceptions(concreteMethod, abstractMethods[i]);
+}
+/*
+For each inherited method identifier (message pattern - vm signature minus the return type)
+       if current method exists
+               if current's vm signature does not match an inherited signature then complain 
+               else compare current's exceptions & visibility against each inherited method
+       else
+               if inherited methods = 1
+                       if inherited is abstract && type is NOT an interface or abstract, complain
+               else
+                       if vm signatures do not match complain
+                       else
+                               find the concrete implementation amongst the abstract methods (can only be 1)
+                               if one exists then
+                                       it must be a public instance method
+                                       compare concrete's exceptions against each abstract method
+                               else
+                                       complain about missing implementation only if type is NOT an interface or abstract
+*/
+
+private void checkMethods() {
+       boolean mustImplementAbstractMethods = this.type.isClass() && !this.type.isAbstract();
+       char[][] methodSelectors = this.inheritedMethods.keyTable;
+       for (int s = methodSelectors.length; --s >= 0;) {
+               if (methodSelectors[s] != null) {
+                       MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
+                       MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];
+
+                       int index = -1;
+                       MethodBinding[] matchingInherited = new MethodBinding[inherited.length];
+                       if (current != null) {
+                               for (int i = 0, length1 = current.length; i < length1; i++) {
+                                       while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+                                       MethodBinding currentMethod = current[i];
+                                       for (int j = 0, length2 = inherited.length; j < length2; j++) {
+                                               if (inherited[j] != null && currentMethod.areParametersEqual(inherited[j])) {
+                                                       matchingInherited[++index] = inherited[j];
+                                                       inherited[j] = null; // do not want to find it again
+                                               }
+                                       }
+                                       if (index >= 0)
+                                               this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
+                               }
+                       }
+                       for (int i = 0, length = inherited.length; i < length; i++) {
+                               while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+                               if (inherited[i] != null) {
+                                       matchingInherited[++index] = inherited[i];
+                                       for (int j = i + 1; j < length; j++) {
+                                               if (inherited[j] != null && inherited[i].areParametersEqual(inherited[j])) {
+                                                       matchingInherited[++index] = inherited[j];
+                                                       inherited[j] = null; // do not want to find it again
+                                               }
+                                       }
+                               }
+                               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]);
+                                                       }
+                                               }
+                               }
+                       }
+               }
+       }
+}
+/*
+Binding creation is responsible for reporting:
+       - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations)
+               - plus invalid modifiers given the context... examples:
+                       - interface methods can only be public
+                       - abstract methods can only be defined by abstract classes
+       - collisions... 2 methods with identical vmSelectors
+       - multiple methods with the same message pattern but different return types
+       - ambiguous, invisible or missing return/argument/exception types
+       - check the type of any array is not void
+       - check that each exception type is Throwable or a subclass of it
+*/
+private void computeInheritedMethods() {
+       this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
+       ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+       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();
+       }
+       MethodBinding[] nonVisibleDefaultMethods = null;
+       int nonVisibleCount = 0;
+
+       while (superType != null) {
+               if (superType.isValidBinding()) {
+                       ReferenceBinding[] itsInterfaces = superType.superInterfaces();
+                       if (itsInterfaces != NoSuperInterfaces) {
+                               if (++lastPosition == interfacesToVisit.length)
+                                       System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+                               interfacesToVisit[lastPosition] = itsInterfaces;
+                       }
+
+                       MethodBinding[] methods = superType.methods();
+                       nextMethod : for (int m = methods.length; --m >= 0;) {
+                               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 (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.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
+                                                       System.arraycopy(existingMethods, 0,
+                                                               (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
+                                               existingMethods[existingMethods.length - 1] = method;
+                                               this.inheritedMethods.put(method.selector, existingMethods);
+                                       } else {
+                                               if (nonVisibleDefaultMethods == null)
+                                                       nonVisibleDefaultMethods = new MethodBinding[10];
+                                               else if (nonVisibleCount == nonVisibleDefaultMethods.length)
+                                                       System.arraycopy(nonVisibleDefaultMethods, 0,
+                                                               (nonVisibleDefaultMethods = new MethodBinding[nonVisibleCount * 2]), 0, nonVisibleCount);
+                                               nonVisibleDefaultMethods[nonVisibleCount++] = method;
+
+                                               if (method.isAbstract() && !this.type.isAbstract()) // non visible abstract methods cannot be overridden so the type must be defined abstract
+                                                       this.problemReporter().abstractMethodCannotBeOverridden(this.type, method);
+
+                                               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;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       superType = superType.superclass();
+               }
+       }
+
+       for (int i = 0; i <= lastPosition; i++) {
+               ReferenceBinding[] interfaces = interfacesToVisit[i];
+               for (int j = 0, length = interfaces.length; j < length; j++) {
+                       superType = interfaces[j];
+                       if ((superType.tagBits & InterfaceVisited) == 0) {
+                               superType.tagBits |= InterfaceVisited;
+                               if (superType.isValidBinding()) {
+                                       ReferenceBinding[] itsInterfaces = superType.superInterfaces();
+                                       if (itsInterfaces != NoSuperInterfaces) {
+                                               if (++lastPosition == interfacesToVisit.length)
+                                                       System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+                                               interfacesToVisit[lastPosition] = itsInterfaces;
+                                       }
+
+                                       MethodBinding[] methods = superType.methods();
+                                       for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
+                                               MethodBinding method = methods[m];
+                                               MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
+                                               if (existingMethods == null)
+                                                       existingMethods = new MethodBinding[1];
+                                               else
+                                                       System.arraycopy(existingMethods, 0,
+                                                               (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
+                                               existingMethods[existingMethods.length - 1] = method;
+                                               this.inheritedMethods.put(method.selector, existingMethods);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // bit reinitialization
+       for (int i = 0; i <= lastPosition; i++) {
+               ReferenceBinding[] interfaces = interfacesToVisit[i];
+               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();
+       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;) {
+               MethodBinding method = methods[m];
+               if (!(method.isConstructor() || method.isDefaultAbstract())) { // keep all methods which are NOT constructors or default abstract
+                       MethodBinding[] existingMethods = (MethodBinding[]) this.currentMethods.get(method.selector);
+                       if (existingMethods == null)
+                               existingMethods = new MethodBinding[1];
+                       else
+                               System.arraycopy(existingMethods, 0,
+                                       (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
+                       existingMethods[existingMethods.length - 1] = method;
+                       this.currentMethods.put(method.selector, existingMethods);
+               }
+       }
+}
+private ReferenceBinding errorException() {
+       if (errorException == null)
+               this.errorException = this.type.scope.getJavaLangError();
+       return errorException;
+}
+private boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
+       if (inheritedMethod.modifiers == newMethod.modifiers) return true;
+
+       if (newMethod.isPublic()) return true;          // Covers everything
+       if (inheritedMethod.isPublic()) return false;
+
+       if (newMethod.isProtected()) return true;
+       if (inheritedMethod.isProtected()) return false;
+
+       return !newMethod.isPrivate();          // The inheritedMethod cannot be private since it would not be visible
+}
+private boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
+       do {
+               if (testClass == superclass) return true;
+       } while ((testClass = testClass.superclass()) != null);
+       return false;
+}
+private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
+       // if the type's superclass is an abstract class, then all abstract methods must be implemented
+       // otherwise, skip it if the type's superclass must implement any of the inherited methods
+       ReferenceBinding superclass = this.type.superclass();
+       ReferenceBinding declaringClass = abstractMethod.declaringClass;
+       if (declaringClass.isClass()) {
+               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();
+               while (superclass.isAbstract() && !superclass.implementsInterface(declaringClass, false))
+                       superclass = superclass.superclass(); // find the first concrete superclass or the superclass which implements the interface
+       }
+       return superclass.isAbstract();         // if it is a concrete class then we have already reported problem against it
+}
+private ProblemReporter problemReporter() {
+       return this.type.scope.problemReporter();
+}
+private ProblemReporter problemReporter(MethodBinding currentMethod) {
+       ProblemReporter reporter = problemReporter();
+       if (currentMethod.declaringClass == type)       // only report against the currentMethod if its implemented by the type
+               reporter.referenceContext = currentMethod.sourceMethod();
+       return reporter;
+}
+private ReferenceBinding runtimeException() {
+       if (runtimeException == null)
+               this.runtimeException = this.type.scope.getJavaLangRuntimeException();
+       return runtimeException;
+}
+public void verify(SourceTypeBinding type) {
+       this.type = type;
+       this.computeMethods();
+       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() {
+}
+}