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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
15 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
16 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
19 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
20 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
21 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
23 import org.eclipse.jdt.internal.compiler.env.IGenericType;
24 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
25 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
26 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
28 public class ClassScope extends Scope {
29 public TypeDeclaration referenceContext;
30 private TypeReference superTypeReference;
32 private final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
34 public ClassScope(Scope parent, TypeDeclaration context) {
35 super(CLASS_SCOPE, parent);
36 this.referenceContext = context;
39 void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
41 LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
43 SourceTypeBinding sourceType = referenceContext.binding;
44 if (supertype.isInterface()) {
45 sourceType.superclass = getJavaLangObject();
46 sourceType.superInterfaces = new ReferenceBinding[] { supertype };
48 sourceType.superclass = supertype;
49 sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
52 buildFieldsAndMethods();
53 anonymousType.faultInTypesForFieldsAndMethods();
54 sourceType.verifyMethods(environment().methodVerifier());
57 private void buildFields() {
58 boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
59 if (referenceContext.fields == null) {
60 if (hierarchyIsInconsistent) { // 72468
61 referenceContext.binding.fields = new FieldBinding[1];
62 referenceContext.binding.fields[0] =
63 new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
65 referenceContext.binding.fields = NoFields;
69 // count the number of fields vs. initializers
70 FieldDeclaration[] fields = referenceContext.fields;
71 int size = fields.length;
73 for (int i = 0; i < size; i++) {
74 switch (fields[i].getKind()) {
75 case AbstractVariableDeclaration.FIELD:
76 case AbstractVariableDeclaration.ENUM_CONSTANT:
81 if (hierarchyIsInconsistent)
83 // iterate the field declarations to create the bindings, lose all duplicates
84 FieldBinding[] fieldBindings = new FieldBinding[count];
85 HashtableOfObject knownFieldNames = new HashtableOfObject(count);
86 boolean duplicate = false;
88 for (int i = 0; i < size; i++) {
89 FieldDeclaration field = fields[i];
90 if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
91 if (referenceContext.binding.isInterface())
92 problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
94 FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
95 // field's type will be resolved when needed for top level types
96 checkAndSetModifiersForField(fieldBinding, field);
98 if (knownFieldNames.containsKey(field.name)) {
100 FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
101 if (previousBinding != null) {
102 for (int f = 0; f < i; f++) {
103 FieldDeclaration previousField = fields[f];
104 if (previousField.binding == previousBinding) {
105 problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
106 previousField.binding = null;
111 knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
112 problemReporter().duplicateFieldInType(referenceContext.binding, field);
113 field.binding = null;
115 knownFieldNames.put(field.name, fieldBinding);
116 // remember that we have seen a field with this name
117 if (fieldBinding != null)
118 fieldBindings[count++] = fieldBinding;
122 // remove duplicate fields
124 FieldBinding[] newFieldBindings = new FieldBinding[fieldBindings.length];
125 // we know we'll be removing at least 1 duplicate name
128 for (int i = 0; i < size; i++) {
129 FieldBinding fieldBinding = fieldBindings[i];
130 if (knownFieldNames.get(fieldBinding.name) != null)
131 newFieldBindings[count++] = fieldBinding;
133 fieldBindings = newFieldBindings;
135 if (hierarchyIsInconsistent)
136 fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
138 if (count != fieldBindings.length)
139 System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
140 for (int i = 0; i < count; i++)
141 fieldBindings[i].id = i;
142 referenceContext.binding.fields = fieldBindings;
145 void buildFieldsAndMethods() {
149 SourceTypeBinding sourceType = referenceContext.binding;
150 if (sourceType.isMemberType() && !sourceType.isLocalType())
151 ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
153 ReferenceBinding[] memberTypes = sourceType.memberTypes;
154 for (int i = 0, length = memberTypes.length; i < length; i++)
155 ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
158 private LocalTypeBinding buildLocalType(
159 SourceTypeBinding enclosingType,
160 PackageBinding packageBinding) {
162 referenceContext.scope = this;
163 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
164 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
166 // build the binding or the local type
167 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
168 referenceContext.binding = localType;
169 checkAndSetModifiers();
170 buildTypeVariables();
172 // Look at member types
173 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
174 if (referenceContext.memberTypes != null) {
175 int size = referenceContext.memberTypes.length;
176 memberTypeBindings = new ReferenceBinding[size];
178 nextMember : for (int i = 0; i < size; i++) {
179 TypeDeclaration memberContext = referenceContext.memberTypes[i];
180 if (memberContext.kind() == IGenericType.INTERFACE_DECL) {
181 problemReporter().nestedClassCannotDeclareInterface(memberContext);
184 ReferenceBinding type = localType;
185 // check that the member does not conflict with an enclosing type
187 if (CharOperation.equals(type.sourceName, memberContext.name)) {
188 problemReporter().hidingEnclosingType(memberContext);
191 type = type.enclosingType();
192 } while (type != null);
193 // check the member type does not conflict with another sibling member type
194 for (int j = 0; j < i; j++) {
195 if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
196 problemReporter().duplicateNestedType(memberContext);
200 ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
201 LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
202 memberBinding.setAsMemberType();
203 memberTypeBindings[count++] = memberBinding;
206 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
208 localType.memberTypes = memberTypeBindings;
212 void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
214 LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
215 connectTypeHierarchy();
216 buildFieldsAndMethods();
217 localType.faultInTypesForFieldsAndMethods();
219 referenceContext.binding.verifyMethods(environment().methodVerifier());
222 private void buildMemberTypes(AccessRestriction accessRestriction) {
223 SourceTypeBinding sourceType = referenceContext.binding;
224 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
225 if (referenceContext.memberTypes != null) {
226 int length = referenceContext.memberTypes.length;
227 memberTypeBindings = new ReferenceBinding[length];
229 nextMember : for (int i = 0; i < length; i++) {
230 TypeDeclaration memberContext = referenceContext.memberTypes[i];
231 if (memberContext.kind() == IGenericType.INTERFACE_DECL
232 && sourceType.isNestedType()
233 && sourceType.isClass()
234 && !sourceType.isStatic()) {
235 problemReporter().nestedClassCannotDeclareInterface(memberContext);
238 ReferenceBinding type = sourceType;
239 // check that the member does not conflict with an enclosing type
241 if (CharOperation.equals(type.sourceName, memberContext.name)) {
242 problemReporter().hidingEnclosingType(memberContext);
245 type = type.enclosingType();
246 } while (type != null);
247 // check that the member type does not conflict with another sibling member type
248 for (int j = 0; j < i; j++) {
249 if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
250 problemReporter().duplicateNestedType(memberContext);
255 ClassScope memberScope = new ClassScope(this, memberContext);
256 memberTypeBindings[count++] = memberScope.buildType(sourceType, sourceType.fPackage, accessRestriction);
259 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
261 sourceType.memberTypes = memberTypeBindings;
264 private void buildMethods() {
265 boolean isEnum = referenceContext.kind() == IGenericType.ENUM_DECL;
266 if (referenceContext.methods == null && !isEnum) {
267 referenceContext.binding.methods = NoMethods;
271 // iterate the method declarations to create the bindings
272 AbstractMethodDeclaration[] methods = referenceContext.methods;
273 int size = methods == null ? 0 : methods.length;
274 // look for <clinit> method
275 int clinitIndex = -1;
276 for (int i = 0; i < size; i++) {
277 if (methods[i].isClinit()) {
283 int count = isEnum ? 2 : 0; // reserve 2 slots for special enum methods: #values() and #valueOf(String)
284 MethodBinding[] methodBindings = new MethodBinding[(clinitIndex == -1 ? size : size - 1) + count];
285 // create special methods for enums
287 SourceTypeBinding sourceType = referenceContext.binding;
288 methodBindings[0] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUES); // add <EnumType>[] values()
289 methodBindings[1] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUEOF); // add <EnumType> valueOf()
291 // create bindings for source methods
292 for (int i = 0; i < size; i++) {
293 if (i != clinitIndex) {
294 MethodScope scope = new MethodScope(this, methods[i], false);
295 MethodBinding methodBinding = scope.createMethod(methods[i]);
296 if (methodBinding != null) // is null if binding could not be created
297 methodBindings[count++] = methodBinding;
300 if (count != methodBindings.length)
301 System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
303 referenceContext.binding.methods = methodBindings;
304 referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
307 SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
308 // provide the typeDeclaration with needed scopes
309 referenceContext.scope = this;
310 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
311 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
313 if (enclosingType == null) {
314 char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
315 referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
317 char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
318 className[className.length - 1] =
319 CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
320 referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
323 SourceTypeBinding sourceType = referenceContext.binding;
324 environment().setAccessRestriction(sourceType, accessRestriction);
325 sourceType.fPackage.addType(sourceType);
326 checkAndSetModifiers();
327 buildTypeVariables();
328 buildMemberTypes(accessRestriction);
332 private void buildTypeVariables() {
334 SourceTypeBinding sourceType = referenceContext.binding;
335 TypeParameter[] typeParameters = referenceContext.typeParameters;
337 // do not construct type variables if source < 1.5
338 if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) {
339 sourceType.typeVariables = NoTypeVariables;
342 sourceType.typeVariables = NoTypeVariables; // safety
344 if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
345 problemReporter().objectCannotBeGeneric(referenceContext);
348 sourceType.typeVariables = createTypeVariables(typeParameters, sourceType);
349 sourceType.modifiers |= AccGenericSignature;
352 private void checkAndSetModifiers() {
353 SourceTypeBinding sourceType = referenceContext.binding;
354 int modifiers = sourceType.modifiers;
355 if ((modifiers & AccAlternateModifierProblem) != 0)
356 problemReporter().duplicateModifierForType(sourceType);
358 ReferenceBinding enclosingType = sourceType.enclosingType();
359 boolean isMemberType = sourceType.isMemberType();
362 // checks for member types before local types to catch local members
363 if (enclosingType.isStrictfp())
364 modifiers |= AccStrictfp;
365 if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
366 modifiers |= AccDeprecatedImplicitly;
367 if ((enclosingType.modifiers & AccInterface) != 0)
368 modifiers |= AccPublic;
369 if (sourceType.isEnum())
370 modifiers |= AccStatic;
371 } else if (sourceType.isLocalType()) {
372 if (sourceType.isAnonymousType()) {
373 modifiers |= AccFinal;
374 // set AccEnum flag for anonymous body of enum constants
375 if (referenceContext.allocation.type == null) {
376 modifiers |= AccEnum;
381 switch (scope.kind) {
383 MethodScope methodScope = (MethodScope) scope;
384 if (methodScope.isInsideInitializer()) {
385 SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
387 // inside field declaration ? check field modifier to see if deprecated
388 if (methodScope.initializedField != null) {
389 // currently inside this field initialization
390 if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
391 modifiers |= AccDeprecatedImplicitly;
394 if (type.isStrictfp())
395 modifiers |= AccStrictfp;
396 if (type.isViewedAsDeprecated() && !sourceType.isDeprecated())
397 modifiers |= AccDeprecatedImplicitly;
400 MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
402 if (method.isStrictfp())
403 modifiers |= AccStrictfp;
404 if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
405 modifiers |= AccDeprecatedImplicitly;
411 if (enclosingType.isStrictfp())
412 modifiers |= AccStrictfp;
413 if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
414 modifiers |= AccDeprecatedImplicitly;
417 scope = scope.parent;
418 } while (scope != null);
420 // after this point, tests on the 16 bits reserved.
421 int realModifiers = modifiers & AccJustFlag;
423 if ((realModifiers & AccInterface) != 0) { // interface and annotation type
424 // detect abnormal cases for interfaces
426 int unexpectedModifiers =
427 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
428 if ((realModifiers & unexpectedModifiers) != 0) {
429 if ((realModifiers & AccAnnotation) != 0) {
430 problemReporter().illegalModifierForAnnotationMemberType(sourceType);
432 problemReporter().illegalModifierForMemberInterface(sourceType);
436 } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
437 int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
438 if ((realModifiers & unexpectedModifiers) != 0)
439 problemReporter().illegalModifierForLocalInterface(sourceType);
442 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
443 if ((realModifiers & unexpectedModifiers) != 0) {
444 if ((realModifiers & AccAnnotation) != 0) {
445 problemReporter().illegalModifierForAnnotationType(sourceType);
447 problemReporter().illegalModifierForInterface(sourceType);
451 modifiers |= AccAbstract;
452 } else if ((realModifiers & AccEnum) != 0) {
453 // detect abnormal cases for enums
454 if (isMemberType) { // includes member types defined inside local types
455 int unexpectedModifiers =
456 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccStrictfp | AccEnum);
457 if ((realModifiers & unexpectedModifiers) != 0)
458 problemReporter().illegalModifierForMemberEnum(sourceType);
459 } else if (sourceType.isLocalType()) {
460 int unexpectedModifiers = ~(AccStrictfp | AccFinal | AccEnum); // add final since implicitly set for anonymous type
461 if ((realModifiers & unexpectedModifiers) != 0)
462 problemReporter().illegalModifierForLocalEnum(sourceType);
464 int unexpectedModifiers = ~(AccPublic | AccStrictfp | AccEnum);
465 if ((realModifiers & unexpectedModifiers) != 0)
466 problemReporter().illegalModifierForEnum(sourceType);
468 if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) {
469 modifiers |= AccAbstract;
473 // detect abnormal cases for classes
474 if (isMemberType) { // includes member types defined inside local types
475 int unexpectedModifiers =
476 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
477 if ((realModifiers & unexpectedModifiers) != 0)
478 problemReporter().illegalModifierForMemberClass(sourceType);
479 } else if (sourceType.isLocalType()) {
480 int unexpectedModifiers = ~(AccAbstract | AccFinal | AccStrictfp);
481 if ((realModifiers & unexpectedModifiers) != 0)
482 problemReporter().illegalModifierForLocalClass(sourceType);
484 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal | AccStrictfp);
485 if ((realModifiers & unexpectedModifiers) != 0)
486 problemReporter().illegalModifierForClass(sourceType);
489 // check that Final and Abstract are not set together
490 if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
491 problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
495 // test visibility modifiers inconsistency, isolate the accessors bits
496 if (enclosingType.isInterface()) {
497 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
498 problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
500 // need to keep the less restrictive
501 if ((realModifiers & AccProtected) != 0)
502 modifiers &= ~AccProtected;
503 if ((realModifiers & AccPrivate) != 0)
504 modifiers &= ~AccPrivate;
507 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
508 if ((accessorBits & (accessorBits - 1)) > 1) {
509 problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
511 // need to keep the less restrictive
512 if ((accessorBits & AccPublic) != 0) {
513 if ((accessorBits & AccProtected) != 0)
514 modifiers &= ~AccProtected;
515 if ((accessorBits & AccPrivate) != 0)
516 modifiers &= ~AccPrivate;
518 if ((accessorBits & AccProtected) != 0)
519 if ((accessorBits & AccPrivate) != 0)
520 modifiers &= ~AccPrivate;
524 // static modifier test
525 if ((realModifiers & AccStatic) == 0) {
526 if (enclosingType.isInterface())
527 modifiers |= AccStatic;
529 if (!enclosingType.isStatic())
530 // error the enclosing type of a static field must be static or a top-level type
531 problemReporter().illegalStaticModifierForMemberType(sourceType);
535 sourceType.modifiers = modifiers;
538 /* This method checks the modifiers of a field.
541 * Need to integrate the check for the final modifiers for nested types
543 * Note : A scope is accessible by : fieldBinding.declaringClass.scope
545 private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
546 int modifiers = fieldBinding.modifiers;
547 if ((modifiers & AccAlternateModifierProblem) != 0)
548 problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
550 if ((fieldBinding.declaringClass.modifiers & AccInterface) != 0) {
551 int expectedValue = AccPublic | AccStatic | AccFinal;
553 modifiers |= expectedValue;
555 // and then check that they are the only ones
556 if ((modifiers & AccJustFlag) != expectedValue) {
557 if ((fieldBinding.declaringClass.modifiers & AccAnnotation) != 0) {
558 problemReporter().illegalModifierForAnnotationField(fieldDecl);
560 problemReporter().illegalModifierForInterfaceField(fieldDecl);
563 fieldBinding.modifiers = modifiers;
565 } else if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
566 // check that they are not modifiers in source
567 if ((modifiers & AccJustFlag) != 0)
568 problemReporter().illegalModifierForEnumConstant(fieldBinding.declaringClass, fieldDecl);
571 int implicitValue = AccPublic | AccStatic | AccFinal | AccEnum;
572 fieldBinding.modifiers|= implicitValue;
576 // after this point, tests on the 16 bits reserved.
577 int realModifiers = modifiers & AccJustFlag;
578 int unexpectedModifiers =
579 ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic | AccTransient | AccVolatile);
580 if ((realModifiers & unexpectedModifiers) != 0)
581 problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
583 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
584 if ((accessorBits & (accessorBits - 1)) > 1) {
585 problemReporter().illegalVisibilityModifierCombinationForField(
586 fieldBinding.declaringClass,
589 // need to keep the less restrictive
590 if ((accessorBits & AccPublic) != 0) {
591 if ((accessorBits & AccProtected) != 0)
592 modifiers &= ~AccProtected;
593 if ((accessorBits & AccPrivate) != 0)
594 modifiers &= ~AccPrivate;
596 if ((accessorBits & AccProtected) != 0)
597 if ((accessorBits & AccPrivate) != 0)
598 modifiers &= ~AccPrivate;
601 if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
602 problemReporter().illegalModifierCombinationFinalVolatileForField(
603 fieldBinding.declaringClass,
606 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
607 modifiers |= AccBlankFinal;
609 fieldBinding.modifiers = modifiers;
612 private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
613 // search up the hierarchy of the sourceType to see if any superType defines a member type
614 // when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
615 // assumes super types have already been checked & tagged
616 ReferenceBinding currentType = sourceType;
617 ReferenceBinding[][] interfacesToVisit = null;
618 int lastPosition = -1;
620 if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
623 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
624 if (itsInterfaces != NoSuperInterfaces) {
625 if (interfacesToVisit == null)
626 interfacesToVisit = new ReferenceBinding[5][];
627 if (++lastPosition == interfacesToVisit.length)
628 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
629 interfacesToVisit[lastPosition] = itsInterfaces;
631 } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
633 if (interfacesToVisit != null) {
634 // contains the interfaces between the sourceType and any superclass, which was tagged as having no member types
635 boolean needToTag = false;
636 for (int i = 0; i <= lastPosition; i++) {
637 ReferenceBinding[] interfaces = interfacesToVisit[i];
638 for (int j = 0, length = interfaces.length; j < length; j++) {
639 ReferenceBinding anInterface = interfaces[j];
640 if ((anInterface.tagBits & HasNoMemberTypes) == 0) { // skip interface if it already knows it has no member types
641 if (anInterface.hasMemberTypes()) // avoid resolving member types eagerly
645 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
646 if (itsInterfaces != NoSuperInterfaces) {
647 if (++lastPosition == interfacesToVisit.length)
648 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
649 interfacesToVisit[lastPosition] = itsInterfaces;
656 for (int i = 0; i <= lastPosition; i++) {
657 ReferenceBinding[] interfaces = interfacesToVisit[i];
658 for (int j = 0, length = interfaces.length; j < length; j++)
659 interfaces[j].tagBits |= HasNoMemberTypes;
664 // tag the sourceType and all of its superclasses, unless they have already been tagged
665 currentType = sourceType;
667 currentType.tagBits |= HasNoMemberTypes;
668 } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
670 // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
671 private void checkParameterizedTypeBounds() {
672 TypeReference superclass = referenceContext.superclass;
673 if (superclass != null) {
674 superclass.checkBounds(this);
676 TypeReference[] superinterfaces = referenceContext.superInterfaces;
677 if (superinterfaces != null) {
678 for (int i = 0, length = superinterfaces.length; i < length; i++) {
679 superinterfaces[i].checkBounds(this);
682 TypeParameter[] typeParameters = referenceContext.typeParameters;
683 if (typeParameters != null) {
684 for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
685 typeParameters[i].checkBounds(this);
690 private void connectMemberTypes() {
691 SourceTypeBinding sourceType = referenceContext.binding;
692 if (sourceType.memberTypes != NoMemberTypes)
693 for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
694 ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
697 Our current belief based on available JCK tests is:
698 inherited member types are visible as a potential superclass.
699 inherited interfaces are not visible when defining a superinterface.
701 Error recovery story:
702 ensure the superclass is set to java.lang.Object if a problem is detected
703 resolving the superclass.
705 Answer false if an error was reported against the sourceType.
707 private boolean connectSuperclass() {
708 SourceTypeBinding sourceType = referenceContext.binding;
709 if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
710 sourceType.superclass = null;
711 sourceType.superInterfaces = NoSuperInterfaces;
712 if (!sourceType.isClass())
713 problemReporter().objectMustBeClass(sourceType);
714 if (referenceContext.superclass != null || (referenceContext.superInterfaces != null && referenceContext.superInterfaces.length > 0))
715 problemReporter().objectCannotHaveSuperTypes(sourceType);
716 return true; // do not propagate Object's hierarchy problems down to every subtype
718 if (referenceContext.superclass == null) {
719 if (sourceType.isEnum() && environment().options.sourceLevel >= JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
720 return connectEnumSuperclass();
721 sourceType.superclass = getJavaLangObject();
722 return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
724 TypeReference superclassRef = referenceContext.superclass;
725 ReferenceBinding superclass = findSupertype(superclassRef);
726 if (superclass != null) { // is null if a cycle was detected cycle or a problem
727 if (!superclass.isClass()) {
728 problemReporter().superclassMustBeAClass(sourceType, superclassRef, superclass);
729 } else if (superclass.isFinal()) {
730 problemReporter().classExtendFinalClass(sourceType, superclassRef, superclass);
731 } else if ((superclass.tagBits & TagBits.HasDirectWildcard) != 0) {
732 problemReporter().superTypeCannotUseWildcard(sourceType, superclassRef, superclass);
733 } else if (superclass.erasure().id == T_JavaLangEnum) {
734 problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
736 // only want to reach here when no errors are reported
737 sourceType.superclass = superclass;
741 sourceType.tagBits |= HierarchyHasProblems;
742 sourceType.superclass = getJavaLangObject();
743 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
744 detectHierarchyCycle(sourceType, sourceType.superclass, null);
745 return false; // reported some error against the source type
749 * enum X (implicitly) extends Enum<X>
751 private boolean connectEnumSuperclass() {
752 SourceTypeBinding sourceType = referenceContext.binding;
753 ReferenceBinding rootEnumType = getJavaLangEnum();
754 boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null);
755 // arity check for well-known Enum<E>
756 TypeVariableBinding[] refTypeVariables = rootEnumType.typeVariables();
757 if (refTypeVariables == NoTypeVariables) { // check generic
758 problemReporter().nonGenericTypeCannotBeParameterized(null, rootEnumType, new TypeBinding[]{ sourceType });
759 return false; // cannot reach here as AbortCompilation is thrown
760 } else if (1 != refTypeVariables.length) { // check arity
761 problemReporter().incorrectArityForParameterizedType(null, rootEnumType, new TypeBinding[]{ sourceType });
762 return false; // cannot reach here as AbortCompilation is thrown
764 // check argument type compatibility
765 ParameterizedTypeBinding superType = createParameterizedType(rootEnumType, new TypeBinding[]{ sourceType } , null);
766 sourceType.superclass = superType;
768 if (!refTypeVariables[0].boundCheck(superType, sourceType)) {
769 problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
775 Our current belief based on available JCK 1.3 tests is:
776 inherited member types are visible as a potential superclass.
777 inherited interfaces are visible when defining a superinterface.
779 Error recovery story:
780 ensure the superinterfaces contain only valid visible interfaces.
782 Answer false if an error was reported against the sourceType.
784 private boolean connectSuperInterfaces() {
785 SourceTypeBinding sourceType = referenceContext.binding;
786 sourceType.superInterfaces = NoSuperInterfaces;
787 if (referenceContext.superInterfaces == null) {
788 if (sourceType.isAnnotationType() && environment().options.sourceLevel >= JDK1_5) { // do not connect if source < 1.5 as annotation already got flagged as syntax error) {
789 ReferenceBinding annotationType = getJavaLangAnnotationAnnotation();
790 boolean foundCycle = detectHierarchyCycle(sourceType, annotationType, null);
791 sourceType.superInterfaces = new ReferenceBinding[] { annotationType };
796 if (sourceType.id == T_JavaLangObject) // already handled the case of redefining java.lang.Object
799 boolean noProblems = true;
800 int length = referenceContext.superInterfaces.length;
801 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
803 nextInterface : for (int i = 0; i < length; i++) {
804 TypeReference superInterfaceRef = referenceContext.superInterfaces[i];
805 ReferenceBinding superInterface = findSupertype(superInterfaceRef);
806 if (superInterface == null) { // detected cycle
807 sourceType.tagBits |= HierarchyHasProblems;
809 continue nextInterface;
811 superInterfaceRef.resolvedType = superInterface; // hold onto the problem type
812 // Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
813 for (int k = 0; k < count; k++) {
814 if (interfaceBindings[k] == superInterface) {
815 // should this be treated as a warning?
816 problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
817 continue nextInterface;
820 if (!superInterface.isInterface()) {
821 problemReporter().superinterfaceMustBeAnInterface(sourceType, superInterfaceRef, superInterface);
822 sourceType.tagBits |= HierarchyHasProblems;
824 continue nextInterface;
826 if ((superInterface.tagBits & TagBits.HasDirectWildcard) != 0) {
827 problemReporter().superTypeCannotUseWildcard(sourceType, superInterfaceRef, superInterface);
828 sourceType.tagBits |= HierarchyHasProblems;
830 continue nextInterface;
832 ReferenceBinding invalid = findAmbiguousInterface(superInterface, sourceType);
833 if (invalid != null) {
834 ReferenceBinding generic = null;
835 if (superInterface.isParameterizedType())
836 generic = ((ParameterizedTypeBinding) superInterface).type;
837 else if (invalid.isParameterizedType())
838 generic = ((ParameterizedTypeBinding) invalid).type;
839 problemReporter().superinterfacesCollide(generic, referenceContext, superInterface, invalid);
840 sourceType.tagBits |= HierarchyHasProblems;
842 continue nextInterface;
845 // only want to reach here when no errors are reported
846 interfaceBindings[count++] = superInterface;
848 // hold onto all correctly resolved superinterfaces
851 System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
852 sourceType.superInterfaces = interfaceBindings;
857 void connectTypeHierarchy() {
858 SourceTypeBinding sourceType = referenceContext.binding;
859 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
860 sourceType.tagBits |= BeginHierarchyCheck;
861 boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
862 noProblems &= connectSuperclass();
863 noProblems &= connectSuperInterfaces();
864 sourceType.tagBits |= EndHierarchyCheck;
865 if (noProblems && sourceType.isHierarchyInconsistent())
866 problemReporter().hierarchyHasProblems(sourceType);
868 // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
869 checkParameterizedTypeBounds();
870 connectMemberTypes();
872 checkForInheritedMemberTypes(sourceType);
873 } catch (AbortCompilation e) {
874 e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
879 private void connectTypeHierarchyWithoutMembers() {
880 // must ensure the imports are resolved
881 if (parent instanceof CompilationUnitScope) {
882 if (((CompilationUnitScope) parent).imports == null)
883 ((CompilationUnitScope) parent).checkAndSetImports();
884 } else if (parent instanceof ClassScope) {
885 // ensure that the enclosing type has already been checked
886 ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
889 // double check that the hierarchy search has not already begun...
890 SourceTypeBinding sourceType = referenceContext.binding;
891 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
894 sourceType.tagBits |= BeginHierarchyCheck;
895 boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
896 noProblems &= connectSuperclass();
897 noProblems &= connectSuperInterfaces();
898 sourceType.tagBits |= EndHierarchyCheck;
899 if (noProblems && sourceType.isHierarchyInconsistent())
900 problemReporter().hierarchyHasProblems(sourceType);
903 public boolean detectAnnotationCycle(TypeBinding sourceType, TypeBinding annotationElementType, TypeReference reference) {
904 if (!annotationElementType.isAnnotationType())
907 if (sourceType == annotationElementType) {
908 problemReporter().annotationCircularity(sourceType, annotationElementType, reference);
911 // TODO (kent) add support for detecting indirect cases using TagBits.BeginAnnotationCheck/EndAnnotationCheck
915 public boolean detectHierarchyCycle(TypeBinding superType, TypeReference reference, TypeBinding[] argTypes) {
916 if (!(superType instanceof ReferenceBinding)) return false;
918 if (argTypes != null) {
919 for (int i = 0, l = argTypes.length; i < l; i++) {
920 TypeBinding argType = argTypes[i].leafComponentType();
921 if ((argType.tagBits & BeginHierarchyCheck) == 0 && argType instanceof SourceTypeBinding)
922 // ensure if this is a source argument type that it has already been checked
923 ((SourceTypeBinding) argType).scope.connectTypeHierarchyWithoutMembers();
927 if (reference == this.superTypeReference) { // see findSuperType()
928 if (superType.isTypeVariable())
929 return false; // error case caught in resolveSuperType()
930 // abstract class X<K,V> implements java.util.Map<K,V>
931 // static abstract class M<K,V> implements Entry<K,V>
932 if (superType.isParameterizedType())
933 superType = ((ParameterizedTypeBinding) superType).type;
934 compilationUnitScope().recordSuperTypeReference(superType); // to record supertypes
935 return detectHierarchyCycle(referenceContext.binding, (ReferenceBinding) superType, reference);
938 if ((superType.tagBits & BeginHierarchyCheck) == 0 && superType instanceof SourceTypeBinding)
939 // ensure if this is a source superclass that it has already been checked
940 ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
944 // Answer whether a cycle was found between the sourceType & the superType
945 private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
946 if (superType.isRawType())
947 superType = ((RawTypeBinding) superType).type;
948 // by this point the superType must be a binary or source type
950 if (sourceType == superType) {
951 problemReporter().hierarchyCircularity(sourceType, superType, reference);
952 sourceType.tagBits |= HierarchyHasProblems;
956 if (superType.isMemberType()) {
957 ReferenceBinding current = superType.enclosingType();
959 if (current.isHierarchyBeingConnected()) {
960 problemReporter().hierarchyCircularity(sourceType, current, reference);
961 sourceType.tagBits |= HierarchyHasProblems;
962 current.tagBits |= HierarchyHasProblems;
965 } while ((current = current.enclosingType()) != null);
968 if (superType.isBinaryBinding()) {
969 // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
970 // - a binary type... this case MUST be caught & reported here
971 // - another source type... this case is reported against the other source type
972 boolean hasCycle = false;
973 if (superType.superclass() != null) {
974 if (sourceType == superType.superclass()) {
975 problemReporter().hierarchyCircularity(sourceType, superType, reference);
976 sourceType.tagBits |= HierarchyHasProblems;
977 superType.tagBits |= HierarchyHasProblems;
980 ReferenceBinding parentType = superType.superclass();
981 if (parentType.isParameterizedType())
982 parentType = ((ParameterizedTypeBinding) parentType).type;
983 hasCycle |= detectHierarchyCycle(sourceType, parentType, reference);
984 if ((parentType.tagBits & HierarchyHasProblems) != 0) {
985 sourceType.tagBits |= HierarchyHasProblems;
986 parentType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
990 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
991 if (itsInterfaces != NoSuperInterfaces) {
992 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
993 ReferenceBinding anInterface = itsInterfaces[i];
994 if (sourceType == anInterface) {
995 problemReporter().hierarchyCircularity(sourceType, superType, reference);
996 sourceType.tagBits |= HierarchyHasProblems;
997 superType.tagBits |= HierarchyHasProblems;
1000 if (anInterface.isParameterizedType())
1001 anInterface = ((ParameterizedTypeBinding) anInterface).type;
1002 hasCycle |= detectHierarchyCycle(sourceType, anInterface, reference);
1003 if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
1004 sourceType.tagBits |= HierarchyHasProblems;
1005 superType.tagBits |= HierarchyHasProblems;
1012 if (superType.isHierarchyBeingConnected()) {
1013 if (((SourceTypeBinding) superType).scope.superTypeReference != null) { // if null then its connecting its type variables
1014 problemReporter().hierarchyCircularity(sourceType, superType, reference);
1015 sourceType.tagBits |= HierarchyHasProblems;
1016 superType.tagBits |= HierarchyHasProblems;
1020 if ((superType.tagBits & BeginHierarchyCheck) == 0)
1021 // ensure if this is a source superclass that it has already been checked
1022 ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
1023 if ((superType.tagBits & HierarchyHasProblems) != 0)
1024 sourceType.tagBits |= HierarchyHasProblems;
1028 private ReferenceBinding findAmbiguousInterface(ReferenceBinding newInterface, ReferenceBinding currentType) {
1029 TypeBinding newErasure = newInterface.erasure();
1030 if (newInterface == newErasure) return null;
1032 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
1033 int lastPosition = -1;
1035 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1036 if (itsInterfaces != NoSuperInterfaces) {
1037 if (++lastPosition == interfacesToVisit.length)
1038 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
1039 interfacesToVisit[lastPosition] = itsInterfaces;
1041 } while ((currentType = currentType.superclass()) != null);
1043 for (int i = 0; i <= lastPosition; i++) {
1044 ReferenceBinding[] interfaces = interfacesToVisit[i];
1045 for (int j = 0, length = interfaces.length; j < length; j++) {
1046 currentType = interfaces[j];
1047 if (currentType.erasure() == newErasure)
1048 if (currentType != newInterface)
1051 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1052 if (itsInterfaces != NoSuperInterfaces) {
1053 if (++lastPosition == interfacesToVisit.length)
1054 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
1055 interfacesToVisit[lastPosition] = itsInterfaces;
1062 private ReferenceBinding findSupertype(TypeReference typeReference) {
1064 typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
1065 compilationUnitScope().recordQualifiedReference(typeReference.getTypeName());
1066 this.superTypeReference = typeReference;
1067 ReferenceBinding superType = (ReferenceBinding) typeReference.resolveSuperType(this);
1068 this.superTypeReference = null;
1070 } catch (AbortCompilation e) {
1071 e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
1076 /* Answer the problem reporter to use for raising new problems.
1078 * Note that as a side-effect, this updates the current reference context
1079 * (unit, type or method) in case the problem handler decides it is necessary
1082 public ProblemReporter problemReporter() {
1083 MethodScope outerMethodScope;
1084 if ((outerMethodScope = outerMostMethodScope()) == null) {
1085 ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
1086 problemReporter.referenceContext = referenceContext;
1087 return problemReporter;
1089 return outerMethodScope.problemReporter();
1092 /* Answer the reference type of this scope.
1093 * It is the nearest enclosing type of this scope.
1095 public TypeDeclaration referenceType() {
1096 return referenceContext;
1099 public String toString() {
1100 if (referenceContext != null)
1101 return "--- Class Scope ---\n\n" //$NON-NLS-1$
1102 + referenceContext.binding.toString();
1103 return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$