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.impl.ReferenceContext;
15 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
16 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
17 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
18 import net.sourceforge.phpeclipse.internal.compiler.ast.Clinit;
19 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
21 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
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, ReferenceBinding supertype) {
33 LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
35 SourceTypeBinding sourceType = referenceContext.binding;
36 if (supertype.isInterface()) {
37 sourceType.superclass = getJavaLangObject();
38 sourceType.superInterfaces = new ReferenceBinding[] { supertype };
40 sourceType.superclass = supertype;
41 sourceType.superInterfaces = TypeBinding.NoSuperInterfaces;
44 buildFieldsAndMethods();
45 anonymousType.faultInTypesForFieldsAndMethods();
46 sourceType.verifyMethods(environment().methodVerifier());
49 private void buildFields() {
50 if (referenceContext.fields == null) {
51 referenceContext.binding.fields = NoFields;
54 // count the number of fields vs. initializers
55 FieldDeclaration[] fields = referenceContext.fields;
56 int size = fields.length;
58 for (int i = 0; i < size; i++)
59 if (fields[i].isField())
62 // iterate the field declarations to create the bindings, lose all duplicates
63 FieldBinding[] fieldBindings = new FieldBinding[count];
64 HashtableOfObject knownFieldNames = new HashtableOfObject(count);
65 boolean duplicate = false;
67 for (int i = 0; i < size; i++) {
68 FieldDeclaration field = fields[i];
69 if (!field.isField()) {
70 if (referenceContext.binding.isInterface())
71 problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
73 FieldBinding fieldBinding = new FieldBinding(field, null, referenceContext.binding);
74 // field's type will be resolved when needed for top level types
75 checkAndSetModifiersForField(fieldBinding, field);
77 if (knownFieldNames.containsKey(field.name)) {
79 FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
80 if (previousBinding != null) {
81 for (int f = 0; f < i; f++) {
82 FieldDeclaration previousField = fields[f];
83 if (previousField.binding == previousBinding) {
84 problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
85 previousField.binding = null;
90 knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
91 problemReporter().duplicateFieldInType(referenceContext.binding, field);
94 knownFieldNames.put(field.name, fieldBinding);
95 // remember that we have seen a field with this name
96 if (fieldBinding != null)
97 fieldBindings[count++] = fieldBinding;
101 // remove duplicate fields
103 FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
104 // we know we'll be removing at least 1 duplicate name
107 for (int i = 0; i < size; i++) {
108 FieldBinding fieldBinding = fieldBindings[i];
109 if (knownFieldNames.get(fieldBinding.name) != null)
110 newFieldBindings[count++] = fieldBinding;
112 fieldBindings = newFieldBindings;
115 if (count != fieldBindings.length)
116 System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
117 for (int i = 0; i < count; i++)
118 fieldBindings[i].id = i;
119 referenceContext.binding.fields = fieldBindings;
122 void buildFieldsAndMethods() {
126 SourceTypeBinding sourceType = referenceContext.binding;
127 if (sourceType.isMemberType() && !sourceType.isLocalType())
128 ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
130 ReferenceBinding[] memberTypes = sourceType.memberTypes;
131 for (int i = 0, length = memberTypes.length; i < length; i++)
132 ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
135 private LocalTypeBinding buildLocalType(
136 SourceTypeBinding enclosingType,
137 PackageBinding packageBinding) {
138 referenceContext.scope = this;
139 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
140 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
142 // build the binding or the local type
143 LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType);
144 referenceContext.binding = localType;
145 checkAndSetModifiers();
147 // Look at member types
148 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
149 if (referenceContext.memberTypes != null) {
150 int size = referenceContext.memberTypes.length;
151 memberTypeBindings = new ReferenceBinding[size];
153 nextMember : for (int i = 0; i < size; i++) {
154 TypeDeclaration memberContext = referenceContext.memberTypes[i];
155 if (memberContext.isInterface()) {
156 problemReporter().nestedClassCannotDeclareInterface(memberContext);
159 ReferenceBinding type = localType;
160 // check that the member does not conflict with an enclosing type
162 if (CharOperation.equals(type.sourceName, memberContext.name)) {
163 problemReporter().hidingEnclosingType(memberContext);
166 type = type.enclosingType();
167 } while (type != null);
168 // check the member type does not conflict with another sibling member type
169 for (int j = 0; j < i; j++) {
170 if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
171 problemReporter().duplicateNestedType(memberContext);
176 ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
177 LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
178 memberBinding.setAsMemberType();
179 memberTypeBindings[count++] = memberBinding;
182 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
184 localType.memberTypes = memberTypeBindings;
188 void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
190 LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
191 connectTypeHierarchy();
192 buildFieldsAndMethods();
193 localType.faultInTypesForFieldsAndMethods();
195 referenceContext.binding.verifyMethods(environment().methodVerifier());
198 private void buildMethods() {
199 if (referenceContext.methods == null) {
200 referenceContext.binding.methods = NoMethods;
204 // iterate the method declarations to create the bindings
205 AbstractMethodDeclaration[] methods = referenceContext.methods;
206 int size = methods.length;
207 int clinitIndex = -1;
208 for (int i = 0; i < size; i++) {
209 if (methods[i] instanceof Clinit) {
214 MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
217 for (int i = 0; i < size; i++) {
218 if (i != clinitIndex) {
219 MethodScope scope = new MethodScope(this, methods[i], false);
220 MethodBinding methodBinding = scope.createMethod(methods[i]);
221 if (methodBinding != null) // is null if binding could not be created
222 methodBindings[count++] = methodBinding;
225 if (count != methodBindings.length)
226 System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
228 referenceContext.binding.methods = methodBindings;
229 referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
231 SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
232 // provide the typeDeclaration with needed scopes
233 referenceContext.scope = this;
234 referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
235 referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
237 if (enclosingType == null) {
238 char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
239 referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
241 char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
242 className[className.length - 1] =
243 CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
244 referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
247 SourceTypeBinding sourceType = referenceContext.binding;
248 sourceType.fPackage.addType(sourceType);
249 checkAndSetModifiers();
251 // Look at member types
252 ReferenceBinding[] memberTypeBindings = NoMemberTypes;
253 if (referenceContext.memberTypes != null) {
254 int size = referenceContext.memberTypes.length;
255 memberTypeBindings = new ReferenceBinding[size];
257 nextMember : for (int i = 0; i < size; i++) {
258 TypeDeclaration memberContext = referenceContext.memberTypes[i];
259 if (memberContext.isInterface()
260 && sourceType.isNestedType()
261 && sourceType.isClass()
262 && !sourceType.isStatic()) {
263 problemReporter().nestedClassCannotDeclareInterface(memberContext);
266 ReferenceBinding type = sourceType;
267 // check that the member does not conflict with an enclosing type
269 if (CharOperation.equals(type.sourceName, memberContext.name)) {
270 problemReporter().hidingEnclosingType(memberContext);
273 type = type.enclosingType();
274 } while (type != null);
275 // check that the member type does not conflict with another sibling member type
276 for (int j = 0; j < i; j++) {
277 if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
278 problemReporter().duplicateNestedType(memberContext);
283 ClassScope memberScope = new ClassScope(this, memberContext);
284 memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
287 System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
289 sourceType.memberTypes = memberTypeBindings;
293 private void checkAndSetModifiers() {
294 SourceTypeBinding sourceType = referenceContext.binding;
295 int modifiers = sourceType.modifiers;
296 if ((modifiers & AccAlternateModifierProblem) != 0)
297 problemReporter().duplicateModifierForType(sourceType);
299 ReferenceBinding enclosingType = sourceType.enclosingType();
300 boolean isMemberType = sourceType.isMemberType();
303 // checks for member types before local types to catch local members
304 // if (enclosingType.isStrictfp())
305 // modifiers |= AccStrictfp;
306 if (enclosingType.isDeprecated())
307 modifiers |= AccDeprecatedImplicitly;
308 if (enclosingType.isInterface())
309 modifiers |= AccPublic;
310 } else if (sourceType.isLocalType()) {
311 if (sourceType.isAnonymousType())
312 modifiers |= AccFinal;
313 ReferenceContext refContext = methodScope().referenceContext;
314 if (refContext instanceof TypeDeclaration) {
315 ReferenceBinding type = ((TypeDeclaration) refContext).binding;
316 // if (type.isStrictfp())
317 // modifiers |= AccStrictfp;
318 if (type.isDeprecated())
319 modifiers |= AccDeprecatedImplicitly;
321 MethodBinding method = ((AbstractMethodDeclaration) refContext).binding;
323 // if (method.isStrictfp())
324 // modifiers |= AccStrictfp;
325 if (method.isDeprecated())
326 modifiers |= AccDeprecatedImplicitly;
330 // after this point, tests on the 16 bits reserved.
331 int realModifiers = modifiers & AccJustFlag;
333 if ((realModifiers & AccInterface) != 0) {
334 // detect abnormal cases for interfaces
336 int unexpectedModifiers =
337 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface );//| AccStrictfp);
338 if ((realModifiers & unexpectedModifiers) != 0)
339 problemReporter().illegalModifierForMemberInterface(sourceType);
341 } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
342 int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
343 if ((realModifiers & unexpectedModifiers) != 0)
344 problemReporter().illegalModifierForLocalInterface(sourceType);
347 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface);// | AccStrictfp);
348 if ((realModifiers & unexpectedModifiers) != 0)
349 problemReporter().illegalModifierForInterface(sourceType);
351 modifiers |= AccAbstract;
353 // detect abnormal cases for types
354 if (isMemberType) { // includes member types defined inside local types
355 int unexpectedModifiers =
356 ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal);// | AccStrictfp);
357 if ((realModifiers & unexpectedModifiers) != 0)
358 problemReporter().illegalModifierForMemberClass(sourceType);
359 } else if (sourceType.isLocalType()) {
360 int unexpectedModifiers = ~(AccAbstract | AccFinal);// | AccStrictfp);
361 if ((realModifiers & unexpectedModifiers) != 0)
362 problemReporter().illegalModifierForLocalClass(sourceType);
364 int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal);// | AccStrictfp);
365 if ((realModifiers & unexpectedModifiers) != 0)
366 problemReporter().illegalModifierForClass(sourceType);
369 // check that Final and Abstract are not set together
370 if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
371 problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
375 // test visibility modifiers inconsistency, isolate the accessors bits
376 if (enclosingType.isInterface()) {
377 if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
378 problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
380 // need to keep the less restrictive
381 if ((realModifiers & AccProtected) != 0)
382 modifiers ^= AccProtected;
383 if ((realModifiers & AccPrivate) != 0)
384 modifiers ^= AccPrivate;
387 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
388 if ((accessorBits & (accessorBits - 1)) > 1) {
389 problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
391 // need to keep the less restrictive
392 if ((accessorBits & AccPublic) != 0) {
393 if ((accessorBits & AccProtected) != 0)
394 modifiers ^= AccProtected;
395 if ((accessorBits & AccPrivate) != 0)
396 modifiers ^= AccPrivate;
398 if ((accessorBits & AccProtected) != 0)
399 if ((accessorBits & AccPrivate) != 0)
400 modifiers ^= AccPrivate;
404 // static modifier test
405 if ((realModifiers & AccStatic) == 0) {
406 if (enclosingType.isInterface())
407 modifiers |= AccStatic;
409 if (!enclosingType.isStatic())
410 // error the enclosing type of a static field must be static or a top-level type
411 problemReporter().illegalStaticModifierForMemberType(sourceType);
415 sourceType.modifiers = modifiers;
418 /* This method checks the modifiers of a field.
421 * Need to integrate the check for the final modifiers for nested types
423 * Note : A scope is accessible by : fieldBinding.declaringClass.scope
425 private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
426 int modifiers = fieldBinding.modifiers;
427 if ((modifiers & AccAlternateModifierProblem) != 0)
428 problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
430 if (fieldBinding.declaringClass.isInterface()) {
431 int expectedValue = AccPublic | AccStatic | AccFinal;
433 modifiers |= expectedValue;
435 // and then check that they are the only ones
436 if ((modifiers & AccJustFlag) != expectedValue)
437 problemReporter().illegalModifierForInterfaceField(fieldBinding.declaringClass, fieldDecl);
438 fieldBinding.modifiers = modifiers;
442 // after this point, tests on the 16 bits reserved.
443 int realModifiers = modifiers & AccJustFlag;
444 int unexpectedModifiers =
445 ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic);// | AccTransient | AccVolatile);
446 if ((realModifiers & unexpectedModifiers) != 0)
447 problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
449 int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
450 if ((accessorBits & (accessorBits - 1)) > 1) {
451 problemReporter().illegalVisibilityModifierCombinationForField(
452 fieldBinding.declaringClass,
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;
467 // if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
468 // problemReporter().illegalModifierCombinationFinalVolatileForField(
469 // fieldBinding.declaringClass,
472 if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
473 modifiers |= AccBlankFinal;
475 fieldBinding.modifiers = modifiers;
478 private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
479 // search up the hierarchy of the sourceType to see if any superType defines a member type
480 // when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
481 ReferenceBinding currentType = sourceType;
482 ReferenceBinding[][] interfacesToVisit = null;
483 int lastPosition = -1;
485 if ((currentType.tagBits & HasNoMemberTypes) != 0)
486 break; // already know it has no inherited member types, can stop looking up
487 if (currentType.memberTypes() != NoMemberTypes)
488 return; // has member types
489 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
490 if (itsInterfaces != NoSuperInterfaces) {
491 if (interfacesToVisit == null)
492 interfacesToVisit = new ReferenceBinding[5][];
493 if (++lastPosition == interfacesToVisit.length)
497 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
500 interfacesToVisit[lastPosition] = itsInterfaces;
502 } while ((currentType = currentType.superclass()) != null);
504 boolean hasMembers = false;
505 if (interfacesToVisit != null) {
506 done : for (int i = 0; i <= lastPosition; i++) {
507 ReferenceBinding[] interfaces = interfacesToVisit[i];
508 for (int j = 0, length = interfaces.length; j < length; j++) {
509 ReferenceBinding anInterface = interfaces[j];
510 if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
511 anInterface.tagBits |= InterfaceVisited;
512 if ((anInterface.tagBits & HasNoMemberTypes) != 0)
513 continue; // already know it has no inherited member types
514 if (anInterface.memberTypes() != NoMemberTypes) {
519 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
520 if (itsInterfaces != NoSuperInterfaces) {
521 if (++lastPosition == interfacesToVisit.length)
525 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
528 interfacesToVisit[lastPosition] = itsInterfaces;
534 for (int i = 0; i <= lastPosition; i++) {
535 ReferenceBinding[] interfaces = interfacesToVisit[i];
536 for (int j = 0, length = interfaces.length; j < length; j++) {
537 interfaces[j].tagBits &= ~InterfaceVisited;
539 interfaces[j].tagBits |= HasNoMemberTypes;
545 currentType = sourceType;
547 currentType.tagBits |= HasNoMemberTypes;
548 } while ((currentType = currentType.superclass()) != null);
552 private void connectMemberTypes() {
553 SourceTypeBinding sourceType = referenceContext.binding;
554 if (sourceType.memberTypes != NoMemberTypes)
555 for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
556 ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
559 Our current belief based on available JCK tests is:
560 inherited member types are visible as a potential superclass.
561 inherited interfaces are not visible when defining a superinterface.
563 Error recovery story:
564 ensure the superclass is set to java.lang.Object if a problem is detected
565 resolving the superclass.
567 Answer false if an error was reported against the sourceType.
569 private boolean connectSuperclass() {
570 SourceTypeBinding sourceType = referenceContext.binding;
571 if (isJavaLangObject(sourceType)) { // handle the case of redefining java.lang.Object up front
572 sourceType.superclass = null;
573 sourceType.superInterfaces = NoSuperInterfaces;
574 if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
575 problemReporter().objectCannotHaveSuperTypes(sourceType);
576 return true; // do not propagate Object's hierarchy problems down to every subtype
578 if (referenceContext.superclass == null) {
579 sourceType.superclass = getJavaLangObject();
580 return !detectCycle(sourceType, sourceType.superclass, null);
582 ReferenceBinding superclass = findSupertype(referenceContext.superclass);
583 if (superclass != null) { // is null if a cycle was detected cycle
584 if (!superclass.isValidBinding()) {
585 problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
586 } else if (superclass.isInterface()) {
587 problemReporter().superclassMustBeAClass(sourceType, referenceContext.superclass, superclass);
588 } else if (superclass.isFinal()) {
589 problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
591 // only want to reach here when no errors are reported
592 referenceContext.superclass.resolvedType = superclass;
593 sourceType.superclass = superclass;
597 sourceType.tagBits |= HierarchyHasProblems;
598 sourceType.superclass = getJavaLangObject();
599 if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
600 detectCycle(sourceType, sourceType.superclass, null);
601 return false; // reported some error against the source type
605 Our current belief based on available JCK 1.3 tests is:
606 inherited member types are visible as a potential superclass.
607 inherited interfaces are visible when defining a superinterface.
609 Error recovery story:
610 ensure the superinterfaces contain only valid visible interfaces.
612 Answer false if an error was reported against the sourceType.
614 private boolean connectSuperInterfaces() {
615 SourceTypeBinding sourceType = referenceContext.binding;
616 sourceType.superInterfaces = NoSuperInterfaces;
617 if (referenceContext.superInterfaces == null)
619 if (isJavaLangObject(sourceType)) // already handled the case of redefining java.lang.Object
622 boolean noProblems = true;
623 int length = referenceContext.superInterfaces.length;
624 ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
626 nextInterface : for (int i = 0; i < length; i++) {
627 ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
628 if (superInterface == null) { // detected cycle
630 continue nextInterface;
632 if (!superInterface.isValidBinding()) {
633 problemReporter().invalidSuperinterface(
635 referenceContext.superInterfaces[i],
637 sourceType.tagBits |= HierarchyHasProblems;
639 continue nextInterface;
641 // Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
642 for (int k = 0; k < count; k++) {
643 if (interfaceBindings[k] == superInterface) {
644 // should this be treated as a warning?
645 problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
646 continue nextInterface;
649 if (superInterface.isClass()) {
650 problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
651 sourceType.tagBits |= HierarchyHasProblems;
653 continue nextInterface;
656 referenceContext.superInterfaces[i].resolvedType = superInterface;
657 // only want to reach here when no errors are reported
658 interfaceBindings[count++] = superInterface;
660 // hold onto all correctly resolved superinterfaces
663 System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
664 sourceType.superInterfaces = interfaceBindings;
669 void connectTypeHierarchy() {
670 SourceTypeBinding sourceType = referenceContext.binding;
671 if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
672 boolean noProblems = true;
673 sourceType.tagBits |= BeginHierarchyCheck;
674 if (sourceType.isClass())
675 noProblems &= connectSuperclass();
676 noProblems &= connectSuperInterfaces();
677 sourceType.tagBits |= EndHierarchyCheck;
678 if (noProblems && sourceType.isHierarchyInconsistent())
679 problemReporter().hierarchyHasProblems(sourceType);
681 connectMemberTypes();
682 checkForInheritedMemberTypes(sourceType);
685 private void connectTypeHierarchyWithoutMembers() {
686 // must ensure the imports are resolved
687 if (parent instanceof CompilationUnitScope) {
688 if (((CompilationUnitScope) parent).imports == null)
689 ((CompilationUnitScope) parent).checkAndSetImports();
690 } else if (parent instanceof ClassScope) {
691 // ensure that the enclosing type has already been checked
692 ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
695 // double check that the hierarchy search has not already begun...
696 SourceTypeBinding sourceType = referenceContext.binding;
697 if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
700 boolean noProblems = true;
701 sourceType.tagBits |= BeginHierarchyCheck;
702 if (sourceType.isClass())
703 noProblems &= connectSuperclass();
704 noProblems &= connectSuperInterfaces();
705 sourceType.tagBits |= EndHierarchyCheck;
706 if (noProblems && sourceType.isHierarchyInconsistent())
707 problemReporter().hierarchyHasProblems(sourceType);
710 // Answer whether a cycle was found between the sourceType & the superType
711 private boolean detectCycle(
712 SourceTypeBinding sourceType,
713 ReferenceBinding superType,
714 TypeReference reference) {
715 if (sourceType == superType) {
716 problemReporter().hierarchyCircularity(sourceType, superType, reference);
717 sourceType.tagBits |= HierarchyHasProblems;
721 if (superType.isBinaryBinding()) {
722 // force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
723 // - a binary type... this case MUST be caught & reported here
724 // - another source type... this case is reported against the other source type
725 boolean hasCycle = false;
726 if (superType.superclass() != null) {
727 if (sourceType == superType.superclass()) {
728 problemReporter().hierarchyCircularity(sourceType, superType, reference);
729 sourceType.tagBits |= HierarchyHasProblems;
730 superType.tagBits |= HierarchyHasProblems;
733 hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
734 if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
735 sourceType.tagBits |= HierarchyHasProblems;
736 superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
740 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
741 if (itsInterfaces != NoSuperInterfaces) {
742 for (int i = 0, length = itsInterfaces.length; i < length; i++) {
743 ReferenceBinding anInterface = itsInterfaces[i];
744 if (sourceType == anInterface) {
745 problemReporter().hierarchyCircularity(sourceType, superType, reference);
746 sourceType.tagBits |= HierarchyHasProblems;
747 superType.tagBits |= HierarchyHasProblems;
750 hasCycle |= detectCycle(sourceType, anInterface, reference);
751 if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
752 sourceType.tagBits |= HierarchyHasProblems;
753 superType.tagBits |= HierarchyHasProblems;
760 if ((superType.tagBits & EndHierarchyCheck) == 0
761 && (superType.tagBits & BeginHierarchyCheck) != 0) {
762 problemReporter().hierarchyCircularity(sourceType, superType, reference);
763 sourceType.tagBits |= HierarchyHasProblems;
764 superType.tagBits |= HierarchyHasProblems;
767 if ((superType.tagBits & BeginHierarchyCheck) == 0)
768 // ensure if this is a source superclass that it has already been checked
769 ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
770 if ((superType.tagBits & HierarchyHasProblems) != 0)
771 sourceType.tagBits |= HierarchyHasProblems;
775 private ReferenceBinding findSupertype(TypeReference typeReference) {
776 typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
777 char[][] compoundName = typeReference.getTypeName();
778 compilationUnitScope().recordQualifiedReference(compoundName);
779 SourceTypeBinding sourceType = referenceContext.binding;
780 int size = compoundName.length;
782 ReferenceBinding superType;
784 // resolve the first name of the compoundName
785 if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
786 superType = sourceType;
787 // match against the sourceType even though nested members cannot be supertypes
789 Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
790 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
791 return new ProblemReferenceBinding(
793 typeOrPackage == null ? NotFound : typeOrPackage.problemId());
795 boolean checkVisibility = false;
796 for (; n < size; n++) {
797 if (!(typeOrPackage instanceof PackageBinding))
799 PackageBinding packageBinding = (PackageBinding) typeOrPackage;
800 typeOrPackage = packageBinding.getTypeOrPackage(compoundName[n]);
801 if (typeOrPackage == null || !typeOrPackage.isValidBinding())
802 return new ProblemReferenceBinding(
803 CharOperation.subarray(compoundName, 0, n + 1),
804 typeOrPackage == null ? NotFound : typeOrPackage.problemId());
805 checkVisibility = true;
808 // convert to a ReferenceBinding
809 if (typeOrPackage instanceof PackageBinding) // error, the compoundName is a packageName
810 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
811 superType = (ReferenceBinding) typeOrPackage;
812 compilationUnitScope().recordTypeReference(superType); // to record supertypes
815 && n == size) { // if we're finished and know the final supertype then check visibility
816 if (!superType.canBeSeenBy(sourceType.fPackage))
817 // its a toplevel type so just check package access
818 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), superType, NotVisible);
821 // at this point we know we have a type but we have to look for cycles
823 // must detect cycles & force connection up the hierarchy... also handle cycles with binary types.
824 // must be guaranteed that the superType knows its entire hierarchy
825 if (detectCycle(sourceType, superType, typeReference))
826 return null; // cycle error was already reported
831 // retrieve the next member type
832 char[] typeName = compoundName[n++];
833 superType = findMemberType(typeName, superType);
834 if (superType == null)
835 return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
836 if (!superType.isValidBinding()) {
837 superType.compoundName = CharOperation.subarray(compoundName, 0, n);
844 /* Answer the problem reporter to use for raising new problems.
846 * Note that as a side-effect, this updates the current reference context
847 * (unit, type or method) in case the problem handler decides it is necessary
850 public ProblemReporter problemReporter() {
851 MethodScope outerMethodScope;
852 if ((outerMethodScope = outerMostMethodScope()) == null) {
853 ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
854 problemReporter.referenceContext = referenceContext;
855 return problemReporter;
857 return outerMethodScope.problemReporter();
861 /* Answer the reference type of this scope.
862 * It is the nearest enclosing type of this scope.
864 public TypeDeclaration referenceType() {
865 return referenceContext;
868 public String toString() {
869 if (referenceContext != null)
870 return "--- Class Scope ---\n\n" //$NON-NLS-1$
871 +referenceContext.binding.toString();
873 return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$