A variable description (like PHPFunctionDeclaration)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / classfmt / FieldInfo.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.classfmt;
12
13 import net.sourceforge.phpdt.internal.compiler.codegen.AttributeNamesConstants;
14 import net.sourceforge.phpdt.internal.compiler.env.IBinaryField;
15 import net.sourceforge.phpdt.internal.compiler.impl.BooleanConstant;
16 import net.sourceforge.phpdt.internal.compiler.impl.ByteConstant;
17 import net.sourceforge.phpdt.internal.compiler.impl.CharConstant;
18 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
19 import net.sourceforge.phpdt.internal.compiler.impl.DoubleConstant;
20 import net.sourceforge.phpdt.internal.compiler.impl.FloatConstant;
21 import net.sourceforge.phpdt.internal.compiler.impl.IntConstant;
22 import net.sourceforge.phpdt.internal.compiler.impl.LongConstant;
23 import net.sourceforge.phpdt.internal.compiler.impl.ShortConstant;
24 import net.sourceforge.phpdt.internal.compiler.impl.StringConstant;
25 import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
26 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
27
28 public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
29         private Constant constant;
30         private boolean isDeprecated;
31         private boolean isSynthetic;
32         private int[] constantPoolOffsets;
33         private int accessFlags;
34         private char[] name;
35         private char[] signature;
36         private int attributesCount;
37         private int attributeBytes;
38         private Object wrappedConstantValue;
39 /**
40  * @param classFileBytes byte[]
41  * @param offsets int[]
42  * @param offset int
43  */
44 public FieldInfo (byte classFileBytes[], int offsets[], int offset) throws ClassFormatException {
45         super(classFileBytes, offset);
46         constantPoolOffsets = offsets;
47         accessFlags = -1;
48         int attributesCount = u2At(6);
49         int readOffset = 8;
50         for (int i = 0; i < attributesCount; i++) {
51                 readOffset += (6 + u4At(readOffset + 2));
52         }
53         attributeBytes = readOffset;
54 }
55 /**
56  * Return the constant of the field.
57  * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
58  * @return org.eclipse.jdt.internal.compiler.impl.Constant
59  */
60 public Constant getConstant() {
61         if (constant == null) {
62                 // read constant
63                 readConstantAttribute();
64         }
65         return constant;
66 }
67 /**
68  * Answer an int whose bits are set according the access constants
69  * defined by the VM spec.
70  * Set the AccDeprecated and AccSynthetic bits if necessary
71  * @return int
72  */
73 public int getModifiers() {
74         if (accessFlags == -1) {
75                 // compute the accessflag. Don't forget the deprecated attribute
76                 accessFlags = u2At(0);
77                 readDeprecatedAndSyntheticAttributes();
78                 if (isDeprecated) {
79                         accessFlags |= AccDeprecated;
80                 }
81                 if (isSynthetic) {
82                         accessFlags |= AccSynthetic;
83                 }
84         }
85         return accessFlags;
86 }
87 /**
88  * Answer the name of the field.
89  * @return char[]
90  */
91 public char[] getName() {
92         if (name == null) {
93                 // read the name
94                 int utf8Offset = constantPoolOffsets[u2At(2)] - structOffset;
95                 name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
96         }
97         return name;
98 }
99 /**
100  * Answer the resolved name of the receiver's type in the
101  * class file format as specified in section 4.3.2 of the Java 2 VM spec.
102  *
103  * For example:
104  *   - java.lang.String is Ljava/lang/String;
105  *   - an int is I
106  *   - a 2 dimensional array of strings is [[Ljava/lang/String;
107  *   - an array of floats is [F
108  * @return char[]
109  */
110 public char[] getTypeName() {
111         if (signature == null) {
112                 // read the signature
113                 int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
114                 signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
115         }
116         return signature;
117 }
118 /**
119  * Return a wrapper that contains the constant of the field.
120  * Throws a java.ibm.compiler.java.classfmt.ClassFormatException in case the signature is 
121  * incompatible with the constant tag.
122  * 
123  * @exception java.ibm.compiler.java.classfmt.ClassFormatException
124  * @return java.lang.Object
125  */
126 public Object getWrappedConstantValue() throws ClassFormatException {
127
128         if (this.wrappedConstantValue == null) {
129                 if (hasConstant()) {
130                         Constant constant = getConstant();
131                         switch (constant.typeID()) {
132                                 case T_int :
133                                         this.wrappedConstantValue = new Integer(constant.intValue());
134                                         break;
135                                 case T_byte :
136                                         this.wrappedConstantValue = new Byte(constant.byteValue());
137                                         break;
138                                 case T_short :
139                                         this.wrappedConstantValue = new Short(constant.shortValue());
140                                         break;
141                                 case T_char :
142                                         this.wrappedConstantValue = new Character(constant.charValue());
143                                         break;
144                                 case T_float :
145                                         this.wrappedConstantValue = new Float(constant.floatValue());
146                                         break;
147                                 case T_double :
148                                         this.wrappedConstantValue = new Double(constant.doubleValue());
149                                         break;
150                                 case T_boolean :
151                                         this.wrappedConstantValue = new Boolean(constant.booleanValue());
152                                         break;
153                                 case T_long :
154                                         this.wrappedConstantValue = new Long(constant.longValue());
155                                         break;
156                                 case T_String :
157                                         this.wrappedConstantValue = constant.stringValue();
158                         }
159                 }
160         }
161         return this.wrappedConstantValue;
162 }
163 /**
164  * Return true if the field has a constant value attribute, false otherwise.
165  * @return boolean
166  */
167 public boolean hasConstant() {
168         return getConstant() != Constant.NotAConstant;
169 }
170 /**
171  * Return true if the field is a synthetic field, false otherwise.
172  * @return boolean
173  */
174 public boolean isSynthetic() {
175         return (getModifiers() & AccSynthetic) != 0;
176 }
177
178 private void readConstantAttribute() {
179         int attributesCount = u2At(6);
180         int readOffset = 8;
181         boolean isConstant = false;
182         for (int i = 0; i < attributesCount; i++) {
183                 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
184                 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
185                 if (CharOperation
186                         .equals(attributeName, ConstantValueName)) {
187                         isConstant = true;
188                         // read the right constant
189                         int relativeOffset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
190                         switch (u1At(relativeOffset)) {
191                                 case IntegerTag :
192                                         char[] sign = getTypeName();
193                                         if (sign.length == 1) {
194                                                 switch (sign[0]) {
195                                                         case 'Z' : // boolean constant
196                                                                 constant = new BooleanConstant(i4At(relativeOffset + 1) == 1);
197                                                                 break;
198                                                         case 'I' : // integer constant
199                                                                 constant = new IntConstant(i4At(relativeOffset + 1));
200                                                                 break;
201                                                         case 'C' : // char constant
202                                                                 constant = new CharConstant((char) i4At(relativeOffset + 1));
203                                                                 break;
204                                                         case 'B' : // byte constant
205                                                                 constant = new ByteConstant((byte) i4At(relativeOffset + 1));
206                                                                 break;
207                                                         case 'S' : // short constant
208                                                                 constant = new ShortConstant((short) i4At(relativeOffset + 1));
209                                                                 break;
210                                                         default:
211                                                                 constant = Constant.NotAConstant;                   
212                                                 }
213                                         } else {
214                                                 constant = Constant.NotAConstant;
215                                         }
216                                         break;
217                                 case FloatTag :
218                                         constant = new FloatConstant(floatAt(relativeOffset + 1));
219                                         break;
220                                 case DoubleTag :
221                                         constant = new DoubleConstant(doubleAt(relativeOffset + 1));
222                                         break;
223                                 case LongTag :
224                                         constant = new LongConstant(i8At(relativeOffset + 1));
225                                         break;
226                                 case StringTag :
227                                         utf8Offset = constantPoolOffsets[u2At(relativeOffset + 1)] - structOffset;
228                                         constant = 
229                                                 new StringConstant(
230                                                         String.valueOf(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)))); 
231                                         break;
232                         }
233                 }
234                 readOffset += (6 + u4At(readOffset + 2));
235         }
236         if (!isConstant) {
237                 constant = Constant.NotAConstant;
238         }
239 }
240 private void readDeprecatedAndSyntheticAttributes() {
241         int attributesCount = u2At(6);
242         int readOffset = 8;
243         for (int i = 0; i < attributesCount; i++) {
244                 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
245                 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
246                 if (CharOperation.equals(attributeName, DeprecatedName)) {
247                         isDeprecated = true;
248                 } else if (CharOperation.equals(attributeName, SyntheticName)) {
249                         isSynthetic = true;
250                 }
251                 readOffset += (6 + u4At(readOffset + 2));
252         }
253 }
254 /**
255  * Answer the size of the receiver in bytes.
256  * 
257  * @return int
258  */
259 public int sizeInBytes() {
260         return attributeBytes;
261 }
262 public void throwFormatException() throws ClassFormatException {
263         throw new ClassFormatException(ClassFormatException.ErrBadFieldInfo);
264 }
265 public String toString() {
266         StringBuffer buffer = new StringBuffer(this.getClass().getName());
267         int modifiers = getModifiers();
268         return buffer
269                 .append("{") //$NON-NLS-1$
270                 .append(
271                         ((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
272                                 + ((modifiers & 0x0001) == 1 ? "public " : "") //$NON-NLS-1$ //$NON-NLS-2$
273                                 + ((modifiers & 0x0002) == 0x0002 ? "private " : "") //$NON-NLS-1$ //$NON-NLS-2$
274                                 + ((modifiers & 0x0004) == 0x0004 ? "protected " : "") //$NON-NLS-1$ //$NON-NLS-2$
275                                 + ((modifiers & 0x0008) == 0x000008 ? "static " : "") //$NON-NLS-1$ //$NON-NLS-2$
276                                 + ((modifiers & 0x0010) == 0x0010 ? "final " : "") //$NON-NLS-1$ //$NON-NLS-2$
277                                 + ((modifiers & 0x0040) == 0x0040 ? "volatile " : "") //$NON-NLS-1$ //$NON-NLS-2$
278                                 + ((modifiers & 0x0080) == 0x0080 ? "transient " : "")) //$NON-NLS-1$ //$NON-NLS-2$
279                 .append(getTypeName())
280                 .append(" ") //$NON-NLS-1$
281                 .append(getName())
282                 .append(" ") //$NON-NLS-1$
283                 .append(getConstant())
284                 .append("}") //$NON-NLS-1$
285                 .toString(); 
286 }
287
288 public int compareTo(Object o) {
289         if (!(o instanceof FieldInfo)) {
290                 throw new ClassCastException();
291         }
292         return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
293 }
294 /**
295  * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
296  * will be therefore fully initialized and we can get rid of the bytes.
297  */
298 void initialize() {
299         getModifiers();
300         getName();
301         getConstant();
302         getTypeName();
303         reset();
304 }
305 protected void reset() {
306         this.constantPoolOffsets = null;
307         super.reset();
308 }
309
310 }