added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / ClassScope.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
15 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
16 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
19 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
20 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
21 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
23 import org.eclipse.jdt.internal.compiler.env.IGenericType;
24 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
25 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
26 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
27
28 public class ClassScope extends Scope {
29         public TypeDeclaration referenceContext;
30         private TypeReference superTypeReference;
31
32         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'};
33
34         public ClassScope(Scope parent, TypeDeclaration context) {
35                 super(CLASS_SCOPE, parent);
36                 this.referenceContext = context;
37         }
38         
39         void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
40                 
41                 LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
42
43                 SourceTypeBinding sourceType = referenceContext.binding;
44                 if (supertype.isInterface()) {
45                         sourceType.superclass = getJavaLangObject();
46                         sourceType.superInterfaces = new ReferenceBinding[] { supertype };
47                 } else {
48                         sourceType.superclass = supertype;
49                         sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
50                 }
51                 connectMemberTypes();
52                 buildFieldsAndMethods();
53                 anonymousType.faultInTypesForFieldsAndMethods();
54                 sourceType.verifyMethods(environment().methodVerifier());
55         }
56         
57         private void buildFields() {
58                 boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
59                 if (referenceContext.fields == null) {
60                         if (hierarchyIsInconsistent) { // 72468
61                                 referenceContext.binding.fields = new FieldBinding[1];
62                                 referenceContext.binding.fields[0] =
63                                         new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
64                         } else {
65                                 referenceContext.binding.fields = NoFields;
66                         }
67                         return;
68                 }
69                 // count the number of fields vs. initializers
70                 FieldDeclaration[] fields = referenceContext.fields;
71                 int size = fields.length;
72                 int count = 0;
73                 for (int i = 0; i < size; i++) {
74                         switch (fields[i].getKind()) {
75                                 case AbstractVariableDeclaration.FIELD:
76                                 case AbstractVariableDeclaration.ENUM_CONSTANT:
77                                         count++;
78                         }
79                 }
80
81                 if (hierarchyIsInconsistent)
82                         count++;
83                 // iterate the field declarations to create the bindings, lose all duplicates
84                 FieldBinding[] fieldBindings = new FieldBinding[count];
85                 HashtableOfObject knownFieldNames = new HashtableOfObject(count);
86                 boolean duplicate = false;
87                 count = 0;
88                 for (int i = 0; i < size; i++) {
89                         FieldDeclaration field = fields[i];
90                         if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
91                                 if (referenceContext.binding.isInterface())
92                                         problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
93                         } else {
94                                 FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
95                                 // field's type will be resolved when needed for top level types
96                                 checkAndSetModifiersForField(fieldBinding, field);
97
98                                 if (knownFieldNames.containsKey(field.name)) {
99                                         duplicate = true;
100                                         FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
101                                         if (previousBinding != null) {
102                                                 for (int f = 0; f < i; f++) {
103                                                         FieldDeclaration previousField = fields[f];
104                                                         if (previousField.binding == previousBinding) {
105                                                                 problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
106                                                                 previousField.binding = null;
107                                                                 break;
108                                                         }
109                                                 }
110                                         }
111                                         knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
112                                         problemReporter().duplicateFieldInType(referenceContext.binding, field);
113                                         field.binding = null;
114                                 } else {
115                                         knownFieldNames.put(field.name, fieldBinding);
116                                         // remember that we have seen a field with this name
117                                         if (fieldBinding != null)
118                                                 fieldBindings[count++] = fieldBinding;
119                                 }
120                         }
121                 }
122                 // remove duplicate fields
123                 if (duplicate) {
124                         FieldBinding[] newFieldBindings = new FieldBinding[fieldBindings.length];
125                         // we know we'll be removing at least 1 duplicate name
126                         size = count;
127                         count = 0;
128                         for (int i = 0; i < size; i++) {
129                                 FieldBinding fieldBinding = fieldBindings[i];
130                                 if (knownFieldNames.get(fieldBinding.name) != null)
131                                         newFieldBindings[count++] = fieldBinding;
132                         }
133                         fieldBindings = newFieldBindings;
134                 }
135                 if (hierarchyIsInconsistent)
136                         fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
137
138                 if (count != fieldBindings.length)
139                         System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
140                 for (int i = 0; i < count; i++)
141                         fieldBindings[i].id = i;
142                 referenceContext.binding.fields = fieldBindings;
143         }
144         
145         void buildFieldsAndMethods() {
146                 buildFields();
147                 buildMethods();
148
149                 SourceTypeBinding sourceType = referenceContext.binding;
150                 if (sourceType.isMemberType() && !sourceType.isLocalType())
151                          ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
152
153                 ReferenceBinding[] memberTypes = sourceType.memberTypes;
154                 for (int i = 0, length = memberTypes.length; i < length; i++)
155                          ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
156         }
157         
158         private LocalTypeBinding buildLocalType(
159                 SourceTypeBinding enclosingType,
160                 PackageBinding packageBinding) {
161             
162                 referenceContext.scope = this;
163                 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
164                 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
165
166                 // build the binding or the local type
167                 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
168                 referenceContext.binding = localType;
169                 checkAndSetModifiers();
170                 buildTypeVariables();
171                 
172                 // Look at member types
173                 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
174                 if (referenceContext.memberTypes != null) {
175                         int size = referenceContext.memberTypes.length;
176                         memberTypeBindings = new ReferenceBinding[size];
177                         int count = 0;
178                         nextMember : for (int i = 0; i < size; i++) {
179                                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
180                                 if (memberContext.kind() == IGenericType.INTERFACE_DECL) {
181                                         problemReporter().nestedClassCannotDeclareInterface(memberContext);
182                                         continue nextMember;
183                                 }
184                                 ReferenceBinding type = localType;
185                                 // check that the member does not conflict with an enclosing type
186                                 do {
187                                         if (CharOperation.equals(type.sourceName, memberContext.name)) {
188                                                 problemReporter().hidingEnclosingType(memberContext);
189                                                 continue nextMember;
190                                         }
191                                         type = type.enclosingType();
192                                 } while (type != null);
193                                 // check the member type does not conflict with another sibling member type
194                                 for (int j = 0; j < i; j++) {
195                                         if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
196                                                 problemReporter().duplicateNestedType(memberContext);
197                                                 continue nextMember;
198                                         }
199                                 }
200                                 ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
201                                 LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
202                                 memberBinding.setAsMemberType();
203                                 memberTypeBindings[count++] = memberBinding;
204                         }
205                         if (count != size)
206                                 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
207                 }
208                 localType.memberTypes = memberTypeBindings;
209                 return localType;
210         }
211         
212         void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
213
214                 LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
215                 connectTypeHierarchy();
216                 buildFieldsAndMethods();
217                 localType.faultInTypesForFieldsAndMethods();
218
219                 referenceContext.binding.verifyMethods(environment().methodVerifier());
220         }
221         
222         private void buildMemberTypes(AccessRestriction accessRestriction) {
223             SourceTypeBinding sourceType = referenceContext.binding;
224                 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
225                 if (referenceContext.memberTypes != null) {
226                         int length = referenceContext.memberTypes.length;
227                         memberTypeBindings = new ReferenceBinding[length];
228                         int count = 0;
229                         nextMember : for (int i = 0; i < length; i++) {
230                                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
231                                 if (memberContext.kind() == IGenericType.INTERFACE_DECL
232                                         && sourceType.isNestedType()
233                                         && sourceType.isClass()
234                                         && !sourceType.isStatic()) {
235                                         problemReporter().nestedClassCannotDeclareInterface(memberContext);
236                                         continue nextMember;
237                                 }
238                                 ReferenceBinding type = sourceType;
239                                 // check that the member does not conflict with an enclosing type
240                                 do {
241                                         if (CharOperation.equals(type.sourceName, memberContext.name)) {
242                                                 problemReporter().hidingEnclosingType(memberContext);
243                                                 continue nextMember;
244                                         }
245                                         type = type.enclosingType();
246                                 } while (type != null);
247                                 // check that the member type does not conflict with another sibling member type
248                                 for (int j = 0; j < i; j++) {
249                                         if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
250                                                 problemReporter().duplicateNestedType(memberContext);
251                                                 continue nextMember;
252                                         }
253                                 }
254
255                                 ClassScope memberScope = new ClassScope(this, memberContext);
256                                 memberTypeBindings[count++] = memberScope.buildType(sourceType, sourceType.fPackage, accessRestriction);
257                         }
258                         if (count != length)
259                                 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
260                 }
261                 sourceType.memberTypes = memberTypeBindings;
262         }
263         
264         private void buildMethods() {
265                 boolean isEnum = referenceContext.kind() == IGenericType.ENUM_DECL;
266                 if (referenceContext.methods == null && !isEnum) {
267                         referenceContext.binding.methods = NoMethods;
268                         return;
269                 }
270
271                 // iterate the method declarations to create the bindings
272                 AbstractMethodDeclaration[] methods = referenceContext.methods;
273                 int size = methods == null ? 0 : methods.length;
274                 // look for <clinit> method
275                 int clinitIndex = -1;
276                 for (int i = 0; i < size; i++) {
277                         if (methods[i].isClinit()) {
278                                 clinitIndex = i;
279                                 break;
280                         }
281                 }
282
283                 int count = isEnum ? 2 : 0; // reserve 2 slots for special enum methods: #values() and #valueOf(String)
284                 MethodBinding[] methodBindings = new MethodBinding[(clinitIndex == -1 ? size : size - 1) + count];
285                 // create special methods for enums
286                 if (isEnum) {
287                     SourceTypeBinding sourceType = referenceContext.binding;
288                         methodBindings[0] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUES); // add <EnumType>[] values() 
289                         methodBindings[1] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUEOF); // add <EnumType> valueOf() 
290                 }
291                 // create bindings for source methods
292                 for (int i = 0; i < size; i++) {
293                         if (i != clinitIndex) {
294                                 MethodScope scope = new MethodScope(this, methods[i], false);
295                                 MethodBinding methodBinding = scope.createMethod(methods[i]);
296                                 if (methodBinding != null) // is null if binding could not be created
297                                         methodBindings[count++] = methodBinding;
298                         }
299                 }
300                 if (count != methodBindings.length)
301                         System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
302
303                 referenceContext.binding.methods = methodBindings;
304                 referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
305         }
306         
307         SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
308                 // provide the typeDeclaration with needed scopes
309                 referenceContext.scope = this;
310                 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
311                 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
312
313                 if (enclosingType == null) {
314                         char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
315                         referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
316                 } else {
317                         char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
318                         className[className.length - 1] =
319                                 CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
320                         referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
321                 }
322
323                 SourceTypeBinding sourceType = referenceContext.binding;
324                 environment().setAccessRestriction(sourceType, accessRestriction);              
325                 sourceType.fPackage.addType(sourceType);
326                 checkAndSetModifiers();
327                 buildTypeVariables();
328                 buildMemberTypes(accessRestriction);
329                 return sourceType;
330         }
331         
332         private void buildTypeVariables() {
333             
334             SourceTypeBinding sourceType = referenceContext.binding;
335                 TypeParameter[] typeParameters = referenceContext.typeParameters;
336                 
337             // do not construct type variables if source < 1.5
338                 if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) {
339                     sourceType.typeVariables = NoTypeVariables;
340                     return;
341                 }
342                 sourceType.typeVariables = NoTypeVariables; // safety
343
344                 if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
345                         problemReporter().objectCannotBeGeneric(referenceContext);
346                         return; 
347                 }
348                 sourceType.typeVariables = createTypeVariables(typeParameters, sourceType);
349                 sourceType.modifiers |= AccGenericSignature;
350         }
351         
352         private void checkAndSetModifiers() {
353                 SourceTypeBinding sourceType = referenceContext.binding;
354                 int modifiers = sourceType.modifiers;
355                 if ((modifiers & AccAlternateModifierProblem) != 0)
356                         problemReporter().duplicateModifierForType(sourceType);
357
358                 ReferenceBinding enclosingType = sourceType.enclosingType();
359                 boolean isMemberType = sourceType.isMemberType();
360                 
361                 if (isMemberType) {
362                         // checks for member types before local types to catch local members
363                         if (enclosingType.isStrictfp())
364                                 modifiers |= AccStrictfp;
365                         if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
366                                 modifiers |= AccDeprecatedImplicitly;
367                         if ((enclosingType.modifiers & AccInterface) != 0)
368                                 modifiers |= AccPublic;
369                         if (sourceType.isEnum())
370                                 modifiers |= AccStatic;
371                 } else if (sourceType.isLocalType()) {
372                         if (sourceType.isAnonymousType()) {
373                             modifiers |= AccFinal;
374                             // set AccEnum flag for anonymous body of enum constants
375                             if (referenceContext.allocation.type == null) {
376                                 modifiers |= AccEnum;
377                             }
378                         }
379                         Scope scope = this;
380                         do {
381                                 switch (scope.kind) {
382                                         case METHOD_SCOPE :
383                                                 MethodScope methodScope = (MethodScope) scope;
384                                                 if (methodScope.isInsideInitializer()) {
385                                                         SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
386                         
387                                                         // inside field declaration ? check field modifier to see if deprecated
388                                                         if (methodScope.initializedField != null) {
389                                                                         // currently inside this field initialization
390                                                                 if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
391                                                                         modifiers |= AccDeprecatedImplicitly;
392                                                                 }
393                                                         } else {
394                                                                 if (type.isStrictfp())
395                                                                         modifiers |= AccStrictfp;
396                                                                 if (type.isViewedAsDeprecated() && !sourceType.isDeprecated()) 
397                                                                         modifiers |= AccDeprecatedImplicitly;
398                                                         }                                       
399                                                 } else {
400                                                         MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
401                                                         if (method != null){
402                                                                 if (method.isStrictfp())
403                                                                         modifiers |= AccStrictfp;
404                                                                 if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
405                                                                         modifiers |= AccDeprecatedImplicitly;
406                                                         }
407                                                 }
408                                                 break;
409                                         case CLASS_SCOPE :
410                                                 // local member
411                                                 if (enclosingType.isStrictfp())
412                                                         modifiers |= AccStrictfp;
413                                                 if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
414                                                         modifiers |= AccDeprecatedImplicitly;
415                                                 break;
416                                 }
417                                 scope = scope.parent;
418                         } while (scope != null);
419                 }
420                 // after this point, tests on the 16 bits reserved.
421                 int realModifiers = modifiers & AccJustFlag;
422
423                 if ((realModifiers & AccInterface) != 0) { // interface and annotation type
424                         // detect abnormal cases for interfaces
425                         if (isMemberType) {
426                                 int unexpectedModifiers =
427                                         ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
428                                 if ((realModifiers & unexpectedModifiers) != 0) {
429                                         if ((realModifiers & AccAnnotation) != 0) {
430                                                 problemReporter().illegalModifierForAnnotationMemberType(sourceType);
431                                         } else {
432                                                 problemReporter().illegalModifierForMemberInterface(sourceType);
433                                         }
434                                 }
435                                 /*
436                                 } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
437                                         int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
438                                         if ((realModifiers & unexpectedModifiers) != 0)
439                                                 problemReporter().illegalModifierForLocalInterface(sourceType);
440                                 */
441                         } else {
442                                 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
443                                 if ((realModifiers & unexpectedModifiers) != 0) {
444                                         if ((realModifiers & AccAnnotation) != 0) {
445                                                 problemReporter().illegalModifierForAnnotationType(sourceType);
446                                         } else {
447                                                 problemReporter().illegalModifierForInterface(sourceType);
448                                         }
449                                 }
450                         }
451                         modifiers |= AccAbstract;
452                 } else if ((realModifiers & AccEnum) != 0) {
453                         // detect abnormal cases for enums
454                         if (isMemberType) { // includes member types defined inside local types
455                                 int unexpectedModifiers =
456                                         ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccStrictfp | AccEnum);
457                                 if ((realModifiers & unexpectedModifiers) != 0)
458                                         problemReporter().illegalModifierForMemberEnum(sourceType);
459                         } else if (sourceType.isLocalType()) {
460                                 int unexpectedModifiers = ~(AccStrictfp | AccFinal | AccEnum); // add final since implicitly set for anonymous type
461                                 if ((realModifiers & unexpectedModifiers) != 0)
462                                         problemReporter().illegalModifierForLocalEnum(sourceType);
463                         } else {
464                                 int unexpectedModifiers = ~(AccPublic | AccStrictfp | AccEnum);
465                                 if ((realModifiers & unexpectedModifiers) != 0)
466                                         problemReporter().illegalModifierForEnum(sourceType);
467                         }
468                         if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) {
469                                 modifiers |= AccAbstract;
470                         }
471                         
472                 } else {
473                         // detect abnormal cases for classes
474                         if (isMemberType) { // includes member types defined inside local types
475                                 int unexpectedModifiers =
476                                         ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
477                                 if ((realModifiers & unexpectedModifiers) != 0)
478                                         problemReporter().illegalModifierForMemberClass(sourceType);
479                         } else if (sourceType.isLocalType()) {
480                                 int unexpectedModifiers = ~(AccAbstract | AccFinal | AccStrictfp);
481                                 if ((realModifiers & unexpectedModifiers) != 0)
482                                         problemReporter().illegalModifierForLocalClass(sourceType);
483                         } else {
484                                 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal | AccStrictfp);
485                                 if ((realModifiers & unexpectedModifiers) != 0)
486                                         problemReporter().illegalModifierForClass(sourceType);
487                         }
488
489                         // check that Final and Abstract are not set together
490                         if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
491                                 problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
492                 }
493
494                 if (isMemberType) {
495                         // test visibility modifiers inconsistency, isolate the accessors bits
496                         if (enclosingType.isInterface()) {
497                                 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
498                                         problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
499
500                                         // need to keep the less restrictive
501                                         if ((realModifiers & AccProtected) != 0)
502                                                 modifiers &= ~AccProtected;
503                                         if ((realModifiers & AccPrivate) != 0)
504                                                 modifiers &= ~AccPrivate;
505                                 }
506                         } else {
507                                 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
508                                 if ((accessorBits & (accessorBits - 1)) > 1) {
509                                         problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
510
511                                         // need to keep the less restrictive
512                                         if ((accessorBits & AccPublic) != 0) {
513                                                 if ((accessorBits & AccProtected) != 0)
514                                                         modifiers &= ~AccProtected;
515                                                 if ((accessorBits & AccPrivate) != 0)
516                                                         modifiers &= ~AccPrivate;
517                                         }
518                                         if ((accessorBits & AccProtected) != 0)
519                                                 if ((accessorBits & AccPrivate) != 0)
520                                                         modifiers &= ~AccPrivate;
521                                 }
522                         }
523
524                         // static modifier test
525                         if ((realModifiers & AccStatic) == 0) {
526                                 if (enclosingType.isInterface())
527                                         modifiers |= AccStatic;
528                         } else {
529                                 if (!enclosingType.isStatic())
530                                         // error the enclosing type of a static field must be static or a top-level type
531                                         problemReporter().illegalStaticModifierForMemberType(sourceType);
532                         }
533                 }
534
535                 sourceType.modifiers = modifiers;
536         }
537         
538         /* This method checks the modifiers of a field.
539         *
540         * 9.3 & 8.3
541         * Need to integrate the check for the final modifiers for nested types
542         *
543         * Note : A scope is accessible by : fieldBinding.declaringClass.scope
544         */
545         private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
546                 int modifiers = fieldBinding.modifiers;
547                 if ((modifiers & AccAlternateModifierProblem) != 0)
548                         problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
549
550                 if ((fieldBinding.declaringClass.modifiers  & AccInterface) != 0) {
551                         int expectedValue = AccPublic | AccStatic | AccFinal;
552                         // set the modifiers
553                         modifiers |= expectedValue;
554
555                         // and then check that they are the only ones
556                         if ((modifiers & AccJustFlag) != expectedValue) {
557                                 if ((fieldBinding.declaringClass.modifiers  & AccAnnotation) != 0) {
558                                         problemReporter().illegalModifierForAnnotationField(fieldDecl);
559                                 } else {
560                                         problemReporter().illegalModifierForInterfaceField(fieldDecl);
561                                 }
562                         }
563                         fieldBinding.modifiers = modifiers;
564                         return;
565                 } else if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
566                         // check that they are not modifiers in source
567                         if ((modifiers & AccJustFlag) != 0)
568                                 problemReporter().illegalModifierForEnumConstant(fieldBinding.declaringClass, fieldDecl);
569                 
570                         // set the modifiers
571                         int implicitValue = AccPublic | AccStatic | AccFinal | AccEnum;
572                         fieldBinding.modifiers|= implicitValue;
573                         return;
574                 }
575
576                 // after this point, tests on the 16 bits reserved.
577                 int realModifiers = modifiers & AccJustFlag;
578                 int unexpectedModifiers =
579                         ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic | AccTransient | AccVolatile);
580                 if ((realModifiers & unexpectedModifiers) != 0)
581                         problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
582
583                 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
584                 if ((accessorBits & (accessorBits - 1)) > 1) {
585                         problemReporter().illegalVisibilityModifierCombinationForField(
586                                 fieldBinding.declaringClass,
587                                 fieldDecl);
588
589                         // need to keep the less restrictive
590                         if ((accessorBits & AccPublic) != 0) {
591                                 if ((accessorBits & AccProtected) != 0)
592                                         modifiers &= ~AccProtected;
593                                 if ((accessorBits & AccPrivate) != 0)
594                                         modifiers &= ~AccPrivate;
595                         }
596                         if ((accessorBits & AccProtected) != 0)
597                                 if ((accessorBits & AccPrivate) != 0)
598                                         modifiers &= ~AccPrivate;
599                 }
600
601                 if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
602                         problemReporter().illegalModifierCombinationFinalVolatileForField(
603                                 fieldBinding.declaringClass,
604                                 fieldDecl);
605
606                 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
607                         modifiers |= AccBlankFinal;
608                 }
609                 fieldBinding.modifiers = modifiers;
610         }
611
612         private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
613                 // search up the hierarchy of the sourceType to see if any superType defines a member type
614                 // when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
615                 // assumes super types have already been checked & tagged
616                 ReferenceBinding currentType = sourceType;
617                 ReferenceBinding[][] interfacesToVisit = null;
618                 int lastPosition = -1;
619                 do {
620                         if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
621                                 return;
622
623                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
624                         if (itsInterfaces != NoSuperInterfaces) {
625                                 if (interfacesToVisit == null)
626                                         interfacesToVisit = new ReferenceBinding[5][];
627                                 if (++lastPosition == interfacesToVisit.length)
628                                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
629                                 interfacesToVisit[lastPosition] = itsInterfaces;
630                         }
631                 } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
632
633                 if (interfacesToVisit != null) {
634                         // contains the interfaces between the sourceType and any superclass, which was tagged as having no member types
635                         boolean needToTag = false;
636                         for (int i = 0; i <= lastPosition; i++) {
637                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
638                                 for (int j = 0, length = interfaces.length; j < length; j++) {
639                                         ReferenceBinding anInterface = interfaces[j];
640                                         if ((anInterface.tagBits & HasNoMemberTypes) == 0) { // skip interface if it already knows it has no member types
641                                                 if (anInterface.hasMemberTypes()) // avoid resolving member types eagerly
642                                                         return;
643
644                                                 needToTag = true;
645                                                 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
646                                                 if (itsInterfaces != NoSuperInterfaces) {
647                                                         if (++lastPosition == interfacesToVisit.length)
648                                                                 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
649                                                         interfacesToVisit[lastPosition] = itsInterfaces;
650                                                 }
651                                         }
652                                 }
653                         }
654
655                         if (needToTag) {
656                                 for (int i = 0; i <= lastPosition; i++) {
657                                         ReferenceBinding[] interfaces = interfacesToVisit[i];
658                                         for (int j = 0, length = interfaces.length; j < length; j++)
659                                                 interfaces[j].tagBits |= HasNoMemberTypes;
660                                 }
661                         }
662                 }
663
664                 // tag the sourceType and all of its superclasses, unless they have already been tagged
665                 currentType = sourceType;
666                 do {
667                         currentType.tagBits |= HasNoMemberTypes;
668                 } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
669         }
670         // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
671         private void  checkParameterizedTypeBounds() {
672                 TypeReference superclass = referenceContext.superclass;
673                 if (superclass != null) {
674                         superclass.checkBounds(this);
675                 }
676                 TypeReference[] superinterfaces = referenceContext.superInterfaces;
677                 if (superinterfaces != null) {
678                         for (int i = 0, length = superinterfaces.length; i < length; i++) {
679                                 superinterfaces[i].checkBounds(this);
680                         }
681                 }
682                 TypeParameter[] typeParameters = referenceContext.typeParameters;
683                 if (typeParameters != null) {
684                         for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
685                                 typeParameters[i].checkBounds(this);
686                         }
687                 }
688         }
689
690         private void connectMemberTypes() {
691                 SourceTypeBinding sourceType = referenceContext.binding;
692                 if (sourceType.memberTypes != NoMemberTypes)
693                         for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
694                                  ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
695         }
696         /*
697                 Our current belief based on available JCK tests is:
698                         inherited member types are visible as a potential superclass.
699                         inherited interfaces are not visible when defining a superinterface.
700         
701                 Error recovery story:
702                         ensure the superclass is set to java.lang.Object if a problem is detected
703                         resolving the superclass.
704         
705                 Answer false if an error was reported against the sourceType.
706         */
707         private boolean connectSuperclass() {
708                 SourceTypeBinding sourceType = referenceContext.binding;
709                 if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
710                         sourceType.superclass = null;
711                         sourceType.superInterfaces = NoSuperInterfaces;
712                         if (!sourceType.isClass())
713                                 problemReporter().objectMustBeClass(sourceType);
714                         if (referenceContext.superclass != null || (referenceContext.superInterfaces != null && referenceContext.superInterfaces.length > 0))
715                                 problemReporter().objectCannotHaveSuperTypes(sourceType);
716                         return true; // do not propagate Object's hierarchy problems down to every subtype
717                 }
718                 if (referenceContext.superclass == null) {
719                         if (sourceType.isEnum() && environment().options.sourceLevel >= JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
720                                 return connectEnumSuperclass();
721                         sourceType.superclass = getJavaLangObject();
722                         return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
723                 }
724                 TypeReference superclassRef = referenceContext.superclass;
725                 ReferenceBinding superclass = findSupertype(superclassRef);
726                 if (superclass != null) { // is null if a cycle was detected cycle or a problem
727                         if (!superclass.isClass()) {
728                                 problemReporter().superclassMustBeAClass(sourceType, superclassRef, superclass);
729                         } else if (superclass.isFinal()) {
730                                 problemReporter().classExtendFinalClass(sourceType, superclassRef, superclass);
731                         } else if ((superclass.tagBits & TagBits.HasDirectWildcard) != 0) {
732                                 problemReporter().superTypeCannotUseWildcard(sourceType, superclassRef, superclass);
733                         } else if (superclass.erasure().id == T_JavaLangEnum) {
734                                 problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
735                         } else {
736                                 // only want to reach here when no errors are reported
737                                 sourceType.superclass = superclass;
738                                 return true;
739                         }
740                 }
741                 sourceType.tagBits |= HierarchyHasProblems;
742                 sourceType.superclass = getJavaLangObject();
743                 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
744                         detectHierarchyCycle(sourceType, sourceType.superclass, null);
745                 return false; // reported some error against the source type
746         }
747
748         /**
749          *  enum X (implicitly) extends Enum<X>
750          */
751         private boolean connectEnumSuperclass() {
752                 SourceTypeBinding sourceType = referenceContext.binding;
753                 ReferenceBinding rootEnumType = getJavaLangEnum();
754                 boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null);
755                 // arity check for well-known Enum<E>
756                 TypeVariableBinding[] refTypeVariables = rootEnumType.typeVariables();
757                 if (refTypeVariables == NoTypeVariables) { // check generic
758                         problemReporter().nonGenericTypeCannotBeParameterized(null, rootEnumType, new TypeBinding[]{ sourceType });
759                         return false; // cannot reach here as AbortCompilation is thrown
760                 } else if (1 != refTypeVariables.length) { // check arity
761                         problemReporter().incorrectArityForParameterizedType(null, rootEnumType, new TypeBinding[]{ sourceType });
762                         return false; // cannot reach here as AbortCompilation is thrown
763                 }                       
764                 // check argument type compatibility
765                 ParameterizedTypeBinding  superType = createParameterizedType(rootEnumType, new TypeBinding[]{ sourceType } , null);
766                 sourceType.superclass = superType;
767                 // bound check
768                 if (!refTypeVariables[0].boundCheck(superType, sourceType)) {
769                         problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
770                 }
771                 return !foundCycle;
772         }
773
774         /*
775                 Our current belief based on available JCK 1.3 tests is:
776                         inherited member types are visible as a potential superclass.
777                         inherited interfaces are visible when defining a superinterface.
778         
779                 Error recovery story:
780                         ensure the superinterfaces contain only valid visible interfaces.
781         
782                 Answer false if an error was reported against the sourceType.
783         */
784         private boolean connectSuperInterfaces() {
785                 SourceTypeBinding sourceType = referenceContext.binding;
786                 sourceType.superInterfaces = NoSuperInterfaces;
787                 if (referenceContext.superInterfaces == null) {
788                         if (sourceType.isAnnotationType() && environment().options.sourceLevel >= JDK1_5) { // do not connect if source < 1.5 as annotation already got flagged as syntax error) {
789                                 ReferenceBinding annotationType = getJavaLangAnnotationAnnotation();
790                                 boolean foundCycle = detectHierarchyCycle(sourceType, annotationType, null);
791                                 sourceType.superInterfaces = new ReferenceBinding[] { annotationType };
792                                 return !foundCycle;
793                         }
794                         return true;
795                 }
796                 if (sourceType.id == T_JavaLangObject) // already handled the case of redefining java.lang.Object
797                         return true;
798
799                 boolean noProblems = true;
800                 int length = referenceContext.superInterfaces.length;
801                 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
802                 int count = 0;
803                 nextInterface : for (int i = 0; i < length; i++) {
804                     TypeReference superInterfaceRef = referenceContext.superInterfaces[i];
805                         ReferenceBinding superInterface = findSupertype(superInterfaceRef);
806                         if (superInterface == null) { // detected cycle
807                                 sourceType.tagBits |= HierarchyHasProblems;
808                                 noProblems = false;
809                                 continue nextInterface;
810                         }
811                         superInterfaceRef.resolvedType = superInterface; // hold onto the problem type
812                         // Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
813                         for (int k = 0; k < count; k++) {
814                                 if (interfaceBindings[k] == superInterface) {
815                                         // should this be treated as a warning?
816                                         problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
817                                         continue nextInterface;
818                                 }
819                         }
820                         if (!superInterface.isInterface()) {
821                                 problemReporter().superinterfaceMustBeAnInterface(sourceType, superInterfaceRef, superInterface);
822                                 sourceType.tagBits |= HierarchyHasProblems;
823                                 noProblems = false;
824                                 continue nextInterface;
825                         }
826                         if ((superInterface.tagBits & TagBits.HasDirectWildcard) != 0) {
827                                 problemReporter().superTypeCannotUseWildcard(sourceType, superInterfaceRef, superInterface);
828                                 sourceType.tagBits |= HierarchyHasProblems;
829                                 noProblems = false;
830                                 continue nextInterface;
831                         }
832                         ReferenceBinding invalid = findAmbiguousInterface(superInterface, sourceType);
833                         if (invalid != null) {
834                                 ReferenceBinding generic = null;
835                                 if (superInterface.isParameterizedType())
836                                         generic = ((ParameterizedTypeBinding) superInterface).type;
837                                 else if (invalid.isParameterizedType())
838                                         generic = ((ParameterizedTypeBinding) invalid).type;
839                                 problemReporter().superinterfacesCollide(generic, referenceContext, superInterface, invalid);
840                                 sourceType.tagBits |= HierarchyHasProblems;
841                                 noProblems = false;
842                                 continue nextInterface;
843                         }
844
845                         // only want to reach here when no errors are reported
846                         interfaceBindings[count++] = superInterface;
847                 }
848                 // hold onto all correctly resolved superinterfaces
849                 if (count > 0) {
850                         if (count != length)
851                                 System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
852                         sourceType.superInterfaces = interfaceBindings;
853                 }
854                 return noProblems;
855         }
856         
857         void connectTypeHierarchy() {
858                 SourceTypeBinding sourceType = referenceContext.binding;
859                 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
860                         sourceType.tagBits |= BeginHierarchyCheck;
861                         boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
862                         noProblems &= connectSuperclass();
863                         noProblems &= connectSuperInterfaces();
864                         sourceType.tagBits |= EndHierarchyCheck;
865                         if (noProblems && sourceType.isHierarchyInconsistent())
866                                 problemReporter().hierarchyHasProblems(sourceType);
867                 }
868                 // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
869                 checkParameterizedTypeBounds();
870                 connectMemberTypes();
871                 try {
872                         checkForInheritedMemberTypes(sourceType);
873                 } catch (AbortCompilation e) {
874                         e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
875                         throw e;
876                 }
877         }
878         
879         private void connectTypeHierarchyWithoutMembers() {
880                 // must ensure the imports are resolved
881                 if (parent instanceof CompilationUnitScope) {
882                         if (((CompilationUnitScope) parent).imports == null)
883                                  ((CompilationUnitScope) parent).checkAndSetImports();
884                 } else if (parent instanceof ClassScope) {
885                         // ensure that the enclosing type has already been checked
886                          ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
887                 }
888
889                 // double check that the hierarchy search has not already begun...
890                 SourceTypeBinding sourceType = referenceContext.binding;
891                 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
892                         return;
893
894                 sourceType.tagBits |= BeginHierarchyCheck;
895                 boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
896                 noProblems &= connectSuperclass();
897                 noProblems &= connectSuperInterfaces();
898                 sourceType.tagBits |= EndHierarchyCheck;
899                 if (noProblems && sourceType.isHierarchyInconsistent())
900                         problemReporter().hierarchyHasProblems(sourceType);
901         }
902
903         public boolean detectAnnotationCycle(TypeBinding sourceType, TypeBinding annotationElementType, TypeReference reference) {
904                 if (!annotationElementType.isAnnotationType()) 
905                         return false;
906
907                 if (sourceType == annotationElementType) {
908                         problemReporter().annotationCircularity(sourceType, annotationElementType, reference);
909                         return true;
910                 }
911                 // TODO (kent) add support for detecting indirect cases using TagBits.BeginAnnotationCheck/EndAnnotationCheck
912                 return false;
913         }
914
915         public boolean detectHierarchyCycle(TypeBinding superType, TypeReference reference, TypeBinding[] argTypes) {
916                 if (!(superType instanceof ReferenceBinding)) return false;
917
918                 if (argTypes != null) {
919                         for (int i = 0, l = argTypes.length; i < l; i++) {
920                                 TypeBinding argType = argTypes[i].leafComponentType();
921                                 if ((argType.tagBits & BeginHierarchyCheck) == 0 && argType instanceof SourceTypeBinding)
922                                 // ensure if this is a source argument type that it has already been checked
923                                 ((SourceTypeBinding) argType).scope.connectTypeHierarchyWithoutMembers();
924                         }
925                 }
926
927                 if (reference == this.superTypeReference) { // see findSuperType()
928                         if (superType.isTypeVariable())
929                                 return false; // error case caught in resolveSuperType()
930                         // abstract class X<K,V> implements java.util.Map<K,V>
931                         //    static abstract class M<K,V> implements Entry<K,V>
932                         if (superType.isParameterizedType())
933                                 superType = ((ParameterizedTypeBinding) superType).type;
934                         compilationUnitScope().recordSuperTypeReference(superType); // to record supertypes
935                         return detectHierarchyCycle(referenceContext.binding, (ReferenceBinding) superType, reference);
936                 }
937
938                 if ((superType.tagBits & BeginHierarchyCheck) == 0 && superType instanceof SourceTypeBinding)
939                         // ensure if this is a source superclass that it has already been checked
940                         ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
941                 return false;
942         }
943
944         // Answer whether a cycle was found between the sourceType & the superType
945         private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
946                 if (superType.isRawType())
947                         superType = ((RawTypeBinding) superType).type;
948                 // by this point the superType must be a binary or source type
949
950                 if (sourceType == superType) {
951                         problemReporter().hierarchyCircularity(sourceType, superType, reference);
952                         sourceType.tagBits |= HierarchyHasProblems;
953                         return true;
954                 }
955
956                 if (superType.isMemberType()) {
957                         ReferenceBinding current = superType.enclosingType();
958                         do {
959                                 if (current.isHierarchyBeingConnected()) {
960                                         problemReporter().hierarchyCircularity(sourceType, current, reference);
961                                         sourceType.tagBits |= HierarchyHasProblems;
962                                         current.tagBits |= HierarchyHasProblems;
963                                         return true;
964                                 }
965                         } while ((current = current.enclosingType()) != null);
966                 }
967
968                 if (superType.isBinaryBinding()) {
969                         // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
970                         //              - a binary type... this case MUST be caught & reported here
971                         //              - another source type... this case is reported against the other source type
972                         boolean hasCycle = false;
973                         if (superType.superclass() != null) {
974                                 if (sourceType == superType.superclass()) {
975                                         problemReporter().hierarchyCircularity(sourceType, superType, reference);
976                                         sourceType.tagBits |= HierarchyHasProblems;
977                                         superType.tagBits |= HierarchyHasProblems;
978                                         return true;
979                                 }
980                                 ReferenceBinding parentType = superType.superclass();
981                                 if (parentType.isParameterizedType())
982                                         parentType = ((ParameterizedTypeBinding) parentType).type;
983                                 hasCycle |= detectHierarchyCycle(sourceType, parentType, reference);
984                                 if ((parentType.tagBits & HierarchyHasProblems) != 0) {
985                                         sourceType.tagBits |= HierarchyHasProblems;
986                                         parentType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
987                                 }
988                         }
989
990                         ReferenceBinding[] itsInterfaces = superType.superInterfaces();
991                         if (itsInterfaces != NoSuperInterfaces) {
992                                 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
993                                         ReferenceBinding anInterface = itsInterfaces[i];
994                                         if (sourceType == anInterface) {
995                                                 problemReporter().hierarchyCircularity(sourceType, superType, reference);
996                                                 sourceType.tagBits |= HierarchyHasProblems;
997                                                 superType.tagBits |= HierarchyHasProblems;
998                                                 return true;
999                                         }
1000                                         if (anInterface.isParameterizedType())
1001                                                 anInterface = ((ParameterizedTypeBinding) anInterface).type;
1002                                         hasCycle |= detectHierarchyCycle(sourceType, anInterface, reference);
1003                                         if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
1004                                                 sourceType.tagBits |= HierarchyHasProblems;
1005                                                 superType.tagBits |= HierarchyHasProblems;
1006                                         }
1007                                 }
1008                         }
1009                         return hasCycle;
1010                 }
1011
1012                 if (superType.isHierarchyBeingConnected()) {
1013                         if (((SourceTypeBinding) superType).scope.superTypeReference != null) { // if null then its connecting its type variables
1014                                 problemReporter().hierarchyCircularity(sourceType, superType, reference);
1015                                 sourceType.tagBits |= HierarchyHasProblems;
1016                                 superType.tagBits |= HierarchyHasProblems;
1017                                 return true;
1018                         }
1019                 }
1020                 if ((superType.tagBits & BeginHierarchyCheck) == 0)
1021                         // ensure if this is a source superclass that it has already been checked
1022                         ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
1023                 if ((superType.tagBits & HierarchyHasProblems) != 0)
1024                         sourceType.tagBits |= HierarchyHasProblems;
1025                 return false;
1026         }
1027
1028         private ReferenceBinding findAmbiguousInterface(ReferenceBinding newInterface, ReferenceBinding currentType) {
1029                 TypeBinding newErasure = newInterface.erasure();
1030                 if (newInterface == newErasure) return null;
1031
1032                 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
1033                 int lastPosition = -1;
1034                 do {
1035                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1036                         if (itsInterfaces != NoSuperInterfaces) {
1037                                 if (++lastPosition == interfacesToVisit.length)
1038                                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
1039                                 interfacesToVisit[lastPosition] = itsInterfaces;
1040                         }
1041                 } while ((currentType = currentType.superclass()) != null);
1042
1043                 for (int i = 0; i <= lastPosition; i++) {
1044                         ReferenceBinding[] interfaces = interfacesToVisit[i];
1045                         for (int j = 0, length = interfaces.length; j < length; j++) {
1046                                 currentType = interfaces[j];
1047                                 if (currentType.erasure() == newErasure)
1048                                         if (currentType != newInterface)
1049                                                 return currentType;
1050
1051                                 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1052                                 if (itsInterfaces != NoSuperInterfaces) {
1053                                         if (++lastPosition == interfacesToVisit.length)
1054                                                 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
1055                                         interfacesToVisit[lastPosition] = itsInterfaces;
1056                                 }
1057                         }
1058                 }
1059                 return null;
1060         }
1061
1062         private ReferenceBinding findSupertype(TypeReference typeReference) {
1063                 try {
1064                         typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
1065                         compilationUnitScope().recordQualifiedReference(typeReference.getTypeName());
1066                         this.superTypeReference = typeReference;
1067                         ReferenceBinding superType = (ReferenceBinding) typeReference.resolveSuperType(this);
1068                         this.superTypeReference = null;
1069                         return superType;
1070                 } catch (AbortCompilation e) {
1071                         e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
1072                         throw e;
1073                 }                       
1074         }
1075
1076         /* Answer the problem reporter to use for raising new problems.
1077         *
1078         * Note that as a side-effect, this updates the current reference context
1079         * (unit, type or method) in case the problem handler decides it is necessary
1080         * to abort.
1081         */
1082         public ProblemReporter problemReporter() {
1083                 MethodScope outerMethodScope;
1084                 if ((outerMethodScope = outerMostMethodScope()) == null) {
1085                         ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
1086                         problemReporter.referenceContext = referenceContext;
1087                         return problemReporter;
1088                 }
1089                 return outerMethodScope.problemReporter();
1090         }
1091
1092         /* Answer the reference type of this scope.
1093         * It is the nearest enclosing type of this scope.
1094         */
1095         public TypeDeclaration referenceType() {
1096                 return referenceContext;
1097         }
1098         
1099         public String toString() {
1100                 if (referenceContext != null)
1101                         return "--- Class Scope ---\n\n"  //$NON-NLS-1$
1102                                                         + referenceContext.binding.toString();
1103                 return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$
1104         }
1105 }