+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * 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-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.lookup;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Clinit;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-
-public class ClassScope extends Scope {
- public TypeDeclaration referenceContext;
-
- private final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
-
- public ClassScope(Scope parent, TypeDeclaration context) {
- super(CLASS_SCOPE, parent);
- this.referenceContext = context;
- }
-
- void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
-
- LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
-
- SourceTypeBinding sourceType = referenceContext.binding;
- if (supertype.isInterface()) {
- sourceType.superclass = getJavaLangObject();
- sourceType.superInterfaces = new ReferenceBinding[] { supertype };
- } else {
- sourceType.superclass = supertype;
- sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
- }
- connectMemberTypes();
- buildFieldsAndMethods();
- anonymousType.faultInTypesForFieldsAndMethods();
- sourceType.verifyMethods(environment().methodVerifier());
- }
-
- private void buildFields() {
- boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
- if (referenceContext.fields == null) {
- if (hierarchyIsInconsistent) { // 72468
- referenceContext.binding.fields = new FieldBinding[1];
- referenceContext.binding.fields[0] =
- new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
- } else {
- referenceContext.binding.fields = NoFields;
- }
- return;
- }
- // count the number of fields vs. initializers
- FieldDeclaration[] fields = referenceContext.fields;
- int size = fields.length;
- int count = 0;
- for (int i = 0; i < size; i++)
- if (fields[i].isField())
- count++;
-
- if (hierarchyIsInconsistent)
- count++;
- // iterate the field declarations to create the bindings, lose all duplicates
- FieldBinding[] fieldBindings = new FieldBinding[count];
- HashtableOfObject knownFieldNames = new HashtableOfObject(count);
- boolean duplicate = false;
- count = 0;
- for (int i = 0; i < size; i++) {
- FieldDeclaration field = fields[i];
- if (!field.isField()) {
- if (referenceContext.binding.isInterface())
- problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
- } else {
- FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
- // field's type will be resolved when needed for top level types
- checkAndSetModifiersForField(fieldBinding, field);
-
- if (knownFieldNames.containsKey(field.name)) {
- duplicate = true;
- FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
- if (previousBinding != null) {
- for (int f = 0; f < i; f++) {
- FieldDeclaration previousField = fields[f];
- if (previousField.binding == previousBinding) {
- problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
- previousField.binding = null;
- break;
- }
- }
- }
- knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
- problemReporter().duplicateFieldInType(referenceContext.binding, field);
- field.binding = null;
- } else {
- knownFieldNames.put(field.name, fieldBinding);
- // remember that we have seen a field with this name
- if (fieldBinding != null)
- fieldBindings[count++] = fieldBinding;
- }
- }
- }
- // remove duplicate fields
- if (duplicate) {
- FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
- // we know we'll be removing at least 1 duplicate name
- size = count;
- count = 0;
- for (int i = 0; i < size; i++) {
- FieldBinding fieldBinding = fieldBindings[i];
- if (knownFieldNames.get(fieldBinding.name) != null)
- newFieldBindings[count++] = fieldBinding;
- }
- fieldBindings = newFieldBindings;
- }
- if (hierarchyIsInconsistent)
- fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
-
- if (count != fieldBindings.length)
- System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
- for (int i = 0; i < count; i++)
- fieldBindings[i].id = i;
- referenceContext.binding.fields = fieldBindings;
- }
-
- void buildFieldsAndMethods() {
- buildFields();
- buildMethods();
-
- SourceTypeBinding sourceType = referenceContext.binding;
- if (sourceType.isMemberType() && !sourceType.isLocalType())
- ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
-
- ReferenceBinding[] memberTypes = sourceType.memberTypes;
- for (int i = 0, length = memberTypes.length; i < length; i++)
- ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
- }
-
- private LocalTypeBinding buildLocalType(
- SourceTypeBinding enclosingType,
- PackageBinding packageBinding) {
-
- referenceContext.scope = this;
- referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
- referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
-
- // build the binding or the local type
- LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
- referenceContext.binding = localType;
- checkAndSetModifiers();
-
- // Look at member types
- ReferenceBinding[] memberTypeBindings = NoMemberTypes;
- if (referenceContext.memberTypes != null) {
- int size = referenceContext.memberTypes.length;
- memberTypeBindings = new ReferenceBinding[size];
- int count = 0;
- nextMember : for (int i = 0; i < size; i++) {
- TypeDeclaration memberContext = referenceContext.memberTypes[i];
- if (memberContext.isInterface()) {
- problemReporter().nestedClassCannotDeclareInterface(memberContext);
- continue nextMember;
- }
- ReferenceBinding type = localType;
- // check that the member does not conflict with an enclosing type
- do {
- if (CharOperation.equals(type.sourceName, memberContext.name)) {
- problemReporter().hidingEnclosingType(memberContext);
- continue nextMember;
- }
- type = type.enclosingType();
- } while (type != null);
- // check the member type does not conflict with another sibling member type
- for (int j = 0; j < i; j++) {
- if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
- problemReporter().duplicateNestedType(memberContext);
- continue nextMember;
- }
- }
-
- ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
- LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
- memberBinding.setAsMemberType();
- memberTypeBindings[count++] = memberBinding;
- }
- if (count != size)
- System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
- }
- localType.memberTypes = memberTypeBindings;
- return localType;
- }
-
- void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
-
- LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
- connectTypeHierarchy();
- buildFieldsAndMethods();
- localType.faultInTypesForFieldsAndMethods();
-
- referenceContext.binding.verifyMethods(environment().methodVerifier());
- }
-
- private void buildMethods() {
- if (referenceContext.methods == null) {
- referenceContext.binding.methods = NoMethods;
- return;
- }
-
- // iterate the method declarations to create the bindings
- AbstractMethodDeclaration[] methods = referenceContext.methods;
- int size = methods.length;
- int clinitIndex = -1;
- for (int i = 0; i < size; i++) {
- if (methods[i] instanceof Clinit) {
- clinitIndex = i;
- break;
- }
- }
- MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
-
- int count = 0;
- for (int i = 0; i < size; i++) {
- if (i != clinitIndex) {
- MethodScope scope = new MethodScope(this, methods[i], false);
- MethodBinding methodBinding = scope.createMethod(methods[i]);
- if (methodBinding != null) // is null if binding could not be created
- methodBindings[count++] = methodBinding;
- }
- }
- if (count != methodBindings.length)
- System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
-
- referenceContext.binding.methods = methodBindings;
- referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
- }
- SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
- // provide the typeDeclaration with needed scopes
- referenceContext.scope = this;
- referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
- referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
-
- if (enclosingType == null) {
- char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
- referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
- } else {
- char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
- className[className.length - 1] =
- CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
- referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
- }
-
- SourceTypeBinding sourceType = referenceContext.binding;
- sourceType.fPackage.addType(sourceType);
- checkAndSetModifiers();
-
- // Look at member types
- ReferenceBinding[] memberTypeBindings = NoMemberTypes;
- if (referenceContext.memberTypes != null) {
- int size = referenceContext.memberTypes.length;
- memberTypeBindings = new ReferenceBinding[size];
- int count = 0;
- nextMember : for (int i = 0; i < size; i++) {
- TypeDeclaration memberContext = referenceContext.memberTypes[i];
- if (memberContext.isInterface()
- && sourceType.isNestedType()
- && sourceType.isClass()
- && !sourceType.isStatic()) {
- problemReporter().nestedClassCannotDeclareInterface(memberContext);
- continue nextMember;
- }
- ReferenceBinding type = sourceType;
- // check that the member does not conflict with an enclosing type
- do {
- if (CharOperation.equals(type.sourceName, memberContext.name)) {
- problemReporter().hidingEnclosingType(memberContext);
- continue nextMember;
- }
- type = type.enclosingType();
- } while (type != null);
- // check that the member type does not conflict with another sibling member type
- for (int j = 0; j < i; j++) {
- if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
- problemReporter().duplicateNestedType(memberContext);
- continue nextMember;
- }
- }
-
- ClassScope memberScope = new ClassScope(this, memberContext);
- memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
- }
- if (count != size)
- System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
- }
- sourceType.memberTypes = memberTypeBindings;
- return sourceType;
- }
-
- private void checkAndSetModifiers() {
- SourceTypeBinding sourceType = referenceContext.binding;
- int modifiers = sourceType.modifiers;
- if ((modifiers & AccAlternateModifierProblem) != 0)
- problemReporter().duplicateModifierForType(sourceType);
-
- ReferenceBinding enclosingType = sourceType.enclosingType();
- boolean isMemberType = sourceType.isMemberType();
-
- if (isMemberType) {
- // checks for member types before local types to catch local members
- if (enclosingType.isStrictfp())
- modifiers |= AccStrictfp;
- if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
- modifiers |= AccDeprecatedImplicitly;
- if (enclosingType.isInterface())
- modifiers |= AccPublic;
- } else if (sourceType.isLocalType()) {
- if (sourceType.isAnonymousType())
- modifiers |= AccFinal;
- Scope scope = this;
- do {
- switch (scope.kind) {
- case METHOD_SCOPE :
- MethodScope methodScope = (MethodScope) scope;
- if (methodScope.isInsideInitializer()) {
- SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
-
- // inside field declaration ? check field modifier to see if deprecated
- if (methodScope.initializedField != null) {
- // currently inside this field initialization
- if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
- modifiers |= AccDeprecatedImplicitly;
- }
- } else {
- if (type.isStrictfp())
- modifiers |= AccStrictfp;
- if (type.isViewedAsDeprecated() && !sourceType.isDeprecated())
- modifiers |= AccDeprecatedImplicitly;
- }
- } else {
- MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
- if (method != null){
- if (method.isStrictfp())
- modifiers |= AccStrictfp;
- if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
- modifiers |= AccDeprecatedImplicitly;
- }
- }
- break;
- case CLASS_SCOPE :
- // local member
- if (enclosingType.isStrictfp())
- modifiers |= AccStrictfp;
- if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
- modifiers |= AccDeprecatedImplicitly;
- break;
- }
- scope = scope.parent;
- } while (scope != null);
- }
- // after this point, tests on the 16 bits reserved.
- int realModifiers = modifiers & AccJustFlag;
-
- if ((realModifiers & AccInterface) != 0) {
- // detect abnormal cases for interfaces
- if (isMemberType) {
- int unexpectedModifiers =
- ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForMemberInterface(sourceType);
- /*
- } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
- int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForLocalInterface(sourceType);
- */
- } else {
- int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForInterface(sourceType);
- }
- modifiers |= AccAbstract;
- } else {
- // detect abnormal cases for types
- if (isMemberType) { // includes member types defined inside local types
- int unexpectedModifiers =
- ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForMemberClass(sourceType);
- } else if (sourceType.isLocalType()) {
- int unexpectedModifiers = ~(AccAbstract | AccFinal | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForLocalClass(sourceType);
- } else {
- int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForClass(sourceType);
- }
-
- // check that Final and Abstract are not set together
- if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
- problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
- }
-
- if (isMemberType) {
- // test visibility modifiers inconsistency, isolate the accessors bits
- if (enclosingType.isInterface()) {
- if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
- problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
-
- // need to keep the less restrictive
- if ((realModifiers & AccProtected) != 0)
- modifiers ^= AccProtected;
- if ((realModifiers & AccPrivate) != 0)
- modifiers ^= AccPrivate;
- }
- } else {
- int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
- if ((accessorBits & (accessorBits - 1)) > 1) {
- problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
-
- // need to keep the less restrictive
- if ((accessorBits & AccPublic) != 0) {
- if ((accessorBits & AccProtected) != 0)
- modifiers ^= AccProtected;
- if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
- }
- if ((accessorBits & AccProtected) != 0)
- if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
- }
- }
-
- // static modifier test
- if ((realModifiers & AccStatic) == 0) {
- if (enclosingType.isInterface())
- modifiers |= AccStatic;
- } else {
- if (!enclosingType.isStatic())
- // error the enclosing type of a static field must be static or a top-level type
- problemReporter().illegalStaticModifierForMemberType(sourceType);
- }
- }
-
- sourceType.modifiers = modifiers;
- }
-
- /* This method checks the modifiers of a field.
- *
- * 9.3 & 8.3
- * Need to integrate the check for the final modifiers for nested types
- *
- * Note : A scope is accessible by : fieldBinding.declaringClass.scope
- */
- private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
- int modifiers = fieldBinding.modifiers;
- if ((modifiers & AccAlternateModifierProblem) != 0)
- problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
-
- if (fieldBinding.declaringClass.isInterface()) {
- int expectedValue = AccPublic | AccStatic | AccFinal;
- // set the modifiers
- modifiers |= expectedValue;
-
- // and then check that they are the only ones
- if ((modifiers & AccJustFlag) != expectedValue)
- problemReporter().illegalModifierForInterfaceField(fieldBinding.declaringClass, fieldDecl);
- fieldBinding.modifiers = modifiers;
- return;
- }
-
- // after this point, tests on the 16 bits reserved.
- int realModifiers = modifiers & AccJustFlag;
- int unexpectedModifiers =
- ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic | AccTransient | AccVolatile);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
-
- int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
- if ((accessorBits & (accessorBits - 1)) > 1) {
- problemReporter().illegalVisibilityModifierCombinationForField(
- fieldBinding.declaringClass,
- fieldDecl);
-
- // need to keep the less restrictive
- if ((accessorBits & AccPublic) != 0) {
- if ((accessorBits & AccProtected) != 0)
- modifiers ^= AccProtected;
- if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
- }
- if ((accessorBits & AccProtected) != 0)
- if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
- }
-
- if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
- problemReporter().illegalModifierCombinationFinalVolatileForField(
- fieldBinding.declaringClass,
- fieldDecl);
-
- if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
- modifiers |= AccBlankFinal;
- }
- fieldBinding.modifiers = modifiers;
- }
-
- private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
- // search up the hierarchy of the sourceType to see if any superType defines a member type
- // when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
- ReferenceBinding currentType = sourceType;
- ReferenceBinding[][] interfacesToVisit = null;
- int lastPosition = -1;
- do {
- if ((currentType.tagBits & HasNoMemberTypes) != 0)
- break; // already know it has no inherited member types, can stop looking up
- if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
- return; // has member types
- ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (interfacesToVisit == null)
- interfacesToVisit = new ReferenceBinding[5][];
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
- } while ((currentType = currentType.superclass()) != null);
-
- boolean hasMembers = false;
- if (interfacesToVisit != null) {
- done : for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- ReferenceBinding anInterface = interfaces[j];
- if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
- anInterface.tagBits |= InterfaceVisited;
- if ((anInterface.tagBits & HasNoMemberTypes) != 0)
- continue; // already know it has no inherited member types
- if (anInterface.memberTypes() != NoMemberTypes) {
- hasMembers = true;
- break done;
- }
-
- ReferenceBinding[] itsInterfaces = anInterface.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];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- interfaces[j].tagBits &= ~InterfaceVisited;
- if (!hasMembers)
- interfaces[j].tagBits |= HasNoMemberTypes;
- }
- }
- }
-
- if (!hasMembers) {
- currentType = sourceType;
- do {
- currentType.tagBits |= HasNoMemberTypes;
- } while ((currentType = currentType.superclass()) != null);
- }
- }
-
- private void connectMemberTypes() {
- SourceTypeBinding sourceType = referenceContext.binding;
- if (sourceType.memberTypes != NoMemberTypes)
- for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
- ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
- }
- /*
- Our current belief based on available JCK tests is:
- inherited member types are visible as a potential superclass.
- inherited interfaces are not visible when defining a superinterface.
-
- Error recovery story:
- ensure the superclass is set to java.lang.Object if a problem is detected
- resolving the superclass.
-
- Answer false if an error was reported against the sourceType.
- */
- private boolean connectSuperclass() {
- SourceTypeBinding sourceType = referenceContext.binding;
- if (sourceType.id == T_Object) { // handle the case of redefining java.lang.Object up front
- sourceType.superclass = null;
- sourceType.superInterfaces = NoSuperInterfaces;
- if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
- problemReporter().objectCannotHaveSuperTypes(sourceType);
- return true; // do not propagate Object's hierarchy problems down to every subtype
- }
- if (referenceContext.superclass == null) {
- sourceType.superclass = getJavaLangObject();
- return !detectCycle(sourceType, sourceType.superclass, null);
- }
- ReferenceBinding superclass = findSupertype(referenceContext.superclass);
- if (superclass != null) { // is null if a cycle was detected cycle
- referenceContext.superclass.resolvedType = superclass; // hold onto the problem type
- if (!superclass.isValidBinding()) {
- problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
- } else if (superclass.isInterface()) {
- problemReporter().superclassMustBeAClass(sourceType, referenceContext.superclass, superclass);
- } else if (superclass.isFinal()) {
- problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
- } else {
- // only want to reach here when no errors are reported
- sourceType.superclass = superclass;
- return true;
- }
- }
- sourceType.tagBits |= HierarchyHasProblems;
- sourceType.superclass = getJavaLangObject();
- if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
- detectCycle(sourceType, sourceType.superclass, null);
- return false; // reported some error against the source type
- }
-
- /*
- Our current belief based on available JCK 1.3 tests is:
- inherited member types are visible as a potential superclass.
- inherited interfaces are visible when defining a superinterface.
-
- Error recovery story:
- ensure the superinterfaces contain only valid visible interfaces.
-
- Answer false if an error was reported against the sourceType.
- */
- private boolean connectSuperInterfaces() {
- SourceTypeBinding sourceType = referenceContext.binding;
- sourceType.superInterfaces = NoSuperInterfaces;
- if (referenceContext.superInterfaces == null)
- return true;
- if (sourceType.id == T_Object) // already handled the case of redefining java.lang.Object
- return true;
-
- boolean noProblems = true;
- int length = referenceContext.superInterfaces.length;
- ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
- int count = 0;
- nextInterface : for (int i = 0; i < length; i++) {
- ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
- if (superInterface == null) { // detected cycle
- noProblems = false;
- continue nextInterface;
- }
- referenceContext.superInterfaces[i].resolvedType = superInterface; // hold onto the problem type
- if (!superInterface.isValidBinding()) {
- problemReporter().invalidSuperinterface(
- sourceType,
- referenceContext.superInterfaces[i],
- superInterface);
- sourceType.tagBits |= HierarchyHasProblems;
- noProblems = false;
- continue nextInterface;
- }
- // Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
- for (int k = 0; k < count; k++) {
- if (interfaceBindings[k] == superInterface) {
- // should this be treated as a warning?
- problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
- continue nextInterface;
- }
- }
- if (superInterface.isClass()) {
- problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
- sourceType.tagBits |= HierarchyHasProblems;
- noProblems = false;
- continue nextInterface;
- }
-
- // only want to reach here when no errors are reported
- interfaceBindings[count++] = superInterface;
- }
- // hold onto all correctly resolved superinterfaces
- if (count > 0) {
- if (count != length)
- System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
- sourceType.superInterfaces = interfaceBindings;
- }
- return noProblems;
- }
-
- void connectTypeHierarchy() {
- SourceTypeBinding sourceType = referenceContext.binding;
- if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
- boolean noProblems = true;
- sourceType.tagBits |= BeginHierarchyCheck;
- if (sourceType.isClass())
- noProblems &= connectSuperclass();
- noProblems &= connectSuperInterfaces();
- sourceType.tagBits |= EndHierarchyCheck;
- if (noProblems && sourceType.isHierarchyInconsistent())
- problemReporter().hierarchyHasProblems(sourceType);
- }
- connectMemberTypes();
- try {
- checkForInheritedMemberTypes(sourceType);
- } catch (AbortCompilation e) {
- e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
- throw e;
- }
- }
-
- private void connectTypeHierarchyWithoutMembers() {
- // must ensure the imports are resolved
- if (parent instanceof CompilationUnitScope) {
- if (((CompilationUnitScope) parent).imports == null)
- ((CompilationUnitScope) parent).checkAndSetImports();
- } else if (parent instanceof ClassScope) {
- // ensure that the enclosing type has already been checked
- ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
- }
-
- // double check that the hierarchy search has not already begun...
- SourceTypeBinding sourceType = referenceContext.binding;
- if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
- return;
-
- boolean noProblems = true;
- sourceType.tagBits |= BeginHierarchyCheck;
- if (sourceType.isClass())
- noProblems &= connectSuperclass();
- noProblems &= connectSuperInterfaces();
- sourceType.tagBits |= EndHierarchyCheck;
- if (noProblems && sourceType.isHierarchyInconsistent())
- problemReporter().hierarchyHasProblems(sourceType);
- }
-
- // Answer whether a cycle was found between the sourceType & the superType
- private boolean detectCycle(
- SourceTypeBinding sourceType,
- ReferenceBinding superType,
- TypeReference reference) {
- if (sourceType == superType) {
- problemReporter().hierarchyCircularity(sourceType, superType, reference);
- sourceType.tagBits |= HierarchyHasProblems;
- return true;
- }
-
- if (superType.isBinaryBinding()) {
- // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
- // - a binary type... this case MUST be caught & reported here
- // - another source type... this case is reported against the other source type
- boolean hasCycle = false;
- if (superType.superclass() != null) {
- if (sourceType == superType.superclass()) {
- problemReporter().hierarchyCircularity(sourceType, superType, reference);
- sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems;
- return true;
- }
- hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
- if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
- sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
- }
- }
-
- ReferenceBinding[] itsInterfaces = superType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- for (int i = 0, length = itsInterfaces.length; i < length; i++) {
- ReferenceBinding anInterface = itsInterfaces[i];
- if (sourceType == anInterface) {
- problemReporter().hierarchyCircularity(sourceType, superType, reference);
- sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems;
- return true;
- }
- hasCycle |= detectCycle(sourceType, anInterface, reference);
- if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
- sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems;
- }
- }
- }
- return hasCycle;
- }
-
- if ((superType.tagBits & EndHierarchyCheck) == 0
- && (superType.tagBits & BeginHierarchyCheck) != 0) {
- problemReporter().hierarchyCircularity(sourceType, superType, reference);
- sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems;
- return true;
- }
- if ((superType.tagBits & BeginHierarchyCheck) == 0)
- // ensure if this is a source superclass that it has already been checked
- ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
- if ((superType.tagBits & HierarchyHasProblems) != 0)
- sourceType.tagBits |= HierarchyHasProblems;
- return false;
- }
-
- private ReferenceBinding findSupertype(TypeReference typeReference) {
- try {
- typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
- char[][] compoundName = typeReference.getTypeName();
- compilationUnitScope().recordQualifiedReference(compoundName);
- SourceTypeBinding sourceType = referenceContext.binding;
- int size = compoundName.length;
- int n = 1;
- ReferenceBinding superType;
-
- // resolve the first name of the compoundName
- if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
- superType = sourceType;
- // match against the sourceType even though nested members cannot be supertypes
- } else {
- Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
- if (typeOrPackage == null || !typeOrPackage.isValidBinding())
- return new ProblemReferenceBinding(
- compoundName[0],
- typeOrPackage == null ? NotFound : typeOrPackage.problemId());
-
- boolean checkVisibility = false;
- for (; n < size; n++) {
- if (!(typeOrPackage instanceof PackageBinding))
- break;
- PackageBinding packageBinding = (PackageBinding) typeOrPackage;
- typeOrPackage = packageBinding.getTypeOrPackage(compoundName[n]);
- if (typeOrPackage == null || !typeOrPackage.isValidBinding())
- return new ProblemReferenceBinding(
- CharOperation.subarray(compoundName, 0, n + 1),
- typeOrPackage == null ? NotFound : typeOrPackage.problemId());
- checkVisibility = true;
- }
-
- // convert to a ReferenceBinding
- if (typeOrPackage instanceof PackageBinding) // error, the compoundName is a packageName
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
- superType = (ReferenceBinding) typeOrPackage;
- compilationUnitScope().recordTypeReference(superType); // to record supertypes
-
- if (checkVisibility
- && n == size) { // if we're finished and know the final supertype then check visibility
- if (!superType.canBeSeenBy(sourceType.fPackage))
- // its a toplevel type so just check package access
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), superType, NotVisible);
- }
- }
- // at this point we know we have a type but we have to look for cycles
- while (true) {
- // must detect cycles & force connection up the hierarchy... also handle cycles with binary types.
- // must be guaranteed that the superType knows its entire hierarchy
- if (detectCycle(sourceType, superType, typeReference))
- return null; // cycle error was already reported
-
- if (n >= size)
- break;
-
- // retrieve the next member type
- char[] typeName = compoundName[n++];
- superType = findMemberType(typeName, superType);
- if (superType == null)
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
- if (!superType.isValidBinding()) {
- superType.compoundName = CharOperation.subarray(compoundName, 0, n);
- return superType;
- }
- }
- return superType;
- } catch (AbortCompilation e) {
- e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
- throw e;
- }
- }
-
- /* Answer the problem reporter to use for raising new problems.
- *
- * Note that as a side-effect, this updates the current reference context
- * (unit, type or method) in case the problem handler decides it is necessary
- * to abort.
- */
- public ProblemReporter problemReporter() {
- MethodScope outerMethodScope;
- if ((outerMethodScope = outerMostMethodScope()) == null) {
- ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
- problemReporter.referenceContext = referenceContext;
- return problemReporter;
- }
- return outerMethodScope.problemReporter();
- }
-
- /* Answer the reference type of this scope.
- * It is the nearest enclosing type of this scope.
- */
- public TypeDeclaration referenceType() {
- return referenceContext;
- }
-
- public String toString() {
- if (referenceContext != null)
- return "--- Class Scope ---\n\n" //$NON-NLS-1$
- + referenceContext.binding.toString();
- return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$
- }
-}