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.AbstractMethodDeclaration;
15 import org.eclipse.jdt.internal.compiler.ast.Clinit;
16 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
19 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
20 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
21 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
23 public class ClassScope extends Scope {
24 public TypeDeclaration referenceContext;
26 private final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
28 public ClassScope(Scope parent, TypeDeclaration context) {
29 super(CLASS_SCOPE, parent);
30 this.referenceContext = context;
33 void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
35 LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
37 SourceTypeBinding sourceType = referenceContext.binding;
38 if (supertype.isInterface()) {
39 sourceType.superclass = getJavaLangObject();
40 sourceType.superInterfaces = new ReferenceBinding[] { supertype };
42 sourceType.superclass = supertype;
43 sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
46 buildFieldsAndMethods();
47 anonymousType.faultInTypesForFieldsAndMethods();
48 sourceType.verifyMethods(environment().methodVerifier());
51 private void buildFields() {
52 boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
53 if (referenceContext.fields == null) {
54 if (hierarchyIsInconsistent) { // 72468
55 referenceContext.binding.fields = new FieldBinding[1];
56 referenceContext.binding.fields[0] =
57 new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
59 referenceContext.binding.fields = NoFields;
63 // count the number of fields vs. initializers
64 FieldDeclaration[] fields = referenceContext.fields;
65 int size = fields.length;
67 for (int i = 0; i < size; i++)
68 if (fields[i].isField())
71 if (hierarchyIsInconsistent)
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;
78 for (int i = 0; i < size; i++) {
79 FieldDeclaration field = fields[i];
80 if (!field.isField()) {
81 if (referenceContext.binding.isInterface())
82 problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
84 FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
85 // field's type will be resolved when needed for top level types
86 checkAndSetModifiersForField(fieldBinding, field);
88 if (knownFieldNames.containsKey(field.name)) {
90 FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
91 if (previousBinding != null) {
92 for (int f = 0; f < i; f++) {
93 FieldDeclaration previousField = fields[f];
94 if (previousField.binding == previousBinding) {
95 problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
96 previousField.binding = null;
101 knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
102 problemReporter().duplicateFieldInType(referenceContext.binding, field);
103 field.binding = null;
105 knownFieldNames.put(field.name, fieldBinding);
106 // remember that we have seen a field with this name
107 if (fieldBinding != null)
108 fieldBindings[count++] = fieldBinding;
112 // remove duplicate fields
114 FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
115 // we know we'll be removing at least 1 duplicate name
118 for (int i = 0; i < size; i++) {
119 FieldBinding fieldBinding = fieldBindings[i];
120 if (knownFieldNames.get(fieldBinding.name) != null)
121 newFieldBindings[count++] = fieldBinding;
123 fieldBindings = newFieldBindings;
125 if (hierarchyIsInconsistent)
126 fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
128 if (count != fieldBindings.length)
129 System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
130 for (int i = 0; i < count; i++)
131 fieldBindings[i].id = i;
132 referenceContext.binding.fields = fieldBindings;
135 void buildFieldsAndMethods() {
139 SourceTypeBinding sourceType = referenceContext.binding;
140 if (sourceType.isMemberType() && !sourceType.isLocalType())
141 ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
143 ReferenceBinding[] memberTypes = sourceType.memberTypes;
144 for (int i = 0, length = memberTypes.length; i < length; i++)
145 ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
148 private LocalTypeBinding buildLocalType(
149 SourceTypeBinding enclosingType,
150 PackageBinding packageBinding) {
152 referenceContext.scope = this;
153 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
154 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
156 // build the binding or the local type
157 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
158 referenceContext.binding = localType;
159 checkAndSetModifiers();
161 // Look at member types
162 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
163 if (referenceContext.memberTypes != null) {
164 int size = referenceContext.memberTypes.length;
165 memberTypeBindings = new ReferenceBinding[size];
167 nextMember : for (int i = 0; i < size; i++) {
168 TypeDeclaration memberContext = referenceContext.memberTypes[i];
169 if (memberContext.isInterface()) {
170 problemReporter().nestedClassCannotDeclareInterface(memberContext);
173 ReferenceBinding type = localType;
174 // check that the member does not conflict with an enclosing type
176 if (CharOperation.equals(type.sourceName, memberContext.name)) {
177 problemReporter().hidingEnclosingType(memberContext);
180 type = type.enclosingType();
181 } while (type != null);
182 // check the member type does not conflict with another sibling member type
183 for (int j = 0; j < i; j++) {
184 if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
185 problemReporter().duplicateNestedType(memberContext);
190 ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
191 LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
192 memberBinding.setAsMemberType();
193 memberTypeBindings[count++] = memberBinding;
196 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
198 localType.memberTypes = memberTypeBindings;
202 void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
204 LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
205 connectTypeHierarchy();
206 buildFieldsAndMethods();
207 localType.faultInTypesForFieldsAndMethods();
209 referenceContext.binding.verifyMethods(environment().methodVerifier());
212 private void buildMethods() {
213 if (referenceContext.methods == null) {
214 referenceContext.binding.methods = NoMethods;
218 // iterate the method declarations to create the bindings
219 AbstractMethodDeclaration[] methods = referenceContext.methods;
220 int size = methods.length;
221 int clinitIndex = -1;
222 for (int i = 0; i < size; i++) {
223 if (methods[i] instanceof Clinit) {
228 MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
231 for (int i = 0; i < size; i++) {
232 if (i != clinitIndex) {
233 MethodScope scope = new MethodScope(this, methods[i], false);
234 MethodBinding methodBinding = scope.createMethod(methods[i]);
235 if (methodBinding != null) // is null if binding could not be created
236 methodBindings[count++] = methodBinding;
239 if (count != methodBindings.length)
240 System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
242 referenceContext.binding.methods = methodBindings;
243 referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
245 SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
246 // provide the typeDeclaration with needed scopes
247 referenceContext.scope = this;
248 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
249 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
251 if (enclosingType == null) {
252 char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
253 referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
255 char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
256 className[className.length - 1] =
257 CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
258 referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
261 SourceTypeBinding sourceType = referenceContext.binding;
262 sourceType.fPackage.addType(sourceType);
263 checkAndSetModifiers();
265 // Look at member types
266 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
267 if (referenceContext.memberTypes != null) {
268 int size = referenceContext.memberTypes.length;
269 memberTypeBindings = new ReferenceBinding[size];
271 nextMember : for (int i = 0; i < size; i++) {
272 TypeDeclaration memberContext = referenceContext.memberTypes[i];
273 if (memberContext.isInterface()
274 && sourceType.isNestedType()
275 && sourceType.isClass()
276 && !sourceType.isStatic()) {
277 problemReporter().nestedClassCannotDeclareInterface(memberContext);
280 ReferenceBinding type = sourceType;
281 // check that the member does not conflict with an enclosing type
283 if (CharOperation.equals(type.sourceName, memberContext.name)) {
284 problemReporter().hidingEnclosingType(memberContext);
287 type = type.enclosingType();
288 } while (type != null);
289 // check that the member type does not conflict with another sibling member type
290 for (int j = 0; j < i; j++) {
291 if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
292 problemReporter().duplicateNestedType(memberContext);
297 ClassScope memberScope = new ClassScope(this, memberContext);
298 memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
301 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
303 sourceType.memberTypes = memberTypeBindings;
307 private void checkAndSetModifiers() {
308 SourceTypeBinding sourceType = referenceContext.binding;
309 int modifiers = sourceType.modifiers;
310 if ((modifiers & AccAlternateModifierProblem) != 0)
311 problemReporter().duplicateModifierForType(sourceType);
313 ReferenceBinding enclosingType = sourceType.enclosingType();
314 boolean isMemberType = sourceType.isMemberType();
317 // checks for member types before local types to catch local members
318 if (enclosingType.isStrictfp())
319 modifiers |= AccStrictfp;
320 if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
321 modifiers |= AccDeprecatedImplicitly;
322 if (enclosingType.isInterface())
323 modifiers |= AccPublic;
324 } else if (sourceType.isLocalType()) {
325 if (sourceType.isAnonymousType())
326 modifiers |= AccFinal;
329 switch (scope.kind) {
331 MethodScope methodScope = (MethodScope) scope;
332 if (methodScope.isInsideInitializer()) {
333 SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
335 // inside field declaration ? check field modifier to see if deprecated
336 if (methodScope.initializedField != null) {
337 // currently inside this field initialization
338 if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
339 modifiers |= AccDeprecatedImplicitly;
342 if (type.isStrictfp())
343 modifiers |= AccStrictfp;
344 if (type.isViewedAsDeprecated() && !sourceType.isDeprecated())
345 modifiers |= AccDeprecatedImplicitly;
348 MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
350 if (method.isStrictfp())
351 modifiers |= AccStrictfp;
352 if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
353 modifiers |= AccDeprecatedImplicitly;
359 if (enclosingType.isStrictfp())
360 modifiers |= AccStrictfp;
361 if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
362 modifiers |= AccDeprecatedImplicitly;
365 scope = scope.parent;
366 } while (scope != null);
368 // after this point, tests on the 16 bits reserved.
369 int realModifiers = modifiers & AccJustFlag;
371 if ((realModifiers & AccInterface) != 0) {
372 // detect abnormal cases for interfaces
374 int unexpectedModifiers =
375 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp);
376 if ((realModifiers & unexpectedModifiers) != 0)
377 problemReporter().illegalModifierForMemberInterface(sourceType);
379 } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
380 int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
381 if ((realModifiers & unexpectedModifiers) != 0)
382 problemReporter().illegalModifierForLocalInterface(sourceType);
385 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp);
386 if ((realModifiers & unexpectedModifiers) != 0)
387 problemReporter().illegalModifierForInterface(sourceType);
389 modifiers |= AccAbstract;
391 // detect abnormal cases for types
392 if (isMemberType) { // includes member types defined inside local types
393 int unexpectedModifiers =
394 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
395 if ((realModifiers & unexpectedModifiers) != 0)
396 problemReporter().illegalModifierForMemberClass(sourceType);
397 } else if (sourceType.isLocalType()) {
398 int unexpectedModifiers = ~(AccAbstract | AccFinal | AccStrictfp);
399 if ((realModifiers & unexpectedModifiers) != 0)
400 problemReporter().illegalModifierForLocalClass(sourceType);
402 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal | AccStrictfp);
403 if ((realModifiers & unexpectedModifiers) != 0)
404 problemReporter().illegalModifierForClass(sourceType);
407 // check that Final and Abstract are not set together
408 if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
409 problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
413 // test visibility modifiers inconsistency, isolate the accessors bits
414 if (enclosingType.isInterface()) {
415 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
416 problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
418 // need to keep the less restrictive
419 if ((realModifiers & AccProtected) != 0)
420 modifiers ^= AccProtected;
421 if ((realModifiers & AccPrivate) != 0)
422 modifiers ^= AccPrivate;
425 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
426 if ((accessorBits & (accessorBits - 1)) > 1) {
427 problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
429 // need to keep the less restrictive
430 if ((accessorBits & AccPublic) != 0) {
431 if ((accessorBits & AccProtected) != 0)
432 modifiers ^= AccProtected;
433 if ((accessorBits & AccPrivate) != 0)
434 modifiers ^= AccPrivate;
436 if ((accessorBits & AccProtected) != 0)
437 if ((accessorBits & AccPrivate) != 0)
438 modifiers ^= AccPrivate;
442 // static modifier test
443 if ((realModifiers & AccStatic) == 0) {
444 if (enclosingType.isInterface())
445 modifiers |= AccStatic;
447 if (!enclosingType.isStatic())
448 // error the enclosing type of a static field must be static or a top-level type
449 problemReporter().illegalStaticModifierForMemberType(sourceType);
453 sourceType.modifiers = modifiers;
456 /* This method checks the modifiers of a field.
459 * Need to integrate the check for the final modifiers for nested types
461 * Note : A scope is accessible by : fieldBinding.declaringClass.scope
463 private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
464 int modifiers = fieldBinding.modifiers;
465 if ((modifiers & AccAlternateModifierProblem) != 0)
466 problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
468 if (fieldBinding.declaringClass.isInterface()) {
469 int expectedValue = AccPublic | AccStatic | AccFinal;
471 modifiers |= expectedValue;
473 // and then check that they are the only ones
474 if ((modifiers & AccJustFlag) != expectedValue)
475 problemReporter().illegalModifierForInterfaceField(fieldBinding.declaringClass, fieldDecl);
476 fieldBinding.modifiers = modifiers;
480 // after this point, tests on the 16 bits reserved.
481 int realModifiers = modifiers & AccJustFlag;
482 int unexpectedModifiers =
483 ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic | AccTransient | AccVolatile);
484 if ((realModifiers & unexpectedModifiers) != 0)
485 problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
487 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
488 if ((accessorBits & (accessorBits - 1)) > 1) {
489 problemReporter().illegalVisibilityModifierCombinationForField(
490 fieldBinding.declaringClass,
493 // need to keep the less restrictive
494 if ((accessorBits & AccPublic) != 0) {
495 if ((accessorBits & AccProtected) != 0)
496 modifiers ^= AccProtected;
497 if ((accessorBits & AccPrivate) != 0)
498 modifiers ^= AccPrivate;
500 if ((accessorBits & AccProtected) != 0)
501 if ((accessorBits & AccPrivate) != 0)
502 modifiers ^= AccPrivate;
505 if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
506 problemReporter().illegalModifierCombinationFinalVolatileForField(
507 fieldBinding.declaringClass,
510 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
511 modifiers |= AccBlankFinal;
513 fieldBinding.modifiers = modifiers;
516 private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
517 // search up the hierarchy of the sourceType to see if any superType defines a member type
518 // when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
519 ReferenceBinding currentType = sourceType;
520 ReferenceBinding[][] interfacesToVisit = null;
521 int lastPosition = -1;
523 if ((currentType.tagBits & HasNoMemberTypes) != 0)
524 break; // already know it has no inherited member types, can stop looking up
525 if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
526 return; // has member types
527 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
528 if (itsInterfaces != NoSuperInterfaces) {
529 if (interfacesToVisit == null)
530 interfacesToVisit = new ReferenceBinding[5][];
531 if (++lastPosition == interfacesToVisit.length)
535 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
538 interfacesToVisit[lastPosition] = itsInterfaces;
540 } while ((currentType = currentType.superclass()) != null);
542 boolean hasMembers = false;
543 if (interfacesToVisit != null) {
544 done : for (int i = 0; i <= lastPosition; i++) {
545 ReferenceBinding[] interfaces = interfacesToVisit[i];
546 for (int j = 0, length = interfaces.length; j < length; j++) {
547 ReferenceBinding anInterface = interfaces[j];
548 if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
549 anInterface.tagBits |= InterfaceVisited;
550 if ((anInterface.tagBits & HasNoMemberTypes) != 0)
551 continue; // already know it has no inherited member types
552 if (anInterface.memberTypes() != NoMemberTypes) {
557 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
558 if (itsInterfaces != NoSuperInterfaces) {
559 if (++lastPosition == interfacesToVisit.length)
563 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
566 interfacesToVisit[lastPosition] = itsInterfaces;
572 for (int i = 0; i <= lastPosition; i++) {
573 ReferenceBinding[] interfaces = interfacesToVisit[i];
574 for (int j = 0, length = interfaces.length; j < length; j++) {
575 interfaces[j].tagBits &= ~InterfaceVisited;
577 interfaces[j].tagBits |= HasNoMemberTypes;
583 currentType = sourceType;
585 currentType.tagBits |= HasNoMemberTypes;
586 } while ((currentType = currentType.superclass()) != null);
590 private void connectMemberTypes() {
591 SourceTypeBinding sourceType = referenceContext.binding;
592 if (sourceType.memberTypes != NoMemberTypes)
593 for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
594 ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
597 Our current belief based on available JCK tests is:
598 inherited member types are visible as a potential superclass.
599 inherited interfaces are not visible when defining a superinterface.
601 Error recovery story:
602 ensure the superclass is set to java.lang.Object if a problem is detected
603 resolving the superclass.
605 Answer false if an error was reported against the sourceType.
607 private boolean connectSuperclass() {
608 SourceTypeBinding sourceType = referenceContext.binding;
609 if (sourceType.id == T_Object) { // handle the case of redefining java.lang.Object up front
610 sourceType.superclass = null;
611 sourceType.superInterfaces = NoSuperInterfaces;
612 if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
613 problemReporter().objectCannotHaveSuperTypes(sourceType);
614 return true; // do not propagate Object's hierarchy problems down to every subtype
616 if (referenceContext.superclass == null) {
617 sourceType.superclass = getJavaLangObject();
618 return !detectCycle(sourceType, sourceType.superclass, null);
620 ReferenceBinding superclass = findSupertype(referenceContext.superclass);
621 if (superclass != null) { // is null if a cycle was detected cycle
622 referenceContext.superclass.resolvedType = superclass; // hold onto the problem type
623 if (!superclass.isValidBinding()) {
624 problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
625 } else if (superclass.isInterface()) {
626 problemReporter().superclassMustBeAClass(sourceType, referenceContext.superclass, superclass);
627 } else if (superclass.isFinal()) {
628 problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
630 // only want to reach here when no errors are reported
631 sourceType.superclass = superclass;
635 sourceType.tagBits |= HierarchyHasProblems;
636 sourceType.superclass = getJavaLangObject();
637 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
638 detectCycle(sourceType, sourceType.superclass, null);
639 return false; // reported some error against the source type
643 Our current belief based on available JCK 1.3 tests is:
644 inherited member types are visible as a potential superclass.
645 inherited interfaces are visible when defining a superinterface.
647 Error recovery story:
648 ensure the superinterfaces contain only valid visible interfaces.
650 Answer false if an error was reported against the sourceType.
652 private boolean connectSuperInterfaces() {
653 SourceTypeBinding sourceType = referenceContext.binding;
654 sourceType.superInterfaces = NoSuperInterfaces;
655 if (referenceContext.superInterfaces == null)
657 if (sourceType.id == T_Object) // already handled the case of redefining java.lang.Object
660 boolean noProblems = true;
661 int length = referenceContext.superInterfaces.length;
662 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
664 nextInterface : for (int i = 0; i < length; i++) {
665 ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
666 if (superInterface == null) { // detected cycle
668 continue nextInterface;
670 referenceContext.superInterfaces[i].resolvedType = superInterface; // hold onto the problem type
671 if (!superInterface.isValidBinding()) {
672 problemReporter().invalidSuperinterface(
674 referenceContext.superInterfaces[i],
676 sourceType.tagBits |= HierarchyHasProblems;
678 continue nextInterface;
680 // Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
681 for (int k = 0; k < count; k++) {
682 if (interfaceBindings[k] == superInterface) {
683 // should this be treated as a warning?
684 problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
685 continue nextInterface;
688 if (superInterface.isClass()) {
689 problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
690 sourceType.tagBits |= HierarchyHasProblems;
692 continue nextInterface;
695 // only want to reach here when no errors are reported
696 interfaceBindings[count++] = superInterface;
698 // hold onto all correctly resolved superinterfaces
701 System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
702 sourceType.superInterfaces = interfaceBindings;
707 void connectTypeHierarchy() {
708 SourceTypeBinding sourceType = referenceContext.binding;
709 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
710 boolean noProblems = true;
711 sourceType.tagBits |= BeginHierarchyCheck;
712 if (sourceType.isClass())
713 noProblems &= connectSuperclass();
714 noProblems &= connectSuperInterfaces();
715 sourceType.tagBits |= EndHierarchyCheck;
716 if (noProblems && sourceType.isHierarchyInconsistent())
717 problemReporter().hierarchyHasProblems(sourceType);
719 connectMemberTypes();
721 checkForInheritedMemberTypes(sourceType);
722 } catch (AbortCompilation e) {
723 e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
728 private void connectTypeHierarchyWithoutMembers() {
729 // must ensure the imports are resolved
730 if (parent instanceof CompilationUnitScope) {
731 if (((CompilationUnitScope) parent).imports == null)
732 ((CompilationUnitScope) parent).checkAndSetImports();
733 } else if (parent instanceof ClassScope) {
734 // ensure that the enclosing type has already been checked
735 ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
738 // double check that the hierarchy search has not already begun...
739 SourceTypeBinding sourceType = referenceContext.binding;
740 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
743 boolean noProblems = true;
744 sourceType.tagBits |= BeginHierarchyCheck;
745 if (sourceType.isClass())
746 noProblems &= connectSuperclass();
747 noProblems &= connectSuperInterfaces();
748 sourceType.tagBits |= EndHierarchyCheck;
749 if (noProblems && sourceType.isHierarchyInconsistent())
750 problemReporter().hierarchyHasProblems(sourceType);
753 // Answer whether a cycle was found between the sourceType & the superType
754 private boolean detectCycle(
755 SourceTypeBinding sourceType,
756 ReferenceBinding superType,
757 TypeReference reference) {
758 if (sourceType == superType) {
759 problemReporter().hierarchyCircularity(sourceType, superType, reference);
760 sourceType.tagBits |= HierarchyHasProblems;
764 if (superType.isBinaryBinding()) {
765 // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
766 // - a binary type... this case MUST be caught & reported here
767 // - another source type... this case is reported against the other source type
768 boolean hasCycle = false;
769 if (superType.superclass() != null) {
770 if (sourceType == superType.superclass()) {
771 problemReporter().hierarchyCircularity(sourceType, superType, reference);
772 sourceType.tagBits |= HierarchyHasProblems;
773 superType.tagBits |= HierarchyHasProblems;
776 hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
777 if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
778 sourceType.tagBits |= HierarchyHasProblems;
779 superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
783 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
784 if (itsInterfaces != NoSuperInterfaces) {
785 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
786 ReferenceBinding anInterface = itsInterfaces[i];
787 if (sourceType == anInterface) {
788 problemReporter().hierarchyCircularity(sourceType, superType, reference);
789 sourceType.tagBits |= HierarchyHasProblems;
790 superType.tagBits |= HierarchyHasProblems;
793 hasCycle |= detectCycle(sourceType, anInterface, reference);
794 if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
795 sourceType.tagBits |= HierarchyHasProblems;
796 superType.tagBits |= HierarchyHasProblems;
803 if ((superType.tagBits & EndHierarchyCheck) == 0
804 && (superType.tagBits & BeginHierarchyCheck) != 0) {
805 problemReporter().hierarchyCircularity(sourceType, superType, reference);
806 sourceType.tagBits |= HierarchyHasProblems;
807 superType.tagBits |= HierarchyHasProblems;
810 if ((superType.tagBits & BeginHierarchyCheck) == 0)
811 // ensure if this is a source superclass that it has already been checked
812 ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
813 if ((superType.tagBits & HierarchyHasProblems) != 0)
814 sourceType.tagBits |= HierarchyHasProblems;
818 private ReferenceBinding findSupertype(TypeReference typeReference) {
820 typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
821 char[][] compoundName = typeReference.getTypeName();
822 compilationUnitScope().recordQualifiedReference(compoundName);
823 SourceTypeBinding sourceType = referenceContext.binding;
824 int size = compoundName.length;
826 ReferenceBinding superType;
828 // resolve the first name of the compoundName
829 if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
830 superType = sourceType;
831 // match against the sourceType even though nested members cannot be supertypes
833 Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
834 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
835 return new ProblemReferenceBinding(
837 typeOrPackage == null ? NotFound : typeOrPackage.problemId());
839 boolean checkVisibility = false;
840 for (; n < size; n++) {
841 if (!(typeOrPackage instanceof PackageBinding))
843 PackageBinding packageBinding = (PackageBinding) typeOrPackage;
844 typeOrPackage = packageBinding.getTypeOrPackage(compoundName[n]);
845 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
846 return new ProblemReferenceBinding(
847 CharOperation.subarray(compoundName, 0, n + 1),
848 typeOrPackage == null ? NotFound : typeOrPackage.problemId());
849 checkVisibility = true;
852 // convert to a ReferenceBinding
853 if (typeOrPackage instanceof PackageBinding) // error, the compoundName is a packageName
854 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
855 superType = (ReferenceBinding) typeOrPackage;
856 compilationUnitScope().recordTypeReference(superType); // to record supertypes
859 && n == size) { // if we're finished and know the final supertype then check visibility
860 if (!superType.canBeSeenBy(sourceType.fPackage))
861 // its a toplevel type so just check package access
862 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), superType, NotVisible);
865 // at this point we know we have a type but we have to look for cycles
867 // must detect cycles & force connection up the hierarchy... also handle cycles with binary types.
868 // must be guaranteed that the superType knows its entire hierarchy
869 if (detectCycle(sourceType, superType, typeReference))
870 return null; // cycle error was already reported
875 // retrieve the next member type
876 char[] typeName = compoundName[n++];
877 superType = findMemberType(typeName, superType);
878 if (superType == null)
879 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
880 if (!superType.isValidBinding()) {
881 superType.compoundName = CharOperation.subarray(compoundName, 0, n);
886 } catch (AbortCompilation e) {
887 e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
892 /* Answer the problem reporter to use for raising new problems.
894 * Note that as a side-effect, this updates the current reference context
895 * (unit, type or method) in case the problem handler decides it is necessary
898 public ProblemReporter problemReporter() {
899 MethodScope outerMethodScope;
900 if ((outerMethodScope = outerMostMethodScope()) == null) {
901 ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
902 problemReporter.referenceContext = referenceContext;
903 return problemReporter;
905 return outerMethodScope.problemReporter();
908 /* Answer the reference type of this scope.
909 * It is the nearest enclosing type of this scope.
911 public TypeDeclaration referenceType() {
912 return referenceContext;
915 public String toString() {
916 if (referenceContext != null)
917 return "--- Class Scope ---\n\n" //$NON-NLS-1$
918 + referenceContext.binding.toString();
919 return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$