/*******************************************************************************
- * 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;
}
}
}
}
}
+ 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() {
-}
}