import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / classfmt / FieldInfo.java
index 26392d8..b986492 100644 (file)
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.classfmt;
 
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
@@ -23,18 +24,21 @@ import org.eclipse.jdt.internal.compiler.impl.IntConstant;
 import org.eclipse.jdt.internal.compiler.impl.LongConstant;
 import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
+       private int accessFlags;
+       private int attributeBytes;
        private Constant constant;
-       private boolean isDeprecated;
-       private boolean isSynthetic;
        private int[] constantPoolOffsets;
-       private int accessFlags;
+       private char[] descriptor;
        private char[] name;
        private char[] signature;
-       private int attributeBytes;
+       private int signatureUtf8Offset;
+       private long tagBits;   
        private Object wrappedConstantValue;
 /**
  * @param classFileBytes byte[]
@@ -47,11 +51,105 @@ public FieldInfo (byte classFileBytes[], int offsets[], int offset) {
        accessFlags = -1;
        int attributesCount = u2At(6);
        int readOffset = 8;
+       this.signatureUtf8Offset = -1;
        for (int i = 0; i < attributesCount; i++) {
+               // check the name of each attribute
+               int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+               char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+               if (attributeName.length > 0) {
+                       switch(attributeName[0]) {
+                               case 'S' :
+                                       if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) {
+                                               this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
+                                       }
+                                       break;
+                               case 'R' :
+                                       if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+                                               decodeStandardAnnotations(readOffset);
+                                       }
+                       }
+               }
                readOffset += (6 + u4At(readOffset + 2));
        }
        attributeBytes = readOffset;
 }
+
+public int compareTo(Object o) {
+       if (!(o instanceof FieldInfo)) {
+               throw new ClassCastException();
+       }
+       return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
+}
+private int decodeAnnotation(int offset) {
+       int readOffset = offset;
+       int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset;
+       char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+       typeName = Signature.toCharArray(typeName);
+       CharOperation.replace(typeName, '/', '.');
+       char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+       int numberOfPairs = u2At(offset + 2);
+       readOffset += 4;
+       if (qualifiedTypeName.length == 3) {
+               char[] lastPart = qualifiedTypeName[2];
+               if (lastPart[0] == 'D') {
+                       if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+                               this.tagBits |= TagBits.AnnotationDeprecated;
+                               return readOffset;              
+                       }
+               }
+       }
+       for (int i = 0; i < numberOfPairs; i++) {
+               readOffset += 2;
+               readOffset = decodeElementValue(readOffset);
+       }
+       return readOffset;
+}
+private int decodeElementValue(int offset) {
+       int readOffset = offset;
+       int tag = u1At(readOffset);
+       readOffset++;
+       switch(tag) {
+               case 'B' :
+               case 'C' :
+               case 'D' :
+               case 'F' :
+               case 'I' :
+               case 'J' :
+               case 'S' :
+               case 'Z' :
+               case 's' :
+                       readOffset += 2;
+                       break;
+               case 'e' :
+                       readOffset += 4;
+                       break;
+               case 'c' :
+                       readOffset += 2;
+                       break;
+               case '@' :
+                       readOffset += decodeAnnotation(readOffset);
+                       break;
+               case '[' :
+                       int numberOfValues = u2At(readOffset);
+                       readOffset += 2;
+                       for (int i = 0; i < numberOfValues; i++) {
+                               readOffset = decodeElementValue(readOffset);
+                       }
+                       break;
+       }
+       return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible 
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+       int numberOfAnnotations = u2At(offset + 6);
+       int readOffset = offset + 8;
+       for (int i = 0; i < numberOfAnnotations; i++) {
+               readOffset = decodeAnnotation(readOffset);
+       }
+}
 /**
  * Return the constant of the field.
  * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
@@ -64,6 +162,16 @@ public Constant getConstant() {
        }
        return constant;
 }
+public char[] getGenericSignature() {
+       if (this.signatureUtf8Offset != -1) {
+               if (this.signature == null) {
+                       // decode the signature
+                       this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
+               }
+               return this.signature;
+       }
+       return null;
+}
 /**
  * Answer an int whose bits are set according the access constants
  * defined by the VM spec.
@@ -71,18 +179,12 @@ public Constant getConstant() {
  * @return int
  */
 public int getModifiers() {
-       if (accessFlags == -1) {
+       if (this.accessFlags == -1) {
                // compute the accessflag. Don't forget the deprecated attribute
-               accessFlags = u2At(0);
-               readDeprecatedAndSyntheticAttributes();
-               if (isDeprecated) {
-                       accessFlags |= AccDeprecated;
-               }
-               if (isSynthetic) {
-                       accessFlags |= AccSynthetic;
-               }
+               this.accessFlags = u2At(0);
+               readModifierRelatedAttributes();
        }
-       return accessFlags;
+       return this.accessFlags;
 }
 /**
  * Answer the name of the field.
@@ -96,6 +198,9 @@ public char[] getName() {
        }
        return name;
 }
+public long getTagBits() {
+       return this.tagBits;
+}
 /**
  * Answer the resolved name of the receiver's type in the
  * class file format as specified in section 4.3.2 of the Java 2 VM spec.
@@ -108,12 +213,12 @@ public char[] getName() {
  * @return char[]
  */
 public char[] getTypeName() {
-       if (signature == null) {
+       if (descriptor == null) {
                // read the signature
                int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
-               signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+               descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
        }
-       return signature;
+       return descriptor;
 }
 /**
  * Return a wrapper that contains the constant of the field.
@@ -149,7 +254,7 @@ public Object getWrappedConstantValue() {
                                case T_long :
                                        this.wrappedConstantValue = new Long(fieldConstant.longValue());
                                        break;
-                               case T_String :
+                               case T_JavaLangString :
                                        this.wrappedConstantValue = fieldConstant.stringValue();
                        }
                }
@@ -164,6 +269,18 @@ public boolean hasConstant() {
        return getConstant() != Constant.NotAConstant;
 }
 /**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+       getModifiers();
+       getName();
+       getConstant();
+       getTypeName();
+       getGenericSignature();
+       reset();
+}
+/**
  * Return true if the field is a synthetic field, false otherwise.
  * @return boolean
  */
@@ -233,20 +350,32 @@ private void readConstantAttribute() {
                constant = Constant.NotAConstant;
        }
 }
-private void readDeprecatedAndSyntheticAttributes() {
+private void readModifierRelatedAttributes() {
        int attributesCount = u2At(6);
        int readOffset = 8;
        for (int i = 0; i < attributesCount; i++) {
                int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
                char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
-               if (CharOperation.equals(attributeName, DeprecatedName)) {
-                       isDeprecated = true;
-               } else if (CharOperation.equals(attributeName, SyntheticName)) {
-                       isSynthetic = true;
+               // test added for obfuscated .class file. See 79772
+               if (attributeName.length != 0) {
+                       switch(attributeName[0]) {
+                               case 'D' :
+                                       if (CharOperation.equals(attributeName, DeprecatedName))
+                                               this.accessFlags |= AccDeprecated;
+                                       break;
+                               case 'S' :
+                                       if (CharOperation.equals(attributeName, SyntheticName))
+                                               this.accessFlags |= AccSynthetic;
+                                       break;
+                       }
                }
                readOffset += (6 + u4At(readOffset + 2));
        }
 }
+protected void reset() {
+       this.constantPoolOffsets = null;
+       super.reset();
+}
 /**
  * Answer the size of the receiver in bytes.
  * 
@@ -281,26 +410,4 @@ public String toString() {
                .toString(); 
 }
 
-public int compareTo(Object o) {
-       if (!(o instanceof FieldInfo)) {
-               throw new ClassCastException();
-       }
-       return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
-}
-/**
- * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
- * will be therefore fully initialized and we can get rid of the bytes.
- */
-void initialize() {
-       getModifiers();
-       getName();
-       getConstant();
-       getTypeName();
-       reset();
-}
-protected void reset() {
-       this.constantPoolOffsets = null;
-       super.reset();
-}
-
 }