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 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);
127 * Answer true if the receiver is visible to the type provided by the scope.
130 public final boolean canBeSeenBy(Scope scope) {
132 if (isPublic()) return true;
134 if (scope.kind == Scope.COMPILATION_UNIT_SCOPE){
135 return this.canBeSeenBy(((CompilationUnitScope)scope).fPackage);
138 SourceTypeBinding invocationType = scope.enclosingSourceType();
139 if (invocationType == this) return true;
142 // answer true if the invocationType is the declaringClass or they are in the same package
143 // OR the invocationType is a subclass of the declaringClass
144 // AND the invocationType is the invocationType or its subclass
145 // OR the type is a static method accessed directly through a type
146 // OR previous assertions are true for one of the enclosing type
147 if (invocationType.fPackage == fPackage) return true;
149 ReferenceBinding currentType = invocationType;
150 ReferenceBinding declaringClass = enclosingType(); // protected types always have an enclosing one
151 if (declaringClass == null) return false; // could be null if incorrect top-level protected type
154 if (declaringClass == invocationType) return true;
155 if (declaringClass.isSuperclassOf(currentType)) return true;
157 currentType = currentType.enclosingType();
158 } while (currentType != null);
162 // answer true if the receiver and the invocationType have a common enclosingType
163 // already know they are not the identical type
164 ReferenceBinding outerInvocationType = invocationType;
165 ReferenceBinding temp = outerInvocationType.enclosingType();
166 while (temp != null) {
167 outerInvocationType = temp;
168 temp = temp.enclosingType();
171 ReferenceBinding outerDeclaringClass = this;
172 temp = outerDeclaringClass.enclosingType();
173 while (temp != null) {
174 outerDeclaringClass = temp;
175 temp = temp.enclosingType();
177 return outerInvocationType == outerDeclaringClass;
181 return invocationType.fPackage == fPackage;
183 public void computeId() {
184 if (compoundName.length != 3) {
185 if (compoundName.length == 4 && CharOperation.equals(JAVA_LANG_REFLECT_CONSTRUCTOR, compoundName)) {
186 id = T_JavaLangReflectConstructor;
189 return; // all other types are in java.*.*
192 if (!CharOperation.equals(JAVA, compoundName[0]))
193 return; // assumes we only look up types in java
195 if (!CharOperation.equals(LANG, compoundName[1])) {
196 if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
197 id = T_JavaIoPrintStream;
200 return; // all other types are in java.lang
203 if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
204 id = T_JavaLangObject;
207 if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
208 id = T_JavaLangString;
212 // well-known exception types
213 if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
214 id = T_JavaLangThrowable;
217 if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
218 id = T_JavaLangError;
221 if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
222 id = T_JavaLangException;
225 if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName)) {
226 id = T_JavaLangClassNotFoundException;
229 if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
230 id = T_JavaLangNoClassDefError;
234 // other well-known types
235 if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
236 id = T_JavaLangClass;
239 if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
240 id = T_JavaLangStringBuffer;
243 if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
244 id = T_JavaLangSystem;
248 if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
249 id = T_JavaLangInteger;
253 if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
258 if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
259 id = T_JavaLangCharacter;
263 if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
264 id = T_JavaLangFloat;
268 if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
269 id = T_JavaLangDouble;
273 if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
274 id = T_JavaLangBoolean;
278 if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
279 id = T_JavaLangShort;
283 if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
288 if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
293 if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
294 id = T_JavaLangAssertionError;
298 /* Answer the receiver's constant pool name.
300 * NOTE: This method should only be used during/after code gen.
303 public char[] constantPoolName() /* java/lang/Object */ {
304 if (constantPoolName != null) return constantPoolName;
305 return constantPoolName = CharOperation.concatWith(compoundName, '/');
308 return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
310 public final int depth() {
312 ReferenceBinding current = this;
313 while ((current = current.enclosingType()) != null)
317 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
320 public ReferenceBinding enclosingType() {
323 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
324 ReferenceBinding current = this;
325 while (relativeDepth-- > 0 && current != null)
326 current = current.enclosingType();
329 public int fieldCount() {
330 return fields().length;
332 public FieldBinding[] fields() {
335 public final int getAccessFlags() {
336 return modifiers & AccJustFlag;
338 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
341 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
344 public FieldBinding getField(char[] fieldName) {
348 * Answer the file name which defines the type.
350 * The path part (optional) must be separated from the actual
351 * file proper name by a java.io.File.separator.
353 * The proper file name includes the suffix extension (e.g. ".java")
355 * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
358 public char[] getFileName() {
361 public ReferenceBinding getMemberType(char[] typeName) {
362 ReferenceBinding[] memberTypes = memberTypes();
363 for (int i = memberTypes.length; --i >= 0;)
364 if (CharOperation.equals(memberTypes[i].sourceName, typeName))
365 return memberTypes[i];
368 public MethodBinding[] getMethods(char[] selector) {
371 public PackageBinding getPackage() {
374 /* Answer true if the receiver implements anInterface or is identical to anInterface.
375 * If searchHierarchy is true, then also search the receiver's superclasses.
377 * NOTE: Assume that anInterface is an interface.
380 public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
381 if (this == anInterface)
384 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
385 int lastPosition = -1;
386 ReferenceBinding currentType = this;
388 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
389 if (itsInterfaces != NoSuperInterfaces) {
390 if (++lastPosition == interfacesToVisit.length)
391 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
392 interfacesToVisit[lastPosition] = itsInterfaces;
394 } while (searchHierarchy && (currentType = currentType.superclass()) != null);
396 for (int i = 0; i <= lastPosition; i++) {
397 ReferenceBinding[] interfaces = interfacesToVisit[i];
398 for (int j = 0, length = interfaces.length; j < length; j++) {
399 if ((currentType = interfaces[j]) == anInterface)
402 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
403 if (itsInterfaces != NoSuperInterfaces) {
404 if (++lastPosition == interfacesToVisit.length)
405 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
406 interfacesToVisit[lastPosition] = itsInterfaces;
412 // Internal method... assume its only sent to classes NOT interfaces
414 boolean implementsMethod(MethodBinding method) {
415 ReferenceBinding type = this;
416 while (type != null) {
417 MethodBinding[] methods = type.getMethods(method.selector);
418 for (int i = methods.length; --i >= 0;)
419 if (methods[i].areParametersEqual(method))
421 type = type.superclass();
425 /* Answer true if the receiver is an abstract type
428 public final boolean isAbstract() {
429 return (modifiers & AccAbstract) != 0;
431 public final boolean isAnonymousType() {
432 return (tagBits & IsAnonymousType) != 0;
434 public final boolean isBinaryBinding() {
435 return (tagBits & IsBinaryBinding) != 0;
437 public final boolean isClass() {
438 return (modifiers & AccInterface) == 0;
440 /* Answer true if the receiver type can be assigned to the argument type (right)
443 public boolean isCompatibleWith(TypeBinding right) {
446 if (right.id == T_Object)
448 if (!(right instanceof ReferenceBinding))
451 ReferenceBinding referenceBinding = (ReferenceBinding) right;
452 if (referenceBinding.isInterface())
453 return implementsInterface(referenceBinding, true);
454 if (isInterface()) // Explicit conversion from an interface to a class is not allowed
456 return referenceBinding.isSuperclassOf(this);
458 /* Answer true if the receiver has default visibility
461 public final boolean isDefault() {
462 return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
464 /* Answer true if the receiver is a deprecated type
467 public final boolean isDeprecated() {
468 return (modifiers & AccDeprecated) != 0;
470 /* Answer true if the receiver is final and cannot be subclassed
473 public final boolean isFinal() {
474 return (modifiers & AccFinal) != 0;
476 public final boolean isInterface() {
477 return (modifiers & AccInterface) != 0;
479 public final boolean isLocalType() {
480 return (tagBits & IsLocalType) != 0;
482 public final boolean isMemberType() {
483 return (tagBits & IsMemberType) != 0;
485 public final boolean isNestedType() {
486 return (tagBits & IsNestedType) != 0;
488 /* Answer true if the receiver has private visibility
491 public final boolean isPrivate() {
492 return (modifiers & AccPrivate) != 0;
494 /* Answer true if the receiver has private visibility and is used locally
497 public final boolean isPrivateUsed() {
498 return (modifiers & AccPrivateUsed) != 0;
500 /* Answer true if the receiver has protected visibility
503 public final boolean isProtected() {
504 return (modifiers & AccProtected) != 0;
506 /* Answer true if the receiver has public visibility
509 public final boolean isPublic() {
510 return (modifiers & AccPublic) != 0;
512 /* Answer true if the receiver is a static member type (or toplevel)
515 public final boolean isStatic() {
516 return (modifiers & (AccStatic | AccInterface)) != 0 ||
517 (tagBits & IsNestedType) == 0;
519 /* Answer true if all float operations must adher to IEEE 754 float/double rules
522 //public final boolean isStrictfp() {
523 // return (modifiers & AccStrictfp) != 0;
525 /* Answer true if the receiver is in the superclass hierarchy of aType
527 * NOTE: Object.isSuperclassOf(Object) -> false
530 public boolean isSuperclassOf(ReferenceBinding type) {
532 if (this == (type = type.superclass())) return true;
533 } while (type != null);
537 /* Answer true if the receiver is deprecated (or any of its enclosing types)
540 public final boolean isViewedAsDeprecated() {
541 return (modifiers & AccDeprecated) != 0 ||
542 (modifiers & AccDeprecatedImplicitly) != 0;
544 public ReferenceBinding[] memberTypes() {
545 return NoMemberTypes;
547 public MethodBinding[] methods() {
551 * Answer the source name for the type.
552 * In the case of member types, as the qualified name from its top level type.
553 * For example, for a member type N defined inside M & A: "A.M.N".
556 public char[] qualifiedSourceName() {
557 if (isMemberType()) {
558 return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
563 public char[] readableName() /*java.lang.Object*/ {
565 return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
567 return CharOperation.concatWith(compoundName, '.');
570 public char[] shortReadableName() /*Object*/ {
572 return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
577 /* Answer the receiver's signature.
579 * NOTE: This method should only be used during/after code gen.
582 public char[] signature() /* Ljava/lang/Object; */ {
583 if (signature != null)
586 return signature = CharOperation.concat('L', constantPoolName(), ';');
588 public char[] sourceName() {
591 public ReferenceBinding superclass() {
594 public ReferenceBinding[] superInterfaces() {
595 return NoSuperInterfaces;
597 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
598 if (isStatic()) return null;
600 ReferenceBinding enclosingType = enclosingType();
601 if (enclosingType == null)
604 return new ReferenceBinding[] {enclosingType};
606 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
607 return null; // is null if no enclosing instances are required