KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > ClassScope


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.lookup;
12
13 import java.util.*;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
17 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
19 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
20 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
23 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
24 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
25 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
26 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
27 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
28 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
29
30 public class ClassScope extends Scope {
31     
32     public TypeDeclaration referenceContext;
33     public TypeReference superTypeReference;
34
35     public ClassScope(Scope parent, TypeDeclaration context) {
36         super(CLASS_SCOPE, parent);
37         this.referenceContext = context;
38     }
39     
40     void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
41         LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
42         SourceTypeBinding sourceType = referenceContext.binding;
43         if (supertype.isInterface()) {
44             sourceType.superclass = getJavaLangObject();
45             sourceType.superInterfaces = new ReferenceBinding[] { supertype };
46         } else {
47             sourceType.superclass = supertype;
48             sourceType.superInterfaces = Binding.NO_SUPERINTERFACES;
49         }
50         connectMemberTypes();
51         buildFieldsAndMethods();
52         anonymousType.faultInTypesForFieldsAndMethods();
53         sourceType.verifyMethods(environment().methodVerifier());
54     }
55     
56     private void buildFields() {
57         if (referenceContext.fields == null) {
58             referenceContext.binding.setFields(Binding.NO_FIELDS);
59             return;
60         }
61         // count the number of fields vs. initializers
62
FieldDeclaration[] fields = referenceContext.fields;
63         int size = fields.length;
64         int count = 0;
65         for (int i = 0; i < size; i++) {
66             switch (fields[i].getKind()) {
67                 case AbstractVariableDeclaration.FIELD:
68                 case AbstractVariableDeclaration.ENUM_CONSTANT:
69                     count++;
70             }
71         }
72
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.getKind() == AbstractVariableDeclaration.INITIALIZER) {
81                 if (referenceContext.binding.isInterface())
82                     problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
83             } else {
84                 FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | ExtraCompilerModifiers.AccUnresolved, referenceContext.binding);
85                 fieldBinding.id = count;
86                 // field's type will be resolved when needed for top level types
87
checkAndSetModifiersForField(fieldBinding, field);
88
89                 if (knownFieldNames.containsKey(field.name)) {
90                     duplicate = true;
91                     FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
92                     if (previousBinding != null) {
93                         for (int f = 0; f < i; f++) {
94                             FieldDeclaration previousField = fields[f];
95                             if (previousField.binding == previousBinding) {
96                                 problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
97                                 previousField.binding = null;
98                                 break;
99                             }
100                         }
101                     }
102                     knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
103
problemReporter().duplicateFieldInType(referenceContext.binding, field);
104                     field.binding = null;
105                 } else {
106                     knownFieldNames.put(field.name, fieldBinding);
107                     // remember that we have seen a field with this name
108
fieldBindings[count++] = fieldBinding;
109                 }
110             }
111         }
112         // remove duplicate fields
113
if (duplicate) {
114             FieldBinding[] newFieldBindings = new FieldBinding[fieldBindings.length];
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                     fieldBinding.id = count;
122                     newFieldBindings[count++] = fieldBinding;
123                 }
124             }
125             fieldBindings = newFieldBindings;
126         }
127         if (count != fieldBindings.length)
128             System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
129         referenceContext.binding.setFields(fieldBindings);
130     }
131     
132     void buildFieldsAndMethods() {
133         buildFields();
134         buildMethods();
135
136         SourceTypeBinding sourceType = referenceContext.binding;
137         if (sourceType.isMemberType() && !sourceType.isLocalType())
138              ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
139
140         ReferenceBinding[] memberTypes = sourceType.memberTypes;
141         for (int i = 0, length = memberTypes.length; i < length; i++)
142              ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
143     }
144     
145     private LocalTypeBinding buildLocalType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
146         
147         referenceContext.scope = this;
148         referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
149         referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
150
151         // build the binding or the local type
152
LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.innermostSwitchCase());
153         referenceContext.binding = localType;
154         checkAndSetModifiers();
155         buildTypeVariables();
156         
157         // Look at member types
158
ReferenceBinding[] memberTypeBindings = Binding.NO_MEMBER_TYPES;
159         if (referenceContext.memberTypes != null) {
160             int size = referenceContext.memberTypes.length;
161             memberTypeBindings = new ReferenceBinding[size];
162             int count = 0;
163             nextMember : for (int i = 0; i < size; i++) {
164                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
165                 switch(TypeDeclaration.kind(memberContext.modifiers)) {
166                     case TypeDeclaration.INTERFACE_DECL :
167                     case TypeDeclaration.ANNOTATION_TYPE_DECL :
168                         problemReporter().illegalLocalTypeDeclaration(memberContext);
169                         continue nextMember;
170                 }
171                 ReferenceBinding type = localType;
172                 // check that the member does not conflict with an enclosing type
173
do {
174                     if (CharOperation.equals(type.sourceName, memberContext.name)) {
175                         problemReporter().typeCollidesWithEnclosingType(memberContext);
176                         continue nextMember;
177                     }
178                     type = type.enclosingType();
179                 } while (type != null);
180                 // check the member type does not conflict with another sibling member type
181
for (int j = 0; j < i; j++) {
182                     if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
183                         problemReporter().duplicateNestedType(memberContext);
184                         continue nextMember;
185                     }
186                 }
187                 ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
188                 LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
189                 memberBinding.setAsMemberType();
190                 memberTypeBindings[count++] = memberBinding;
191             }
192             if (count != size)
193                 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
194         }
195         localType.memberTypes = memberTypeBindings;
196         return localType;
197     }
198     
199     void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
200
201         LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
202         connectTypeHierarchy();
203         buildFieldsAndMethods();
204         localType.faultInTypesForFieldsAndMethods();
205
206         referenceContext.binding.verifyMethods(environment().methodVerifier());
207     }
208     
209     private void buildMemberTypes(AccessRestriction accessRestriction) {
210         SourceTypeBinding sourceType = referenceContext.binding;
211         ReferenceBinding[] memberTypeBindings = Binding.NO_MEMBER_TYPES;
212         if (referenceContext.memberTypes != null) {
213             int length = referenceContext.memberTypes.length;
214             memberTypeBindings = new ReferenceBinding[length];
215             int count = 0;
216             nextMember : for (int i = 0; i < length; i++) {
217                 TypeDeclaration memberContext = referenceContext.memberTypes[i];
218                 switch(TypeDeclaration.kind(memberContext.modifiers)) {
219                     case TypeDeclaration.INTERFACE_DECL :
220                     case TypeDeclaration.ANNOTATION_TYPE_DECL :
221                         if (sourceType.isNestedType()
222                                 && sourceType.isClass() // no need to check for enum, since implicitly static
223
&& !sourceType.isStatic()) {
224                             problemReporter().illegalLocalTypeDeclaration(memberContext);
225                             continue nextMember;
226                         }
227                     break;
228                 }
229                 ReferenceBinding type = sourceType;
230                 // check that the member does not conflict with an enclosing type
231
do {
232                     if (CharOperation.equals(type.sourceName, memberContext.name)) {
233                         problemReporter().typeCollidesWithEnclosingType(memberContext);
234                         continue nextMember;
235                     }
236                     type = type.enclosingType();
237                 } while (type != null);
238                 // check that the member type does not conflict with another sibling member type
239
for (int j = 0; j < i; j++) {
240                     if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
241                         problemReporter().duplicateNestedType(memberContext);
242                         continue nextMember;
243                     }
244                 }
245
246                 ClassScope memberScope = new ClassScope(this, memberContext);
247                 memberTypeBindings[count++] = memberScope.buildType(sourceType, sourceType.fPackage, accessRestriction);
248             }
249             if (count != length)
250                 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
251         }
252         sourceType.memberTypes = memberTypeBindings;
253     }
254     
255     private void buildMethods() {
256         boolean isEnum = TypeDeclaration.kind(referenceContext.modifiers) == TypeDeclaration.ENUM_DECL;
257         if (referenceContext.methods == null && !isEnum) {
258             referenceContext.binding.setMethods(Binding.NO_METHODS);
259             return;
260         }
261
262         // iterate the method declarations to create the bindings
263
AbstractMethodDeclaration[] methods = referenceContext.methods;
264         int size = methods == null ? 0 : methods.length;
265         // look for <clinit> method
266
int clinitIndex = -1;
267         for (int i = 0; i < size; i++) {
268             if (methods[i].isClinit()) {
269                 clinitIndex = i;
270                 break;
271             }
272         }
273
274         int count = isEnum ? 2 : 0; // reserve 2 slots for special enum methods: #values() and #valueOf(String)
275
MethodBinding[] methodBindings = new MethodBinding[(clinitIndex == -1 ? size : size - 1) + count];
276         // create special methods for enums
277
SourceTypeBinding sourceType = referenceContext.binding;
278         if (isEnum) {
279             methodBindings[0] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUES); // add <EnumType>[] values()
280
methodBindings[1] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUEOF); // add <EnumType> valueOf()
281
}
282         // create bindings for source methods
283
for (int i = 0; i < size; i++) {
284             if (i != clinitIndex) {
285                 MethodScope scope = new MethodScope(this, methods[i], false);
286                 MethodBinding methodBinding = scope.createMethod(methods[i]);
287                 if (methodBinding != null) // is null if binding could not be created
288
methodBindings[count++] = methodBinding;
289             }
290         }
291         if (count != methodBindings.length)
292             System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
293         sourceType.tagBits &= ~TagBits.AreMethodsSorted; // in case some static imports reached already into this type
294
sourceType.setMethods(methodBindings);
295     }
296     
297     SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
298         // provide the typeDeclaration with needed scopes
299
referenceContext.scope = this;
300         referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
301         referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
302
303         if (enclosingType == null) {
304             char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
305             referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
306         } else {
307             char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
308             className[className.length - 1] =
309                 CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
310             ReferenceBinding existingType = packageBinding.getType0(className[className.length - 1]);
311             if (existingType != null) {
312                 if (existingType instanceof UnresolvedReferenceBinding) {
313                     // its possible that a BinaryType referenced the member type before its enclosing source type was built
314
// so just replace the unresolved type with a new member type
315
} else {
316                     // report the error against the parent - its still safe to answer the member type
317
this.parent.problemReporter().duplicateNestedType(referenceContext);
318                 }
319             }
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 || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
339             sourceType.typeVariables = Binding.NO_TYPE_VARIABLES;
340             return;
341         }
342         sourceType.typeVariables = Binding.NO_TYPE_VARIABLES; // 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 |= ExtraCompilerModifiers.AccGenericSignature;
350     }
351     
352     private void checkAndSetModifiers() {
353         SourceTypeBinding sourceType = referenceContext.binding;
354         int modifiers = sourceType.modifiers;
355         if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
356             problemReporter().duplicateModifierForType(sourceType);
357         ReferenceBinding enclosingType = sourceType.enclosingType();
358         boolean isMemberType = sourceType.isMemberType();
359         if (isMemberType) {
360             modifiers |= (enclosingType.modifiers & (ExtraCompilerModifiers.AccGenericSignature|ClassFileConstants.AccStrictfp));
361             // checks for member types before local types to catch local members
362
if (enclosingType.isInterface())
363                 modifiers |= ClassFileConstants.AccPublic;
364             if (sourceType.isEnum()) {
365                 if (!enclosingType.isStatic())
366                     problemReporter().nonStaticContextForEnumMemberType(sourceType);
367                 else
368                     modifiers |= ClassFileConstants.AccStatic;
369             }
370             if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
371                 modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
372         } else if (sourceType.isLocalType()) {
373             if (sourceType.isEnum()) {
374                 problemReporter().illegalLocalTypeDeclaration(referenceContext);
375                 sourceType.modifiers = 0;
376                 return;
377             }
378             if (sourceType.isAnonymousType()) {
379                 modifiers |= ClassFileConstants.AccFinal;
380                 // set AccEnum flag for anonymous body of enum constants
381
if (referenceContext.allocation.type == null)
382                     modifiers |= ClassFileConstants.AccEnum;
383             }
384             Scope scope = this;
385             do {
386                 switch (scope.kind) {
387                     case METHOD_SCOPE :
388                         MethodScope methodScope = (MethodScope) scope;
389                         if (methodScope.isInsideInitializer()) {
390                             SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
391             
392                             // inside field declaration ? check field modifier to see if deprecated
393
if (methodScope.initializedField != null) {
394                                     // currently inside this field initialization
395
if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated())
396                                     modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
397                             } else {
398                                 if (type.isStrictfp())
399                                     modifiers |= ClassFileConstants.AccStrictfp;
400                                 if (type.isViewedAsDeprecated() && !sourceType.isDeprecated())
401                                     modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
402                             }
403                         } else {
404                             MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
405                             if (method != null) {
406                                 if (method.isStrictfp())
407                                     modifiers |= ClassFileConstants.AccStrictfp;
408                                 if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
409                                     modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
410                             }
411                         }
412                         break;
413                     case CLASS_SCOPE :
414                         // local member
415
if (enclosingType.isStrictfp())
416                             modifiers |= ClassFileConstants.AccStrictfp;
417                         if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
418                             modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
419                         break;
420                 }
421                 scope = scope.parent;
422             } while (scope != null);
423         }
424
425         // after this point, tests on the 16 bits reserved.
426
int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
427
428         if ((realModifiers & ClassFileConstants.AccInterface) != 0) { // interface and annotation type
429
// detect abnormal cases for interfaces
430
if (isMemberType) {
431                 final int UNEXPECTED_MODIFIERS =
432                     ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccStrictfp | ClassFileConstants.AccAnnotation);
433                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
434                     if ((realModifiers & ClassFileConstants.AccAnnotation) != 0)
435                         problemReporter().illegalModifierForAnnotationMemberType(sourceType);
436                     else
437                         problemReporter().illegalModifierForMemberInterface(sourceType);
438                 }
439                 /*
440                 } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
441                     int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
442                     if ((realModifiers & unexpectedModifiers) != 0)
443                         problemReporter().illegalModifierForLocalInterface(sourceType);
444                 */

445             } else {
446                 final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccStrictfp | ClassFileConstants.AccAnnotation);
447                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
448                     if ((realModifiers & ClassFileConstants.AccAnnotation) != 0)
449                         problemReporter().illegalModifierForAnnotationType(sourceType);
450                     else
451                         problemReporter().illegalModifierForInterface(sourceType);
452                 }
453             }
454             modifiers |= ClassFileConstants.AccAbstract;
455         } else if ((realModifiers & ClassFileConstants.AccEnum) != 0) {
456             // detect abnormal cases for enums
457
if (isMemberType) { // includes member types defined inside local types
458
final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccStrictfp | ClassFileConstants.AccEnum);
459                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0)
460                     problemReporter().illegalModifierForMemberEnum(sourceType);
461             } else if (sourceType.isLocalType()) { // each enum constant is an anonymous local type
462
final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccFinal | ClassFileConstants.AccEnum); // add final since implicitly set for anonymous type
463
if ((realModifiers & UNEXPECTED_MODIFIERS) != 0)
464                     problemReporter().illegalModifierForLocalEnum(sourceType);
465             } else {
466                 final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccStrictfp | ClassFileConstants.AccEnum);
467                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0)
468                     problemReporter().illegalModifierForEnum(sourceType);
469             }
470             if (!sourceType.isAnonymousType()) {
471                 checkAbstractEnum: {
472                     // does define abstract methods ?
473
if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) {
474                         modifiers |= ClassFileConstants.AccAbstract;
475                         break checkAbstractEnum;
476                     }
477                     // body of enum constant must implement any inherited abstract methods
478
// enum type needs to implement abstract methods if one of its constants does not supply a body
479
TypeDeclaration typeDeclaration = this.referenceContext;
480                     FieldDeclaration[] fields = typeDeclaration.fields;
481                     int fieldsLength = fields == null ? 0 : fields.length;
482                     if (fieldsLength == 0) break checkAbstractEnum; // has no constants so must implement the method itself
483
AbstractMethodDeclaration[] methods = typeDeclaration.methods;
484                     int methodsLength = methods == null ? 0 : methods.length;
485                     // TODO (kent) cannot tell that the superinterfaces are empty or that their methods are implemented
486
boolean definesAbstractMethod = typeDeclaration.superInterfaces != null;
487                     for (int i = 0; i < methodsLength && !definesAbstractMethod; i++)
488                         definesAbstractMethod = methods[i].isAbstract();
489                     if (!definesAbstractMethod) break checkAbstractEnum; // all methods have bodies
490
boolean needAbstractBit = false;
491                     for (int i = 0; i < fieldsLength; i++) {
492                         FieldDeclaration fieldDecl = fields[i];
493                         if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
494                             if (fieldDecl.initialization instanceof QualifiedAllocationExpression) {
495                                 needAbstractBit = true;
496                             } else {
497                                 break checkAbstractEnum;
498                             }
499                         }
500                     }
501                     // tag this enum as abstract since an abstract method must be implemented AND all enum constants define an anonymous body
502
// as a result, each of its anonymous constants will see it as abstract and must implement each inherited abstract method
503
if (needAbstractBit) {
504                         modifiers |= ClassFileConstants.AccAbstract;
505                     }
506                 }
507                 // final if no enum constant with anonymous body
508
checkFinalEnum: {
509                     TypeDeclaration typeDeclaration = this.referenceContext;
510                     FieldDeclaration[] fields = typeDeclaration.fields;
511                     if (fields != null) {
512                         for (int i = 0, fieldsLength = fields.length; i < fieldsLength; i++) {
513                             FieldDeclaration fieldDecl = fields[i];
514                             if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
515                                 if (fieldDecl.initialization instanceof QualifiedAllocationExpression) {
516                                     break checkFinalEnum;
517                                 }
518                             }
519                         }
520                     }
521                     modifiers |= ClassFileConstants.AccFinal;
522                 }
523             }
524         } else {
525             // detect abnormal cases for classes
526
if (isMemberType) { // includes member types defined inside local types
527
final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp);
528                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0)
529                     problemReporter().illegalModifierForMemberClass(sourceType);
530             } else if (sourceType.isLocalType()) {
531                 final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp);
532                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0)
533                     problemReporter().illegalModifierForLocalClass(sourceType);
534             } else {
535                 final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp);
536                 if ((realModifiers & UNEXPECTED_MODIFIERS) != 0)
537                     problemReporter().illegalModifierForClass(sourceType);
538             }
539
540             // check that Final and Abstract are not set together
541
if ((realModifiers & (ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract)) == (ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract))
542                 problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
543         }
544
545         if (isMemberType) {
546             // test visibility modifiers inconsistency, isolate the accessors bits
547
if (enclosingType.isInterface()) {
548                 if ((realModifiers & (ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate)) != 0) {
549                     problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
550
551                     // need to keep the less restrictive
552
if ((realModifiers & ClassFileConstants.AccProtected) != 0)
553                         modifiers &= ~ClassFileConstants.AccProtected;
554                     if ((realModifiers & ClassFileConstants.AccPrivate) != 0)
555                         modifiers &= ~ClassFileConstants.AccPrivate;
556                 }
557             } else {
558                 int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
559                 if ((accessorBits & (accessorBits - 1)) > 1) {
560                     problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
561
562                     // need to keep the less restrictive so disable Protected/Private as necessary
563
if ((accessorBits & ClassFileConstants.AccPublic) != 0) {
564                         if ((accessorBits & ClassFileConstants.AccProtected) != 0)
565                             modifiers &= ~ClassFileConstants.AccProtected;
566                         if ((accessorBits & ClassFileConstants.AccPrivate) != 0)
567                             modifiers &= ~ClassFileConstants.AccPrivate;
568                     } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) {
569                         modifiers &= ~ClassFileConstants.AccPrivate;
570                     }
571                 }
572             }
573
574             // static modifier test
575
if ((realModifiers & ClassFileConstants.AccStatic) == 0) {
576                 if (enclosingType.isInterface())
577                     modifiers |= ClassFileConstants.AccStatic;
578             } else if (!enclosingType.isStatic()) {
579                 // error the enclosing type of a static field must be static or a top-level type
580
problemReporter().illegalStaticModifierForMemberType(sourceType);
581             }
582         }
583
584         sourceType.modifiers = modifiers;
585     }
586     
587     /* This method checks the modifiers of a field.
588     *
589     * 9.3 & 8.3
590     * Need to integrate the check for the final modifiers for nested types
591     *
592     * Note : A scope is accessible by : fieldBinding.declaringClass.scope
593     */

594     private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
595         int modifiers = fieldBinding.modifiers;
596         final ReferenceBinding declaringClass = fieldBinding.declaringClass;
597         if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
598             problemReporter().duplicateModifierForField(declaringClass, fieldDecl);
599
600         if (declaringClass.isInterface()) {
601             final int IMPLICIT_MODIFIERS = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal;
602             // set the modifiers
603
modifiers |= IMPLICIT_MODIFIERS;
604
605             // and then check that they are the only ones
606
if ((modifiers & ExtraCompilerModifiers.AccJustFlag) != IMPLICIT_MODIFIERS) {
607                 if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0)
608                     problemReporter().illegalModifierForAnnotationField(fieldDecl);
609                 else
610                     problemReporter().illegalModifierForInterfaceField(fieldDecl);
611             }
612             fieldBinding.modifiers = modifiers;
613             return;
614         } else if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
615             // check that they are not modifiers in source
616
if ((modifiers & ExtraCompilerModifiers.AccJustFlag) != 0)
617                 problemReporter().illegalModifierForEnumConstant(declaringClass, fieldDecl);
618         
619             // set the modifiers
620
final int IMPLICIT_MODIFIERS = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccEnum;
621             fieldBinding.modifiers|= IMPLICIT_MODIFIERS;
622             return;
623         }
624
625         // after this point, tests on the 16 bits reserved.
626
int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
627         final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccFinal | ClassFileConstants.AccStatic | ClassFileConstants.AccTransient | ClassFileConstants.AccVolatile);
628         if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
629             problemReporter().illegalModifierForField(declaringClass, fieldDecl);
630             modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS;
631         }
632
633         int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
634         if ((accessorBits & (accessorBits - 1)) > 1) {
635             problemReporter().illegalVisibilityModifierCombinationForField(declaringClass, fieldDecl);
636
637             // need to keep the less restrictive so disable Protected/Private as necessary
638
if ((accessorBits & ClassFileConstants.AccPublic) != 0) {
639                 if ((accessorBits & ClassFileConstants.AccProtected) != 0)
640                     modifiers &= ~ClassFileConstants.AccProtected;
641                 if ((accessorBits & ClassFileConstants.AccPrivate) != 0)
642                     modifiers &= ~ClassFileConstants.AccPrivate;
643             } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) {
644                 modifiers &= ~ClassFileConstants.AccPrivate;
645             }
646         }
647
648         if ((realModifiers & (ClassFileConstants.AccFinal | ClassFileConstants.AccVolatile)) == (ClassFileConstants.AccFinal | ClassFileConstants.AccVolatile))
649             problemReporter().illegalModifierCombinationFinalVolatileForField(declaringClass, fieldDecl);
650
651         if (fieldDecl.initialization == null && (modifiers & ClassFileConstants.AccFinal) != 0)
652             modifiers |= ExtraCompilerModifiers.AccBlankFinal;
653         fieldBinding.modifiers = modifiers;
654     }
655
656     public void checkParameterizedSuperTypeCollisions() {
657         // check for parameterized interface collisions (when different parameterizations occur)
658
SourceTypeBinding sourceType = referenceContext.binding;
659         ReferenceBinding[] interfaces = sourceType.superInterfaces;
660         Map invocations = new HashMap(2);
661         ReferenceBinding itsSuperclass = sourceType.isInterface() ? null : sourceType.superclass;
662         nextInterface: for (int i = 0, length = interfaces.length; i < length; i++) {
663             ReferenceBinding one = interfaces[i];
664             if (one == null) continue nextInterface;
665             if (itsSuperclass != null && hasErasedCandidatesCollisions(itsSuperclass, one, invocations, sourceType, referenceContext))
666                 continue nextInterface;
667             nextOtherInterface: for (int j = 0; j < i; j++) {
668                 ReferenceBinding two = interfaces[j];
669                 if (two == null) continue nextOtherInterface;
670                 if (hasErasedCandidatesCollisions(one, two, invocations, sourceType, referenceContext))
671                     continue nextInterface;
672             }
673         }
674
675         TypeParameter[] typeParameters = this.referenceContext.typeParameters;
676         nextVariable : for (int i = 0, paramLength = typeParameters == null ? 0 : typeParameters.length; i < paramLength; i++) {
677             TypeParameter typeParameter = typeParameters[i];
678             TypeVariableBinding typeVariable = typeParameter.binding;
679             if (typeVariable == null || !typeVariable.isValidBinding()) continue nextVariable;
680
681             TypeReference[] boundRefs = typeParameter.bounds;
682             if (boundRefs != null) {
683                 boolean checkSuperclass = typeVariable.firstBound == typeVariable.superclass;
684                 for (int j = 0, boundLength = boundRefs.length; j < boundLength; j++) {
685                     TypeReference typeRef = boundRefs[j];
686                     TypeBinding superType = typeRef.resolvedType;
687                     if (superType == null || !superType.isValidBinding()) continue;
688
689                     // check against superclass
690
if (checkSuperclass)
691                         if (hasErasedCandidatesCollisions(superType, typeVariable.superclass, invocations, typeVariable, typeRef))
692                             continue nextVariable;
693                     // check against superinterfaces
694
for (int index = typeVariable.superInterfaces.length; --index >= 0;)
695                         if (hasErasedCandidatesCollisions(superType, typeVariable.superInterfaces[index], invocations, typeVariable, typeRef))
696                             continue nextVariable;
697                 }
698             }
699         }
700
701         ReferenceBinding[] memberTypes = referenceContext.binding.memberTypes;
702         if (memberTypes != null && memberTypes != Binding.NO_MEMBER_TYPES)
703             for (int i = 0, size = memberTypes.length; i < size; i++)
704                  ((SourceTypeBinding) memberTypes[i]).scope.checkParameterizedSuperTypeCollisions();
705     }
706
707     private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
708         // search up the hierarchy of the sourceType to see if any superType defines a member type
709
// when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
710
// assumes super types have already been checked & tagged
711
ReferenceBinding currentType = sourceType;
712         ReferenceBinding[] interfacesToVisit = null;
713         int nextPosition = 0;
714         do {
715             if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
716
return;
717
718             ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
719             // in code assist cases when source types are added late, may not be finished connecting hierarchy
720
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
721                 if (interfacesToVisit == null) {
722                     interfacesToVisit = itsInterfaces;
723                     nextPosition = interfacesToVisit.length;
724                 } else {
725                     int itsLength = itsInterfaces.length;
726                     if (nextPosition + itsLength >= interfacesToVisit.length)
727                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
728                     nextInterface : for (int a = 0; a < itsLength; a++) {
729                         ReferenceBinding next = itsInterfaces[a];
730                         for (int b = 0; b < nextPosition; b++)
731                             if (next == interfacesToVisit[b]) continue nextInterface;
732                         interfacesToVisit[nextPosition++] = next;
733                     }
734                 }
735             }
736         } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & TagBits.HasNoMemberTypes) == 0);
737
738         if (interfacesToVisit != null) {
739             // contains the interfaces between the sourceType and any superclass, which was tagged as having no member types
740
boolean needToTag = false;
741             for (int i = 0; i < nextPosition; i++) {
742                 ReferenceBinding anInterface = interfacesToVisit[i];
743                 if ((anInterface.tagBits & TagBits.HasNoMemberTypes) == 0) { // skip interface if it already knows it has no member types
744
if (anInterface.hasMemberTypes()) // avoid resolving member types eagerly
745
return;
746
747                     needToTag = true;
748                     ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
749                     if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
750                         int itsLength = itsInterfaces.length;
751                         if (nextPosition + itsLength >= interfacesToVisit.length)
752                             System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
753                         nextInterface : for (int a = 0; a < itsLength; a++) {
754                             ReferenceBinding next = itsInterfaces[a];
755                             for (int b = 0; b < nextPosition; b++)
756                                 if (next == interfacesToVisit[b]) continue nextInterface;
757                             interfacesToVisit[nextPosition++] = next;
758                         }
759                     }
760                 }
761             }
762
763             if (needToTag) {
764                 for (int i = 0; i < nextPosition; i++)
765                     interfacesToVisit[i].tagBits |= TagBits.HasNoMemberTypes;
766             }
767         }
768
769         // tag the sourceType and all of its superclasses, unless they have already been tagged
770
currentType = sourceType;
771         do {
772             currentType.tagBits |= TagBits.HasNoMemberTypes;
773         } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & TagBits.HasNoMemberTypes) == 0);
774     }
775
776     // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
777
public void checkParameterizedTypeBounds() {
778         TypeReference superclass = referenceContext.superclass;
779         if (superclass != null)
780             superclass.checkBounds(this);
781
782         TypeReference[] superinterfaces = referenceContext.superInterfaces;
783         if (superinterfaces != null)
784             for (int i = 0, length = superinterfaces.length; i < length; i++)
785                 superinterfaces[i].checkBounds(this);
786
787         TypeParameter[] typeParameters = referenceContext.typeParameters;
788         if (typeParameters != null)
789             for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++)
790                 typeParameters[i].checkBounds(this);
791
792         ReferenceBinding[] memberTypes = referenceContext.binding.memberTypes;
793         if (memberTypes != null && memberTypes != Binding.NO_MEMBER_TYPES)
794             for (int i = 0, size = memberTypes.length; i < size; i++)
795                  ((SourceTypeBinding) memberTypes[i]).scope.checkParameterizedTypeBounds();
796     }
797
798     private void connectMemberTypes() {
799         SourceTypeBinding sourceType = referenceContext.binding;
800         ReferenceBinding[] memberTypes = sourceType.memberTypes;
801         if (memberTypes != null && memberTypes != Binding.NO_MEMBER_TYPES) {
802             for (int i = 0, size = memberTypes.length; i < size; i++)
803                  ((SourceTypeBinding) memberTypes[i]).scope.connectTypeHierarchy();
804         }
805     }
806     /*
807         Our current belief based on available JCK tests is:
808             inherited member types are visible as a potential superclass.
809             inherited interfaces are not visible when defining a superinterface.
810     
811         Error recovery story:
812             ensure the superclass is set to java.lang.Object if a problem is detected
813             resolving the superclass.
814     
815         Answer false if an error was reported against the sourceType.
816     */

817     private boolean connectSuperclass() {
818         SourceTypeBinding sourceType = referenceContext.binding;
819         if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
820
sourceType.superclass = null;
821             sourceType.superInterfaces = Binding.NO_SUPERINTERFACES;
822             if (!sourceType.isClass())
823                 problemReporter().objectMustBeClass(sourceType);
824             if (referenceContext.superclass != null || (referenceContext.superInterfaces != null && referenceContext.superInterfaces.length > 0))
825                 problemReporter().objectCannotHaveSuperTypes(sourceType);
826             return true; // do not propagate Object's hierarchy problems down to every subtype
827
}
828         if (referenceContext.superclass == null) {
829             if (sourceType.isEnum() && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
830
return connectEnumSuperclass();
831             sourceType.superclass = getJavaLangObject();
832             return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
833         }
834         TypeReference superclassRef = referenceContext.superclass;
835         ReferenceBinding superclass = findSupertype(superclassRef);
836         if (superclass != null) { // is null if a cycle was detected cycle or a problem
837
if (!superclass.isClass()) {
838                 problemReporter().superclassMustBeAClass(sourceType, superclassRef, superclass);
839             } else if (superclass.isFinal()) {
840                 problemReporter().classExtendFinalClass(sourceType, superclassRef, superclass);
841             } else if ((superclass.tagBits & TagBits.HasDirectWildcard) != 0) {
842                 problemReporter().superTypeCannotUseWildcard(sourceType, superclassRef, superclass);
843             } else if (superclass.erasure().id == T_JavaLangEnum) {
844                 problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
845             } else {
846                 // only want to reach here when no errors are reported
847
sourceType.superclass = superclass;
848                 return true;
849             }
850         }
851         sourceType.tagBits |= TagBits.HierarchyHasProblems;
852         sourceType.superclass = getJavaLangObject();
853         if ((sourceType.superclass.tagBits & TagBits.BeginHierarchyCheck) == 0)
854             detectHierarchyCycle(sourceType, sourceType.superclass, null);
855         return false; // reported some error against the source type
856
}
857
858     /**
859      * enum X (implicitly) extends Enum<X>
860      */

861     private boolean connectEnumSuperclass() {
862         SourceTypeBinding sourceType = referenceContext.binding;
863         ReferenceBinding rootEnumType = getJavaLangEnum();
864         boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null);
865         // arity check for well-known Enum<E>
866
TypeVariableBinding[] refTypeVariables = rootEnumType.typeVariables();
867         if (refTypeVariables == Binding.NO_TYPE_VARIABLES) { // check generic
868
problemReporter().nonGenericTypeCannotBeParameterized(null, rootEnumType, new TypeBinding[]{ sourceType });
869             return false; // cannot reach here as AbortCompilation is thrown
870
} else if (1 != refTypeVariables.length) { // check arity
871
problemReporter().incorrectArityForParameterizedType(null, rootEnumType, new TypeBinding[]{ sourceType });
872             return false; // cannot reach here as AbortCompilation is thrown
873
}
874         // check argument type compatibility
875
ParameterizedTypeBinding superType = environment().createParameterizedType(rootEnumType, new TypeBinding[]{ environment().convertToRawType(sourceType) } , null);
876         sourceType.superclass = superType;
877         // bound check (in case of bogus definition of Enum type)
878
if (refTypeVariables[0].boundCheck(superType, sourceType) != TypeConstants.OK) {
879             problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
880         }
881         return !foundCycle;
882     }
883
884     /*
885         Our current belief based on available JCK 1.3 tests is:
886             inherited member types are visible as a potential superclass.
887             inherited interfaces are visible when defining a superinterface.
888     
889         Error recovery story:
890             ensure the superinterfaces contain only valid visible interfaces.
891     
892         Answer false if an error was reported against the sourceType.
893     */

894     private boolean connectSuperInterfaces() {
895         SourceTypeBinding sourceType = referenceContext.binding;
896         sourceType.superInterfaces = Binding.NO_SUPERINTERFACES;
897         if (referenceContext.superInterfaces == null) {
898             if (sourceType.isAnnotationType() && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // do not connect if source < 1.5 as annotation already got flagged as syntax error) {
899
ReferenceBinding annotationType = getJavaLangAnnotationAnnotation();
900                 boolean foundCycle = detectHierarchyCycle(sourceType, annotationType, null);
901                 sourceType.superInterfaces = new ReferenceBinding[] { annotationType };
902                 return !foundCycle;
903             }
904             return true;
905         }
906         if (sourceType.id == T_JavaLangObject) // already handled the case of redefining java.lang.Object
907
return true;
908
909         boolean noProblems = true;
910         int length = referenceContext.superInterfaces.length;
911         ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
912         int count = 0;
913         nextInterface : for (int i = 0; i < length; i++) {
914             TypeReference superInterfaceRef = referenceContext.superInterfaces[i];
915             ReferenceBinding superInterface = findSupertype(superInterfaceRef);
916             if (superInterface == null) { // detected cycle
917
sourceType.tagBits |= TagBits.HierarchyHasProblems;
918                 noProblems = false;
919                 continue nextInterface;
920             }
921             superInterfaceRef.resolvedType = superInterface; // hold onto the problem type
922
// check for simple interface collisions
923
// Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
924
for (int j = 0; j < i; j++) {
925                 if (interfaceBindings[j] == superInterface) {
926                     problemReporter().duplicateSuperinterface(sourceType, superInterfaceRef, superInterface);
927                     continue nextInterface;
928                 }
929             }
930             if (!superInterface.isInterface()) {
931                 problemReporter().superinterfaceMustBeAnInterface(sourceType, superInterfaceRef, superInterface);
932                 sourceType.tagBits |= TagBits.HierarchyHasProblems;
933                 noProblems = false;
934                 continue nextInterface;
935             } else if (superInterface.isAnnotationType()){
936                 problemReporter().annotationTypeUsedAsSuperinterface(sourceType, superInterfaceRef, superInterface);
937             }
938             if ((superInterface.tagBits & TagBits.HasDirectWildcard) != 0) {
939                 problemReporter().superTypeCannotUseWildcard(sourceType, superInterfaceRef, superInterface);
940                 sourceType.tagBits |= TagBits.HierarchyHasProblems;
941                 noProblems = false;
942                 continue nextInterface;
943             }
944             // only want to reach here when no errors are reported
945
interfaceBindings[count++] = superInterface;
946         }
947         // hold onto all correctly resolved superinterfaces
948
if (count > 0) {
949             if (count != length)
950                 System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
951             sourceType.superInterfaces = interfaceBindings;
952         }
953         return noProblems;
954     }
955     
956     void connectTypeHierarchy() {
957         SourceTypeBinding sourceType = referenceContext.binding;
958         if ((sourceType.tagBits & TagBits.BeginHierarchyCheck) == 0) {
959             sourceType.tagBits |= TagBits.BeginHierarchyCheck;
960             boolean noProblems = connectSuperclass();
961             noProblems &= connectSuperInterfaces();
962             sourceType.tagBits |= TagBits.EndHierarchyCheck;
963             noProblems &= connectTypeVariables(referenceContext.typeParameters, false);
964             sourceType.tagBits |= TagBits.TypeVariablesAreConnected;
965             if (noProblems && sourceType.isHierarchyInconsistent())
966                 problemReporter().hierarchyHasProblems(sourceType);
967         }
968         connectMemberTypes();
969         LookupEnvironment env = environment();
970         try {
971             env.missingClassFileLocation = referenceContext;
972             checkForInheritedMemberTypes(sourceType);
973         } catch (AbortCompilation e) {
974             e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
975             throw e;
976         } finally {
977             env.missingClassFileLocation = null;
978         }
979     }
980     
981     private void connectTypeHierarchyWithoutMembers() {
982         // must ensure the imports are resolved
983
if (parent instanceof CompilationUnitScope) {
984             if (((CompilationUnitScope) parent).imports == null)
985                  ((CompilationUnitScope) parent).checkAndSetImports();
986         } else if (parent instanceof ClassScope) {
987             // ensure that the enclosing type has already been checked
988
((ClassScope) parent).connectTypeHierarchyWithoutMembers();
989         }
990
991         // double check that the hierarchy search has not already begun...
992
SourceTypeBinding sourceType = referenceContext.binding;
993         if ((sourceType.tagBits & TagBits.BeginHierarchyCheck) != 0)
994             return;
995
996         sourceType.tagBits |= TagBits.BeginHierarchyCheck;
997         boolean noProblems = connectSuperclass();
998         noProblems &= connectSuperInterfaces();
999         sourceType.tagBits |= TagBits.EndHierarchyCheck;
1000        noProblems &= connectTypeVariables(referenceContext.typeParameters, false);
1001        sourceType.tagBits |= TagBits.TypeVariablesAreConnected;
1002        if (noProblems && sourceType.isHierarchyInconsistent())
1003            problemReporter().hierarchyHasProblems(sourceType);
1004    }
1005
1006    public boolean detectHierarchyCycle(TypeBinding superType, TypeReference reference) {
1007        if (!(superType instanceof ReferenceBinding)) return false;
1008
1009        if (reference == this.superTypeReference) { // see findSuperType()
1010
if (superType.isTypeVariable())
1011                return false; // error case caught in resolveSuperType()
1012
// abstract class X<K,V> implements java.util.Map<K,V>
1013
// static abstract class M<K,V> implements Entry<K,V>
1014
if (superType.isParameterizedType())
1015                superType = ((ParameterizedTypeBinding) superType).genericType();
1016            compilationUnitScope().recordSuperTypeReference(superType); // to record supertypes
1017
return detectHierarchyCycle(referenceContext.binding, (ReferenceBinding) superType, reference);
1018        }
1019
1020        if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0 && superType instanceof SourceTypeBinding)
1021            // ensure if this is a source superclass that it has already been checked
1022
((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
1023        return false;
1024    }
1025
1026    // Answer whether a cycle was found between the sourceType & the superType
1027
private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
1028        if (superType.isRawType())
1029            superType = ((RawTypeBinding) superType).genericType();
1030        // by this point the superType must be a binary or source type
1031

1032        if (sourceType == superType) {
1033            problemReporter().hierarchyCircularity(sourceType, superType, reference);
1034            sourceType.tagBits |= TagBits.HierarchyHasProblems;
1035            return true;
1036        }
1037
1038        if (superType.isMemberType()) {
1039            ReferenceBinding current = superType.enclosingType();
1040            do {
1041                if (current.isHierarchyBeingConnected() && current == sourceType) {
1042                    problemReporter().hierarchyCircularity(sourceType, current, reference);
1043                    sourceType.tagBits |= TagBits.HierarchyHasProblems;
1044                    current.tagBits |= TagBits.HierarchyHasProblems;
1045                    return true;
1046                }
1047            } while ((current = current.enclosingType()) != null);
1048        }
1049
1050        if (superType.isBinaryBinding()) {
1051            // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
1052
// - a binary type... this case MUST be caught & reported here
1053
// - another source type... this case is reported against the other source type
1054
boolean hasCycle = false;
1055            ReferenceBinding parentType = superType.superclass();
1056            if (parentType != null) {
1057                if (sourceType == parentType) {
1058                    problemReporter().hierarchyCircularity(sourceType, superType, reference);
1059                    sourceType.tagBits |= TagBits.HierarchyHasProblems;
1060                    superType.tagBits |= TagBits.HierarchyHasProblems;
1061                    return true;
1062                }
1063                if (parentType.isParameterizedType())
1064                    parentType = ((ParameterizedTypeBinding) parentType).genericType();
1065                hasCycle |= detectHierarchyCycle(sourceType, parentType, reference);
1066                if ((parentType.tagBits & TagBits.HierarchyHasProblems) != 0) {
1067                    sourceType.tagBits |= TagBits.HierarchyHasProblems;
1068                    parentType.tagBits |= TagBits.HierarchyHasProblems; // propagate down the hierarchy
1069
}
1070            }
1071
1072            ReferenceBinding[] itsInterfaces = superType.superInterfaces();
1073            if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
1074                for (int i = 0, length = itsInterfaces.length; i < length; i++) {
1075                    ReferenceBinding anInterface = itsInterfaces[i];
1076                    if (sourceType == anInterface) {
1077                        problemReporter().hierarchyCircularity(sourceType, superType, reference);
1078                        sourceType.tagBits |= TagBits.HierarchyHasProblems;
1079                        superType.tagBits |= TagBits.HierarchyHasProblems;
1080                        return true;
1081                    }
1082                    if (anInterface.isParameterizedType())
1083                        anInterface = ((ParameterizedTypeBinding) anInterface).genericType();
1084                    hasCycle |= detectHierarchyCycle(sourceType, anInterface, reference);
1085                    if ((anInterface.tagBits & TagBits.HierarchyHasProblems) != 0) {
1086                        sourceType.tagBits |= TagBits.HierarchyHasProblems;
1087                        superType.tagBits |= TagBits.HierarchyHasProblems;
1088                    }
1089                }
1090            }
1091            return hasCycle;
1092        }
1093
1094        if (superType.isHierarchyBeingConnected()) {
1095            org.eclipse.jdt.internal.compiler.ast.TypeReference ref = ((SourceTypeBinding) superType).scope.superTypeReference;
1096            // https://bugs.eclipse.org/bugs/show_bug.cgi?id=133071
1097
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=121734
1098
if (ref != null && (ref.resolvedType == null || ((ReferenceBinding) ref.resolvedType).isHierarchyBeingConnected())) {
1099                problemReporter().hierarchyCircularity(sourceType, superType, reference);
1100                sourceType.tagBits |= TagBits.HierarchyHasProblems;
1101                superType.tagBits |= TagBits.HierarchyHasProblems;
1102                return true;
1103            }
1104        }
1105        if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0)
1106            // ensure if this is a source superclass that it has already been checked
1107
((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
1108        if ((superType.tagBits & TagBits.HierarchyHasProblems) != 0)
1109            sourceType.tagBits |= TagBits.HierarchyHasProblems;
1110        return false;
1111    }
1112
1113    private ReferenceBinding findSupertype(TypeReference typeReference) {
1114        CompilationUnitScope unitScope = compilationUnitScope();
1115        LookupEnvironment env = unitScope.environment;
1116        try {
1117            env.missingClassFileLocation = typeReference;
1118            typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
1119
unitScope.recordQualifiedReference(typeReference.getTypeName());
1120            this.superTypeReference = typeReference;
1121            ReferenceBinding superType = (ReferenceBinding) typeReference.resolveSuperType(this);
1122            return superType;
1123        } catch (AbortCompilation e) {
1124            SourceTypeBinding sourceType = this.referenceContext.binding;
1125            if (sourceType.superInterfaces == null) sourceType.superInterfaces = Binding.NO_SUPERINTERFACES; // be more resilient for hierarchies (144976)
1126
e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
1127            throw e;
1128        } finally {
1129            env.missingClassFileLocation = null;
1130            this.superTypeReference = null;
1131        }
1132    }
1133
1134    /* Answer the problem reporter to use for raising new problems.
1135    *
1136    * Note that as a side-effect, this updates the current reference context
1137    * (unit, type or method) in case the problem handler decides it is necessary
1138    * to abort.
1139    */

1140    public ProblemReporter problemReporter() {
1141        MethodScope outerMethodScope;
1142        if ((outerMethodScope = outerMostMethodScope()) == null) {
1143            ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
1144            problemReporter.referenceContext = referenceContext;
1145            return problemReporter;
1146        }
1147        return outerMethodScope.problemReporter();
1148    }
1149
1150    /* Answer the reference type of this scope.
1151    * It is the nearest enclosing type of this scope.
1152    */

1153    public TypeDeclaration referenceType() {
1154        return referenceContext;
1155    }
1156    
1157    public String JavaDoc toString() {
1158        if (referenceContext != null)
1159            return "--- Class Scope ---\n\n" //$NON-NLS-1$
1160
+ referenceContext.binding.toString();
1161        return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$
1162
}
1163}
1164
Popular Tags