1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.lookup;
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.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;
190 if (!CharOperation.equals(JAVA, compoundName[0]))
193 // remaining types MUST be in java.*.*
194 if (!CharOperation.equals(LANG, compoundName[1])) {
195 if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName))
196 id = T_JavaIoPrintStream;
197 else if (CharOperation.equals(JAVA_IO_SERIALIZABLE, compoundName))
198 id = T_JavaIoSerializable;
202 // remaining types MUST be in java.lang.*
203 char[] typeName = compoundName[2];
204 if (typeName.length == 0) return; // just to be safe
205 switch (typeName[0]) {
207 if (CharOperation.equals(typeName, JAVA_LANG_ASSERTIONERROR[2]))
208 id = T_JavaLangAssertionError;
211 if (CharOperation.equals(typeName, JAVA_LANG_BOOLEAN[2]))
212 id = T_JavaLangBoolean;
213 else if (CharOperation.equals(typeName, JAVA_LANG_BYTE[2]))
217 if (CharOperation.equals(typeName, JAVA_LANG_CHARACTER[2]))
218 id = T_JavaLangCharacter;
219 else if (CharOperation.equals(typeName, JAVA_LANG_CLASS[2]))
220 id = T_JavaLangClass;
221 else if (CharOperation.equals(typeName, JAVA_LANG_CLASSNOTFOUNDEXCEPTION[2]))
222 id = T_JavaLangClassNotFoundException;
223 else if (CharOperation.equals(typeName, JAVA_LANG_CLONEABLE[2]))
224 id = T_JavaLangCloneable;
227 if (CharOperation.equals(typeName, JAVA_LANG_DOUBLE[2]))
228 id = T_JavaLangDouble;
231 if (CharOperation.equals(typeName, JAVA_LANG_ERROR[2]))
232 id = T_JavaLangError;
233 else if (CharOperation.equals(typeName, JAVA_LANG_EXCEPTION[2]))
234 id = T_JavaLangException;
237 if (CharOperation.equals(typeName, JAVA_LANG_FLOAT[2]))
238 id = T_JavaLangFloat;
241 if (CharOperation.equals(typeName, JAVA_LANG_INTEGER[2]))
242 id = T_JavaLangInteger;
245 if (CharOperation.equals(typeName, JAVA_LANG_LONG[2]))
249 if (CharOperation.equals(typeName, JAVA_LANG_NOCLASSDEFERROR[2]))
250 id = T_JavaLangNoClassDefError;
253 if (CharOperation.equals(typeName, JAVA_LANG_OBJECT[2]))
254 id = T_JavaLangObject;
257 if (CharOperation.equals(typeName, JAVA_LANG_STRING[2]))
258 id = T_JavaLangString;
259 else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUFFER[2]))
260 id = T_JavaLangStringBuffer;
261 else if (CharOperation.equals(typeName, JAVA_LANG_SYSTEM[2]))
262 id = T_JavaLangSystem;
263 else if (CharOperation.equals(typeName, JAVA_LANG_SHORT[2]))
264 id = T_JavaLangShort;
267 if (CharOperation.equals(typeName, JAVA_LANG_THROWABLE[2]))
268 id = T_JavaLangThrowable;
271 if (CharOperation.equals(typeName, JAVA_LANG_VOID[2]))
276 /* Answer the receiver's constant pool name.
278 * NOTE: This method should only be used during/after code gen.
281 public char[] constantPoolName() /* java/lang/Object */ {
282 if (constantPoolName != null) return constantPoolName;
283 return constantPoolName = CharOperation.concatWith(compoundName, '/');
286 return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
288 public final int depth() {
290 ReferenceBinding current = this;
291 while ((current = current.enclosingType()) != null)
295 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
298 public ReferenceBinding enclosingType() {
301 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
302 ReferenceBinding current = this;
303 while (relativeDepth-- > 0 && current != null)
304 current = current.enclosingType();
307 public int fieldCount() {
308 return fields().length;
310 public FieldBinding[] fields() {
313 public final int getAccessFlags() {
314 return modifiers & AccJustFlag;
316 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
319 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
322 public FieldBinding getField(char[] fieldName, boolean needResolve) {
326 * Answer the file name which defines the type.
328 * The path part (optional) must be separated from the actual
329 * file proper name by a java.io.File.separator.
331 * The proper file name includes the suffix extension (e.g. ".java")
333 * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
336 public char[] getFileName() {
339 public ReferenceBinding getMemberType(char[] typeName) {
340 ReferenceBinding[] memberTypes = memberTypes();
341 for (int i = memberTypes.length; --i >= 0;)
342 if (CharOperation.equals(memberTypes[i].sourceName, typeName))
343 return memberTypes[i];
346 public MethodBinding[] getMethods(char[] selector) {
349 public PackageBinding getPackage() {
352 public boolean hasMemberTypes() {
355 /* Answer true if the receiver implements anInterface or is identical to anInterface.
356 * If searchHierarchy is true, then also search the receiver's superclasses.
358 * NOTE: Assume that anInterface is an interface.
361 public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
362 if (this == anInterface)
365 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
366 int lastPosition = -1;
367 ReferenceBinding currentType = this;
369 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
370 if (itsInterfaces != NoSuperInterfaces) {
371 if (++lastPosition == interfacesToVisit.length)
372 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
373 interfacesToVisit[lastPosition] = itsInterfaces;
375 } while (searchHierarchy && (currentType = currentType.superclass()) != null);
377 for (int i = 0; i <= lastPosition; i++) {
378 ReferenceBinding[] interfaces = interfacesToVisit[i];
379 for (int j = 0, length = interfaces.length; j < length; j++) {
380 if ((currentType = interfaces[j]) == anInterface)
383 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
384 if (itsInterfaces != NoSuperInterfaces) {
385 if (++lastPosition == interfacesToVisit.length)
386 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
387 interfacesToVisit[lastPosition] = itsInterfaces;
393 // Internal method... assume its only sent to classes NOT interfaces
395 boolean implementsMethod(MethodBinding method) {
396 ReferenceBinding type = this;
397 while (type != null) {
398 MethodBinding[] methods = type.getMethods(method.selector);
399 for (int i = methods.length; --i >= 0;)
400 if (methods[i].areParametersEqual(method))
402 type = type.superclass();
406 /* Answer true if the receiver is an abstract type
409 public final boolean isAbstract() {
410 return (modifiers & AccAbstract) != 0;
412 public final boolean isAnonymousType() {
413 return (tagBits & IsAnonymousType) != 0;
415 public final boolean isBinaryBinding() {
416 return (tagBits & IsBinaryBinding) != 0;
418 public final boolean isClass() {
419 return (modifiers & AccInterface) == 0;
421 /* Answer true if the receiver type can be assigned to the argument type (right)
424 public boolean isCompatibleWith(TypeBinding right) {
427 if (right.id == T_Object)
429 if (!(right instanceof ReferenceBinding))
432 ReferenceBinding referenceBinding = (ReferenceBinding) right;
433 if (referenceBinding.isInterface())
434 return implementsInterface(referenceBinding, true);
435 if (isInterface()) // Explicit conversion from an interface to a class is not allowed
437 return referenceBinding.isSuperclassOf(this);
439 /* Answer true if the receiver has default visibility
442 public final boolean isDefault() {
443 return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
445 /* Answer true if the receiver is a deprecated type
448 public final boolean isDeprecated() {
449 return (modifiers & AccDeprecated) != 0;
451 /* Answer true if the receiver is final and cannot be subclassed
454 public final boolean isFinal() {
455 return (modifiers & AccFinal) != 0;
457 public final boolean isInterface() {
458 return (modifiers & AccInterface) != 0;
460 public final boolean isLocalType() {
461 return (tagBits & IsLocalType) != 0;
463 public final boolean isMemberType() {
464 return (tagBits & IsMemberType) != 0;
466 public final boolean isNestedType() {
467 return (tagBits & IsNestedType) != 0;
469 /* Answer true if the receiver has private visibility
472 public final boolean isPrivate() {
473 return (modifiers & AccPrivate) != 0;
475 /* Answer true if the receiver has private visibility and is used locally
478 public final boolean isPrivateUsed() {
479 return (modifiers & AccPrivateUsed) != 0;
481 /* Answer true if the receiver has protected visibility
484 public final boolean isProtected() {
485 return (modifiers & AccProtected) != 0;
487 /* Answer true if the receiver has public visibility
490 public final boolean isPublic() {
491 return (modifiers & AccPublic) != 0;
493 /* Answer true if the receiver is a static member type (or toplevel)
496 public final boolean isStatic() {
497 return (modifiers & (AccStatic | AccInterface)) != 0 ||
498 (tagBits & IsNestedType) == 0;
500 /* Answer true if all float operations must adher to IEEE 754 float/double rules
503 public final boolean isStrictfp() {
504 return (modifiers & AccStrictfp) != 0;
506 /* Answer true if the receiver is in the superclass hierarchy of aType
508 * NOTE: Object.isSuperclassOf(Object) -> false
511 public boolean isSuperclassOf(ReferenceBinding type) {
513 if (this == (type = type.superclass())) return true;
514 } while (type != null);
518 /* Answer true if the receiver is deprecated (or any of its enclosing types)
521 public final boolean isViewedAsDeprecated() {
522 return (modifiers & AccDeprecated) != 0 ||
523 (modifiers & AccDeprecatedImplicitly) != 0;
525 public ReferenceBinding[] memberTypes() {
526 return NoMemberTypes;
528 public MethodBinding[] methods() {
532 * Answer the source name for the type.
533 * In the case of member types, as the qualified name from its top level type.
534 * For example, for a member type N defined inside M & A: "A.M.N".
537 public char[] qualifiedSourceName() {
539 return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
543 public char[] readableName() /*java.lang.Object*/ {
545 return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
546 return CharOperation.concatWith(compoundName, '.');
549 public char[] shortReadableName() /*Object*/ {
551 return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
555 /* Answer the receiver's signature.
557 * NOTE: This method should only be used during/after code gen.
560 public char[] signature() /* Ljava/lang/Object; */ {
561 if (signature != null)
564 return signature = CharOperation.concat('L', constantPoolName(), ';');
566 public char[] sourceName() {
569 public ReferenceBinding superclass() {
572 public ReferenceBinding[] superInterfaces() {
573 return NoSuperInterfaces;
575 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
576 if (isStatic()) return null;
578 ReferenceBinding enclosingType = enclosingType();
579 if (enclosingType == null)
581 return new ReferenceBinding[] {enclosingType};
583 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
584 return null; // is null if no enclosing instances are required
586 MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types