1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.compiler.lookup;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
15 import net.sourceforge.phpdt.internal.compiler.ast.Clinit;
16 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
17 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
19 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
20 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
21 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
23 public class ClassScope extends Scope {
24 public TypeDeclaration referenceContext;
26 public ClassScope(Scope parent, TypeDeclaration context) {
27 super(CLASS_SCOPE, parent);
28 this.referenceContext = context;
31 void buildAnonymousTypeBinding(SourceTypeBinding enclosingType,
32 ReferenceBinding supertype) {
34 LocalTypeBinding anonymousType = buildLocalType(enclosingType,
35 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 = TypeBinding.NoSuperInterfaces;
46 buildFieldsAndMethods();
47 anonymousType.faultInTypesForFieldsAndMethods();
48 sourceType.verifyMethods(environment().methodVerifier());
51 private void buildFields() {
52 if (referenceContext.fields == null) {
53 referenceContext.binding.fields = NoFields;
56 // count the number of fields vs. initializers
57 FieldDeclaration[] fields = referenceContext.fields;
58 int size = fields.length;
60 for (int i = 0; i < size; i++)
61 if (fields[i].isField())
64 // iterate the field declarations to create the bindings, lose all
66 FieldBinding[] fieldBindings = new FieldBinding[count];
67 HashtableOfObject knownFieldNames = new HashtableOfObject(count);
68 boolean duplicate = false;
70 for (int i = 0; i < size; i++) {
71 FieldDeclaration field = fields[i];
72 if (!field.isField()) {
73 if (referenceContext.binding.isInterface())
74 problemReporter().interfaceCannotHaveInitializers(
75 referenceContext.binding, field);
77 FieldBinding fieldBinding = new FieldBinding(field, null,
78 referenceContext.binding);
79 // field's type will be resolved when needed for top level types
80 checkAndSetModifiersForField(fieldBinding, field);
82 if (knownFieldNames.containsKey(field.name)) {
84 FieldBinding previousBinding = (FieldBinding) knownFieldNames
86 if (previousBinding != null) {
87 for (int f = 0; f < i; f++) {
88 FieldDeclaration previousField = fields[f];
89 if (previousField.binding == previousBinding) {
91 .duplicateFieldInType(
92 referenceContext.binding,
94 previousField.binding = null;
99 knownFieldNames.put(field.name, null); // ensure that the
103 problemReporter().duplicateFieldInType(
104 referenceContext.binding, field);
105 field.binding = null;
107 knownFieldNames.put(field.name, fieldBinding);
108 // remember that we have seen a field with this name
109 if (fieldBinding != null)
110 fieldBindings[count++] = fieldBinding;
114 // remove duplicate fields
116 FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames
118 // we know we'll be removing at least 1 duplicate name
121 for (int i = 0; i < size; i++) {
122 FieldBinding fieldBinding = fieldBindings[i];
123 if (knownFieldNames.get(fieldBinding.name) != null)
124 newFieldBindings[count++] = fieldBinding;
126 fieldBindings = newFieldBindings;
129 if (count != fieldBindings.length)
130 System.arraycopy(fieldBindings, 0,
131 fieldBindings = new FieldBinding[count], 0, count);
132 for (int i = 0; i < count; i++)
133 fieldBindings[i].id = i;
134 referenceContext.binding.fields = fieldBindings;
137 void buildFieldsAndMethods() {
141 SourceTypeBinding sourceType = referenceContext.binding;
142 if (sourceType.isMemberType() && !sourceType.isLocalType())
143 ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
145 ReferenceBinding[] memberTypes = sourceType.memberTypes;
146 for (int i = 0, length = memberTypes.length; i < length; i++)
147 ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
150 private LocalTypeBinding buildLocalType(SourceTypeBinding enclosingType,
151 PackageBinding packageBinding) {
152 referenceContext.scope = this;
153 referenceContext.staticInitializerScope = new MethodScope(this,
154 referenceContext, true);
155 referenceContext.initializerScope = new MethodScope(this,
156 referenceContext, false);
158 // build the binding or the local type
159 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType);
160 referenceContext.binding = localType;
161 checkAndSetModifiers();
163 // Look at member types
164 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
165 if (referenceContext.memberTypes != null) {
166 int size = referenceContext.memberTypes.length;
167 memberTypeBindings = new ReferenceBinding[size];
169 nextMember: for (int i = 0; i < size; i++) {
170 TypeDeclaration memberContext = referenceContext.memberTypes[i];
171 if (memberContext.isInterface()) {
172 problemReporter().nestedClassCannotDeclareInterface(
176 ReferenceBinding type = localType;
177 // check that the member does not conflict with an enclosing
180 if (CharOperation.equals(type.sourceName,
181 memberContext.name)) {
182 problemReporter().hidingEnclosingType(memberContext);
185 type = type.enclosingType();
186 } while (type != null);
187 // check the member type does not conflict with another sibling
189 for (int j = 0; j < i; j++) {
190 if (CharOperation.equals(
191 referenceContext.memberTypes[j].name,
192 memberContext.name)) {
193 problemReporter().duplicateNestedType(memberContext);
198 ClassScope memberScope = new ClassScope(this,
199 referenceContext.memberTypes[i]);
200 LocalTypeBinding memberBinding = memberScope.buildLocalType(
201 localType, packageBinding);
202 memberBinding.setAsMemberType();
203 memberTypeBindings[count++] = memberBinding;
206 System.arraycopy(memberTypeBindings, 0,
207 memberTypeBindings = new ReferenceBinding[count], 0,
210 localType.memberTypes = memberTypeBindings;
214 void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
216 LocalTypeBinding localType = buildLocalType(enclosingType,
217 enclosingType.fPackage);
218 connectTypeHierarchy();
219 buildFieldsAndMethods();
220 localType.faultInTypesForFieldsAndMethods();
222 referenceContext.binding.verifyMethods(environment().methodVerifier());
225 private void buildMethods() {
226 if (referenceContext.methods == null) {
227 referenceContext.binding.methods = NoMethods;
231 // iterate the method declarations to create the bindings
232 AbstractMethodDeclaration[] methods = referenceContext.methods;
233 int size = methods.length;
234 int clinitIndex = -1;
235 for (int i = 0; i < size; i++) {
236 if (methods[i] instanceof Clinit) {
241 MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size
245 for (int i = 0; i < size; i++) {
246 if (i != clinitIndex) {
247 MethodScope scope = new MethodScope(this, methods[i], false);
248 MethodBinding methodBinding = scope.createMethod(methods[i]);
249 if (methodBinding != null) // is null if binding could not be
251 methodBindings[count++] = methodBinding;
254 if (count != methodBindings.length)
255 System.arraycopy(methodBindings, 0,
256 methodBindings = new MethodBinding[count], 0, count);
258 referenceContext.binding.methods = methodBindings;
259 referenceContext.binding.modifiers |= AccUnresolved; // until
264 SourceTypeBinding buildType(SourceTypeBinding enclosingType,
265 PackageBinding packageBinding) {
266 // provide the typeDeclaration with needed scopes
267 referenceContext.scope = this;
268 referenceContext.staticInitializerScope = new MethodScope(this,
269 referenceContext, true);
270 referenceContext.initializerScope = new MethodScope(this,
271 referenceContext, false);
273 if (enclosingType == null) {
274 char[][] className = CharOperation.arrayConcat(
275 packageBinding.compoundName, referenceContext.name);
276 referenceContext.binding = new SourceTypeBinding(className,
277 packageBinding, this);
279 char[][] className = CharOperation
280 .deepCopy(enclosingType.compoundName);
281 className[className.length - 1] = CharOperation
282 .concat(className[className.length - 1],
283 referenceContext.name, '$');
284 referenceContext.binding = new MemberTypeBinding(className, this,
288 SourceTypeBinding sourceType = referenceContext.binding;
289 sourceType.fPackage.addType(sourceType);
290 checkAndSetModifiers();
292 // Look at member types
293 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
294 if (referenceContext.memberTypes != null) {
295 int size = referenceContext.memberTypes.length;
296 memberTypeBindings = new ReferenceBinding[size];
298 nextMember: for (int i = 0; i < size; i++) {
299 TypeDeclaration memberContext = referenceContext.memberTypes[i];
300 if (memberContext.isInterface() && sourceType.isNestedType()
301 && sourceType.isClass() && !sourceType.isStatic()) {
302 problemReporter().nestedClassCannotDeclareInterface(
306 ReferenceBinding type = sourceType;
307 // check that the member does not conflict with an enclosing
310 if (CharOperation.equals(type.sourceName,
311 memberContext.name)) {
312 problemReporter().hidingEnclosingType(memberContext);
315 type = type.enclosingType();
316 } while (type != null);
317 // check that the member type does not conflict with another
318 // sibling member type
319 for (int j = 0; j < i; j++) {
320 if (CharOperation.equals(
321 referenceContext.memberTypes[j].name,
322 memberContext.name)) {
323 problemReporter().duplicateNestedType(memberContext);
328 ClassScope memberScope = new ClassScope(this, memberContext);
329 memberTypeBindings[count++] = memberScope.buildType(sourceType,
333 System.arraycopy(memberTypeBindings, 0,
334 memberTypeBindings = new ReferenceBinding[count], 0,
337 sourceType.memberTypes = memberTypeBindings;
341 private void checkAndSetModifiers() {
342 SourceTypeBinding sourceType = referenceContext.binding;
343 int modifiers = sourceType.modifiers;
344 if ((modifiers & AccAlternateModifierProblem) != 0)
345 problemReporter().duplicateModifierForType(sourceType);
347 ReferenceBinding enclosingType = sourceType.enclosingType();
348 boolean isMemberType = sourceType.isMemberType();
351 // checks for member types before local types to catch local members
352 // if (enclosingType.isStrictfp())
353 // modifiers |= AccStrictfp;
354 if (enclosingType.isDeprecated())
355 modifiers |= AccDeprecatedImplicitly;
356 if (enclosingType.isInterface())
357 modifiers |= AccPublic;
358 } else if (sourceType.isLocalType()) {
359 if (sourceType.isAnonymousType())
360 modifiers |= AccFinal;
361 ReferenceContext refContext = methodScope().referenceContext;
362 if (refContext instanceof TypeDeclaration) {
363 ReferenceBinding type = ((TypeDeclaration) refContext).binding;
364 // if (type.isStrictfp())
365 // modifiers |= AccStrictfp;
366 if (type.isDeprecated())
367 modifiers |= AccDeprecatedImplicitly;
369 MethodBinding method = ((AbstractMethodDeclaration) refContext).binding;
370 if (method != null) {
371 // if (method.isStrictfp())
372 // modifiers |= AccStrictfp;
373 if (method.isDeprecated())
374 modifiers |= AccDeprecatedImplicitly;
378 // after this point, tests on the 16 bits reserved.
379 int realModifiers = modifiers & AccJustFlag;
381 if ((realModifiers & AccInterface) != 0) {
382 // detect abnormal cases for interfaces
384 int unexpectedModifiers = ~(AccPublic | AccPrivate
385 | AccProtected | AccStatic | AccAbstract | AccInterface);// |
387 if ((realModifiers & unexpectedModifiers) != 0)
388 problemReporter().illegalModifierForMemberInterface(
391 * } else if (sourceType.isLocalType()) { //interfaces cannot be
392 * defined inside a method int unexpectedModifiers =
393 * ~(AccAbstract | AccInterface | AccStrictfp); if
394 * ((realModifiers & unexpectedModifiers) != 0)
395 * problemReporter().illegalModifierForLocalInterface(sourceType);
398 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface);// |
400 if ((realModifiers & unexpectedModifiers) != 0)
401 problemReporter().illegalModifierForInterface(sourceType);
403 modifiers |= AccAbstract;
405 // detect abnormal cases for types
406 if (isMemberType) { // includes member types defined inside local
408 int unexpectedModifiers = ~(AccPublic | AccPrivate
409 | AccProtected | AccStatic | AccAbstract | AccFinal);// |
411 if ((realModifiers & unexpectedModifiers) != 0)
412 problemReporter().illegalModifierForMemberClass(sourceType);
413 } else if (sourceType.isLocalType()) {
414 int unexpectedModifiers = ~(AccAbstract | AccFinal);// |
416 if ((realModifiers & unexpectedModifiers) != 0)
417 problemReporter().illegalModifierForLocalClass(sourceType);
419 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal);// |
421 if ((realModifiers & unexpectedModifiers) != 0)
422 problemReporter().illegalModifierForClass(sourceType);
425 // check that Final and Abstract are not set together
426 if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
428 .illegalModifierCombinationFinalAbstractForClass(
433 // test visibility modifiers inconsistency, isolate the accessors
435 if (enclosingType.isInterface()) {
436 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
438 .illegalVisibilityModifierForInterfaceMemberType(
441 // need to keep the less restrictive
442 if ((realModifiers & AccProtected) != 0)
443 modifiers ^= AccProtected;
444 if ((realModifiers & AccPrivate) != 0)
445 modifiers ^= AccPrivate;
448 int accessorBits = realModifiers
449 & (AccPublic | AccProtected | AccPrivate);
450 if ((accessorBits & (accessorBits - 1)) > 1) {
452 .illegalVisibilityModifierCombinationForMemberType(
455 // need to keep the less restrictive
456 if ((accessorBits & AccPublic) != 0) {
457 if ((accessorBits & AccProtected) != 0)
458 modifiers ^= AccProtected;
459 if ((accessorBits & AccPrivate) != 0)
460 modifiers ^= AccPrivate;
462 if ((accessorBits & AccProtected) != 0)
463 if ((accessorBits & AccPrivate) != 0)
464 modifiers ^= AccPrivate;
468 // static modifier test
469 if ((realModifiers & AccStatic) == 0) {
470 if (enclosingType.isInterface())
471 modifiers |= AccStatic;
473 if (!enclosingType.isStatic())
474 // error the enclosing type of a static field must be static
475 // or a top-level type
476 problemReporter().illegalStaticModifierForMemberType(
481 sourceType.modifiers = modifiers;
485 * This method checks the modifiers of a field.
487 * 9.3 & 8.3 Need to integrate the check for the final modifiers for nested
490 * Note : A scope is accessible by : fieldBinding.declaringClass.scope
492 private void checkAndSetModifiersForField(FieldBinding fieldBinding,
493 FieldDeclaration fieldDecl) {
494 int modifiers = fieldBinding.modifiers;
495 if ((modifiers & AccAlternateModifierProblem) != 0)
496 problemReporter().duplicateModifierForField(
497 fieldBinding.declaringClass, fieldDecl);
499 if (fieldBinding.declaringClass.isInterface()) {
500 int expectedValue = AccPublic | AccStatic | AccFinal;
502 modifiers |= expectedValue;
504 // and then check that they are the only ones
505 if ((modifiers & AccJustFlag) != expectedValue)
506 problemReporter().illegalModifierForInterfaceField(
507 fieldBinding.declaringClass, fieldDecl);
508 fieldBinding.modifiers = modifiers;
512 // after this point, tests on the 16 bits reserved.
513 int realModifiers = modifiers & AccJustFlag;
514 int unexpectedModifiers = ~(AccPublic | AccPrivate | AccProtected
515 | AccFinal | AccStatic);// | AccTransient | AccVolatile);
516 if ((realModifiers & unexpectedModifiers) != 0)
517 problemReporter().illegalModifierForField(
518 fieldBinding.declaringClass, fieldDecl);
520 int accessorBits = realModifiers
521 & (AccPublic | AccProtected | AccPrivate);
522 if ((accessorBits & (accessorBits - 1)) > 1) {
523 problemReporter().illegalVisibilityModifierCombinationForField(
524 fieldBinding.declaringClass, fieldDecl);
526 // need to keep the less restrictive
527 if ((accessorBits & AccPublic) != 0) {
528 if ((accessorBits & AccProtected) != 0)
529 modifiers ^= AccProtected;
530 if ((accessorBits & AccPrivate) != 0)
531 modifiers ^= AccPrivate;
533 if ((accessorBits & AccProtected) != 0)
534 if ((accessorBits & AccPrivate) != 0)
535 modifiers ^= AccPrivate;
538 // if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal |
540 // problemReporter().illegalModifierCombinationFinalVolatileForField(
541 // fieldBinding.declaringClass,
544 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
545 modifiers |= AccBlankFinal;
547 fieldBinding.modifiers = modifiers;
550 private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
551 // search up the hierarchy of the sourceType to see if any superType
552 // defines a member type
553 // when no member types are defined, tag the sourceType & each superType
554 // with the HasNoMemberTypes bit
555 ReferenceBinding currentType = sourceType;
556 ReferenceBinding[][] interfacesToVisit = null;
557 int lastPosition = -1;
559 if ((currentType.tagBits & HasNoMemberTypes) != 0)
560 break; // already know it has no inherited member types, can
562 if (currentType.memberTypes() != NoMemberTypes)
563 return; // has member types
564 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
565 if (itsInterfaces != NoSuperInterfaces) {
566 if (interfacesToVisit == null)
567 interfacesToVisit = new ReferenceBinding[5][];
568 if (++lastPosition == interfacesToVisit.length)
573 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
575 interfacesToVisit[lastPosition] = itsInterfaces;
577 } while ((currentType = currentType.superclass()) != null);
579 boolean hasMembers = false;
580 if (interfacesToVisit != null) {
581 done: for (int i = 0; i <= lastPosition; i++) {
582 ReferenceBinding[] interfaces = interfacesToVisit[i];
583 for (int j = 0, length = interfaces.length; j < length; j++) {
584 ReferenceBinding anInterface = interfaces[j];
585 if ((anInterface.tagBits & InterfaceVisited) == 0) { // if
592 anInterface.tagBits |= InterfaceVisited;
593 if ((anInterface.tagBits & HasNoMemberTypes) != 0)
594 continue; // already know it has no inherited
596 if (anInterface.memberTypes() != NoMemberTypes) {
601 ReferenceBinding[] itsInterfaces = anInterface
603 if (itsInterfaces != NoSuperInterfaces) {
604 if (++lastPosition == interfacesToVisit.length)
609 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
611 interfacesToVisit[lastPosition] = itsInterfaces;
617 for (int i = 0; i <= lastPosition; i++) {
618 ReferenceBinding[] interfaces = interfacesToVisit[i];
619 for (int j = 0, length = interfaces.length; j < length; j++) {
620 interfaces[j].tagBits &= ~InterfaceVisited;
622 interfaces[j].tagBits |= HasNoMemberTypes;
628 currentType = sourceType;
630 currentType.tagBits |= HasNoMemberTypes;
631 } while ((currentType = currentType.superclass()) != null);
635 private void connectMemberTypes() {
636 SourceTypeBinding sourceType = referenceContext.binding;
637 if (sourceType.memberTypes != NoMemberTypes)
638 for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
639 ((SourceTypeBinding) sourceType.memberTypes[i]).scope
640 .connectTypeHierarchy();
644 * Our current belief based on available JCK tests is: inherited member
645 * types are visible as a potential superclass. inherited interfaces are not
646 * visible when defining a superinterface.
648 * Error recovery story: ensure the superclass is set to java.lang.Object if
649 * a problem is detected resolving the superclass.
651 * Answer false if an error was reported against the sourceType.
653 private boolean connectSuperclass() {
654 SourceTypeBinding sourceType = referenceContext.binding;
655 if (isJavaLangObject(sourceType)) { // handle the case of redefining
656 // java.lang.Object up front
657 sourceType.superclass = null;
658 sourceType.superInterfaces = NoSuperInterfaces;
659 if (referenceContext.superclass != null
660 || referenceContext.superInterfaces != null)
661 problemReporter().objectCannotHaveSuperTypes(sourceType);
662 return true; // do not propagate Object's hierarchy problems down
665 if (referenceContext.superclass == null) {
666 sourceType.superclass = getJavaLangObject();
667 return !detectCycle(sourceType, sourceType.superclass, null);
669 ReferenceBinding superclass = findSupertype(referenceContext.superclass);
670 if (superclass != null) { // is null if a cycle was detected cycle
671 if (!superclass.isValidBinding()) {
672 problemReporter().invalidSuperclass(sourceType,
673 referenceContext.superclass, superclass);
674 } else if (superclass.isInterface()) {
675 problemReporter().superclassMustBeAClass(sourceType,
676 referenceContext.superclass, superclass);
677 } else if (superclass.isFinal()) {
678 problemReporter().classExtendFinalClass(sourceType,
679 referenceContext.superclass, superclass);
681 // only want to reach here when no errors are reported
682 referenceContext.superclass.resolvedType = superclass;
683 sourceType.superclass = superclass;
687 sourceType.tagBits |= HierarchyHasProblems;
688 sourceType.superclass = getJavaLangObject();
689 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
690 detectCycle(sourceType, sourceType.superclass, null);
691 return false; // reported some error against the source type
695 * Our current belief based on available JCK 1.3 tests is: inherited member
696 * types are visible as a potential superclass. inherited interfaces are
697 * visible when defining a superinterface.
699 * Error recovery story: ensure the superinterfaces contain only valid
700 * visible interfaces.
702 * Answer false if an error was reported against the sourceType.
704 private boolean connectSuperInterfaces() {
705 SourceTypeBinding sourceType = referenceContext.binding;
706 sourceType.superInterfaces = NoSuperInterfaces;
707 if (referenceContext.superInterfaces == null)
709 if (isJavaLangObject(sourceType)) // already handled the case of
710 // redefining java.lang.Object
713 boolean noProblems = true;
714 int length = referenceContext.superInterfaces.length;
715 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
717 nextInterface: for (int i = 0; i < length; i++) {
718 ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
719 if (superInterface == null) { // detected cycle
721 continue nextInterface;
723 if (!superInterface.isValidBinding()) {
724 problemReporter().invalidSuperinterface(sourceType,
725 referenceContext.superInterfaces[i], superInterface);
726 sourceType.tagBits |= HierarchyHasProblems;
728 continue nextInterface;
730 // Check for a duplicate interface once the name is resolved,
731 // otherwise we may be confused (ie : a.b.I and c.d.I)
732 for (int k = 0; k < count; k++) {
733 if (interfaceBindings[k] == superInterface) {
734 // should this be treated as a warning?
735 problemReporter().duplicateSuperinterface(sourceType,
736 referenceContext, superInterface);
737 continue nextInterface;
740 if (superInterface.isClass()) {
741 problemReporter().superinterfaceMustBeAnInterface(sourceType,
742 referenceContext, superInterface);
743 sourceType.tagBits |= HierarchyHasProblems;
745 continue nextInterface;
748 referenceContext.superInterfaces[i].resolvedType = superInterface;
749 // only want to reach here when no errors are reported
750 interfaceBindings[count++] = superInterface;
752 // hold onto all correctly resolved superinterfaces
755 System.arraycopy(interfaceBindings, 0,
756 interfaceBindings = new ReferenceBinding[count], 0,
758 sourceType.superInterfaces = interfaceBindings;
763 void connectTypeHierarchy() {
764 SourceTypeBinding sourceType = referenceContext.binding;
765 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
766 boolean noProblems = true;
767 sourceType.tagBits |= BeginHierarchyCheck;
768 if (sourceType.isClass())
769 noProblems &= connectSuperclass();
770 noProblems &= connectSuperInterfaces();
771 sourceType.tagBits |= EndHierarchyCheck;
772 if (noProblems && sourceType.isHierarchyInconsistent())
773 problemReporter().hierarchyHasProblems(sourceType);
775 connectMemberTypes();
776 checkForInheritedMemberTypes(sourceType);
779 private void connectTypeHierarchyWithoutMembers() {
780 // must ensure the imports are resolved
781 if (parent instanceof CompilationUnitScope) {
782 // if (((CompilationUnitScope) parent).imports == null)
783 // ((CompilationUnitScope) parent).checkAndSetImports();
784 } else if (parent instanceof ClassScope) {
785 // ensure that the enclosing type has already been checked
786 ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
789 // double check that the hierarchy search has not already begun...
790 SourceTypeBinding sourceType = referenceContext.binding;
791 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
794 boolean noProblems = true;
795 sourceType.tagBits |= BeginHierarchyCheck;
796 if (sourceType.isClass())
797 noProblems &= connectSuperclass();
798 noProblems &= connectSuperInterfaces();
799 sourceType.tagBits |= EndHierarchyCheck;
800 if (noProblems && sourceType.isHierarchyInconsistent())
801 problemReporter().hierarchyHasProblems(sourceType);
804 // Answer whether a cycle was found between the sourceType & the superType
805 private boolean detectCycle(SourceTypeBinding sourceType,
806 ReferenceBinding superType, TypeReference reference) {
807 if (sourceType == superType) {
808 problemReporter().hierarchyCircularity(sourceType, superType,
810 sourceType.tagBits |= HierarchyHasProblems;
814 if (superType.isBinaryBinding()) {
815 // force its superclass & superinterfaces to be found... 2
816 // possibilities exist - the source type is included in the
818 // - a binary type... this case MUST be caught & reported here
819 // - another source type... this case is reported against the other
821 boolean hasCycle = false;
822 if (superType.superclass() != null) {
823 if (sourceType == superType.superclass()) {
824 problemReporter().hierarchyCircularity(sourceType,
825 superType, reference);
826 sourceType.tagBits |= HierarchyHasProblems;
827 superType.tagBits |= HierarchyHasProblems;
830 hasCycle |= detectCycle(sourceType, superType.superclass(),
832 if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
833 sourceType.tagBits |= HierarchyHasProblems;
834 superType.tagBits |= HierarchyHasProblems; // propagate
840 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
841 if (itsInterfaces != NoSuperInterfaces) {
842 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
843 ReferenceBinding anInterface = itsInterfaces[i];
844 if (sourceType == anInterface) {
845 problemReporter().hierarchyCircularity(sourceType,
846 superType, reference);
847 sourceType.tagBits |= HierarchyHasProblems;
848 superType.tagBits |= HierarchyHasProblems;
851 hasCycle |= detectCycle(sourceType, anInterface, reference);
852 if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
853 sourceType.tagBits |= HierarchyHasProblems;
854 superType.tagBits |= HierarchyHasProblems;
861 if ((superType.tagBits & EndHierarchyCheck) == 0
862 && (superType.tagBits & BeginHierarchyCheck) != 0) {
863 problemReporter().hierarchyCircularity(sourceType, superType,
865 sourceType.tagBits |= HierarchyHasProblems;
866 superType.tagBits |= HierarchyHasProblems;
869 if ((superType.tagBits & BeginHierarchyCheck) == 0)
870 // ensure if this is a source superclass that it has already been
872 ((SourceTypeBinding) superType).scope
873 .connectTypeHierarchyWithoutMembers();
874 if ((superType.tagBits & HierarchyHasProblems) != 0)
875 sourceType.tagBits |= HierarchyHasProblems;
879 private ReferenceBinding findSupertype(TypeReference typeReference) {
880 typeReference.aboutToResolve(this); // allows us to trap completion &
882 char[][] compoundName = typeReference.getTypeName();
883 compilationUnitScope().recordQualifiedReference(compoundName);
884 SourceTypeBinding sourceType = referenceContext.binding;
885 int size = compoundName.length;
887 ReferenceBinding superType;
889 // resolve the first name of the compoundName
890 if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
891 superType = sourceType;
892 // match against the sourceType even though nested members cannot be
895 Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0],
897 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
898 return new ProblemReferenceBinding(compoundName[0],
899 typeOrPackage == null ? NotFound : typeOrPackage
902 boolean checkVisibility = false;
903 for (; n < size; n++) {
904 if (!(typeOrPackage instanceof PackageBinding))
906 PackageBinding packageBinding = (PackageBinding) typeOrPackage;
907 typeOrPackage = packageBinding
908 .getTypeOrPackage(compoundName[n]);
909 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
910 return new ProblemReferenceBinding(CharOperation.subarray(
911 compoundName, 0, n + 1),
912 typeOrPackage == null ? NotFound : typeOrPackage
914 checkVisibility = true;
917 // convert to a ReferenceBinding
918 if (typeOrPackage instanceof PackageBinding) // error, the
921 return new ProblemReferenceBinding(CharOperation.subarray(
922 compoundName, 0, n), NotFound);
923 superType = (ReferenceBinding) typeOrPackage;
924 compilationUnitScope().recordTypeReference(superType); // to record
927 if (checkVisibility && n == size) { // if we're finished and know
928 // the final supertype then
930 if (!superType.canBeSeenBy(sourceType.fPackage))
931 // its a toplevel type so just check package access
932 return new ProblemReferenceBinding(CharOperation.subarray(
933 compoundName, 0, n), superType, NotVisible);
936 // at this point we know we have a type but we have to look for cycles
938 // must detect cycles & force connection up the hierarchy... also
939 // handle cycles with binary types.
940 // must be guaranteed that the superType knows its entire hierarchy
941 if (detectCycle(sourceType, superType, typeReference))
942 return null; // cycle error was already reported
947 // retrieve the next member type
948 char[] typeName = compoundName[n++];
949 superType = findMemberType(typeName, superType);
950 if (superType == null)
951 return new ProblemReferenceBinding(CharOperation.subarray(
952 compoundName, 0, n), NotFound);
953 if (!superType.isValidBinding()) {
954 superType.compoundName = CharOperation.subarray(compoundName,
963 * Answer the problem reporter to use for raising new problems.
965 * Note that as a side-effect, this updates the current reference context
966 * (unit, type or method) in case the problem handler decides it is
967 * necessary to abort.
969 public ProblemReporter problemReporter() {
970 MethodScope outerMethodScope;
971 if ((outerMethodScope = outerMostMethodScope()) == null) {
972 ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
973 problemReporter.referenceContext = referenceContext;
974 return problemReporter;
976 return outerMethodScope.problemReporter();
981 * Answer the reference type of this scope. It is the nearest enclosing type
984 public TypeDeclaration referenceType() {
985 return referenceContext;
988 public String toString() {
989 if (referenceContext != null)
990 return "--- Class Scope ---\n\n" //$NON-NLS-1$
991 + referenceContext.binding.toString();
993 return "--- Class Scope ---\n\n Binding not initialized"; //$NON-NLS-1$