added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / ArrayBinding.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.impl.Constant;
16
17 public final class ArrayBinding extends TypeBinding {
18         // creation and initialization of the length field
19         // the declaringClass of this field is intentionally set to null so it can be distinguished.
20         public static final FieldBinding ArrayLength = new FieldBinding(LENGTH, IntBinding, AccPublic | AccFinal, null, Constant.NotAConstant);
21
22         public TypeBinding leafComponentType;
23         public int dimensions;
24         LookupEnvironment environment;  
25         char[] constantPoolName;
26         char[] genericTypeSignature;
27         
28 public ArrayBinding(TypeBinding type, int dimensions, LookupEnvironment environment) {
29         this.tagBits |= IsArrayType;
30         this.leafComponentType = type;
31         this.dimensions = dimensions;
32         this.environment = environment;
33         if (type instanceof UnresolvedReferenceBinding)
34                 ((UnresolvedReferenceBinding) type).addWrapper(this);
35         else
36         this.tagBits |= type.tagBits & (HasTypeVariable | HasDirectWildcard);
37 }
38
39 public int kind() {
40         return ARRAY_TYPE;
41 }
42
43 /**
44  * Collect the substitutes into a map for certain type variables inside the receiver type
45  * e.g.   Collection<T>.findSubstitute(T, Collection<List<X>>):   T --> List<X>
46  */
47 public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
48     if (otherType.isArrayType()) {
49         int otherDim = otherType.dimensions();
50         if (otherDim == this.dimensions) {
51                     this.leafComponentType.collectSubstitutes(otherType.leafComponentType(), substitutes);
52         } else if (otherDim > this.dimensions) {
53             ArrayBinding otherReducedType = this.environment.createArrayType(otherType.leafComponentType(), otherDim - this.dimensions);
54             this.leafComponentType.collectSubstitutes(otherReducedType, substitutes);
55         }
56     } 
57 }
58
59 /*
60  * brakets leafUniqueKey
61  * p.X[][] --> [[Lp/X;
62  */
63 public char[] computeUniqueKey() {
64         char[] brackets = new char[dimensions];
65         for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
66         return CharOperation.concat(brackets, this.leafComponentType.computeUniqueKey());
67  }
68         
69 /**
70  * Answer the receiver's constant pool name.
71  * NOTE: This method should only be used during/after code gen.
72  * e.g. '[Ljava/lang/Object;'
73  */
74 public char[] constantPoolName() {
75         if (constantPoolName != null)
76                 return constantPoolName;
77
78         char[] brackets = new char[dimensions];
79         for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
80         return constantPoolName = CharOperation.concat(brackets, leafComponentType.signature());
81 }
82 public String debugName() {
83         StringBuffer brackets = new StringBuffer(dimensions * 2);
84         for (int i = dimensions; --i >= 0;)
85                 brackets.append("[]"); //$NON-NLS-1$
86         return leafComponentType.debugName() + brackets.toString();
87 }
88 public int dimensions() {
89         return this.dimensions;
90 }
91
92 /* Answer an array whose dimension size is one less than the receiver.
93 *
94 * When the receiver's dimension size is one then answer the leaf component type.
95 */
96
97 public TypeBinding elementsType() {
98         if (this.dimensions == 1) return this.leafComponentType;
99         return this.environment.createArrayType(this.leafComponentType, this.dimensions - 1);
100 }
101 /**
102  * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
103  */
104 public TypeBinding erasure() {
105     TypeBinding erasedType = this.leafComponentType.erasure();
106     if (this.leafComponentType != erasedType)
107         return this.environment.createArrayType(erasedType, this.dimensions);
108     return this;
109 }
110 public LookupEnvironment environment() {
111     return this.environment;
112 }
113
114 public char[] genericTypeSignature() {
115         
116     if (this.genericTypeSignature == null) {
117                 char[] brackets = new char[dimensions];
118                 for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
119                 this.genericTypeSignature = CharOperation.concat(brackets, leafComponentType.genericTypeSignature());
120     }
121     return this.genericTypeSignature;
122 }
123
124 public PackageBinding getPackage() {
125         return leafComponentType.getPackage();
126 }
127 public int hashCode() {
128         return this.leafComponentType == null ? super.hashCode() : this.leafComponentType.hashCode();
129 }
130 /* Answer true if the receiver type can be assigned to the argument type (right)
131 */
132 public boolean isCompatibleWith(TypeBinding right) {
133         if (this == right)
134                 return true;
135
136         if (right.isArrayType()) {
137                 ArrayBinding rightArray = (ArrayBinding) right;
138                 if (rightArray.leafComponentType.isBaseType())
139                         return false; // relying on the fact that all equal arrays are identical
140                 if (dimensions == rightArray.dimensions)
141                         return leafComponentType.isCompatibleWith(rightArray.leafComponentType);
142                 if (dimensions < rightArray.dimensions)
143                         return false; // cannot assign 'String[]' into 'Object[][]' but can assign 'byte[][]' into 'Object[]'
144         } else {
145                 if (right.isBaseType())
146                         return false;
147                 if (right.isWildcard()) {
148                     return ((WildcardBinding) right).boundCheck(this);
149                 }
150         }
151         //Check dimensions - Java does not support explicitly sized dimensions for types.
152         //However, if it did, the type checking support would go here.
153         switch (right.leafComponentType().id) {
154             case T_JavaLangObject :
155             case T_JavaLangCloneable :
156             case T_JavaIoSerializable :
157                 return true;
158         }
159         return false;
160 }
161
162 public TypeBinding leafComponentType(){
163         return leafComponentType;
164 }
165
166 /* API
167 * Answer the problem id associated with the receiver.
168 * NoError if the receiver is a valid binding.
169 */
170
171 public int problemId() {
172         return leafComponentType.problemId();
173 }
174 /**
175 * Answer the source name for the type.
176 * In the case of member types, as the qualified name from its top level type.
177 * For example, for a member type N defined inside M & A: "A.M.N".
178 */
179
180 public char[] qualifiedSourceName() {
181         char[] brackets = new char[dimensions * 2];
182         for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
183                 brackets[i] = ']';
184                 brackets[i - 1] = '[';
185         }
186         return CharOperation.concat(leafComponentType.qualifiedSourceName(), brackets);
187 }
188 public char[] readableName() /* java.lang.Object[] */ {
189         char[] brackets = new char[dimensions * 2];
190         for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
191                 brackets[i] = ']';
192                 brackets[i - 1] = '[';
193         }
194         return CharOperation.concat(leafComponentType.readableName(), brackets);
195 }
196 public char[] shortReadableName(){
197         char[] brackets = new char[dimensions * 2];
198         for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
199                 brackets[i] = ']';
200                 brackets[i - 1] = '[';
201         }
202         return CharOperation.concat(leafComponentType.shortReadableName(), brackets);
203 }
204 public char[] sourceName() {
205         char[] brackets = new char[dimensions * 2];
206         for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
207                 brackets[i] = ']';
208                 brackets[i - 1] = '[';
209         }
210         return CharOperation.concat(leafComponentType.sourceName(), brackets);
211 }
212 public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
213         if (this.leafComponentType == unresolvedType) {
214                 this.leafComponentType = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
215                 this.tagBits |= this.leafComponentType.tagBits & (HasTypeVariable | HasDirectWildcard);
216         }
217 }
218 public String toString() {
219         return leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
220 }
221 }