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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
14 import org.eclipse.jdt.core.compiler.CharOperation;
15 import org.eclipse.jdt.internal.compiler.impl.Constant;
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);
22 public TypeBinding leafComponentType;
23 public int dimensions;
24 LookupEnvironment environment;
25 char[] constantPoolName;
26 char[] genericTypeSignature;
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);
36 this.tagBits |= type.tagBits & (HasTypeVariable | HasDirectWildcard);
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>
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);
60 * brakets leafUniqueKey
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());
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;'
74 public char[] constantPoolName() {
75 if (constantPoolName != null)
76 return constantPoolName;
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());
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();
88 public int dimensions() {
89 return this.dimensions;
92 /* Answer an array whose dimension size is one less than the receiver.
94 * When the receiver's dimension size is one then answer the leaf component type.
97 public TypeBinding elementsType() {
98 if (this.dimensions == 1) return this.leafComponentType;
99 return this.environment.createArrayType(this.leafComponentType, this.dimensions - 1);
102 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
104 public TypeBinding erasure() {
105 TypeBinding erasedType = this.leafComponentType.erasure();
106 if (this.leafComponentType != erasedType)
107 return this.environment.createArrayType(erasedType, this.dimensions);
110 public LookupEnvironment environment() {
111 return this.environment;
114 public char[] genericTypeSignature() {
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());
121 return this.genericTypeSignature;
124 public PackageBinding getPackage() {
125 return leafComponentType.getPackage();
127 public int hashCode() {
128 return this.leafComponentType == null ? super.hashCode() : this.leafComponentType.hashCode();
130 /* Answer true if the receiver type can be assigned to the argument type (right)
132 public boolean isCompatibleWith(TypeBinding right) {
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[]'
145 if (right.isBaseType())
147 if (right.isWildcard()) {
148 return ((WildcardBinding) right).boundCheck(this);
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 :
162 public TypeBinding leafComponentType(){
163 return leafComponentType;
167 * Answer the problem id associated with the receiver.
168 * NoError if the receiver is a valid binding.
171 public int problemId() {
172 return leafComponentType.problemId();
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".
180 public char[] qualifiedSourceName() {
181 char[] brackets = new char[dimensions * 2];
182 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
184 brackets[i - 1] = '[';
186 return CharOperation.concat(leafComponentType.qualifiedSourceName(), brackets);
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) {
192 brackets[i - 1] = '[';
194 return CharOperation.concat(leafComponentType.readableName(), brackets);
196 public char[] shortReadableName(){
197 char[] brackets = new char[dimensions * 2];
198 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
200 brackets[i - 1] = '[';
202 return CharOperation.concat(leafComponentType.shortReadableName(), brackets);
204 public char[] sourceName() {
205 char[] brackets = new char[dimensions * 2];
206 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
208 brackets[i - 1] = '[';
210 return CharOperation.concat(leafComponentType.sourceName(), brackets);
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);
218 public String toString() {
219 return leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$