added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / TypeBinding.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
12
13 import java.util.Map;
14 import org.eclipse.jdt.core.compiler.CharOperation;
15 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
16
17 /*
18  * Not all fields defined by this type (& its subclasses) are initialized when it is created.
19  * Some are initialized only when needed.
20  *
21  * Accessors have been provided for some public fields so all TypeBindings have the same API...
22  * but access public fields directly whenever possible.
23  * Non-public fields have accessors which should be used everywhere you expect the field to be initialized.
24  *
25  * null is NOT a valid value for a non-public field... it just means the field is not initialized.
26  */
27 abstract public class TypeBinding extends Binding implements BaseTypes, TagBits, TypeConstants, TypeIds {
28         public int id = NoId;
29         public long tagBits = 0; // See values in the interface TagBits below
30 /**
31  * Match a well-known type id to its binding
32  */
33 public static final TypeBinding wellKnownType(Scope scope, int id) {
34                 switch (id) { 
35                         case T_boolean :
36                                 return BooleanBinding;
37                         case T_byte :
38                                 return ByteBinding;
39                         case T_char :
40                                 return CharBinding;
41                         case T_short :
42                                 return ShortBinding;
43                         case T_double :
44                                 return DoubleBinding;
45                         case T_float :
46                                 return FloatBinding;
47                         case T_int :
48                                 return IntBinding;
49                         case T_long :
50                                 return LongBinding;
51                         case T_JavaLangObject :
52                                 return scope.getJavaLangObject();
53                         case T_JavaLangString :
54                                 return scope.getJavaLangString();
55                         default : 
56                                 return null;
57                 }
58         }
59 /* API
60  * Answer the receiver's binding type from Binding.BindingID.
61  */
62
63 public int kind() {
64         return Binding.TYPE;
65 }
66 /* Answer true if the receiver can be instantiated
67  */
68 public boolean canBeInstantiated() {
69         return !isBaseType();
70 }
71 /**
72  * Collect the substitutes into a map for certain type variables inside the receiver type
73  * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
74  */
75 public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
76     // no substitute by default
77 }
78 /*
79  * genericTypeSignature
80  */
81 public char[] computeUniqueKey() {
82         return genericTypeSignature();
83 }
84 /**
85  *  Answer the receiver's constant pool name.
86  *  NOTE: This method should only be used during/after code gen.
87  *  e.g. 'java/lang/Object' 
88  */
89 public abstract char[] constantPoolName();
90
91 public String debugName() {
92         return new String(readableName());
93 }
94 /*
95  * Answer the receiver's dimensions - 0 for non-array types
96  */
97 public int dimensions(){
98         return 0;
99 }
100 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
101 */
102
103 public ReferenceBinding enclosingType() {
104         return null;
105 }
106 public TypeBinding erasure() {
107     return this;
108 }
109 /**
110  * Returns the type to use for generic cast, or null if none required
111  */
112 public TypeBinding genericCast(TypeBinding otherType) {
113     if (this == otherType) return null;
114         if (otherType.isWildcard() && ((WildcardBinding)otherType).kind != Wildcard.EXTENDS) return null;
115         TypeBinding otherErasure = otherType.erasure();
116         if (otherErasure == this.erasure()) return null;
117         return otherErasure;
118 }
119
120 /**
121  * Answer the receiver classfile signature.
122  * Arrays & base types do not distinguish between signature() & constantPoolName().
123  * NOTE: This method should only be used during/after code gen.
124  */
125 public char[] genericTypeSignature() {
126     return signature();
127 }
128 public abstract PackageBinding getPackage();
129 public boolean isAnnotationType() {
130         return false;
131 }
132 /* Answer true if the receiver is an array
133 */
134 public final boolean isArrayType() {
135         return (tagBits & IsArrayType) != 0;
136 }
137 /* Answer true if the receiver is a base type
138 */
139 public final boolean isBaseType() {
140         return (tagBits & IsBaseType) != 0;
141 }
142
143         
144 /**
145  *  Returns true if parameterized type AND not of the form List<?>
146  */
147 public boolean isBoundParameterizedType() {
148         return (this.tagBits & TagBits.IsBoundParameterizedType) != 0;
149 }
150 public boolean isClass() {
151         return false;
152 }
153 /* Answer true if the receiver type can be assigned to the argument type (right)
154 */
155 public abstract boolean isCompatibleWith(TypeBinding right);
156
157 public boolean isEnum() {
158         return false;
159 }
160 /**
161  * Returns true if a type is identical to another one,
162  * or for generic types, true if compared to its raw type.
163  */
164 public boolean isEquivalentTo(TypeBinding otherType) {
165     if (this == otherType) return true;
166     if (otherType == null) return false;
167     if (otherType.isWildcard()) // wildcard
168                 return ((WildcardBinding) otherType).boundCheck(this);
169         return false;
170 }
171
172 public boolean isGenericType() {
173     return false;
174 }
175
176 /* Answer true if the receiver's hierarchy has problems (always false for arrays & base types)
177 */
178 public final boolean isHierarchyInconsistent() {
179         return (tagBits & HierarchyHasProblems) != 0;
180 }
181 public boolean isInterface() {
182         return false;
183 }
184 public final boolean isLocalType() {
185         return (tagBits & IsLocalType) != 0;
186 }
187
188 public final boolean isMemberType() {
189         return (tagBits & IsMemberType) != 0;
190 }
191
192 public final boolean isNestedType() {
193         return (tagBits & IsNestedType) != 0;
194 }
195 public final boolean isNumericType() {
196         switch (id) {
197                 case T_int :
198                 case T_float :
199                 case T_double :
200                 case T_short :
201                 case T_byte :
202                 case T_long :
203                 case T_char :
204                         return true;
205                 default :
206                         return false;
207         }
208 }
209
210 /**
211  * Returns true if the type is parameterized, e.g. List<String>
212  */
213 public boolean isParameterizedType() {
214     return false;
215 }
216         
217 public boolean isPartOfRawType() {
218         TypeBinding current = this;
219         do {
220                 if (current.isRawType())
221                         return true;
222         } while ((current = current.enclosingType()) != null);
223     return false;
224 }
225
226 /**
227  * Returns true if the two types are statically known to be different at compile-time,
228  * e.g. a type variable is not probably known to be distinct from another type
229  */
230 public boolean isProvablyDistinctFrom(TypeBinding otherType, int depth) {
231         if (this == otherType) return false;
232         if (depth > 1) return true;
233         switch (otherType.kind()) {
234                 case Binding.TYPE_PARAMETER :
235                 case Binding.WILDCARD_TYPE :
236                         return false;
237         }
238         switch(kind()) {
239                 
240                 case Binding.TYPE_PARAMETER :
241                 case Binding.WILDCARD_TYPE :
242                         return false;
243                         
244                 case Binding.PARAMETERIZED_TYPE :
245                         ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this;
246                         if (parameterizedType.type.isProvablyDistinctFrom(otherType.erasure(), depth)) return true;
247                         switch (otherType.kind()) {
248                                 case Binding.GENERIC_TYPE :
249                                 case Binding.RAW_TYPE :
250                                         return false;
251                                 case Binding.PARAMETERIZED_TYPE :
252                                         TypeBinding[] arguments = parameterizedType.arguments;
253                                         if (arguments == null) return false;
254                                         ParameterizedTypeBinding otherParameterizedType = (ParameterizedTypeBinding) otherType;
255                                         TypeBinding[] otherArguments = otherParameterizedType.arguments;
256                                         if (otherArguments == null) return false;
257                                         for (int i = 0, length = arguments.length; i < length; i++) {
258                                                 if (arguments[i].isProvablyDistinctFrom(otherArguments[i], depth+1)) return true;
259                                         }
260                                         return false;
261                                         
262                         }
263                         break;
264
265                 case Binding.RAW_TYPE :
266                         return this.erasure().isProvablyDistinctFrom(otherType.erasure(), 0);
267                         
268                 case Binding.GENERIC_TYPE :
269                         return this != otherType.erasure();
270         }
271         return this != otherType;
272 }
273
274 public boolean isRawType() {
275     return false;
276 }
277
278 /**
279  * JLS(3) 4.7
280  */
281 public boolean isReifiable() {
282         
283         TypeBinding leafType = leafComponentType();
284         if (!(leafType instanceof ReferenceBinding)) 
285                 return true;
286         ReferenceBinding current = (ReferenceBinding) leafType;
287         do {
288                 switch(current.kind()) {
289                         
290                         case Binding.TYPE_PARAMETER :
291                         case Binding.WILDCARD_TYPE :
292                         case Binding.GENERIC_TYPE :
293                                 return false;
294                                 
295                         case Binding.PARAMETERIZED_TYPE :
296                                 if (isBoundParameterizedType()) 
297                                         return false;
298                                 break;
299                                 
300                         case Binding.RAW_TYPE :
301                                 return true;
302                 }
303                 if (current.isStatic()) 
304                         return true;
305         } while ((current = current.enclosingType()) != null);
306         return true;
307 }
308
309 // JLS3: 4.5.1.1
310 public boolean isTypeArgumentContainedBy(TypeBinding otherArgument) {
311         if (this == otherArgument)
312                 return true;
313         TypeBinding lowerBound = this;
314         TypeBinding upperBound = this;
315         if (isWildcard()) {
316                 WildcardBinding wildcard = (WildcardBinding) this;
317                 switch(wildcard.kind) {
318                         case Wildcard.EXTENDS :
319                                 upperBound = wildcard.bound;
320                                 lowerBound = null;
321                                 break;
322                         case Wildcard. SUPER :
323                                 upperBound = wildcard.typeVariable();
324                                 lowerBound = wildcard.bound;
325                                 break;
326                         case Wildcard.UNBOUND :
327                                 upperBound = wildcard.typeVariable();
328                                 lowerBound = null;
329                 }
330         }
331         if (otherArgument.isWildcard()) {
332                 WildcardBinding otherWildcard = (WildcardBinding) otherArgument;
333                 switch(otherWildcard.kind) {
334                         case Wildcard.EXTENDS:
335                                 return upperBound != null && upperBound.isCompatibleWith(otherWildcard.bound);
336
337                         case Wildcard.SUPER :
338                                 return lowerBound != null && otherWildcard.bound.isCompatibleWith(lowerBound);
339
340                         case Wildcard.UNBOUND :
341                                 return true;
342                 }
343         }
344         return false;
345 }
346
347 /**
348  * Returns true if the type was declared as a type variable
349  */
350 public boolean isTypeVariable() {
351     return false;
352 }
353 /**
354  * Returns true if wildcard type of the form '?' (no bound)
355  */
356 public boolean isUnboundWildcard() {
357         return false;
358 }
359
360 /**
361  * Returns true if the type is a wildcard
362  */
363 public boolean isWildcard() {
364     return false;
365 }
366         
367 /**
368  * Meant to be invoked on compatible types, to figure if unchecked conversion is necessary
369  */
370 public boolean needsUncheckedConversion(TypeBinding targetType) {
371         return false;
372 }
373
374 public TypeBinding leafComponentType(){
375         return this;
376 }
377
378 /**
379  * Answer the qualified name of the receiver's package separated by periods
380  * or an empty string if its the default package.
381  *
382  * For example, {java.util.Hashtable}.
383  */
384
385 public char[] qualifiedPackageName() {
386         PackageBinding packageBinding = getPackage();
387         return packageBinding == null  || packageBinding.compoundName == CharOperation.NO_CHAR_CHAR
388                 ? CharOperation.NO_CHAR
389                 : packageBinding.readableName();
390 }
391 /**
392 * Answer the source name for the type.
393 * In the case of member types, as the qualified name from its top level type.
394 * For example, for a member type N defined inside M & A: "A.M.N".
395 */
396
397 public abstract char[] qualifiedSourceName();
398
399 /**
400  * Answer the receiver classfile signature.
401  * Arrays & base types do not distinguish between signature() & constantPoolName().
402  * NOTE: This method should only be used during/after code gen.
403  */
404 public char[] signature() {
405         return constantPoolName();
406 }
407
408 public abstract char[] sourceName();
409
410 public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment environment) {
411         // subclasses must override if they wrap another type binding
412 }
413 public TypeVariableBinding[] typeVariables() {
414         return NoTypeVariables;
415 }
416 }