X-Git-Url: http://git.phpeclipse.com 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 index 1debb98..98c7fd2 100644 --- 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 @@ -1,486 +1,469 @@ /******************************************************************************* - * 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 { 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); + + LookupEnvironment environment; + + /* + * 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) + */ + 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; + this.environment = environment; } -} -*/ -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); + + 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 + 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() || + // environment.options.reportDeprecationInsideDeprecatedCode) + // 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; + + /* + * "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); + } } - 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; + 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 + } + if (concreteMethod == null) { + if (this.type.isClass() && !this.type.isAbstract()) { + for (int i = length; --i >= 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]); + MethodDeclaration missingAbstractMethod = typeDeclaration + .addMissingAbstractMethodFor(methods[0]); + missingAbstractMethod.scope.problemReporter() + .abstractMethodMustBeImplemented(this.type, + methods[0]); } else { - this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]); + this.problemReporter().abstractMethodMustBeImplemented( + this.type, methods[0]); } + } + return; } - 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]); } - 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 + /* + * 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 } - 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 + 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 (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]); + MethodDeclaration missingAbstractMethod = typeDeclaration + .addMissingAbstractMethodFor(matchingInherited[0]); + missingAbstractMethod.scope + .problemReporter() + .abstractMethodMustBeImplemented( + this.type, matchingInherited[0]); } else { - this.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]); + 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;) { + 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.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])) + 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) - + * 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 = this.type.isClass() ? this.type + .superclass() : this.type.scope.getJavaLangObject(); // check + // interface + // methods + // against + // Object + 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 + && 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.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); + } + } + } + if (nonVisibleDefaultMethods != null) + for (int i = 0; i < nonVisibleCount; i++) + 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 (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 + && method + .areParametersEqual(current[i])) { + this.problemReporter() + .overridesPackageDefaultMethod( + current[i], method); break foundMatch; } } @@ -488,392 +471,231 @@ private void computeInheritedMethods() { } } } + superType = superType.superclass(); } - 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; - } + 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) { + 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); + 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]; + if (interfaces == null) { + interfaces = new ReferenceBinding[0]; + } + for (int j = 0, length = interfaces.length; j < length; j++) + interfaces[j].tagBits &= ~InterfaceVisited; + } + } + + 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;) { + 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); + } + } } - // 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; + private ReferenceBinding errorException() { + if (errorException == null) + this.errorException = this.type.scope.getJavaLangError(); + return errorException; } -} -/* -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 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)) { + 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 } + return superclass.isAbstract(); // if it is a concrete class then we + // have already reported problem against + // it } -} -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; + private ProblemReporter problemReporter() { + return this.type.scope.problemReporter(); + } - if (newMethod.isProtected()) return true; - if (inheritedMethod.isProtected()) return false; + 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; + } - 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 + private ReferenceBinding runtimeException() { + if (runtimeException == null) + this.runtimeException = this.type.scope + .getJavaLangRuntimeException(); + return runtimeException; } - 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); + + public void verify(SourceTypeBinding type) { + this.type = type; + this.computeMethods(); + this.computeInheritedMethods(); + this.checkMethods(); + } + + 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(); } -} -*/ -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() { -} }