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.env.IDependent;
17 * Not all fields defined by this type (& its subclasses) are initialized when
18 * it is created. Some are initialized only when needed.
20 * Accessors have been provided for some public fields so all TypeBindings have
21 * the same API... but access public fields directly whenever possible.
22 * Non-public fields have accessors which should be used everywhere you expect
23 * the field to be initialized.
25 * null is NOT a valid value for a non-public field... it just means the field
29 abstract public class ReferenceBinding extends TypeBinding implements
31 public char[][] compoundName;
33 public char[] sourceName;
37 public PackageBinding fPackage;
41 char[] constantPoolName;
45 public FieldBinding[] availableFields() {
49 public MethodBinding[] availableMethods() {
54 * Answer true if the receiver can be instantiated
57 public boolean canBeInstantiated() {
58 return !(isAbstract() || isInterface());
62 * Answer true if the receiver is visible to the invocationPackage.
65 public final boolean canBeSeenBy(PackageBinding invocationPackage) {
71 // isProtected() or isDefault()
72 return invocationPackage == fPackage;
76 * Answer true if the receiver is visible to the receiverType and the
80 public final boolean canBeSeenBy(ReferenceBinding receiverType,
81 SourceTypeBinding invocationType) {
85 if (invocationType == this && invocationType == receiverType)
90 // answer true if the invocationType is the declaringClass or they
91 // are in the same package
92 // OR the invocationType is a subclass of the declaringClass
93 // AND the invocationType is the invocationType or its subclass
94 // OR the type is a static method accessed directly through a type
95 // OR previous assertions are true for one of the enclosing type
96 if (invocationType == this)
98 if (invocationType.fPackage == fPackage)
101 ReferenceBinding currentType = invocationType;
102 ReferenceBinding declaringClass = enclosingType(); // protected
106 if (declaringClass == null)
107 return false; // could be null if incorrect top-level
111 if (declaringClass == invocationType)
113 if (declaringClass.isSuperclassOf(currentType))
116 currentType = currentType.enclosingType();
117 } while (currentType != null);
122 // answer true if the receiverType is the receiver or its
124 // AND the invocationType and the receiver have a common
126 if (!(receiverType == this || receiverType == enclosingType()))
129 if (invocationType != this) {
130 ReferenceBinding outerInvocationType = invocationType;
131 ReferenceBinding temp = outerInvocationType.enclosingType();
132 while (temp != null) {
133 outerInvocationType = temp;
134 temp = temp.enclosingType();
137 ReferenceBinding outerDeclaringClass = this;
138 temp = outerDeclaringClass.enclosingType();
139 while (temp != null) {
140 outerDeclaringClass = temp;
141 temp = temp.enclosingType();
143 if (outerInvocationType != outerDeclaringClass)
150 if (invocationType.fPackage != fPackage)
153 ReferenceBinding type = receiverType;
154 ReferenceBinding declaringClass = enclosingType() == null ? this
157 if (declaringClass == type)
159 if (fPackage != type.fPackage)
161 } while ((type = type.superclass()) != null);
166 * Answer true if the receiver is visible to the type provided by the scope.
169 public final boolean canBeSeenBy(Scope scope) {
174 if (scope.kind == Scope.COMPILATION_UNIT_SCOPE) {
175 return this.canBeSeenBy(((CompilationUnitScope) scope).fPackage);
178 SourceTypeBinding invocationType = scope.enclosingSourceType();
179 if (invocationType == this)
183 // answer true if the invocationType is the declaringClass or they
184 // are in the same package
185 // OR the invocationType is a subclass of the declaringClass
186 // AND the invocationType is the invocationType or its subclass
187 // OR the type is a static method accessed directly through a type
188 // OR previous assertions are true for one of the enclosing type
189 if (invocationType.fPackage == fPackage)
192 ReferenceBinding currentType = invocationType;
193 ReferenceBinding declaringClass = enclosingType(); // protected
197 if (declaringClass == null)
198 return false; // could be null if incorrect top-level
202 if (declaringClass == invocationType)
204 if (declaringClass.isSuperclassOf(currentType))
207 currentType = currentType.enclosingType();
208 } while (currentType != null);
212 // answer true if the receiver and the invocationType have a common
214 // already know they are not the identical type
215 ReferenceBinding outerInvocationType = invocationType;
216 ReferenceBinding temp = outerInvocationType.enclosingType();
217 while (temp != null) {
218 outerInvocationType = temp;
219 temp = temp.enclosingType();
222 ReferenceBinding outerDeclaringClass = this;
223 temp = outerDeclaringClass.enclosingType();
224 while (temp != null) {
225 outerDeclaringClass = temp;
226 temp = temp.enclosingType();
228 return outerInvocationType == outerDeclaringClass;
232 return invocationType.fPackage == fPackage;
235 // public void computeId() {
236 // if (compoundName.length != 3) {
237 // if (compoundName.length == 4 &&
238 // CharOperation.equals(JAVA_LANG_REFLECT_CONSTRUCTOR, compoundName)) {
239 // id = T_JavaLangReflectConstructor;
242 // return; // all other types are in java.*.*
245 // if (!CharOperation.equals(JAVA, compoundName[0]))
246 // return; // assumes we only look up types in java
248 // if (!CharOperation.equals(LANG, compoundName[1])) {
249 // if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
250 // id = T_JavaIoPrintStream;
253 // return; // all other types are in java.lang
256 // if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
257 // id = T_JavaLangObject;
260 // if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
261 // id = T_JavaLangString;
265 // // well-known exception types
266 // if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
267 // id = T_JavaLangThrowable;
270 // if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
271 // id = T_JavaLangError;
274 // if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
275 // id = T_JavaLangException;
278 // if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName))
280 // id = T_JavaLangClassNotFoundException;
283 // if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
284 // id = T_JavaLangNoClassDefError;
288 // // other well-known types
289 // if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
290 // id = T_JavaLangClass;
293 // if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
294 // id = T_JavaLangStringBuffer;
297 // if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
298 // id = T_JavaLangSystem;
302 // if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
303 // id = T_JavaLangInteger;
307 // if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
308 // id = T_JavaLangByte;
312 // if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
313 // id = T_JavaLangCharacter;
317 // if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
318 // id = T_JavaLangFloat;
322 // if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
323 // id = T_JavaLangDouble;
327 // if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
328 // id = T_JavaLangBoolean;
332 // if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
333 // id = T_JavaLangShort;
337 // if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
338 // id = T_JavaLangLong;
342 // if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
343 // id = T_JavaLangVoid;
347 // if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
348 // id = T_JavaLangAssertionError;
353 * Answer the receiver's constant pool name.
355 * NOTE: This method should only be used during/after code gen.
358 public char[] constantPoolName() /* java/lang/Object */{
359 if (constantPoolName != null)
360 return constantPoolName;
361 return constantPoolName = CharOperation.concatWith(compoundName, '/');
365 return (compoundName != null) ? new String(readableName())
366 : "UNNAMED TYPE"; //$NON-NLS-1$
369 public final int depth() {
371 ReferenceBinding current = this;
372 while ((current = current.enclosingType()) != null)
378 * Answer the receiver's enclosing type... null if the receiver is a top
382 public ReferenceBinding enclosingType() {
386 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
387 ReferenceBinding current = this;
388 while (relativeDepth-- > 0 && current != null)
389 current = current.enclosingType();
393 public int fieldCount() {
394 return fields().length;
397 public FieldBinding[] fields() {
401 public final int getAccessFlags() {
402 return modifiers & AccJustFlag;
405 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
409 public MethodBinding getExactMethod(char[] selector,
410 TypeBinding[] argumentTypes) {
414 public FieldBinding getField(char[] fieldName) {
419 * Answer the file name which defines the type.
421 * The path part (optional) must be separated from the actual file proper
422 * name by a java.io.File.separator.
424 * The proper file name includes the suffix extension (e.g. ".java")
426 * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
429 public char[] getFileName() {
433 public ReferenceBinding getMemberType(char[] typeName) {
434 ReferenceBinding[] memberTypes = memberTypes();
435 for (int i = memberTypes.length; --i >= 0;)
436 if (CharOperation.equals(memberTypes[i].sourceName, typeName))
437 return memberTypes[i];
441 public MethodBinding[] getMethods(char[] selector) {
445 public PackageBinding getPackage() {
450 * Answer true if the receiver implements anInterface or is identical to
451 * anInterface. If searchHierarchy is true, then also search the receiver's
454 * NOTE: Assume that anInterface is an interface.
457 public boolean implementsInterface(ReferenceBinding anInterface,
458 boolean searchHierarchy) {
459 if (this == anInterface)
462 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
463 int lastPosition = -1;
464 ReferenceBinding currentType = this;
466 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
467 if (itsInterfaces != NoSuperInterfaces) {
468 if (++lastPosition == interfacesToVisit.length)
473 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
475 interfacesToVisit[lastPosition] = itsInterfaces;
477 } while (searchHierarchy
478 && (currentType = currentType.superclass()) != null);
480 for (int i = 0; i <= lastPosition; i++) {
481 ReferenceBinding[] interfaces = interfacesToVisit[i];
482 for (int j = 0, length = interfaces.length; j < length; j++) {
483 if ((currentType = interfaces[j]) == anInterface)
486 ReferenceBinding[] itsInterfaces = currentType
488 if (itsInterfaces != NoSuperInterfaces) {
489 if (++lastPosition == interfacesToVisit.length)
494 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
496 interfacesToVisit[lastPosition] = itsInterfaces;
503 // Internal method... assume its only sent to classes NOT interfaces
505 boolean implementsMethod(MethodBinding method) {
506 ReferenceBinding type = this;
507 while (type != null) {
508 MethodBinding[] methods = type.getMethods(method.selector);
509 for (int i = methods.length; --i >= 0;)
510 if (methods[i].areParametersEqual(method))
512 type = type.superclass();
518 * Answer true if the receiver is an abstract type
521 public final boolean isAbstract() {
522 return (modifiers & AccAbstract) != 0;
525 public final boolean isAnonymousType() {
526 return (tagBits & IsAnonymousType) != 0;
529 public final boolean isBinaryBinding() {
530 return (tagBits & IsBinaryBinding) != 0;
533 public final boolean isClass() {
534 return (modifiers & AccInterface) == 0;
538 * Answer true if the receiver type can be assigned to the argument type
542 public boolean isCompatibleWith(TypeBinding right) {
545 if (right.id == T_Object)
547 if (!(right instanceof ReferenceBinding))
550 ReferenceBinding referenceBinding = (ReferenceBinding) right;
551 if (referenceBinding.isInterface())
552 return implementsInterface(referenceBinding, true);
553 if (isInterface()) // Explicit conversion from an interface to a class
556 return referenceBinding.isSuperclassOf(this);
560 * Answer true if the receiver has default visibility
563 public final boolean isDefault() {
564 return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
568 * Answer true if the receiver is a deprecated type
571 public final boolean isDeprecated() {
572 return (modifiers & AccDeprecated) != 0;
576 * Answer true if the receiver is final and cannot be subclassed
579 public final boolean isFinal() {
580 return (modifiers & AccFinal) != 0;
583 public final boolean isInterface() {
584 return (modifiers & AccInterface) != 0;
587 public final boolean isLocalType() {
588 return (tagBits & IsLocalType) != 0;
591 public final boolean isMemberType() {
592 return (tagBits & IsMemberType) != 0;
595 public final boolean isNestedType() {
596 return (tagBits & IsNestedType) != 0;
600 * Answer true if the receiver has private visibility
603 public final boolean isPrivate() {
604 return (modifiers & AccPrivate) != 0;
608 * Answer true if the receiver has private visibility and is used locally
611 public final boolean isPrivateUsed() {
612 return (modifiers & AccPrivateUsed) != 0;
616 * Answer true if the receiver has protected visibility
619 public final boolean isProtected() {
620 return (modifiers & AccProtected) != 0;
624 * Answer true if the receiver has public visibility
627 public final boolean isPublic() {
628 return (modifiers & AccPublic) != 0;
632 * Answer true if the receiver is a static member type (or toplevel)
635 public final boolean isStatic() {
636 return (modifiers & (AccStatic | AccInterface)) != 0
637 || (tagBits & IsNestedType) == 0;
641 * Answer true if all float operations must adher to IEEE 754 float/double
645 // public final boolean isStrictfp() {
646 // return (modifiers & AccStrictfp) != 0;
649 * Answer true if the receiver is in the superclass hierarchy of aType
651 * NOTE: Object.isSuperclassOf(Object) -> false
654 public boolean isSuperclassOf(ReferenceBinding type) {
656 if (this == (type = type.superclass()))
658 } while (type != null);
664 * Answer true if the receiver is deprecated (or any of its enclosing types)
667 public final boolean isViewedAsDeprecated() {
668 return (modifiers & AccDeprecated) != 0
669 || (modifiers & AccDeprecatedImplicitly) != 0;
672 public ReferenceBinding[] memberTypes() {
673 return NoMemberTypes;
676 public MethodBinding[] methods() {
681 * Answer the source name for the type. In the case of member types, as the
682 * qualified name from its top level type. For example, for a member type N
683 * defined inside M & A: "A.M.N".
686 public char[] qualifiedSourceName() {
687 if (isMemberType()) {
688 return CharOperation.concat(enclosingType().qualifiedSourceName(),
695 public char[] readableName() /* java.lang.Object */{
697 return CharOperation.concat(enclosingType().readableName(),
700 return CharOperation.concatWith(compoundName, '.');
703 public char[] shortReadableName() /* Object */{
705 return CharOperation.concat(enclosingType().shortReadableName(),
712 * Answer the receiver's signature.
714 * NOTE: This method should only be used during/after code gen.
717 public char[] signature() /* Ljava/lang/Object; */{
718 if (signature != null)
721 return signature = CharOperation.concat('L', constantPoolName(), ';');
724 public char[] sourceName() {
728 public ReferenceBinding superclass() {
732 public ReferenceBinding[] superInterfaces() {
733 return NoSuperInterfaces;
736 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
740 ReferenceBinding enclosingType = enclosingType();
741 if (enclosingType == null)
744 return new ReferenceBinding[] { enclosingType };
747 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
748 return null; // is null if no enclosing instances are required