Makefile fixup
[org.ibex.tool.git] / repo / org.ibex.tool / 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.AbstractMethodDeclaration;
15 import org.eclipse.jdt.internal.compiler.ast.Clinit;
16 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
19 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
20 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
21 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
22
23 public class ClassScope extends Scope {
24         public TypeDeclaration referenceContext;
25
26         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'};
27
28         public ClassScope(Scope parent, TypeDeclaration context) {
29                 super(CLASS_SCOPE, parent);
30                 this.referenceContext = context;
31         }
32         
33         void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
34                 
35                 LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
36
37                 SourceTypeBinding sourceType = referenceContext.binding;
38                 if (supertype.isInterface()) {
39                         sourceType.superclass = getJavaLangObject();
40                         sourceType.superInterfaces = new ReferenceBinding[] { supertype };
41                 } else {
42                         sourceType.superclass = supertype;
43                         sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
44                 }
45                 connectMemberTypes();
46                 buildFieldsAndMethods();
47                 anonymousType.faultInTypesForFieldsAndMethods();
48                 sourceType.verifyMethods(environment().methodVerifier());
49         }
50         
51         private void buildFields() {
52                 boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
53                 if (referenceContext.fields == null) {
54                         if (hierarchyIsInconsistent) { // 72468
55                                 referenceContext.binding.fields = new FieldBinding[1];
56                                 referenceContext.binding.fields[0] =
57                                         new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
58                         } else {
59                                 referenceContext.binding.fields = NoFields;
60                         }
61                         return;
62                 }
63                 // count the number of fields vs. initializers
64                 FieldDeclaration[] fields = referenceContext.fields;
65                 int size = fields.length;
66                 int count = 0;
67                 for (int i = 0; i < size; i++)
68                         if (fields[i].isField())
69                                 count++;
70
71                 if (hierarchyIsInconsistent)
72                         count++;
73                 // iterate the field declarations to create the bindings, lose all duplicates
74                 FieldBinding[] fieldBindings = new FieldBinding[count];
75                 HashtableOfObject knownFieldNames = new HashtableOfObject(count);
76                 boolean duplicate = false;
77                 count = 0;
78                 for (int i = 0; i < size; i++) {
79                         FieldDeclaration field = fields[i];
80                         if (!field.isField()) {
81                                 if (referenceContext.binding.isInterface())
82                                         problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
83                         } else {
84                                 FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
85                                 // field's type will be resolved when needed for top level types
86                                 checkAndSetModifiersForField(fieldBinding, field);
87
88                                 if (knownFieldNames.containsKey(field.name)) {
89                                         duplicate = true;
90                                         FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
91                                         if (previousBinding != null) {
92                                                 for (int f = 0; f < i; f++) {
93                                                         FieldDeclaration previousField = fields[f];
94                                                         if (previousField.binding == previousBinding) {
95                                                                 problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
96                                                                 previousField.binding = null;
97                                                                 break;
98                                                         }
99                                                 }
100                                         }
101                                         knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
102                                         problemReporter().duplicateFieldInType(referenceContext.binding, field);
103                                         field.binding = null;
104                                 } else {
105                                         knownFieldNames.put(field.name, fieldBinding);
106                                         // remember that we have seen a field with this name
107                                         if (fieldBinding != null)
108                                                 fieldBindings[count++] = fieldBinding;
109                                 }
110                         }
111                 }
112                 // remove duplicate fields
113                 if (duplicate) {
114                         FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
115                         // we know we'll be removing at least 1 duplicate name
116                         size = count;
117                         count = 0;
118                         for (int i = 0; i < size; i++) {
119                                 FieldBinding fieldBinding = fieldBindings[i];
120                                 if (knownFieldNames.get(fieldBinding.name) != null)
121                                         newFieldBindings[count++] = fieldBinding;
122                         }
123                         fieldBindings = newFieldBindings;
124                 }
125                 if (hierarchyIsInconsistent)
126                         fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
127
128                 if (count != fieldBindings.length)
129                         System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
130                 for (int i = 0; i < count; i++)
131                         fieldBindings[i].id = i;
132                 referenceContext.binding.fields = fieldBindings;
133         }
134         
135         void buildFieldsAndMethods() {
136                 buildFields();
137                 buildMethods();
138
139                 SourceTypeBinding sourceType = referenceContext.binding;
140                 if (sourceType.isMemberType() && !sourceType.isLocalType())
141                          ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
142
143                 ReferenceBinding[] memberTypes = sourceType.memberTypes;
144                 for (int i = 0, length = memberTypes.length; i < length; i++)
145                          ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
146         }
147         
148         private LocalTypeBinding buildLocalType(
149                 SourceTypeBinding enclosingType,
150                 PackageBinding packageBinding) {
151             
152                 referenceContext.scope = this;
153                 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
154                 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
155
156                 // build the binding or the local type
157                 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
158                 referenceContext.binding = localType;
159                 checkAndSetModifiers();
160
161                 // Look at member types
162                 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
163                 if (referenceContext.memberTypes != null) {
164                         int size = referenceContext.memberTypes.length;
165                         memberTypeBindings = new ReferenceBinding[size];
166                         int count = 0;
167                         nextMember : for (int i = 0; i < size; i++) {
168                                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
169                                 if (memberContext.isInterface()) {
170                                         problemReporter().nestedClassCannotDeclareInterface(memberContext);
171                                         continue nextMember;
172                                 }
173                                 ReferenceBinding type = localType;
174                                 // check that the member does not conflict with an enclosing type
175                                 do {
176                                         if (CharOperation.equals(type.sourceName, memberContext.name)) {
177                                                 problemReporter().hidingEnclosingType(memberContext);
178                                                 continue nextMember;
179                                         }
180                                         type = type.enclosingType();
181                                 } while (type != null);
182                                 // check the member type does not conflict with another sibling member type
183                                 for (int j = 0; j < i; j++) {
184                                         if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
185                                                 problemReporter().duplicateNestedType(memberContext);
186                                                 continue nextMember;
187                                         }
188                                 }
189
190                                 ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
191                                 LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
192                                 memberBinding.setAsMemberType();
193                                 memberTypeBindings[count++] = memberBinding;
194                         }
195                         if (count != size)
196                                 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
197                 }
198                 localType.memberTypes = memberTypeBindings;
199                 return localType;
200         }
201         
202         void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
203
204                 LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
205                 connectTypeHierarchy();
206                 buildFieldsAndMethods();
207                 localType.faultInTypesForFieldsAndMethods();
208
209                 referenceContext.binding.verifyMethods(environment().methodVerifier());
210         }
211         
212         private void buildMethods() {
213                 if (referenceContext.methods == null) {
214                         referenceContext.binding.methods = NoMethods;
215                         return;
216                 }
217
218                 // iterate the method declarations to create the bindings
219                 AbstractMethodDeclaration[] methods = referenceContext.methods;
220                 int size = methods.length;
221                 int clinitIndex = -1;
222                 for (int i = 0; i < size; i++) {
223                         if (methods[i] instanceof Clinit) {
224                                 clinitIndex = i;
225                                 break;
226                         }
227                 }
228                 MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
229
230                 int count = 0;
231                 for (int i = 0; i < size; i++) {
232                         if (i != clinitIndex) {
233                                 MethodScope scope = new MethodScope(this, methods[i], false);
234                                 MethodBinding methodBinding = scope.createMethod(methods[i]);
235                                 if (methodBinding != null) // is null if binding could not be created
236                                         methodBindings[count++] = methodBinding;
237                         }
238                 }
239                 if (count != methodBindings.length)
240                         System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
241
242                 referenceContext.binding.methods = methodBindings;
243                 referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
244         }
245         SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
246                 // provide the typeDeclaration with needed scopes
247                 referenceContext.scope = this;
248                 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
249                 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
250
251                 if (enclosingType == null) {
252                         char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
253                         referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
254                 } else {
255                         char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
256                         className[className.length - 1] =
257                                 CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
258                         referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
259                 }
260
261                 SourceTypeBinding sourceType = referenceContext.binding;
262                 sourceType.fPackage.addType(sourceType);
263                 checkAndSetModifiers();
264
265                 // Look at member types
266                 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
267                 if (referenceContext.memberTypes != null) {
268                         int size = referenceContext.memberTypes.length;
269                         memberTypeBindings = new ReferenceBinding[size];
270                         int count = 0;
271                         nextMember : for (int i = 0; i < size; i++) {
272                                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
273                                 if (memberContext.isInterface()
274                                         && sourceType.isNestedType()
275                                         && sourceType.isClass()
276                                         && !sourceType.isStatic()) {
277                                         problemReporter().nestedClassCannotDeclareInterface(memberContext);
278                                         continue nextMember;
279                                 }
280                                 ReferenceBinding type = sourceType;
281                                 // check that the member does not conflict with an enclosing type
282                                 do {
283                                         if (CharOperation.equals(type.sourceName, memberContext.name)) {
284                                                 problemReporter().hidingEnclosingType(memberContext);
285                                                 continue nextMember;
286                                         }
287                                         type = type.enclosingType();
288                                 } while (type != null);
289                                 // check that the member type does not conflict with another sibling member type
290                                 for (int j = 0; j < i; j++) {
291                                         if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
292                                                 problemReporter().duplicateNestedType(memberContext);
293                                                 continue nextMember;
294                                         }
295                                 }
296
297                                 ClassScope memberScope = new ClassScope(this, memberContext);
298                                 memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
299                         }
300                         if (count != size)
301                                 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
302                 }
303                 sourceType.memberTypes = memberTypeBindings;
304                 return sourceType;
305         }
306         
307         private void checkAndSetModifiers() {
308                 SourceTypeBinding sourceType = referenceContext.binding;
309                 int modifiers = sourceType.modifiers;
310                 if ((modifiers & AccAlternateModifierProblem) != 0)
311                         problemReporter().duplicateModifierForType(sourceType);
312
313                 ReferenceBinding enclosingType = sourceType.enclosingType();
314                 boolean isMemberType = sourceType.isMemberType();
315                 
316                 if (isMemberType) {
317                         // checks for member types before local types to catch local members
318                         if (enclosingType.isStrictfp())
319                                 modifiers |= AccStrictfp;
320                         if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
321                                 modifiers |= AccDeprecatedImplicitly;
322                         if (enclosingType.isInterface())
323                                 modifiers |= AccPublic;
324                 } else if (sourceType.isLocalType()) {
325                         if (sourceType.isAnonymousType()) 
326                             modifiers |= AccFinal;
327                         Scope scope = this;
328                         do {
329                                 switch (scope.kind) {
330                                         case METHOD_SCOPE :
331                                                 MethodScope methodScope = (MethodScope) scope;
332                                                 if (methodScope.isInsideInitializer()) {
333                                                         SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
334                         
335                                                         // inside field declaration ? check field modifier to see if deprecated
336                                                         if (methodScope.initializedField != null) {
337                                                                         // currently inside this field initialization
338                                                                 if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
339                                                                         modifiers |= AccDeprecatedImplicitly;
340                                                                 }
341                                                         } else {
342                                                                 if (type.isStrictfp())
343                                                                         modifiers |= AccStrictfp;
344                                                                 if (type.isViewedAsDeprecated() && !sourceType.isDeprecated()) 
345                                                                         modifiers |= AccDeprecatedImplicitly;
346                                                         }                                       
347                                                 } else {
348                                                         MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
349                                                         if (method != null){
350                                                                 if (method.isStrictfp())
351                                                                         modifiers |= AccStrictfp;
352                                                                 if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
353                                                                         modifiers |= AccDeprecatedImplicitly;
354                                                         }
355                                                 }
356                                                 break;
357                                         case CLASS_SCOPE :
358                                                 // local member
359                                                 if (enclosingType.isStrictfp())
360                                                         modifiers |= AccStrictfp;
361                                                 if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
362                                                         modifiers |= AccDeprecatedImplicitly;
363                                                 break;
364                                 }
365                                 scope = scope.parent;
366                         } while (scope != null);
367                 }
368                 // after this point, tests on the 16 bits reserved.
369                 int realModifiers = modifiers & AccJustFlag;
370
371                 if ((realModifiers & AccInterface) != 0) {
372                         // detect abnormal cases for interfaces
373                         if (isMemberType) {
374                                 int unexpectedModifiers =
375                                         ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp);
376                                 if ((realModifiers & unexpectedModifiers) != 0)
377                                         problemReporter().illegalModifierForMemberInterface(sourceType);
378                                 /*
379                                 } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
380                                         int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
381                                         if ((realModifiers & unexpectedModifiers) != 0)
382                                                 problemReporter().illegalModifierForLocalInterface(sourceType);
383                                 */
384                         } else {
385                                 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp);
386                                 if ((realModifiers & unexpectedModifiers) != 0)
387                                         problemReporter().illegalModifierForInterface(sourceType);
388                         }
389                         modifiers |= AccAbstract;
390                 } else {
391                         // detect abnormal cases for types
392                         if (isMemberType) { // includes member types defined inside local types
393                                 int unexpectedModifiers =
394                                         ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
395                                 if ((realModifiers & unexpectedModifiers) != 0)
396                                         problemReporter().illegalModifierForMemberClass(sourceType);
397                         } else if (sourceType.isLocalType()) {
398                                 int unexpectedModifiers = ~(AccAbstract | AccFinal | AccStrictfp);
399                                 if ((realModifiers & unexpectedModifiers) != 0)
400                                         problemReporter().illegalModifierForLocalClass(sourceType);
401                         } else {
402                                 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal | AccStrictfp);
403                                 if ((realModifiers & unexpectedModifiers) != 0)
404                                         problemReporter().illegalModifierForClass(sourceType);
405                         }
406
407                         // check that Final and Abstract are not set together
408                         if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
409                                 problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
410                 }
411
412                 if (isMemberType) {
413                         // test visibility modifiers inconsistency, isolate the accessors bits
414                         if (enclosingType.isInterface()) {
415                                 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
416                                         problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
417
418                                         // need to keep the less restrictive
419                                         if ((realModifiers & AccProtected) != 0)
420                                                 modifiers ^= AccProtected;
421                                         if ((realModifiers & AccPrivate) != 0)
422                                                 modifiers ^= AccPrivate;
423                                 }
424                         } else {
425                                 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
426                                 if ((accessorBits & (accessorBits - 1)) > 1) {
427                                         problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
428
429                                         // need to keep the less restrictive
430                                         if ((accessorBits & AccPublic) != 0) {
431                                                 if ((accessorBits & AccProtected) != 0)
432                                                         modifiers ^= AccProtected;
433                                                 if ((accessorBits & AccPrivate) != 0)
434                                                         modifiers ^= AccPrivate;
435                                         }
436                                         if ((accessorBits & AccProtected) != 0)
437                                                 if ((accessorBits & AccPrivate) != 0)
438                                                         modifiers ^= AccPrivate;
439                                 }
440                         }
441
442                         // static modifier test
443                         if ((realModifiers & AccStatic) == 0) {
444                                 if (enclosingType.isInterface())
445                                         modifiers |= AccStatic;
446                         } else {
447                                 if (!enclosingType.isStatic())
448                                         // error the enclosing type of a static field must be static or a top-level type
449                                         problemReporter().illegalStaticModifierForMemberType(sourceType);
450                         }
451                 }
452
453                 sourceType.modifiers = modifiers;
454         }
455         
456         /* This method checks the modifiers of a field.
457         *
458         * 9.3 & 8.3
459         * Need to integrate the check for the final modifiers for nested types
460         *
461         * Note : A scope is accessible by : fieldBinding.declaringClass.scope
462         */
463         private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
464                 int modifiers = fieldBinding.modifiers;
465                 if ((modifiers & AccAlternateModifierProblem) != 0)
466                         problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
467
468                 if (fieldBinding.declaringClass.isInterface()) {
469                         int expectedValue = AccPublic | AccStatic | AccFinal;
470                         // set the modifiers
471                         modifiers |= expectedValue;
472
473                         // and then check that they are the only ones
474                         if ((modifiers & AccJustFlag) != expectedValue)
475                                 problemReporter().illegalModifierForInterfaceField(fieldBinding.declaringClass, fieldDecl);
476                         fieldBinding.modifiers = modifiers;
477                         return;
478                 }
479
480                 // after this point, tests on the 16 bits reserved.
481                 int realModifiers = modifiers & AccJustFlag;
482                 int unexpectedModifiers =
483                         ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic | AccTransient | AccVolatile);
484                 if ((realModifiers & unexpectedModifiers) != 0)
485                         problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
486
487                 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
488                 if ((accessorBits & (accessorBits - 1)) > 1) {
489                         problemReporter().illegalVisibilityModifierCombinationForField(
490                                 fieldBinding.declaringClass,
491                                 fieldDecl);
492
493                         // need to keep the less restrictive
494                         if ((accessorBits & AccPublic) != 0) {
495                                 if ((accessorBits & AccProtected) != 0)
496                                         modifiers ^= AccProtected;
497                                 if ((accessorBits & AccPrivate) != 0)
498                                         modifiers ^= AccPrivate;
499                         }
500                         if ((accessorBits & AccProtected) != 0)
501                                 if ((accessorBits & AccPrivate) != 0)
502                                         modifiers ^= AccPrivate;
503                 }
504
505                 if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
506                         problemReporter().illegalModifierCombinationFinalVolatileForField(
507                                 fieldBinding.declaringClass,
508                                 fieldDecl);
509
510                 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
511                         modifiers |= AccBlankFinal;
512                 }
513                 fieldBinding.modifiers = modifiers;
514         }
515         
516         private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
517                 // search up the hierarchy of the sourceType to see if any superType defines a member type
518                 // when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
519                 ReferenceBinding currentType = sourceType;
520                 ReferenceBinding[][] interfacesToVisit = null;
521                 int lastPosition = -1;
522                 do {
523                         if ((currentType.tagBits & HasNoMemberTypes) != 0)
524                                 break; // already know it has no inherited member types, can stop looking up
525                         if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
526                                 return; // has member types
527                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
528                         if (itsInterfaces != NoSuperInterfaces) {
529                                 if (interfacesToVisit == null)
530                                         interfacesToVisit = new ReferenceBinding[5][];
531                                 if (++lastPosition == interfacesToVisit.length)
532                                         System.arraycopy(
533                                                 interfacesToVisit,
534                                                 0,
535                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
536                                                 0,
537                                                 lastPosition);
538                                 interfacesToVisit[lastPosition] = itsInterfaces;
539                         }
540                 } while ((currentType = currentType.superclass()) != null);
541
542                 boolean hasMembers = false;
543                 if (interfacesToVisit != null) {
544                         done : for (int i = 0; i <= lastPosition; i++) {
545                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
546                                 for (int j = 0, length = interfaces.length; j < length; j++) {
547                                         ReferenceBinding anInterface = interfaces[j];
548                                         if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
549                                                 anInterface.tagBits |= InterfaceVisited;
550                                                 if ((anInterface.tagBits & HasNoMemberTypes) != 0)
551                                                         continue; // already know it has no inherited member types
552                                                 if (anInterface.memberTypes() != NoMemberTypes) {
553                                                         hasMembers = true;
554                                                         break done;
555                                                 }
556
557                                                 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
558                                                 if (itsInterfaces != NoSuperInterfaces) {
559                                                         if (++lastPosition == interfacesToVisit.length)
560                                                                 System.arraycopy(
561                                                                         interfacesToVisit,
562                                                                         0,
563                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
564                                                                         0,
565                                                                         lastPosition);
566                                                         interfacesToVisit[lastPosition] = itsInterfaces;
567                                                 }
568                                         }
569                                 }
570                         }
571
572                         for (int i = 0; i <= lastPosition; i++) {
573                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
574                                 for (int j = 0, length = interfaces.length; j < length; j++) {
575                                         interfaces[j].tagBits &= ~InterfaceVisited;
576                                         if (!hasMembers)
577                                                 interfaces[j].tagBits |= HasNoMemberTypes;
578                                 }
579                         }
580                 }
581
582                 if (!hasMembers) {
583                         currentType = sourceType;
584                         do {
585                                 currentType.tagBits |= HasNoMemberTypes;
586                         } while ((currentType = currentType.superclass()) != null);
587                 }
588         }
589         
590         private void connectMemberTypes() {
591                 SourceTypeBinding sourceType = referenceContext.binding;
592                 if (sourceType.memberTypes != NoMemberTypes)
593                         for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
594                                  ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
595         }
596         /*
597                 Our current belief based on available JCK tests is:
598                         inherited member types are visible as a potential superclass.
599                         inherited interfaces are not visible when defining a superinterface.
600         
601                 Error recovery story:
602                         ensure the superclass is set to java.lang.Object if a problem is detected
603                         resolving the superclass.
604         
605                 Answer false if an error was reported against the sourceType.
606         */
607         private boolean connectSuperclass() {
608                 SourceTypeBinding sourceType = referenceContext.binding;
609                 if (sourceType.id == T_Object) { // handle the case of redefining java.lang.Object up front
610                         sourceType.superclass = null;
611                         sourceType.superInterfaces = NoSuperInterfaces;
612                         if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
613                                 problemReporter().objectCannotHaveSuperTypes(sourceType);
614                         return true; // do not propagate Object's hierarchy problems down to every subtype
615                 }
616                 if (referenceContext.superclass == null) {
617                         sourceType.superclass = getJavaLangObject();
618                         return !detectCycle(sourceType, sourceType.superclass, null);
619                 }
620                 ReferenceBinding superclass = findSupertype(referenceContext.superclass);
621                 if (superclass != null) { // is null if a cycle was detected cycle
622                         referenceContext.superclass.resolvedType = superclass; // hold onto the problem type
623                         if (!superclass.isValidBinding()) {
624                                 problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
625                         } else if (superclass.isInterface()) {
626                                 problemReporter().superclassMustBeAClass(sourceType, referenceContext.superclass, superclass);
627                         } else if (superclass.isFinal()) {
628                                 problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
629                         } else {
630                                 // only want to reach here when no errors are reported
631                                 sourceType.superclass = superclass;
632                                 return true;
633                         }
634                 }
635                 sourceType.tagBits |= HierarchyHasProblems;
636                 sourceType.superclass = getJavaLangObject();
637                 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
638                         detectCycle(sourceType, sourceType.superclass, null);
639                 return false; // reported some error against the source type
640         }
641
642         /*
643                 Our current belief based on available JCK 1.3 tests is:
644                         inherited member types are visible as a potential superclass.
645                         inherited interfaces are visible when defining a superinterface.
646         
647                 Error recovery story:
648                         ensure the superinterfaces contain only valid visible interfaces.
649         
650                 Answer false if an error was reported against the sourceType.
651         */
652         private boolean connectSuperInterfaces() {
653                 SourceTypeBinding sourceType = referenceContext.binding;
654                 sourceType.superInterfaces = NoSuperInterfaces;
655                 if (referenceContext.superInterfaces == null)
656                         return true;
657                 if (sourceType.id == T_Object) // already handled the case of redefining java.lang.Object
658                         return true;
659
660                 boolean noProblems = true;
661                 int length = referenceContext.superInterfaces.length;
662                 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
663                 int count = 0;
664                 nextInterface : for (int i = 0; i < length; i++) {
665                         ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
666                         if (superInterface == null) { // detected cycle
667                                 noProblems = false;
668                                 continue nextInterface;
669                         }
670                         referenceContext.superInterfaces[i].resolvedType = superInterface; // hold onto the problem type
671                         if (!superInterface.isValidBinding()) {
672                                 problemReporter().invalidSuperinterface(
673                                         sourceType,
674                                         referenceContext.superInterfaces[i],
675                                         superInterface);
676                                 sourceType.tagBits |= HierarchyHasProblems;
677                                 noProblems = false;
678                                 continue nextInterface;
679                         }
680                         // Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
681                         for (int k = 0; k < count; k++) {
682                                 if (interfaceBindings[k] == superInterface) {
683                                         // should this be treated as a warning?
684                                         problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
685                                         continue nextInterface;
686                                 }
687                         }
688                         if (superInterface.isClass()) {
689                                 problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
690                                 sourceType.tagBits |= HierarchyHasProblems;
691                                 noProblems = false;
692                                 continue nextInterface;
693                         }
694
695                         // only want to reach here when no errors are reported
696                         interfaceBindings[count++] = superInterface;
697                 }
698                 // hold onto all correctly resolved superinterfaces
699                 if (count > 0) {
700                         if (count != length)
701                                 System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
702                         sourceType.superInterfaces = interfaceBindings;
703                 }
704                 return noProblems;
705         }
706         
707         void connectTypeHierarchy() {
708                 SourceTypeBinding sourceType = referenceContext.binding;
709                 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
710                         boolean noProblems = true;
711                         sourceType.tagBits |= BeginHierarchyCheck;
712                         if (sourceType.isClass())
713                                 noProblems &= connectSuperclass();
714                         noProblems &= connectSuperInterfaces();
715                         sourceType.tagBits |= EndHierarchyCheck;
716                         if (noProblems && sourceType.isHierarchyInconsistent())
717                                 problemReporter().hierarchyHasProblems(sourceType);
718                 }
719                 connectMemberTypes();
720                 try {
721                         checkForInheritedMemberTypes(sourceType);
722                 } catch (AbortCompilation e) {
723                         e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
724                         throw e;
725                 }
726         }
727         
728         private void connectTypeHierarchyWithoutMembers() {
729                 // must ensure the imports are resolved
730                 if (parent instanceof CompilationUnitScope) {
731                         if (((CompilationUnitScope) parent).imports == null)
732                                  ((CompilationUnitScope) parent).checkAndSetImports();
733                 } else if (parent instanceof ClassScope) {
734                         // ensure that the enclosing type has already been checked
735                          ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
736                 }
737
738                 // double check that the hierarchy search has not already begun...
739                 SourceTypeBinding sourceType = referenceContext.binding;
740                 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
741                         return;
742
743                 boolean noProblems = true;
744                 sourceType.tagBits |= BeginHierarchyCheck;
745                 if (sourceType.isClass())
746                         noProblems &= connectSuperclass();
747                 noProblems &= connectSuperInterfaces();
748                 sourceType.tagBits |= EndHierarchyCheck;
749                 if (noProblems && sourceType.isHierarchyInconsistent())
750                         problemReporter().hierarchyHasProblems(sourceType);
751         }
752         
753         // Answer whether a cycle was found between the sourceType & the superType
754         private boolean detectCycle(
755                 SourceTypeBinding sourceType,
756                 ReferenceBinding superType,
757                 TypeReference reference) {
758                 if (sourceType == superType) {
759                         problemReporter().hierarchyCircularity(sourceType, superType, reference);
760                         sourceType.tagBits |= HierarchyHasProblems;
761                         return true;
762                 }
763
764                 if (superType.isBinaryBinding()) {
765                         // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
766                         //              - a binary type... this case MUST be caught & reported here
767                         //              - another source type... this case is reported against the other source type
768                         boolean hasCycle = false;
769                         if (superType.superclass() != null) {
770                                 if (sourceType == superType.superclass()) {
771                                         problemReporter().hierarchyCircularity(sourceType, superType, reference);
772                                         sourceType.tagBits |= HierarchyHasProblems;
773                                         superType.tagBits |= HierarchyHasProblems;
774                                         return true;
775                                 }
776                                 hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
777                                 if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
778                                         sourceType.tagBits |= HierarchyHasProblems;
779                                         superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
780                                 }
781                         }
782
783                         ReferenceBinding[] itsInterfaces = superType.superInterfaces();
784                         if (itsInterfaces != NoSuperInterfaces) {
785                                 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
786                                         ReferenceBinding anInterface = itsInterfaces[i];
787                                         if (sourceType == anInterface) {
788                                                 problemReporter().hierarchyCircularity(sourceType, superType, reference);
789                                                 sourceType.tagBits |= HierarchyHasProblems;
790                                                 superType.tagBits |= HierarchyHasProblems;
791                                                 return true;
792                                         }
793                                         hasCycle |= detectCycle(sourceType, anInterface, reference);
794                                         if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
795                                                 sourceType.tagBits |= HierarchyHasProblems;
796                                                 superType.tagBits |= HierarchyHasProblems;
797                                         }
798                                 }
799                         }
800                         return hasCycle;
801                 }
802
803                 if ((superType.tagBits & EndHierarchyCheck) == 0
804                         && (superType.tagBits & BeginHierarchyCheck) != 0) {
805                         problemReporter().hierarchyCircularity(sourceType, superType, reference);
806                         sourceType.tagBits |= HierarchyHasProblems;
807                         superType.tagBits |= HierarchyHasProblems;
808                         return true;
809                 }
810                 if ((superType.tagBits & BeginHierarchyCheck) == 0)
811                         // ensure if this is a source superclass that it has already been checked
812                          ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
813                 if ((superType.tagBits & HierarchyHasProblems) != 0)
814                         sourceType.tagBits |= HierarchyHasProblems;
815                 return false;
816         }
817         
818         private ReferenceBinding findSupertype(TypeReference typeReference) {
819                 try {
820                         typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
821                         char[][] compoundName = typeReference.getTypeName();
822                         compilationUnitScope().recordQualifiedReference(compoundName);
823                         SourceTypeBinding sourceType = referenceContext.binding;
824                         int size = compoundName.length;
825                         int n = 1;
826                         ReferenceBinding superType;
827         
828                         // resolve the first name of the compoundName
829                         if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
830                                 superType = sourceType;
831                                 // match against the sourceType even though nested members cannot be supertypes
832                         } else {
833                                 Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
834                                 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
835                                         return new ProblemReferenceBinding(
836                                                 compoundName[0],
837                                                 typeOrPackage == null ? NotFound : typeOrPackage.problemId());
838         
839                                 boolean checkVisibility = false;
840                                 for (; n < size; n++) {
841                                         if (!(typeOrPackage instanceof PackageBinding))
842                                                 break;
843                                         PackageBinding packageBinding = (PackageBinding) typeOrPackage;
844                                         typeOrPackage = packageBinding.getTypeOrPackage(compoundName[n]);
845                                         if (typeOrPackage == null || !typeOrPackage.isValidBinding())
846                                                 return new ProblemReferenceBinding(
847                                                         CharOperation.subarray(compoundName, 0, n + 1),
848                                                         typeOrPackage == null ? NotFound : typeOrPackage.problemId());
849                                         checkVisibility = true;
850                                 }
851         
852                                 // convert to a ReferenceBinding
853                                 if (typeOrPackage instanceof PackageBinding) // error, the compoundName is a packageName
854                                         return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
855                                 superType = (ReferenceBinding) typeOrPackage;
856                                 compilationUnitScope().recordTypeReference(superType); // to record supertypes
857         
858                                 if (checkVisibility
859                                         && n == size) { // if we're finished and know the final supertype then check visibility
860                                         if (!superType.canBeSeenBy(sourceType.fPackage))
861                                                 // its a toplevel type so just check package access
862                                                 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), superType, NotVisible);
863                                 }
864                         }
865                         // at this point we know we have a type but we have to look for cycles
866                         while (true) {
867                                 // must detect cycles & force connection up the hierarchy... also handle cycles with binary types.
868                                 // must be guaranteed that the superType knows its entire hierarchy
869                                 if (detectCycle(sourceType, superType, typeReference))
870                                         return null; // cycle error was already reported
871         
872                                 if (n >= size)
873                                         break;
874         
875                                 // retrieve the next member type
876                                 char[] typeName = compoundName[n++];
877                                 superType = findMemberType(typeName, superType);
878                                 if (superType == null)
879                                         return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
880                                 if (!superType.isValidBinding()) {
881                                         superType.compoundName = CharOperation.subarray(compoundName, 0, n);
882                                         return superType;
883                                 }
884                         }
885                         return superType;
886                 } catch (AbortCompilation e) {
887                         e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
888                         throw e;
889                 }
890         }
891
892         /* Answer the problem reporter to use for raising new problems.
893         *
894         * Note that as a side-effect, this updates the current reference context
895         * (unit, type or method) in case the problem handler decides it is necessary
896         * to abort.
897         */
898         public ProblemReporter problemReporter() {
899                 MethodScope outerMethodScope;
900                 if ((outerMethodScope = outerMostMethodScope()) == null) {
901                         ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
902                         problemReporter.referenceContext = referenceContext;
903                         return problemReporter;
904                 }
905                 return outerMethodScope.problemReporter();
906         }
907
908         /* Answer the reference type of this scope.
909         * It is the nearest enclosing type of this scope.
910         */
911         public TypeDeclaration referenceType() {
912                 return referenceContext;
913         }
914         
915         public String toString() {
916                 if (referenceContext != null)
917                         return "--- Class Scope ---\n\n"  //$NON-NLS-1$
918                                                         + referenceContext.binding.toString();
919                 return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$
920         }
921 }