Fix bug #672
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / ArrayBinding.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.impl.Constant;
15
16 public final class ArrayBinding extends TypeBinding {
17         // creation and initialization of the length field
18         // the declaringClass of this field is intentionally set to null so it can
19         // be distinguished.
20         public static final FieldBinding LengthField = new FieldBinding(LENGTH,
21                         IntBinding, AccPublic | AccFinal, null, Constant.NotAConstant);
22
23         public TypeBinding leafComponentType;
24
25         public int dimensions;
26
27         char[] constantPoolName;
28
29         public ArrayBinding(TypeBinding type, int dimensions) {
30                 this.tagBits |= IsArrayType;
31                 this.leafComponentType = type;
32                 this.dimensions = dimensions;
33         }
34
35         /*
36          * Answer the receiver's constant pool name.
37          * 
38          * NOTE: This method should only be used during/after code gen.
39          */
40
41         public char[] constantPoolName() /* [Ljava/lang/Object; */{
42                 if (constantPoolName != null)
43                         return constantPoolName;
44
45                 char[] brackets = new char[dimensions];
46                 for (int i = dimensions - 1; i >= 0; i--)
47                         brackets[i] = '[';
48                 return constantPoolName = CharOperation.concat(brackets,
49                                 leafComponentType.signature());
50         }
51
52         String debugName() {
53                 StringBuffer brackets = new StringBuffer(dimensions * 2);
54                 for (int i = dimensions; --i >= 0;)
55                         brackets.append("[]"); //$NON-NLS-1$
56                 return leafComponentType.debugName() + brackets.toString();
57         }
58
59         public int dimensions() {
60                 return this.dimensions;
61         }
62
63         /*
64          * Answer an array whose dimension size is one less than the receiver.
65          * 
66          * When the receiver's dimension size is one then answer the leaf component
67          * type.
68          */
69
70         public TypeBinding elementsType(Scope scope) {
71                 if (dimensions == 1)
72                         return leafComponentType;
73                 else
74                         return scope.createArray(leafComponentType, dimensions - 1);
75         }
76
77         public PackageBinding getPackage() {
78                 return leafComponentType.getPackage();
79         }
80
81         /*
82          * Answer true if the receiver type can be assigned to the argument type
83          * (right)
84          */
85
86         public boolean isCompatibleWith(TypeBinding right) {
87                 if (this == right)
88                         return true;
89
90                 char[][] rightName;
91                 if (right.isArrayType()) {
92                         ArrayBinding rightArray = (ArrayBinding) right;
93                         if (rightArray.leafComponentType.isBaseType())
94                                 return false; // relying on the fact that all equal arrays are
95                                                                 // identical
96                         if (dimensions == rightArray.dimensions)
97                                 return leafComponentType
98                                                 .isCompatibleWith(rightArray.leafComponentType);
99                         if (dimensions < rightArray.dimensions)
100                                 return false; // cannot assign 'String[]' into 'Object[][]'
101                                                                 // but can assign 'byte[][]' into 'Object[]'
102                         rightName = ((ReferenceBinding) rightArray.leafComponentType).compoundName;
103                 } else {
104                         if (right.isBaseType())
105                                 return false;
106                         rightName = ((ReferenceBinding) right).compoundName;
107                 }
108                 // Check dimensions - Java does not support explicitly sized dimensions
109                 // for types.
110                 // However, if it did, the type checking support would go here.
111
112                 if (CharOperation.equals(rightName, JAVA_LANG_OBJECT))
113                         return true;
114                 if (CharOperation.equals(rightName, JAVA_LANG_CLONEABLE))
115                         return true;
116                 if (CharOperation.equals(rightName, JAVA_IO_SERIALIZABLE))
117                         return true;
118                 return false;
119         }
120
121         public TypeBinding leafComponentType() {
122                 return leafComponentType;
123         }
124
125         /*
126          * API Answer the problem id associated with the receiver. NoError if the
127          * receiver is a valid binding.
128          */
129
130         public int problemId() {
131                 return leafComponentType.problemId();
132         }
133
134         /**
135          * Answer the source name for the type. In the case of member types, as the
136          * qualified name from its top level type. For example, for a member type N
137          * defined inside M & A: "A.M.N".
138          */
139
140         public char[] qualifiedSourceName() {
141                 char[] brackets = new char[dimensions * 2];
142                 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
143                         brackets[i] = ']';
144                         brackets[i - 1] = '[';
145                 }
146                 return CharOperation.concat(leafComponentType.qualifiedSourceName(),
147                                 brackets);
148         }
149
150         public char[] readableName() /* java.lang.Object[] */{
151                 char[] brackets = new char[dimensions * 2];
152                 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
153                         brackets[i] = ']';
154                         brackets[i - 1] = '[';
155                 }
156                 return CharOperation.concat(leafComponentType.readableName(), brackets);
157         }
158
159         public char[] shortReadableName() {
160                 char[] brackets = new char[dimensions * 2];
161                 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
162                         brackets[i] = ']';
163                         brackets[i - 1] = '[';
164                 }
165                 return CharOperation.concat(leafComponentType.shortReadableName(),
166                                 brackets);
167         }
168
169         public char[] sourceName() {
170                 char[] brackets = new char[dimensions * 2];
171                 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
172                         brackets[i] = ']';
173                         brackets[i - 1] = '[';
174                 }
175                 return CharOperation.concat(leafComponentType.sourceName(), brackets);
176         }
177
178         public String toString() {
179                 return leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
180         }
181 }