1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler.lookup;
 
  13 import net.sourceforge.phpdt.core.compiler.CharOperation;
 
  14 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
 
  15 import net.sourceforge.phpdt.internal.compiler.ast.Clinit;
 
  16 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
 
  17 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
 
  18 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
 
  19 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
 
  20 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
 
  21 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
 
  23 public class ClassScope extends Scope {
 
  24         public TypeDeclaration referenceContext;
 
  26         public ClassScope(Scope parent, TypeDeclaration context) {
 
  27                 super(CLASS_SCOPE, parent);
 
  28                 this.referenceContext = context;
 
  31         void buildAnonymousTypeBinding(SourceTypeBinding enclosingType,
 
  32                         ReferenceBinding supertype) {
 
  34                 LocalTypeBinding anonymousType = buildLocalType(enclosingType,
 
  35                                 enclosingType.fPackage);
 
  37                 SourceTypeBinding sourceType = referenceContext.binding;
 
  38                 if (supertype.isInterface()) {
 
  39                         sourceType.superclass = getJavaLangObject();
 
  40                         sourceType.superInterfaces = new ReferenceBinding[] { supertype };
 
  42                         sourceType.superclass = supertype;
 
  43                         sourceType.superInterfaces = TypeBinding.NoSuperInterfaces;
 
  46                 buildFieldsAndMethods();
 
  47                 anonymousType.faultInTypesForFieldsAndMethods();
 
  48                 sourceType.verifyMethods(environment().methodVerifier());
 
  51         private void buildFields() {
 
  52                 if (referenceContext.fields == null) {
 
  53                         referenceContext.binding.fields = NoFields;
 
  56                 // count the number of fields vs. initializers
 
  57                 FieldDeclaration[] fields = referenceContext.fields;
 
  58                 int size = fields.length;
 
  60                 for (int i = 0; i < size; i++)
 
  61                         if (fields[i].isField())
 
  64                 // iterate the field declarations to create the bindings, lose all
 
  66                 FieldBinding[] fieldBindings = new FieldBinding[count];
 
  67                 HashtableOfObject knownFieldNames = new HashtableOfObject(count);
 
  68                 boolean duplicate = false;
 
  70                 for (int i = 0; i < size; i++) {
 
  71                         FieldDeclaration field = fields[i];
 
  72                         if (!field.isField()) {
 
  73                                 if (referenceContext.binding.isInterface())
 
  74                                         problemReporter().interfaceCannotHaveInitializers(
 
  75                                                         referenceContext.binding, field);
 
  77                                 FieldBinding fieldBinding = new FieldBinding(field, null,
 
  78                                                 referenceContext.binding);
 
  79                                 // field's type will be resolved when needed for top level types
 
  80                                 checkAndSetModifiersForField(fieldBinding, field);
 
  82                                 if (knownFieldNames.containsKey(field.name)) {
 
  84                                         FieldBinding previousBinding = (FieldBinding) knownFieldNames
 
  86                                         if (previousBinding != null) {
 
  87                                                 for (int f = 0; f < i; f++) {
 
  88                                                         FieldDeclaration previousField = fields[f];
 
  89                                                         if (previousField.binding == previousBinding) {
 
  91                                                                                 .duplicateFieldInType(
 
  92                                                                                                 referenceContext.binding,
 
  94                                                                 previousField.binding = null;
 
  99                                         knownFieldNames.put(field.name, null); // ensure that the
 
 103                                         problemReporter().duplicateFieldInType(
 
 104                                                         referenceContext.binding, field);
 
 105                                         field.binding = null;
 
 107                                         knownFieldNames.put(field.name, fieldBinding);
 
 108                                         // remember that we have seen a field with this name
 
 109                                         if (fieldBinding != null)
 
 110                                                 fieldBindings[count++] = fieldBinding;
 
 114                 // remove duplicate fields
 
 116                         FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames
 
 118                         // we know we'll be removing at least 1 duplicate name
 
 121                         for (int i = 0; i < size; i++) {
 
 122                                 FieldBinding fieldBinding = fieldBindings[i];
 
 123                                 if (knownFieldNames.get(fieldBinding.name) != null)
 
 124                                         newFieldBindings[count++] = fieldBinding;
 
 126                         fieldBindings = newFieldBindings;
 
 129                 if (count != fieldBindings.length)
 
 130                         System.arraycopy(fieldBindings, 0,
 
 131                                         fieldBindings = new FieldBinding[count], 0, count);
 
 132                 for (int i = 0; i < count; i++)
 
 133                         fieldBindings[i].id = i;
 
 134                 referenceContext.binding.fields = fieldBindings;
 
 137         void buildFieldsAndMethods() {
 
 141                 SourceTypeBinding sourceType = referenceContext.binding;
 
 142                 if (sourceType.isMemberType() && !sourceType.isLocalType())
 
 143                         ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
 
 145                 ReferenceBinding[] memberTypes = sourceType.memberTypes;
 
 146                 for (int i = 0, length = memberTypes.length; i < length; i++)
 
 147                         ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
 
 150         private LocalTypeBinding buildLocalType(SourceTypeBinding enclosingType,
 
 151                         PackageBinding packageBinding) {
 
 152                 referenceContext.scope = this;
 
 153                 referenceContext.staticInitializerScope = new MethodScope(this,
 
 154                                 referenceContext, true);
 
 155                 referenceContext.initializerScope = new MethodScope(this,
 
 156                                 referenceContext, false);
 
 158                 // build the binding or the local type
 
 159                 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType);
 
 160                 referenceContext.binding = localType;
 
 161                 checkAndSetModifiers();
 
 163                 // Look at member types
 
 164                 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
 
 165                 if (referenceContext.memberTypes != null) {
 
 166                         int size = referenceContext.memberTypes.length;
 
 167                         memberTypeBindings = new ReferenceBinding[size];
 
 169                         nextMember: for (int i = 0; i < size; i++) {
 
 170                                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
 
 171                                 if (memberContext.isInterface()) {
 
 172                                         problemReporter().nestedClassCannotDeclareInterface(
 
 176                                 ReferenceBinding type = localType;
 
 177                                 // check that the member does not conflict with an enclosing
 
 180                                         if (CharOperation.equals(type.sourceName,
 
 181                                                         memberContext.name)) {
 
 182                                                 problemReporter().hidingEnclosingType(memberContext);
 
 185                                         type = type.enclosingType();
 
 186                                 } while (type != null);
 
 187                                 // check the member type does not conflict with another sibling
 
 189                                 for (int j = 0; j < i; j++) {
 
 190                                         if (CharOperation.equals(
 
 191                                                         referenceContext.memberTypes[j].name,
 
 192                                                         memberContext.name)) {
 
 193                                                 problemReporter().duplicateNestedType(memberContext);
 
 198                                 ClassScope memberScope = new ClassScope(this,
 
 199                                                 referenceContext.memberTypes[i]);
 
 200                                 LocalTypeBinding memberBinding = memberScope.buildLocalType(
 
 201                                                 localType, packageBinding);
 
 202                                 memberBinding.setAsMemberType();
 
 203                                 memberTypeBindings[count++] = memberBinding;
 
 206                                 System.arraycopy(memberTypeBindings, 0,
 
 207                                                 memberTypeBindings = new ReferenceBinding[count], 0,
 
 210                 localType.memberTypes = memberTypeBindings;
 
 214         void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
 
 216                 LocalTypeBinding localType = buildLocalType(enclosingType,
 
 217                                 enclosingType.fPackage);
 
 218                 connectTypeHierarchy();
 
 219                 buildFieldsAndMethods();
 
 220                 localType.faultInTypesForFieldsAndMethods();
 
 222                 referenceContext.binding.verifyMethods(environment().methodVerifier());
 
 225         private void buildMethods() {
 
 226                 if (referenceContext.methods == null) {
 
 227                         referenceContext.binding.methods = NoMethods;
 
 231                 // iterate the method declarations to create the bindings
 
 232                 AbstractMethodDeclaration[] methods = referenceContext.methods;
 
 233                 int size = methods.length;
 
 234                 int clinitIndex = -1;
 
 235                 for (int i = 0; i < size; i++) {
 
 236                         if (methods[i] instanceof Clinit) {
 
 241                 MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size
 
 245                 for (int i = 0; i < size; i++) {
 
 246                         if (i != clinitIndex) {
 
 247                                 MethodScope scope = new MethodScope(this, methods[i], false);
 
 248                                 MethodBinding methodBinding = scope.createMethod(methods[i]);
 
 249                                 if (methodBinding != null) // is null if binding could not be
 
 251                                         methodBindings[count++] = methodBinding;
 
 254                 if (count != methodBindings.length)
 
 255                         System.arraycopy(methodBindings, 0,
 
 256                                         methodBindings = new MethodBinding[count], 0, count);
 
 258                 referenceContext.binding.methods = methodBindings;
 
 259                 referenceContext.binding.modifiers |= AccUnresolved; // until
 
 264         SourceTypeBinding buildType(SourceTypeBinding enclosingType,
 
 265                         PackageBinding packageBinding) {
 
 266                 // provide the typeDeclaration with needed scopes
 
 267                 referenceContext.scope = this;
 
 268                 referenceContext.staticInitializerScope = new MethodScope(this,
 
 269                                 referenceContext, true);
 
 270                 referenceContext.initializerScope = new MethodScope(this,
 
 271                                 referenceContext, false);
 
 273                 if (enclosingType == null) {
 
 274                         char[][] className = CharOperation.arrayConcat(
 
 275                                         packageBinding.compoundName, referenceContext.name);
 
 276                         referenceContext.binding = new SourceTypeBinding(className,
 
 277                                         packageBinding, this);
 
 279                         char[][] className = CharOperation
 
 280                                         .deepCopy(enclosingType.compoundName);
 
 281                         className[className.length - 1] = CharOperation
 
 282                                         .concat(className[className.length - 1],
 
 283                                                         referenceContext.name, '$');
 
 284                         referenceContext.binding = new MemberTypeBinding(className, this,
 
 288                 SourceTypeBinding sourceType = referenceContext.binding;
 
 289                 sourceType.fPackage.addType(sourceType);
 
 290                 checkAndSetModifiers();
 
 292                 // Look at member types
 
 293                 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
 
 294                 if (referenceContext.memberTypes != null) {
 
 295                         int size = referenceContext.memberTypes.length;
 
 296                         memberTypeBindings = new ReferenceBinding[size];
 
 298                         nextMember: for (int i = 0; i < size; i++) {
 
 299                                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
 
 300                                 if (memberContext.isInterface() && sourceType.isNestedType()
 
 301                                                 && sourceType.isClass() && !sourceType.isStatic()) {
 
 302                                         problemReporter().nestedClassCannotDeclareInterface(
 
 306                                 ReferenceBinding type = sourceType;
 
 307                                 // check that the member does not conflict with an enclosing
 
 310                                         if (CharOperation.equals(type.sourceName,
 
 311                                                         memberContext.name)) {
 
 312                                                 problemReporter().hidingEnclosingType(memberContext);
 
 315                                         type = type.enclosingType();
 
 316                                 } while (type != null);
 
 317                                 // check that the member type does not conflict with another
 
 318                                 // sibling member type
 
 319                                 for (int j = 0; j < i; j++) {
 
 320                                         if (CharOperation.equals(
 
 321                                                         referenceContext.memberTypes[j].name,
 
 322                                                         memberContext.name)) {
 
 323                                                 problemReporter().duplicateNestedType(memberContext);
 
 328                                 ClassScope memberScope = new ClassScope(this, memberContext);
 
 329                                 memberTypeBindings[count++] = memberScope.buildType(sourceType,
 
 333                                 System.arraycopy(memberTypeBindings, 0,
 
 334                                                 memberTypeBindings = new ReferenceBinding[count], 0,
 
 337                 sourceType.memberTypes = memberTypeBindings;
 
 341         private void checkAndSetModifiers() {
 
 342                 SourceTypeBinding sourceType = referenceContext.binding;
 
 343                 int modifiers = sourceType.modifiers;
 
 344                 if ((modifiers & AccAlternateModifierProblem) != 0)
 
 345                         problemReporter().duplicateModifierForType(sourceType);
 
 347                 ReferenceBinding enclosingType = sourceType.enclosingType();
 
 348                 boolean isMemberType = sourceType.isMemberType();
 
 351                         // checks for member types before local types to catch local members
 
 352                         // if (enclosingType.isStrictfp())
 
 353                         // modifiers |= AccStrictfp;
 
 354                         if (enclosingType.isDeprecated())
 
 355                                 modifiers |= AccDeprecatedImplicitly;
 
 356                         if (enclosingType.isInterface())
 
 357                                 modifiers |= AccPublic;
 
 358                 } else if (sourceType.isLocalType()) {
 
 359                         if (sourceType.isAnonymousType())
 
 360                                 modifiers |= AccFinal;
 
 361                         ReferenceContext refContext = methodScope().referenceContext;
 
 362                         if (refContext instanceof TypeDeclaration) {
 
 363                                 ReferenceBinding type = ((TypeDeclaration) refContext).binding;
 
 364                                 // if (type.isStrictfp())
 
 365                                 // modifiers |= AccStrictfp;
 
 366                                 if (type.isDeprecated())
 
 367                                         modifiers |= AccDeprecatedImplicitly;
 
 369                                 MethodBinding method = ((AbstractMethodDeclaration) refContext).binding;
 
 370                                 if (method != null) {
 
 371                                         // if (method.isStrictfp())
 
 372                                         // modifiers |= AccStrictfp;
 
 373                                         if (method.isDeprecated())
 
 374                                                 modifiers |= AccDeprecatedImplicitly;
 
 378                 // after this point, tests on the 16 bits reserved.
 
 379                 int realModifiers = modifiers & AccJustFlag;
 
 381                 if ((realModifiers & AccInterface) != 0) {
 
 382                         // detect abnormal cases for interfaces
 
 384                                 int unexpectedModifiers = ~(AccPublic | AccPrivate
 
 385                                                 | AccProtected | AccStatic | AccAbstract | AccInterface);// |
 
 387                                 if ((realModifiers & unexpectedModifiers) != 0)
 
 388                                         problemReporter().illegalModifierForMemberInterface(
 
 391                                  * } else if (sourceType.isLocalType()) { //interfaces cannot be
 
 392                                  * defined inside a method int unexpectedModifiers =
 
 393                                  * ~(AccAbstract | AccInterface | AccStrictfp); if
 
 394                                  * ((realModifiers & unexpectedModifiers) != 0)
 
 395                                  * problemReporter().illegalModifierForLocalInterface(sourceType);
 
 398                                 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface);// |
 
 400                                 if ((realModifiers & unexpectedModifiers) != 0)
 
 401                                         problemReporter().illegalModifierForInterface(sourceType);
 
 403                         modifiers |= AccAbstract;
 
 405                         // detect abnormal cases for types
 
 406                         if (isMemberType) { // includes member types defined inside local
 
 408                                 int unexpectedModifiers = ~(AccPublic | AccPrivate
 
 409                                                 | AccProtected | AccStatic | AccAbstract | AccFinal);// |
 
 411                                 if ((realModifiers & unexpectedModifiers) != 0)
 
 412                                         problemReporter().illegalModifierForMemberClass(sourceType);
 
 413                         } else if (sourceType.isLocalType()) {
 
 414                                 int unexpectedModifiers = ~(AccAbstract | AccFinal);// |
 
 416                                 if ((realModifiers & unexpectedModifiers) != 0)
 
 417                                         problemReporter().illegalModifierForLocalClass(sourceType);
 
 419                                 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal);// |
 
 421                                 if ((realModifiers & unexpectedModifiers) != 0)
 
 422                                         problemReporter().illegalModifierForClass(sourceType);
 
 425                         // check that Final and Abstract are not set together
 
 426                         if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
 
 428                                                 .illegalModifierCombinationFinalAbstractForClass(
 
 433                         // test visibility modifiers inconsistency, isolate the accessors
 
 435                         if (enclosingType.isInterface()) {
 
 436                                 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
 
 438                                                         .illegalVisibilityModifierForInterfaceMemberType(
 
 441                                         // need to keep the less restrictive
 
 442                                         if ((realModifiers & AccProtected) != 0)
 
 443                                                 modifiers ^= AccProtected;
 
 444                                         if ((realModifiers & AccPrivate) != 0)
 
 445                                                 modifiers ^= AccPrivate;
 
 448                                 int accessorBits = realModifiers
 
 449                                                 & (AccPublic | AccProtected | AccPrivate);
 
 450                                 if ((accessorBits & (accessorBits - 1)) > 1) {
 
 452                                                         .illegalVisibilityModifierCombinationForMemberType(
 
 455                                         // need to keep the less restrictive
 
 456                                         if ((accessorBits & AccPublic) != 0) {
 
 457                                                 if ((accessorBits & AccProtected) != 0)
 
 458                                                         modifiers ^= AccProtected;
 
 459                                                 if ((accessorBits & AccPrivate) != 0)
 
 460                                                         modifiers ^= AccPrivate;
 
 462                                         if ((accessorBits & AccProtected) != 0)
 
 463                                                 if ((accessorBits & AccPrivate) != 0)
 
 464                                                         modifiers ^= AccPrivate;
 
 468                         // static modifier test
 
 469                         if ((realModifiers & AccStatic) == 0) {
 
 470                                 if (enclosingType.isInterface())
 
 471                                         modifiers |= AccStatic;
 
 473                                 if (!enclosingType.isStatic())
 
 474                                         // error the enclosing type of a static field must be static
 
 475                                         // or a top-level type
 
 476                                         problemReporter().illegalStaticModifierForMemberType(
 
 481                 sourceType.modifiers = modifiers;
 
 485          * This method checks the modifiers of a field.
 
 487          * 9.3 & 8.3 Need to integrate the check for the final modifiers for nested
 
 490          * Note : A scope is accessible by : fieldBinding.declaringClass.scope
 
 492         private void checkAndSetModifiersForField(FieldBinding fieldBinding,
 
 493                         FieldDeclaration fieldDecl) {
 
 494                 int modifiers = fieldBinding.modifiers;
 
 495                 if ((modifiers & AccAlternateModifierProblem) != 0)
 
 496                         problemReporter().duplicateModifierForField(
 
 497                                         fieldBinding.declaringClass, fieldDecl);
 
 499                 if (fieldBinding.declaringClass.isInterface()) {
 
 500                         int expectedValue = AccPublic | AccStatic | AccFinal;
 
 502                         modifiers |= expectedValue;
 
 504                         // and then check that they are the only ones
 
 505                         if ((modifiers & AccJustFlag) != expectedValue)
 
 506                                 problemReporter().illegalModifierForInterfaceField(
 
 507                                                 fieldBinding.declaringClass, fieldDecl);
 
 508                         fieldBinding.modifiers = modifiers;
 
 512                 // after this point, tests on the 16 bits reserved.
 
 513                 int realModifiers = modifiers & AccJustFlag;
 
 514                 int unexpectedModifiers = ~(AccPublic | AccPrivate | AccProtected
 
 515                                 | AccFinal | AccStatic);// | AccTransient | AccVolatile);
 
 516                 if ((realModifiers & unexpectedModifiers) != 0)
 
 517                         problemReporter().illegalModifierForField(
 
 518                                         fieldBinding.declaringClass, fieldDecl);
 
 520                 int accessorBits = realModifiers
 
 521                                 & (AccPublic | AccProtected | AccPrivate);
 
 522                 if ((accessorBits & (accessorBits - 1)) > 1) {
 
 523                         problemReporter().illegalVisibilityModifierCombinationForField(
 
 524                                         fieldBinding.declaringClass, fieldDecl);
 
 526                         // need to keep the less restrictive
 
 527                         if ((accessorBits & AccPublic) != 0) {
 
 528                                 if ((accessorBits & AccProtected) != 0)
 
 529                                         modifiers ^= AccProtected;
 
 530                                 if ((accessorBits & AccPrivate) != 0)
 
 531                                         modifiers ^= AccPrivate;
 
 533                         if ((accessorBits & AccProtected) != 0)
 
 534                                 if ((accessorBits & AccPrivate) != 0)
 
 535                                         modifiers ^= AccPrivate;
 
 538                 // if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal |
 
 540                 // problemReporter().illegalModifierCombinationFinalVolatileForField(
 
 541                 // fieldBinding.declaringClass,
 
 544                 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
 
 545                         modifiers |= AccBlankFinal;
 
 547                 fieldBinding.modifiers = modifiers;
 
 550         private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
 
 551                 // search up the hierarchy of the sourceType to see if any superType
 
 552                 // defines a member type
 
 553                 // when no member types are defined, tag the sourceType & each superType
 
 554                 // with the HasNoMemberTypes bit
 
 555                 ReferenceBinding currentType = sourceType;
 
 556                 ReferenceBinding[][] interfacesToVisit = null;
 
 557                 int lastPosition = -1;
 
 559                         if ((currentType.tagBits & HasNoMemberTypes) != 0)
 
 560                                 break; // already know it has no inherited member types, can
 
 562                         if (currentType.memberTypes() != NoMemberTypes)
 
 563                                 return; // has member types
 
 564                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
 
 565                         if (itsInterfaces != NoSuperInterfaces) {
 
 566                                 if (interfacesToVisit == null)
 
 567                                         interfacesToVisit = new ReferenceBinding[5][];
 
 568                                 if (++lastPosition == interfacesToVisit.length)
 
 573                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
 
 575                                 interfacesToVisit[lastPosition] = itsInterfaces;
 
 577                 } while ((currentType = currentType.superclass()) != null);
 
 579                 boolean hasMembers = false;
 
 580                 if (interfacesToVisit != null) {
 
 581                         done: for (int i = 0; i <= lastPosition; i++) {
 
 582                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
 
 583                                 for (int j = 0, length = interfaces.length; j < length; j++) {
 
 584                                         ReferenceBinding anInterface = interfaces[j];
 
 585                                         if ((anInterface.tagBits & InterfaceVisited) == 0) { // if
 
 592                                                 anInterface.tagBits |= InterfaceVisited;
 
 593                                                 if ((anInterface.tagBits & HasNoMemberTypes) != 0)
 
 594                                                         continue; // already know it has no inherited
 
 596                                                 if (anInterface.memberTypes() != NoMemberTypes) {
 
 601                                                 ReferenceBinding[] itsInterfaces = anInterface
 
 603                                                 if (itsInterfaces != NoSuperInterfaces) {
 
 604                                                         if (++lastPosition == interfacesToVisit.length)
 
 609                                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
 
 611                                                         interfacesToVisit[lastPosition] = itsInterfaces;
 
 617                         for (int i = 0; i <= lastPosition; i++) {
 
 618                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
 
 619                                 for (int j = 0, length = interfaces.length; j < length; j++) {
 
 620                                         interfaces[j].tagBits &= ~InterfaceVisited;
 
 622                                                 interfaces[j].tagBits |= HasNoMemberTypes;
 
 628                         currentType = sourceType;
 
 630                                 currentType.tagBits |= HasNoMemberTypes;
 
 631                         } while ((currentType = currentType.superclass()) != null);
 
 635         private void connectMemberTypes() {
 
 636                 SourceTypeBinding sourceType = referenceContext.binding;
 
 637                 if (sourceType.memberTypes != NoMemberTypes)
 
 638                         for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
 
 639                                 ((SourceTypeBinding) sourceType.memberTypes[i]).scope
 
 640                                                 .connectTypeHierarchy();
 
 644          * Our current belief based on available JCK tests is: inherited member
 
 645          * types are visible as a potential superclass. inherited interfaces are not
 
 646          * visible when defining a superinterface.
 
 648          * Error recovery story: ensure the superclass is set to java.lang.Object if
 
 649          * a problem is detected resolving the superclass.
 
 651          * Answer false if an error was reported against the sourceType.
 
 653         private boolean connectSuperclass() {
 
 654                 SourceTypeBinding sourceType = referenceContext.binding;
 
 655                 if (isJavaLangObject(sourceType)) { // handle the case of redefining
 
 656                                                                                         // java.lang.Object up front
 
 657                         sourceType.superclass = null;
 
 658                         sourceType.superInterfaces = NoSuperInterfaces;
 
 659                         if (referenceContext.superclass != null
 
 660                                         || referenceContext.superInterfaces != null)
 
 661                                 problemReporter().objectCannotHaveSuperTypes(sourceType);
 
 662                         return true; // do not propagate Object's hierarchy problems down
 
 665                 if (referenceContext.superclass == null) {
 
 666                         sourceType.superclass = getJavaLangObject();
 
 667                         return !detectCycle(sourceType, sourceType.superclass, null);
 
 669                 ReferenceBinding superclass = findSupertype(referenceContext.superclass);
 
 670                 if (superclass != null) { // is null if a cycle was detected cycle
 
 671                         if (!superclass.isValidBinding()) {
 
 672                                 problemReporter().invalidSuperclass(sourceType,
 
 673                                                 referenceContext.superclass, superclass);
 
 674                         } else if (superclass.isInterface()) {
 
 675                                 problemReporter().superclassMustBeAClass(sourceType,
 
 676                                                 referenceContext.superclass, superclass);
 
 677                         } else if (superclass.isFinal()) {
 
 678                                 problemReporter().classExtendFinalClass(sourceType,
 
 679                                                 referenceContext.superclass, superclass);
 
 681                                 // only want to reach here when no errors are reported
 
 682                                 referenceContext.superclass.resolvedType = superclass;
 
 683                                 sourceType.superclass = superclass;
 
 687                 sourceType.tagBits |= HierarchyHasProblems;
 
 688                 sourceType.superclass = getJavaLangObject();
 
 689                 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
 
 690                         detectCycle(sourceType, sourceType.superclass, null);
 
 691                 return false; // reported some error against the source type
 
 695          * Our current belief based on available JCK 1.3 tests is: inherited member
 
 696          * types are visible as a potential superclass. inherited interfaces are
 
 697          * visible when defining a superinterface.
 
 699          * Error recovery story: ensure the superinterfaces contain only valid
 
 700          * visible interfaces.
 
 702          * Answer false if an error was reported against the sourceType.
 
 704         private boolean connectSuperInterfaces() {
 
 705                 SourceTypeBinding sourceType = referenceContext.binding;
 
 706                 sourceType.superInterfaces = NoSuperInterfaces;
 
 707                 if (referenceContext.superInterfaces == null)
 
 709                 if (isJavaLangObject(sourceType)) // already handled the case of
 
 710                                                                                         // redefining java.lang.Object
 
 713                 boolean noProblems = true;
 
 714                 int length = referenceContext.superInterfaces.length;
 
 715                 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
 
 717                 nextInterface: for (int i = 0; i < length; i++) {
 
 718                         ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
 
 719                         if (superInterface == null) { // detected cycle
 
 721                                 continue nextInterface;
 
 723                         if (!superInterface.isValidBinding()) {
 
 724                                 problemReporter().invalidSuperinterface(sourceType,
 
 725                                                 referenceContext.superInterfaces[i], superInterface);
 
 726                                 sourceType.tagBits |= HierarchyHasProblems;
 
 728                                 continue nextInterface;
 
 730                         // Check for a duplicate interface once the name is resolved,
 
 731                         // otherwise we may be confused (ie : a.b.I and c.d.I)
 
 732                         for (int k = 0; k < count; k++) {
 
 733                                 if (interfaceBindings[k] == superInterface) {
 
 734                                         // should this be treated as a warning?
 
 735                                         problemReporter().duplicateSuperinterface(sourceType,
 
 736                                                         referenceContext, superInterface);
 
 737                                         continue nextInterface;
 
 740                         if (superInterface.isClass()) {
 
 741                                 problemReporter().superinterfaceMustBeAnInterface(sourceType,
 
 742                                                 referenceContext, superInterface);
 
 743                                 sourceType.tagBits |= HierarchyHasProblems;
 
 745                                 continue nextInterface;
 
 748                         referenceContext.superInterfaces[i].resolvedType = superInterface;
 
 749                         // only want to reach here when no errors are reported
 
 750                         interfaceBindings[count++] = superInterface;
 
 752                 // hold onto all correctly resolved superinterfaces
 
 755                                 System.arraycopy(interfaceBindings, 0,
 
 756                                                 interfaceBindings = new ReferenceBinding[count], 0,
 
 758                         sourceType.superInterfaces = interfaceBindings;
 
 763         void connectTypeHierarchy() {
 
 764                 SourceTypeBinding sourceType = referenceContext.binding;
 
 765                 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
 
 766                         boolean noProblems = true;
 
 767                         sourceType.tagBits |= BeginHierarchyCheck;
 
 768                         if (sourceType.isClass())
 
 769                                 noProblems &= connectSuperclass();
 
 770                         noProblems &= connectSuperInterfaces();
 
 771                         sourceType.tagBits |= EndHierarchyCheck;
 
 772                         if (noProblems && sourceType.isHierarchyInconsistent())
 
 773                                 problemReporter().hierarchyHasProblems(sourceType);
 
 775                 connectMemberTypes();
 
 776                 checkForInheritedMemberTypes(sourceType);
 
 779         private void connectTypeHierarchyWithoutMembers() {
 
 780                 // must ensure the imports are resolved
 
 781                 if (parent instanceof CompilationUnitScope) {
 
 782                         // if (((CompilationUnitScope) parent).imports == null)
 
 783                         // ((CompilationUnitScope) parent).checkAndSetImports();
 
 784                 } else if (parent instanceof ClassScope) {
 
 785                         // ensure that the enclosing type has already been checked
 
 786                         ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
 
 789                 // double check that the hierarchy search has not already begun...
 
 790                 SourceTypeBinding sourceType = referenceContext.binding;
 
 791                 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
 
 794                 boolean noProblems = true;
 
 795                 sourceType.tagBits |= BeginHierarchyCheck;
 
 796                 if (sourceType.isClass())
 
 797                         noProblems &= connectSuperclass();
 
 798                 noProblems &= connectSuperInterfaces();
 
 799                 sourceType.tagBits |= EndHierarchyCheck;
 
 800                 if (noProblems && sourceType.isHierarchyInconsistent())
 
 801                         problemReporter().hierarchyHasProblems(sourceType);
 
 804         // Answer whether a cycle was found between the sourceType & the superType
 
 805         private boolean detectCycle(SourceTypeBinding sourceType,
 
 806                         ReferenceBinding superType, TypeReference reference) {
 
 807                 if (sourceType == superType) {
 
 808                         problemReporter().hierarchyCircularity(sourceType, superType,
 
 810                         sourceType.tagBits |= HierarchyHasProblems;
 
 814                 if (superType.isBinaryBinding()) {
 
 815                         // force its superclass & superinterfaces to be found... 2
 
 816                         // possibilities exist - the source type is included in the
 
 818                         // - a binary type... this case MUST be caught & reported here
 
 819                         // - another source type... this case is reported against the other
 
 821                         boolean hasCycle = false;
 
 822                         if (superType.superclass() != null) {
 
 823                                 if (sourceType == superType.superclass()) {
 
 824                                         problemReporter().hierarchyCircularity(sourceType,
 
 825                                                         superType, reference);
 
 826                                         sourceType.tagBits |= HierarchyHasProblems;
 
 827                                         superType.tagBits |= HierarchyHasProblems;
 
 830                                 hasCycle |= detectCycle(sourceType, superType.superclass(),
 
 832                                 if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
 
 833                                         sourceType.tagBits |= HierarchyHasProblems;
 
 834                                         superType.tagBits |= HierarchyHasProblems; // propagate
 
 840                         ReferenceBinding[] itsInterfaces = superType.superInterfaces();
 
 841                         if (itsInterfaces != NoSuperInterfaces) {
 
 842                                 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
 
 843                                         ReferenceBinding anInterface = itsInterfaces[i];
 
 844                                         if (sourceType == anInterface) {
 
 845                                                 problemReporter().hierarchyCircularity(sourceType,
 
 846                                                                 superType, reference);
 
 847                                                 sourceType.tagBits |= HierarchyHasProblems;
 
 848                                                 superType.tagBits |= HierarchyHasProblems;
 
 851                                         hasCycle |= detectCycle(sourceType, anInterface, reference);
 
 852                                         if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
 
 853                                                 sourceType.tagBits |= HierarchyHasProblems;
 
 854                                                 superType.tagBits |= HierarchyHasProblems;
 
 861                 if ((superType.tagBits & EndHierarchyCheck) == 0
 
 862                                 && (superType.tagBits & BeginHierarchyCheck) != 0) {
 
 863                         problemReporter().hierarchyCircularity(sourceType, superType,
 
 865                         sourceType.tagBits |= HierarchyHasProblems;
 
 866                         superType.tagBits |= HierarchyHasProblems;
 
 869                 if ((superType.tagBits & BeginHierarchyCheck) == 0)
 
 870                         // ensure if this is a source superclass that it has already been
 
 872                         ((SourceTypeBinding) superType).scope
 
 873                                         .connectTypeHierarchyWithoutMembers();
 
 874                 if ((superType.tagBits & HierarchyHasProblems) != 0)
 
 875                         sourceType.tagBits |= HierarchyHasProblems;
 
 879         private ReferenceBinding findSupertype(TypeReference typeReference) {
 
 880                 typeReference.aboutToResolve(this); // allows us to trap completion &
 
 882                 char[][] compoundName = typeReference.getTypeName();
 
 883                 compilationUnitScope().recordQualifiedReference(compoundName);
 
 884                 SourceTypeBinding sourceType = referenceContext.binding;
 
 885                 int size = compoundName.length;
 
 887                 ReferenceBinding superType;
 
 889                 // resolve the first name of the compoundName
 
 890                 if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
 
 891                         superType = sourceType;
 
 892                         // match against the sourceType even though nested members cannot be
 
 895                         Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0],
 
 897                         if (typeOrPackage == null || !typeOrPackage.isValidBinding())
 
 898                                 return new ProblemReferenceBinding(compoundName[0],
 
 899                                                 typeOrPackage == null ? NotFound : typeOrPackage
 
 902                         boolean checkVisibility = false;
 
 903                         for (; n < size; n++) {
 
 904                                 if (!(typeOrPackage instanceof PackageBinding))
 
 906                                 PackageBinding packageBinding = (PackageBinding) typeOrPackage;
 
 907                                 typeOrPackage = packageBinding
 
 908                                                 .getTypeOrPackage(compoundName[n]);
 
 909                                 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
 
 910                                         return new ProblemReferenceBinding(CharOperation.subarray(
 
 911                                                         compoundName, 0, n + 1),
 
 912                                                         typeOrPackage == null ? NotFound : typeOrPackage
 
 914                                 checkVisibility = true;
 
 917                         // convert to a ReferenceBinding
 
 918                         if (typeOrPackage instanceof PackageBinding) // error, the
 
 921                                 return new ProblemReferenceBinding(CharOperation.subarray(
 
 922                                                 compoundName, 0, n), NotFound);
 
 923                         superType = (ReferenceBinding) typeOrPackage;
 
 924                         compilationUnitScope().recordTypeReference(superType); // to record
 
 927                         if (checkVisibility && n == size) { // if we're finished and know
 
 928                                                                                                 // the final supertype then
 
 930                                 if (!superType.canBeSeenBy(sourceType.fPackage))
 
 931                                         // its a toplevel type so just check package access
 
 932                                         return new ProblemReferenceBinding(CharOperation.subarray(
 
 933                                                         compoundName, 0, n), superType, NotVisible);
 
 936                 // at this point we know we have a type but we have to look for cycles
 
 938                         // must detect cycles & force connection up the hierarchy... also
 
 939                         // handle cycles with binary types.
 
 940                         // must be guaranteed that the superType knows its entire hierarchy
 
 941                         if (detectCycle(sourceType, superType, typeReference))
 
 942                                 return null; // cycle error was already reported
 
 947                         // retrieve the next member type
 
 948                         char[] typeName = compoundName[n++];
 
 949                         superType = findMemberType(typeName, superType);
 
 950                         if (superType == null)
 
 951                                 return new ProblemReferenceBinding(CharOperation.subarray(
 
 952                                                 compoundName, 0, n), NotFound);
 
 953                         if (!superType.isValidBinding()) {
 
 954                                 superType.compoundName = CharOperation.subarray(compoundName,
 
 963          * Answer the problem reporter to use for raising new problems.
 
 965          * Note that as a side-effect, this updates the current reference context
 
 966          * (unit, type or method) in case the problem handler decides it is
 
 967          * necessary to abort.
 
 969         public ProblemReporter problemReporter() {
 
 970                 MethodScope outerMethodScope;
 
 971                 if ((outerMethodScope = outerMostMethodScope()) == null) {
 
 972                         ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
 
 973                         problemReporter.referenceContext = referenceContext;
 
 974                         return problemReporter;
 
 976                         return outerMethodScope.problemReporter();
 
 981          * Answer the reference type of this scope. It is the nearest enclosing type
 
 984         public TypeDeclaration referenceType() {
 
 985                 return referenceContext;
 
 988         public String toString() {
 
 989                 if (referenceContext != null)
 
 990                         return "--- Class Scope ---\n\n" //$NON-NLS-1$
 
 991                                         + referenceContext.binding.toString();
 
 993                         return "--- Class Scope ---\n\n Binding not initialized"; //$NON-NLS-1$