A variable description (like PHPFunctionDeclaration)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / ReferenceBinding.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
12
13 import net.sourceforge.phpdt.internal.compiler.env.IDependent;
14 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
15
16 /*
17 Not all fields defined by this type (& its subclasses) are initialized when it is created.
18 Some are initialized only when needed.
19
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.
23
24 null is NOT a valid value for a non-public field... it just means the field is not initialized.
25 */
26
27 abstract public class ReferenceBinding extends TypeBinding implements IDependent {
28         public char[][] compoundName;
29         public char[] sourceName;
30         public int modifiers;
31         public PackageBinding fPackage;
32
33         char[] fileName;
34         char[] constantPoolName;
35         char[] signature;
36
37 public FieldBinding[] availableFields() {
38         return fields();
39 }
40
41 public MethodBinding[] availableMethods() {
42         return methods();
43 }       
44 /* Answer true if the receiver can be instantiated
45 */
46
47 public boolean canBeInstantiated() {
48         return !(isAbstract() || isInterface());
49 }
50 /* Answer true if the receiver is visible to the invocationPackage.
51 */
52
53 public final boolean canBeSeenBy(PackageBinding invocationPackage) {
54         if (isPublic()) return true;
55         if (isPrivate()) return false;
56
57         // isProtected() or isDefault()
58         return invocationPackage == fPackage;
59 }
60 /* Answer true if the receiver is visible to the receiverType and the invocationType.
61 */
62
63 public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBinding invocationType) {
64         if (isPublic()) return true;
65
66         if (invocationType == this && invocationType == receiverType) return true;
67
68         if (isProtected()) {
69
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;
77
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
81                 //int depth = 0;
82                 do {
83                         if (declaringClass == invocationType) return true;
84                         if (declaringClass.isSuperclassOf(currentType)) return true;
85                         //depth++;
86                         currentType = currentType.enclosingType();
87                 } while (currentType != null);
88                 return false;
89         }
90
91         if (isPrivate()) {
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;
95                 
96                 if (invocationType != this) {
97                         ReferenceBinding outerInvocationType = invocationType;
98                         ReferenceBinding temp = outerInvocationType.enclosingType();
99                         while (temp != null) {
100                                 outerInvocationType = temp;
101                                 temp = temp.enclosingType();
102                         }
103
104                         ReferenceBinding outerDeclaringClass = this;
105                         temp = outerDeclaringClass.enclosingType();
106                         while (temp != null) {
107                                 outerDeclaringClass = temp;
108                                 temp = temp.enclosingType();
109                         }
110                         if (outerInvocationType != outerDeclaringClass) return false;
111                 }
112                 return true;
113         }
114
115         // isDefault()
116         if (invocationType.fPackage != fPackage) return false;
117
118         ReferenceBinding type = receiverType;
119         ReferenceBinding declaringClass = enclosingType() == null ? this : enclosingType();
120         do {
121                 if (declaringClass == type) return true;
122                 if (fPackage != type.fPackage) return false;
123         } while ((type = type.superclass()) != null);
124         return false;
125 }
126 /* Answer true if the receiver is visible to the type provided by the scope.
127 *
128 * NOTE: Cannot invoke this method with a compilation unit scope.
129 */
130
131 public final boolean canBeSeenBy(Scope scope) {
132         if (isPublic()) return true;
133
134         SourceTypeBinding invocationType = scope.enclosingSourceType();
135         if (invocationType == this) return true;
136
137         if (isProtected()) {
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
143         }
144
145         if (isProtected()) {
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;
152
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
156                 // int depth = 0;
157                 do {
158                         if (declaringClass == invocationType) return true;
159                         if (declaringClass.isSuperclassOf(currentType)) return true;
160                         // depth++;
161                         currentType = currentType.enclosingType();
162                 } while (currentType != null);
163                 return false;
164         }
165         if (isPrivate()) {
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();
173                 }
174
175                 ReferenceBinding outerDeclaringClass = this;
176                 temp = outerDeclaringClass.enclosingType();
177                 while (temp != null) {
178                         outerDeclaringClass = temp;
179                         temp = temp.enclosingType();
180                 }
181                 return outerInvocationType == outerDeclaringClass;
182         }
183
184         // isDefault()
185         return invocationType.fPackage == fPackage;
186 }
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;
191                         return;
192                 }
193                 return;         // all other types are in java.*.*
194         }
195
196         if (!CharOperation.equals(JAVA, compoundName[0]))
197                 return;         // assumes we only look up types in java
198
199         if (!CharOperation.equals(LANG, compoundName[1])) {
200                 if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
201                         id = T_JavaIoPrintStream;
202                         return;
203                 }
204                 return;         // all other types are in java.lang
205         }
206
207         if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
208                 id = T_JavaLangObject;
209                 return;
210         }
211         if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
212                 id = T_JavaLangString;
213                 return;
214         }
215
216         // well-known exception types
217         if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
218                 id = T_JavaLangThrowable;
219                 return;
220         }
221         if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
222                 id = T_JavaLangError;
223                 return;
224         }
225         if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
226                 id = T_JavaLangException;
227                 return;
228         }
229         if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName)) {
230                 id = T_JavaLangClassNotFoundException;
231                 return;
232         }
233         if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
234                 id = T_JavaLangNoClassDefError;
235                 return;
236         }
237
238         // other well-known types
239         if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
240                 id = T_JavaLangClass;
241                 return;
242         }
243         if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
244                 id = T_JavaLangStringBuffer;
245                 return;
246         }
247         if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
248                 id = T_JavaLangSystem;
249                 return;
250         }
251
252         if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
253                 id = T_JavaLangInteger;
254                 return;
255         }
256
257         if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
258                 id = T_JavaLangByte;
259                 return;
260         }       
261
262         if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
263                 id = T_JavaLangCharacter;
264                 return;
265         }
266
267         if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
268                 id = T_JavaLangFloat;
269                 return;
270         }
271
272         if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
273                 id = T_JavaLangDouble;
274                 return;
275         }
276
277         if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
278                 id = T_JavaLangBoolean;
279                 return;
280         }
281
282         if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
283                 id = T_JavaLangShort;
284                 return;
285         }
286
287         if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
288                 id = T_JavaLangLong;
289                 return;
290         }
291
292         if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
293                 id = T_JavaLangVoid;
294                 return;
295         }
296         
297         if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
298                 id = T_JavaLangAssertionError;
299                 return;
300         }
301 }
302 /* Answer the receiver's constant pool name.
303 *
304 * NOTE: This method should only be used during/after code gen.
305 */
306
307 public char[] constantPoolName() /* java/lang/Object */ {
308         if (constantPoolName != null)   return constantPoolName;
309         return constantPoolName = CharOperation.concatWith(compoundName, '/');
310 }
311 String debugName() {
312         return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
313 }
314 public final int depth() {
315         int depth = 0;
316         ReferenceBinding current = this;
317         while ((current = current.enclosingType()) != null)
318                 depth++;
319         return depth;
320 }
321 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
322 */
323
324 public ReferenceBinding enclosingType() {
325         return null;
326 }
327 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
328         ReferenceBinding current = this;
329         while (relativeDepth-- > 0 && current != null)
330                 current = current.enclosingType();
331         return current;
332 }
333 public int fieldCount() {
334         return fields().length;
335 }
336 public FieldBinding[] fields() {
337         return NoFields;
338 }
339 public final int getAccessFlags() {
340         return modifiers & AccJustFlag;
341 }
342 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
343         return null;
344 }
345 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
346         return null;
347 }
348 public FieldBinding getField(char[] fieldName) {
349         return null;
350 }
351 /**
352  * Answer the file name which defines the type.
353  *
354  * The path part (optional) must be separated from the actual
355  * file proper name by a java.io.File.separator.
356  *
357  * The proper file name includes the suffix extension (e.g. ".java")
358  *
359  * e.g. "c:/com/ibm/compiler/java/api/Compiler.java" 
360  */
361
362 public char[] getFileName() {
363         return fileName;
364 }
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];
370         return null;
371 }
372 public MethodBinding[] getMethods(char[] selector) {
373         return NoMethods;
374 }
375 public PackageBinding getPackage() {
376         return fPackage;
377 }
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.
380 *
381 * NOTE: Assume that anInterface is an interface.
382 */
383
384 public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
385         if (this == anInterface)
386                 return true;
387
388         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
389         int lastPosition = -1;
390         ReferenceBinding currentType = this;
391         do {
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;
397                 }
398         } while (searchHierarchy && (currentType = currentType.superclass()) != null);
399                         
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)
404                                 return true;
405
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;
411                         }
412                 }
413         }
414         return false;
415 }
416 // Internal method... assume its only sent to classes NOT interfaces
417
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))
424                                 return true;
425                 type = type.superclass();
426         }
427         return false;
428 }
429 /* Answer true if the receiver is an abstract type
430 */
431
432 public final boolean isAbstract() {
433         return (modifiers & AccAbstract) != 0;
434 }
435 public final boolean isAnonymousType() {
436         return (tagBits & IsAnonymousType) != 0;
437 }
438 public final boolean isBinaryBinding() {
439         return (tagBits & IsBinaryBinding) != 0;
440 }
441 public final boolean isClass() {
442         return (modifiers & AccInterface) == 0;
443 }
444 /* Answer true if the receiver type can be assigned to the argument type (right)
445 */
446         
447 boolean isCompatibleWith(TypeBinding right) {
448         if (right == this)
449                 return true;
450         if (right.id == T_Object)
451                 return true;
452         if (!(right instanceof ReferenceBinding))
453                 return false;
454
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
459                 return false;
460         return referenceBinding.isSuperclassOf(this);
461 }
462 /* Answer true if the receiver has default visibility
463 */
464
465 public final boolean isDefault() {
466         return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
467 }
468 /* Answer true if the receiver is a deprecated type
469 */
470
471 public final boolean isDeprecated() {
472         return (modifiers & AccDeprecated) != 0;
473 }
474 /* Answer true if the receiver is final and cannot be subclassed
475 */
476
477 public final boolean isFinal() {
478         return (modifiers & AccFinal) != 0;
479 }
480 public final boolean isInterface() {
481         return (modifiers & AccInterface) != 0;
482 }
483 public final boolean isLocalType() {
484         return (tagBits & IsLocalType) != 0;
485 }
486 public final boolean isMemberType() {
487         return (tagBits & IsMemberType) != 0;
488 }
489 public final boolean isNestedType() {
490         return (tagBits & IsNestedType) != 0;
491 }
492 /* Answer true if the receiver has private visibility
493 */
494
495 public final boolean isPrivate() {
496         return (modifiers & AccPrivate) != 0;
497 }
498 /* Answer true if the receiver has protected visibility
499 */
500
501 public final boolean isProtected() {
502         return (modifiers & AccProtected) != 0;
503 }
504 /* Answer true if the receiver has public visibility
505 */
506
507 public final boolean isPublic() {
508         return (modifiers & AccPublic) != 0;
509 }
510 /* Answer true if the receiver is a static member type (or toplevel)
511  */
512
513 public final boolean isStatic() {
514         return (modifiers & (AccStatic | AccInterface)) != 0 ||
515                     (tagBits & IsNestedType) == 0;
516 }
517 /* Answer true if all float operations must adher to IEEE 754 float/double rules
518 */
519
520 public final boolean isStrictfp() {
521         return (modifiers & AccStrictfp) != 0;
522 }
523 /* Answer true if the receiver is in the superclass hierarchy of aType
524 *
525 * NOTE: Object.isSuperclassOf(Object) -> false
526 */
527
528 public boolean isSuperclassOf(ReferenceBinding type) {
529         do {
530                 if (this == (type = type.superclass())) return true;
531         } while (type != null);
532
533         return false;
534 }
535 /* Answer true if the receiver is deprecated (or any of its enclosing types)
536 */
537
538 public final boolean isViewedAsDeprecated() {
539         return (modifiers & AccDeprecated) != 0 ||
540                 (modifiers & AccDeprecatedImplicitly) != 0;
541 }
542 public ReferenceBinding[] memberTypes() {
543         return NoMemberTypes;
544 }
545 public MethodBinding[] methods() {
546         return NoMethods;
547 }
548 /**
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".
552 */
553
554 public char[] qualifiedSourceName() {
555         if (isMemberType()) {
556                 return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
557         } else {
558                 return sourceName();
559         }
560 }
561 public char[] readableName() /*java.lang.Object*/ {
562         if (isMemberType())
563                 return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
564         else
565                 return CharOperation.concatWith(compoundName, '.');
566 }
567 /* Answer the receiver's signature.
568 *
569 * NOTE: This method should only be used during/after code gen.
570 */
571
572 public char[] signature() /* Ljava/lang/Object; */ {
573         if (signature != null)
574                 return signature;
575
576         return signature = CharOperation.concat('L', constantPoolName(), ';');
577 }
578 public char[] sourceName() {
579         return sourceName;
580 }
581 public ReferenceBinding superclass() {
582         return null;
583 }
584 public ReferenceBinding[] superInterfaces() {
585         return NoSuperInterfaces;
586 }
587 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
588         if (isStatic()) return null;
589
590         ReferenceBinding enclosingType = enclosingType();
591         if (enclosingType == null)
592                 return null;
593         else
594                 return new ReferenceBinding[] {enclosingType};
595 }
596 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
597         return null;            // is null if no enclosing instances are required
598 }
599 }