1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 import net.sourceforge.phpdt.internal.compiler.env.IDependent;
14 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
17 Not all fields defined by this type (& its subclasses) are initialized when it is created.
18 Some are initialized only when needed.
20 Accessors have been provided for some public fields so all TypeBindings have the same API...
21 but access public fields directly whenever possible.
22 Non-public fields have accessors which should be used everywhere you expect the field to be initialized.
24 null is NOT a valid value for a non-public field... it just means the field is not initialized.
27 abstract public class ReferenceBinding extends TypeBinding implements IDependent {
28 public char[][] compoundName;
29 public char[] sourceName;
31 public PackageBinding fPackage;
34 char[] constantPoolName;
37 public FieldBinding[] availableFields() {
41 public MethodBinding[] availableMethods() {
44 /* Answer true if the receiver can be instantiated
47 public boolean canBeInstantiated() {
48 return !(isAbstract() || isInterface());
50 /* Answer true if the receiver is visible to the invocationPackage.
53 public final boolean canBeSeenBy(PackageBinding invocationPackage) {
54 if (isPublic()) return true;
55 if (isPrivate()) return false;
57 // isProtected() or isDefault()
58 return invocationPackage == fPackage;
60 /* Answer true if the receiver is visible to the receiverType and the invocationType.
63 public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBinding invocationType) {
64 if (isPublic()) return true;
66 if (invocationType == this && invocationType == receiverType) return true;
70 // answer true if the invocationType is the declaringClass or they are in the same package
71 // OR the invocationType is a subclass of the declaringClass
72 // AND the invocationType is the invocationType or its subclass
73 // OR the type is a static method accessed directly through a type
74 // OR previous assertions are true for one of the enclosing type
75 if (invocationType == this) return true;
76 if (invocationType.fPackage == fPackage) return true;
78 ReferenceBinding currentType = invocationType;
79 ReferenceBinding declaringClass = enclosingType(); // protected types always have an enclosing one
80 if (declaringClass == null) return false; // could be null if incorrect top-level protected type
83 if (declaringClass == invocationType) return true;
84 if (declaringClass.isSuperclassOf(currentType)) return true;
86 currentType = currentType.enclosingType();
87 } while (currentType != null);
92 // answer true if the receiverType is the receiver or its enclosingType
93 // AND the invocationType and the receiver have a common enclosingType
94 if (!(receiverType == this || receiverType == enclosingType())) return false;
96 if (invocationType != this) {
97 ReferenceBinding outerInvocationType = invocationType;
98 ReferenceBinding temp = outerInvocationType.enclosingType();
99 while (temp != null) {
100 outerInvocationType = temp;
101 temp = temp.enclosingType();
104 ReferenceBinding outerDeclaringClass = this;
105 temp = outerDeclaringClass.enclosingType();
106 while (temp != null) {
107 outerDeclaringClass = temp;
108 temp = temp.enclosingType();
110 if (outerInvocationType != outerDeclaringClass) return false;
116 if (invocationType.fPackage != fPackage) return false;
118 ReferenceBinding type = receiverType;
119 ReferenceBinding declaringClass = enclosingType() == null ? this : enclosingType();
121 if (declaringClass == type) return true;
122 if (fPackage != type.fPackage) return false;
123 } while ((type = type.superclass()) != null);
126 /* Answer true if the receiver is visible to the type provided by the scope.
128 * NOTE: Cannot invoke this method with a compilation unit scope.
131 public final boolean canBeSeenBy(Scope scope) {
132 if (isPublic()) return true;
134 SourceTypeBinding invocationType = scope.enclosingSourceType();
135 if (invocationType == this) return true;
138 // answer true if the receiver (or its enclosing type) is the superclass
139 // of the invocationType or in the same package
140 return invocationType.fPackage == fPackage
141 || isSuperclassOf(invocationType)
142 || enclosingType().isSuperclassOf(invocationType); // protected types always have an enclosing one
146 // answer true if the invocationType is the declaringClass or they are in the same package
147 // OR the invocationType is a subclass of the declaringClass
148 // AND the invocationType is the invocationType or its subclass
149 // OR the type is a static method accessed directly through a type
150 // OR previous assertions are true for one of the enclosing type
151 if (invocationType.fPackage == fPackage) return true;
153 ReferenceBinding currentType = invocationType;
154 ReferenceBinding declaringClass = enclosingType(); // protected types always have an enclosing one
155 if (declaringClass == null) return false; // could be null if incorrect top-level protected type
158 if (declaringClass == invocationType) return true;
159 if (declaringClass.isSuperclassOf(currentType)) return true;
161 currentType = currentType.enclosingType();
162 } while (currentType != null);
166 // answer true if the receiver and the invocationType have a common enclosingType
167 // already know they are not the identical type
168 ReferenceBinding outerInvocationType = invocationType;
169 ReferenceBinding temp = outerInvocationType.enclosingType();
170 while (temp != null) {
171 outerInvocationType = temp;
172 temp = temp.enclosingType();
175 ReferenceBinding outerDeclaringClass = this;
176 temp = outerDeclaringClass.enclosingType();
177 while (temp != null) {
178 outerDeclaringClass = temp;
179 temp = temp.enclosingType();
181 return outerInvocationType == outerDeclaringClass;
185 return invocationType.fPackage == fPackage;
187 public void computeId() {
188 if (compoundName.length != 3) {
189 if (compoundName.length == 4 && CharOperation.equals(JAVA_LANG_REFLECT_CONSTRUCTOR, compoundName)) {
190 id = T_JavaLangReflectConstructor;
193 return; // all other types are in java.*.*
196 if (!CharOperation.equals(JAVA, compoundName[0]))
197 return; // assumes we only look up types in java
199 if (!CharOperation.equals(LANG, compoundName[1])) {
200 if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
201 id = T_JavaIoPrintStream;
204 return; // all other types are in java.lang
207 if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
208 id = T_JavaLangObject;
211 if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
212 id = T_JavaLangString;
216 // well-known exception types
217 if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
218 id = T_JavaLangThrowable;
221 if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
222 id = T_JavaLangError;
225 if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
226 id = T_JavaLangException;
229 if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName)) {
230 id = T_JavaLangClassNotFoundException;
233 if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
234 id = T_JavaLangNoClassDefError;
238 // other well-known types
239 if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
240 id = T_JavaLangClass;
243 if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
244 id = T_JavaLangStringBuffer;
247 if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
248 id = T_JavaLangSystem;
252 if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
253 id = T_JavaLangInteger;
257 if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
262 if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
263 id = T_JavaLangCharacter;
267 if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
268 id = T_JavaLangFloat;
272 if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
273 id = T_JavaLangDouble;
277 if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
278 id = T_JavaLangBoolean;
282 if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
283 id = T_JavaLangShort;
287 if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
292 if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
297 if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
298 id = T_JavaLangAssertionError;
302 /* Answer the receiver's constant pool name.
304 * NOTE: This method should only be used during/after code gen.
307 public char[] constantPoolName() /* java/lang/Object */ {
308 if (constantPoolName != null) return constantPoolName;
309 return constantPoolName = CharOperation.concatWith(compoundName, '/');
312 return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
314 public final int depth() {
316 ReferenceBinding current = this;
317 while ((current = current.enclosingType()) != null)
321 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
324 public ReferenceBinding enclosingType() {
327 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
328 ReferenceBinding current = this;
329 while (relativeDepth-- > 0 && current != null)
330 current = current.enclosingType();
333 public int fieldCount() {
334 return fields().length;
336 public FieldBinding[] fields() {
339 public final int getAccessFlags() {
340 return modifiers & AccJustFlag;
342 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
345 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
348 public FieldBinding getField(char[] fieldName) {
352 * Answer the file name which defines the type.
354 * The path part (optional) must be separated from the actual
355 * file proper name by a java.io.File.separator.
357 * The proper file name includes the suffix extension (e.g. ".java")
359 * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
362 public char[] getFileName() {
365 public ReferenceBinding getMemberType(char[] typeName) {
366 ReferenceBinding[] memberTypes = memberTypes();
367 for (int i = memberTypes.length; --i >= 0;)
368 if (CharOperation.equals(memberTypes[i].sourceName, typeName))
369 return memberTypes[i];
372 public MethodBinding[] getMethods(char[] selector) {
375 public PackageBinding getPackage() {
378 /* Answer true if the receiver implements anInterface or is identical to anInterface.
379 * If searchHierarchy is true, then also search the receiver's superclasses.
381 * NOTE: Assume that anInterface is an interface.
384 public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
385 if (this == anInterface)
388 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
389 int lastPosition = -1;
390 ReferenceBinding currentType = this;
392 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
393 if (itsInterfaces != NoSuperInterfaces) {
394 if (++lastPosition == interfacesToVisit.length)
395 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
396 interfacesToVisit[lastPosition] = itsInterfaces;
398 } while (searchHierarchy && (currentType = currentType.superclass()) != null);
400 for (int i = 0; i <= lastPosition; i++) {
401 ReferenceBinding[] interfaces = interfacesToVisit[i];
402 for (int j = 0, length = interfaces.length; j < length; j++) {
403 if ((currentType = interfaces[j]) == anInterface)
406 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
407 if (itsInterfaces != NoSuperInterfaces) {
408 if (++lastPosition == interfacesToVisit.length)
409 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
410 interfacesToVisit[lastPosition] = itsInterfaces;
416 // Internal method... assume its only sent to classes NOT interfaces
418 boolean implementsMethod(MethodBinding method) {
419 ReferenceBinding type = this;
420 while (type != null) {
421 MethodBinding[] methods = type.getMethods(method.selector);
422 for (int i = methods.length; --i >= 0;)
423 if (methods[i].areParametersEqual(method))
425 type = type.superclass();
429 /* Answer true if the receiver is an abstract type
432 public final boolean isAbstract() {
433 return (modifiers & AccAbstract) != 0;
435 public final boolean isAnonymousType() {
436 return (tagBits & IsAnonymousType) != 0;
438 public final boolean isBinaryBinding() {
439 return (tagBits & IsBinaryBinding) != 0;
441 public final boolean isClass() {
442 return (modifiers & AccInterface) == 0;
444 /* Answer true if the receiver type can be assigned to the argument type (right)
447 boolean isCompatibleWith(TypeBinding right) {
450 if (right.id == T_Object)
452 if (!(right instanceof ReferenceBinding))
455 ReferenceBinding referenceBinding = (ReferenceBinding) right;
456 if (referenceBinding.isInterface())
457 return implementsInterface(referenceBinding, true);
458 if (isInterface()) // Explicit conversion from an interface to a class is not allowed
460 return referenceBinding.isSuperclassOf(this);
462 /* Answer true if the receiver has default visibility
465 public final boolean isDefault() {
466 return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
468 /* Answer true if the receiver is a deprecated type
471 public final boolean isDeprecated() {
472 return (modifiers & AccDeprecated) != 0;
474 /* Answer true if the receiver is final and cannot be subclassed
477 public final boolean isFinal() {
478 return (modifiers & AccFinal) != 0;
480 public final boolean isInterface() {
481 return (modifiers & AccInterface) != 0;
483 public final boolean isLocalType() {
484 return (tagBits & IsLocalType) != 0;
486 public final boolean isMemberType() {
487 return (tagBits & IsMemberType) != 0;
489 public final boolean isNestedType() {
490 return (tagBits & IsNestedType) != 0;
492 /* Answer true if the receiver has private visibility
495 public final boolean isPrivate() {
496 return (modifiers & AccPrivate) != 0;
498 /* Answer true if the receiver has protected visibility
501 public final boolean isProtected() {
502 return (modifiers & AccProtected) != 0;
504 /* Answer true if the receiver has public visibility
507 public final boolean isPublic() {
508 return (modifiers & AccPublic) != 0;
510 /* Answer true if the receiver is a static member type (or toplevel)
513 public final boolean isStatic() {
514 return (modifiers & (AccStatic | AccInterface)) != 0 ||
515 (tagBits & IsNestedType) == 0;
517 /* Answer true if all float operations must adher to IEEE 754 float/double rules
520 public final boolean isStrictfp() {
521 return (modifiers & AccStrictfp) != 0;
523 /* Answer true if the receiver is in the superclass hierarchy of aType
525 * NOTE: Object.isSuperclassOf(Object) -> false
528 public boolean isSuperclassOf(ReferenceBinding type) {
530 if (this == (type = type.superclass())) return true;
531 } while (type != null);
535 /* Answer true if the receiver is deprecated (or any of its enclosing types)
538 public final boolean isViewedAsDeprecated() {
539 return (modifiers & AccDeprecated) != 0 ||
540 (modifiers & AccDeprecatedImplicitly) != 0;
542 public ReferenceBinding[] memberTypes() {
543 return NoMemberTypes;
545 public MethodBinding[] methods() {
549 * Answer the source name for the type.
550 * In the case of member types, as the qualified name from its top level type.
551 * For example, for a member type N defined inside M & A: "A.M.N".
554 public char[] qualifiedSourceName() {
555 if (isMemberType()) {
556 return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
561 public char[] readableName() /*java.lang.Object*/ {
563 return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
565 return CharOperation.concatWith(compoundName, '.');
567 /* Answer the receiver's signature.
569 * NOTE: This method should only be used during/after code gen.
572 public char[] signature() /* Ljava/lang/Object; */ {
573 if (signature != null)
576 return signature = CharOperation.concat('L', constantPoolName(), ';');
578 public char[] sourceName() {
581 public ReferenceBinding superclass() {
584 public ReferenceBinding[] superInterfaces() {
585 return NoSuperInterfaces;
587 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
588 if (isStatic()) return null;
590 ReferenceBinding enclosingType = enclosingType();
591 if (enclosingType == null)
594 return new ReferenceBinding[] {enclosingType};
596 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
597 return null; // is null if no enclosing instances are required