synchronized from quantum plugin
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / ReferenceBinding.java
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
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.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.env.IDependent;
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 /* 
127  * Answer true if the receiver is visible to the type provided by the scope.
128  */
129
130 public final boolean canBeSeenBy(Scope scope) {
131         
132         if (isPublic()) return true;
133
134         if (scope.kind == Scope.COMPILATION_UNIT_SCOPE){
135                 return this.canBeSeenBy(((CompilationUnitScope)scope).fPackage);
136         }
137         
138         SourceTypeBinding invocationType = scope.enclosingSourceType();
139         if (invocationType == this) return true;
140
141         if (isProtected()) {
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;
148
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
152                 // int depth = 0;
153                 do {
154                         if (declaringClass == invocationType) return true;
155                         if (declaringClass.isSuperclassOf(currentType)) return true;
156                         // depth++;
157                         currentType = currentType.enclosingType();
158                 } while (currentType != null);
159                 return false;
160         }
161         if (isPrivate()) {
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();
169                 }
170
171                 ReferenceBinding outerDeclaringClass = this;
172                 temp = outerDeclaringClass.enclosingType();
173                 while (temp != null) {
174                         outerDeclaringClass = temp;
175                         temp = temp.enclosingType();
176                 }
177                 return outerInvocationType == outerDeclaringClass;
178         }
179
180         // isDefault()
181         return invocationType.fPackage == fPackage;
182 }
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;
187                         return;
188                 }
189                 return;         // all other types are in java.*.*
190         }
191
192         if (!CharOperation.equals(JAVA, compoundName[0]))
193                 return;         // assumes we only look up types in java
194
195         if (!CharOperation.equals(LANG, compoundName[1])) {
196                 if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
197                         id = T_JavaIoPrintStream;
198                         return;
199                 }
200                 return;         // all other types are in java.lang
201         }
202
203         if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
204                 id = T_JavaLangObject;
205                 return;
206         }
207         if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
208                 id = T_JavaLangString;
209                 return;
210         }
211
212         // well-known exception types
213         if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
214                 id = T_JavaLangThrowable;
215                 return;
216         }
217         if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
218                 id = T_JavaLangError;
219                 return;
220         }
221         if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
222                 id = T_JavaLangException;
223                 return;
224         }
225         if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName)) {
226                 id = T_JavaLangClassNotFoundException;
227                 return;
228         }
229         if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
230                 id = T_JavaLangNoClassDefError;
231                 return;
232         }
233
234         // other well-known types
235         if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
236                 id = T_JavaLangClass;
237                 return;
238         }
239         if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
240                 id = T_JavaLangStringBuffer;
241                 return;
242         }
243         if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
244                 id = T_JavaLangSystem;
245                 return;
246         }
247
248         if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
249                 id = T_JavaLangInteger;
250                 return;
251         }
252
253         if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
254                 id = T_JavaLangByte;
255                 return;
256         }       
257
258         if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
259                 id = T_JavaLangCharacter;
260                 return;
261         }
262
263         if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
264                 id = T_JavaLangFloat;
265                 return;
266         }
267
268         if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
269                 id = T_JavaLangDouble;
270                 return;
271         }
272
273         if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
274                 id = T_JavaLangBoolean;
275                 return;
276         }
277
278         if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
279                 id = T_JavaLangShort;
280                 return;
281         }
282
283         if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
284                 id = T_JavaLangLong;
285                 return;
286         }
287
288         if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
289                 id = T_JavaLangVoid;
290                 return;
291         }
292         
293         if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
294                 id = T_JavaLangAssertionError;
295                 return;
296         }
297 }
298 /* Answer the receiver's constant pool name.
299 *
300 * NOTE: This method should only be used during/after code gen.
301 */
302
303 public char[] constantPoolName() /* java/lang/Object */ {
304         if (constantPoolName != null)   return constantPoolName;
305         return constantPoolName = CharOperation.concatWith(compoundName, '/');
306 }
307 String debugName() {
308         return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
309 }
310 public final int depth() {
311         int depth = 0;
312         ReferenceBinding current = this;
313         while ((current = current.enclosingType()) != null)
314                 depth++;
315         return depth;
316 }
317 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
318 */
319
320 public ReferenceBinding enclosingType() {
321         return null;
322 }
323 public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
324         ReferenceBinding current = this;
325         while (relativeDepth-- > 0 && current != null)
326                 current = current.enclosingType();
327         return current;
328 }
329 public int fieldCount() {
330         return fields().length;
331 }
332 public FieldBinding[] fields() {
333         return NoFields;
334 }
335 public final int getAccessFlags() {
336         return modifiers & AccJustFlag;
337 }
338 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
339         return null;
340 }
341 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
342         return null;
343 }
344 public FieldBinding getField(char[] fieldName) {
345         return null;
346 }
347 /**
348  * Answer the file name which defines the type.
349  *
350  * The path part (optional) must be separated from the actual
351  * file proper name by a java.io.File.separator.
352  *
353  * The proper file name includes the suffix extension (e.g. ".java")
354  *
355  * e.g. "c:/com/ibm/compiler/java/api/Compiler.java" 
356  */
357
358 public char[] getFileName() {
359         return fileName;
360 }
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];
366         return null;
367 }
368 public MethodBinding[] getMethods(char[] selector) {
369         return NoMethods;
370 }
371 public PackageBinding getPackage() {
372         return fPackage;
373 }
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.
376 *
377 * NOTE: Assume that anInterface is an interface.
378 */
379
380 public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
381         if (this == anInterface)
382                 return true;
383
384         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
385         int lastPosition = -1;
386         ReferenceBinding currentType = this;
387         do {
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;
393                 }
394         } while (searchHierarchy && (currentType = currentType.superclass()) != null);
395                         
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)
400                                 return true;
401
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;
407                         }
408                 }
409         }
410         return false;
411 }
412 // Internal method... assume its only sent to classes NOT interfaces
413
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))
420                                 return true;
421                 type = type.superclass();
422         }
423         return false;
424 }
425 /* Answer true if the receiver is an abstract type
426 */
427
428 public final boolean isAbstract() {
429         return (modifiers & AccAbstract) != 0;
430 }
431 public final boolean isAnonymousType() {
432         return (tagBits & IsAnonymousType) != 0;
433 }
434 public final boolean isBinaryBinding() {
435         return (tagBits & IsBinaryBinding) != 0;
436 }
437 public final boolean isClass() {
438         return (modifiers & AccInterface) == 0;
439 }
440 /* Answer true if the receiver type can be assigned to the argument type (right)
441 */
442         
443 public boolean isCompatibleWith(TypeBinding right) {
444         if (right == this)
445                 return true;
446         if (right.id == T_Object)
447                 return true;
448         if (!(right instanceof ReferenceBinding))
449                 return false;
450
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
455                 return false;
456         return referenceBinding.isSuperclassOf(this);
457 }
458 /* Answer true if the receiver has default visibility
459 */
460
461 public final boolean isDefault() {
462         return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
463 }
464 /* Answer true if the receiver is a deprecated type
465 */
466
467 public final boolean isDeprecated() {
468         return (modifiers & AccDeprecated) != 0;
469 }
470 /* Answer true if the receiver is final and cannot be subclassed
471 */
472
473 public final boolean isFinal() {
474         return (modifiers & AccFinal) != 0;
475 }
476 public final boolean isInterface() {
477         return (modifiers & AccInterface) != 0;
478 }
479 public final boolean isLocalType() {
480         return (tagBits & IsLocalType) != 0;
481 }
482 public final boolean isMemberType() {
483         return (tagBits & IsMemberType) != 0;
484 }
485 public final boolean isNestedType() {
486         return (tagBits & IsNestedType) != 0;
487 }
488 /* Answer true if the receiver has private visibility
489 */
490
491 public final boolean isPrivate() {
492         return (modifiers & AccPrivate) != 0;
493 }
494 /* Answer true if the receiver has private visibility and is used locally
495 */
496
497 public final boolean isPrivateUsed() {
498         return (modifiers & AccPrivateUsed) != 0;
499 }
500 /* Answer true if the receiver has protected visibility
501 */
502
503 public final boolean isProtected() {
504         return (modifiers & AccProtected) != 0;
505 }
506 /* Answer true if the receiver has public visibility
507 */
508
509 public final boolean isPublic() {
510         return (modifiers & AccPublic) != 0;
511 }
512 /* Answer true if the receiver is a static member type (or toplevel)
513  */
514
515 public final boolean isStatic() {
516         return (modifiers & (AccStatic | AccInterface)) != 0 ||
517                     (tagBits & IsNestedType) == 0;
518 }
519 /* Answer true if all float operations must adher to IEEE 754 float/double rules
520 */
521
522 //public final boolean isStrictfp() {
523 //      return (modifiers & AccStrictfp) != 0;
524 //}
525 /* Answer true if the receiver is in the superclass hierarchy of aType
526 *
527 * NOTE: Object.isSuperclassOf(Object) -> false
528 */
529
530 public boolean isSuperclassOf(ReferenceBinding type) {
531         do {
532                 if (this == (type = type.superclass())) return true;
533         } while (type != null);
534
535         return false;
536 }
537 /* Answer true if the receiver is deprecated (or any of its enclosing types)
538 */
539
540 public final boolean isViewedAsDeprecated() {
541         return (modifiers & AccDeprecated) != 0 ||
542                 (modifiers & AccDeprecatedImplicitly) != 0;
543 }
544 public ReferenceBinding[] memberTypes() {
545         return NoMemberTypes;
546 }
547 public MethodBinding[] methods() {
548         return NoMethods;
549 }
550 /**
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".
554 */
555
556 public char[] qualifiedSourceName() {
557         if (isMemberType()) {
558                 return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
559         } else {
560                 return sourceName();
561         }
562 }
563 public char[] readableName() /*java.lang.Object*/ {
564         if (isMemberType())
565                 return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
566         else
567                 return CharOperation.concatWith(compoundName, '.');
568 }
569
570 public char[] shortReadableName() /*Object*/ {
571         if (isMemberType())
572                 return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
573         else
574                 return sourceName;
575 }
576
577 /* Answer the receiver's signature.
578 *
579 * NOTE: This method should only be used during/after code gen.
580 */
581
582 public char[] signature() /* Ljava/lang/Object; */ {
583         if (signature != null)
584                 return signature;
585
586         return signature = CharOperation.concat('L', constantPoolName(), ';');
587 }
588 public char[] sourceName() {
589         return sourceName;
590 }
591 public ReferenceBinding superclass() {
592         return null;
593 }
594 public ReferenceBinding[] superInterfaces() {
595         return NoSuperInterfaces;
596 }
597 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
598         if (isStatic()) return null;
599
600         ReferenceBinding enclosingType = enclosingType();
601         if (enclosingType == null)
602                 return null;
603         else
604                 return new ReferenceBinding[] {enclosingType};
605 }
606 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
607         return null;            // is null if no enclosing instances are required
608 }
609 }