Refactory: replaced internal copy of Assert class with org.eclipse.core.runtime.Assert
[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
18  * it is created. Some are initialized only when needed.
19  * 
20  * Accessors have been provided for some public fields so all TypeBindings have
21  * the same API... but access public fields directly whenever possible.
22  * Non-public fields have accessors which should be used everywhere you expect
23  * the field to be initialized.
24  * 
25  * null is NOT a valid value for a non-public field... it just means the field
26  * is not initialized.
27  */
28
29 abstract public class ReferenceBinding extends TypeBinding implements
30                 IDependent {
31         public char[][] compoundName;
32
33         public char[] sourceName;
34
35         public int modifiers;
36
37         public PackageBinding fPackage;
38
39         char[] fileName;
40
41         char[] constantPoolName;
42
43         char[] signature;
44
45         public FieldBinding[] availableFields() {
46                 return fields();
47         }
48
49         public MethodBinding[] availableMethods() {
50                 return methods();
51         }
52
53         /*
54          * Answer true if the receiver can be instantiated
55          */
56
57         public boolean canBeInstantiated() {
58                 return !(isAbstract() || isInterface());
59         }
60
61         /*
62          * Answer true if the receiver is visible to the invocationPackage.
63          */
64
65         public final boolean canBeSeenBy(PackageBinding invocationPackage) {
66                 if (isPublic())
67                         return true;
68                 if (isPrivate())
69                         return false;
70
71                 // isProtected() or isDefault()
72                 return invocationPackage == fPackage;
73         }
74
75         /*
76          * Answer true if the receiver is visible to the receiverType and the
77          * invocationType.
78          */
79
80         public final boolean canBeSeenBy(ReferenceBinding receiverType,
81                         SourceTypeBinding invocationType) {
82                 if (isPublic())
83                         return true;
84
85                 if (invocationType == this && invocationType == receiverType)
86                         return true;
87
88                 if (isProtected()) {
89
90                         // answer true if the invocationType is the declaringClass or they
91                         // are in the same package
92                         // OR the invocationType is a subclass of the declaringClass
93                         // AND the invocationType is the invocationType or its subclass
94                         // OR the type is a static method accessed directly through a type
95                         // OR previous assertions are true for one of the enclosing type
96                         if (invocationType == this)
97                                 return true;
98                         if (invocationType.fPackage == fPackage)
99                                 return true;
100
101                         ReferenceBinding currentType = invocationType;
102                         ReferenceBinding declaringClass = enclosingType(); // protected
103                                                                                                                                 // types always
104                                                                                                                                 // have an
105                                                                                                                                 // enclosing one
106                         if (declaringClass == null)
107                                 return false; // could be null if incorrect top-level
108                                                                 // protected type
109                         // int depth = 0;
110                         do {
111                                 if (declaringClass == invocationType)
112                                         return true;
113                                 if (declaringClass.isSuperclassOf(currentType))
114                                         return true;
115                                 // depth++;
116                                 currentType = currentType.enclosingType();
117                         } while (currentType != null);
118                         return false;
119                 }
120
121                 if (isPrivate()) {
122                         // answer true if the receiverType is the receiver or its
123                         // enclosingType
124                         // AND the invocationType and the receiver have a common
125                         // enclosingType
126                         if (!(receiverType == this || receiverType == enclosingType()))
127                                 return false;
128
129                         if (invocationType != this) {
130                                 ReferenceBinding outerInvocationType = invocationType;
131                                 ReferenceBinding temp = outerInvocationType.enclosingType();
132                                 while (temp != null) {
133                                         outerInvocationType = temp;
134                                         temp = temp.enclosingType();
135                                 }
136
137                                 ReferenceBinding outerDeclaringClass = this;
138                                 temp = outerDeclaringClass.enclosingType();
139                                 while (temp != null) {
140                                         outerDeclaringClass = temp;
141                                         temp = temp.enclosingType();
142                                 }
143                                 if (outerInvocationType != outerDeclaringClass)
144                                         return false;
145                         }
146                         return true;
147                 }
148
149                 // isDefault()
150                 if (invocationType.fPackage != fPackage)
151                         return false;
152
153                 ReferenceBinding type = receiverType;
154                 ReferenceBinding declaringClass = enclosingType() == null ? this
155                                 : enclosingType();
156                 do {
157                         if (declaringClass == type)
158                                 return true;
159                         if (fPackage != type.fPackage)
160                                 return false;
161                 } while ((type = type.superclass()) != null);
162                 return false;
163         }
164
165         /*
166          * Answer true if the receiver is visible to the type provided by the scope.
167          */
168
169         public final boolean canBeSeenBy(Scope scope) {
170
171                 if (isPublic())
172                         return true;
173
174                 if (scope.kind == Scope.COMPILATION_UNIT_SCOPE) {
175                         return this.canBeSeenBy(((CompilationUnitScope) scope).fPackage);
176                 }
177
178                 SourceTypeBinding invocationType = scope.enclosingSourceType();
179                 if (invocationType == this)
180                         return true;
181
182                 if (isProtected()) {
183                         // answer true if the invocationType is the declaringClass or they
184                         // are in the same package
185                         // OR the invocationType is a subclass of the declaringClass
186                         // AND the invocationType is the invocationType or its subclass
187                         // OR the type is a static method accessed directly through a type
188                         // OR previous assertions are true for one of the enclosing type
189                         if (invocationType.fPackage == fPackage)
190                                 return true;
191
192                         ReferenceBinding currentType = invocationType;
193                         ReferenceBinding declaringClass = enclosingType(); // protected
194                                                                                                                                 // types always
195                                                                                                                                 // have an
196                                                                                                                                 // enclosing one
197                         if (declaringClass == null)
198                                 return false; // could be null if incorrect top-level
199                                                                 // protected type
200                         // int depth = 0;
201                         do {
202                                 if (declaringClass == invocationType)
203                                         return true;
204                                 if (declaringClass.isSuperclassOf(currentType))
205                                         return true;
206                                 // depth++;
207                                 currentType = currentType.enclosingType();
208                         } while (currentType != null);
209                         return false;
210                 }
211                 if (isPrivate()) {
212                         // answer true if the receiver and the invocationType have a common
213                         // enclosingType
214                         // already know they are not the identical type
215                         ReferenceBinding outerInvocationType = invocationType;
216                         ReferenceBinding temp = outerInvocationType.enclosingType();
217                         while (temp != null) {
218                                 outerInvocationType = temp;
219                                 temp = temp.enclosingType();
220                         }
221
222                         ReferenceBinding outerDeclaringClass = this;
223                         temp = outerDeclaringClass.enclosingType();
224                         while (temp != null) {
225                                 outerDeclaringClass = temp;
226                                 temp = temp.enclosingType();
227                         }
228                         return outerInvocationType == outerDeclaringClass;
229                 }
230
231                 // isDefault()
232                 return invocationType.fPackage == fPackage;
233         }
234
235         // public void computeId() {
236         // if (compoundName.length != 3) {
237         // if (compoundName.length == 4 &&
238         // CharOperation.equals(JAVA_LANG_REFLECT_CONSTRUCTOR, compoundName)) {
239         // id = T_JavaLangReflectConstructor;
240         // return;
241         // }
242         // return; // all other types are in java.*.*
243         // }
244         //
245         // if (!CharOperation.equals(JAVA, compoundName[0]))
246         // return; // assumes we only look up types in java
247         //
248         // if (!CharOperation.equals(LANG, compoundName[1])) {
249         // if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
250         // id = T_JavaIoPrintStream;
251         // return;
252         // }
253         // return; // all other types are in java.lang
254         // }
255         //
256         // if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
257         // id = T_JavaLangObject;
258         // return;
259         // }
260         // if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
261         // id = T_JavaLangString;
262         // return;
263         // }
264         //
265         // // well-known exception types
266         // if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
267         // id = T_JavaLangThrowable;
268         // return;
269         // }
270         // if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
271         // id = T_JavaLangError;
272         // return;
273         // }
274         // if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
275         // id = T_JavaLangException;
276         // return;
277         // }
278         // if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName))
279         // {
280         // id = T_JavaLangClassNotFoundException;
281         // return;
282         // }
283         // if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
284         // id = T_JavaLangNoClassDefError;
285         // return;
286         // }
287         //
288         // // other well-known types
289         // if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
290         // id = T_JavaLangClass;
291         // return;
292         // }
293         // if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
294         // id = T_JavaLangStringBuffer;
295         // return;
296         // }
297         // if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
298         // id = T_JavaLangSystem;
299         // return;
300         // }
301         //
302         // if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
303         // id = T_JavaLangInteger;
304         // return;
305         // }
306         //
307         // if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
308         // id = T_JavaLangByte;
309         // return;
310         // }
311         //
312         // if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
313         // id = T_JavaLangCharacter;
314         // return;
315         // }
316         //
317         // if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
318         // id = T_JavaLangFloat;
319         // return;
320         // }
321         //
322         // if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
323         // id = T_JavaLangDouble;
324         // return;
325         // }
326         //
327         // if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
328         // id = T_JavaLangBoolean;
329         // return;
330         // }
331         //
332         // if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
333         // id = T_JavaLangShort;
334         // return;
335         // }
336         //
337         // if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
338         // id = T_JavaLangLong;
339         // return;
340         // }
341         //
342         // if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
343         // id = T_JavaLangVoid;
344         // return;
345         // }
346         //      
347         // if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
348         // id = T_JavaLangAssertionError;
349         // return;
350         // }
351         // }
352         /*
353          * Answer the receiver's constant pool name.
354          * 
355          * NOTE: This method should only be used during/after code gen.
356          */
357
358         public char[] constantPoolName() /* java/lang/Object */{
359                 if (constantPoolName != null)
360                         return constantPoolName;
361                 return constantPoolName = CharOperation.concatWith(compoundName, '/');
362         }
363
364         String debugName() {
365                 return (compoundName != null) ? new String(readableName())
366                                 : "UNNAMED TYPE"; //$NON-NLS-1$
367         }
368
369         public final int depth() {
370                 int depth = 0;
371                 ReferenceBinding current = this;
372                 while ((current = current.enclosingType()) != null)
373                         depth++;
374                 return depth;
375         }
376
377         /*
378          * Answer the receiver's enclosing type... null if the receiver is a top
379          * level type.
380          */
381
382         public ReferenceBinding enclosingType() {
383                 return null;
384         }
385
386         public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
387                 ReferenceBinding current = this;
388                 while (relativeDepth-- > 0 && current != null)
389                         current = current.enclosingType();
390                 return current;
391         }
392
393         public int fieldCount() {
394                 return fields().length;
395         }
396
397         public FieldBinding[] fields() {
398                 return NoFields;
399         }
400
401         public final int getAccessFlags() {
402                 return modifiers & AccJustFlag;
403         }
404
405         public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
406                 return null;
407         }
408
409         public MethodBinding getExactMethod(char[] selector,
410                         TypeBinding[] argumentTypes) {
411                 return null;
412         }
413
414         public FieldBinding getField(char[] fieldName) {
415                 return null;
416         }
417
418         /**
419          * Answer the file name which defines the type.
420          * 
421          * The path part (optional) must be separated from the actual file proper
422          * name by a java.io.File.separator.
423          * 
424          * The proper file name includes the suffix extension (e.g. ".java")
425          * 
426          * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
427          */
428
429         public char[] getFileName() {
430                 return fileName;
431         }
432
433         public ReferenceBinding getMemberType(char[] typeName) {
434                 ReferenceBinding[] memberTypes = memberTypes();
435                 for (int i = memberTypes.length; --i >= 0;)
436                         if (CharOperation.equals(memberTypes[i].sourceName, typeName))
437                                 return memberTypes[i];
438                 return null;
439         }
440
441         public MethodBinding[] getMethods(char[] selector) {
442                 return NoMethods;
443         }
444
445         public PackageBinding getPackage() {
446                 return fPackage;
447         }
448
449         /*
450          * Answer true if the receiver implements anInterface or is identical to
451          * anInterface. If searchHierarchy is true, then also search the receiver's
452          * superclasses.
453          * 
454          * NOTE: Assume that anInterface is an interface.
455          */
456
457         public boolean implementsInterface(ReferenceBinding anInterface,
458                         boolean searchHierarchy) {
459                 if (this == anInterface)
460                         return true;
461
462                 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
463                 int lastPosition = -1;
464                 ReferenceBinding currentType = this;
465                 do {
466                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
467                         if (itsInterfaces != NoSuperInterfaces) {
468                                 if (++lastPosition == interfacesToVisit.length)
469                                         System
470                                                         .arraycopy(
471                                                                         interfacesToVisit,
472                                                                         0,
473                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
474                                                                         0, lastPosition);
475                                 interfacesToVisit[lastPosition] = itsInterfaces;
476                         }
477                 } while (searchHierarchy
478                                 && (currentType = currentType.superclass()) != null);
479
480                 for (int i = 0; i <= lastPosition; i++) {
481                         ReferenceBinding[] interfaces = interfacesToVisit[i];
482                         for (int j = 0, length = interfaces.length; j < length; j++) {
483                                 if ((currentType = interfaces[j]) == anInterface)
484                                         return true;
485
486                                 ReferenceBinding[] itsInterfaces = currentType
487                                                 .superInterfaces();
488                                 if (itsInterfaces != NoSuperInterfaces) {
489                                         if (++lastPosition == interfacesToVisit.length)
490                                                 System
491                                                                 .arraycopy(
492                                                                                 interfacesToVisit,
493                                                                                 0,
494                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
495                                                                                 0, lastPosition);
496                                         interfacesToVisit[lastPosition] = itsInterfaces;
497                                 }
498                         }
499                 }
500                 return false;
501         }
502
503         // Internal method... assume its only sent to classes NOT interfaces
504
505         boolean implementsMethod(MethodBinding method) {
506                 ReferenceBinding type = this;
507                 while (type != null) {
508                         MethodBinding[] methods = type.getMethods(method.selector);
509                         for (int i = methods.length; --i >= 0;)
510                                 if (methods[i].areParametersEqual(method))
511                                         return true;
512                         type = type.superclass();
513                 }
514                 return false;
515         }
516
517         /*
518          * Answer true if the receiver is an abstract type
519          */
520
521         public final boolean isAbstract() {
522                 return (modifiers & AccAbstract) != 0;
523         }
524
525         public final boolean isAnonymousType() {
526                 return (tagBits & IsAnonymousType) != 0;
527         }
528
529         public final boolean isBinaryBinding() {
530                 return (tagBits & IsBinaryBinding) != 0;
531         }
532
533         public final boolean isClass() {
534                 return (modifiers & AccInterface) == 0;
535         }
536
537         /*
538          * Answer true if the receiver type can be assigned to the argument type
539          * (right)
540          */
541
542         public boolean isCompatibleWith(TypeBinding right) {
543                 if (right == this)
544                         return true;
545                 if (right.id == T_Object)
546                         return true;
547                 if (!(right instanceof ReferenceBinding))
548                         return false;
549
550                 ReferenceBinding referenceBinding = (ReferenceBinding) right;
551                 if (referenceBinding.isInterface())
552                         return implementsInterface(referenceBinding, true);
553                 if (isInterface()) // Explicit conversion from an interface to a class
554                                                         // is not allowed
555                         return false;
556                 return referenceBinding.isSuperclassOf(this);
557         }
558
559         /*
560          * Answer true if the receiver has default visibility
561          */
562
563         public final boolean isDefault() {
564                 return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
565         }
566
567         /*
568          * Answer true if the receiver is a deprecated type
569          */
570
571         public final boolean isDeprecated() {
572                 return (modifiers & AccDeprecated) != 0;
573         }
574
575         /*
576          * Answer true if the receiver is final and cannot be subclassed
577          */
578
579         public final boolean isFinal() {
580                 return (modifiers & AccFinal) != 0;
581         }
582
583         public final boolean isInterface() {
584                 return (modifiers & AccInterface) != 0;
585         }
586
587         public final boolean isLocalType() {
588                 return (tagBits & IsLocalType) != 0;
589         }
590
591         public final boolean isMemberType() {
592                 return (tagBits & IsMemberType) != 0;
593         }
594
595         public final boolean isNestedType() {
596                 return (tagBits & IsNestedType) != 0;
597         }
598
599         /*
600          * Answer true if the receiver has private visibility
601          */
602
603         public final boolean isPrivate() {
604                 return (modifiers & AccPrivate) != 0;
605         }
606
607         /*
608          * Answer true if the receiver has private visibility and is used locally
609          */
610
611         public final boolean isPrivateUsed() {
612                 return (modifiers & AccPrivateUsed) != 0;
613         }
614
615         /*
616          * Answer true if the receiver has protected visibility
617          */
618
619         public final boolean isProtected() {
620                 return (modifiers & AccProtected) != 0;
621         }
622
623         /*
624          * Answer true if the receiver has public visibility
625          */
626
627         public final boolean isPublic() {
628                 return (modifiers & AccPublic) != 0;
629         }
630
631         /*
632          * Answer true if the receiver is a static member type (or toplevel)
633          */
634
635         public final boolean isStatic() {
636                 return (modifiers & (AccStatic | AccInterface)) != 0
637                                 || (tagBits & IsNestedType) == 0;
638         }
639
640         /*
641          * Answer true if all float operations must adher to IEEE 754 float/double
642          * rules
643          */
644
645         // public final boolean isStrictfp() {
646         // return (modifiers & AccStrictfp) != 0;
647         // }
648         /*
649          * Answer true if the receiver is in the superclass hierarchy of aType
650          * 
651          * NOTE: Object.isSuperclassOf(Object) -> false
652          */
653
654         public boolean isSuperclassOf(ReferenceBinding type) {
655                 do {
656                         if (this == (type = type.superclass()))
657                                 return true;
658                 } while (type != null);
659
660                 return false;
661         }
662
663         /*
664          * Answer true if the receiver is deprecated (or any of its enclosing types)
665          */
666
667         public final boolean isViewedAsDeprecated() {
668                 return (modifiers & AccDeprecated) != 0
669                                 || (modifiers & AccDeprecatedImplicitly) != 0;
670         }
671
672         public ReferenceBinding[] memberTypes() {
673                 return NoMemberTypes;
674         }
675
676         public MethodBinding[] methods() {
677                 return NoMethods;
678         }
679
680         /**
681          * Answer the source name for the type. In the case of member types, as the
682          * qualified name from its top level type. For example, for a member type N
683          * defined inside M & A: "A.M.N".
684          */
685
686         public char[] qualifiedSourceName() {
687                 if (isMemberType()) {
688                         return CharOperation.concat(enclosingType().qualifiedSourceName(),
689                                         sourceName(), '.');
690                 } else {
691                         return sourceName();
692                 }
693         }
694
695         public char[] readableName() /* java.lang.Object */{
696                 if (isMemberType())
697                         return CharOperation.concat(enclosingType().readableName(),
698                                         sourceName, '.');
699                 else
700                         return CharOperation.concatWith(compoundName, '.');
701         }
702
703         public char[] shortReadableName() /* Object */{
704                 if (isMemberType())
705                         return CharOperation.concat(enclosingType().shortReadableName(),
706                                         sourceName, '.');
707                 else
708                         return sourceName;
709         }
710
711         /*
712          * Answer the receiver's signature.
713          * 
714          * NOTE: This method should only be used during/after code gen.
715          */
716
717         public char[] signature() /* Ljava/lang/Object; */{
718                 if (signature != null)
719                         return signature;
720
721                 return signature = CharOperation.concat('L', constantPoolName(), ';');
722         }
723
724         public char[] sourceName() {
725                 return sourceName;
726         }
727
728         public ReferenceBinding superclass() {
729                 return null;
730         }
731
732         public ReferenceBinding[] superInterfaces() {
733                 return NoSuperInterfaces;
734         }
735
736         public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
737                 if (isStatic())
738                         return null;
739
740                 ReferenceBinding enclosingType = enclosingType();
741                 if (enclosingType == null)
742                         return null;
743                 else
744                         return new ReferenceBinding[] { enclosingType };
745         }
746
747         public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
748                 return null; // is null if no enclosing instances are required
749         }
750 }