mirror of
https://github.com/moparisthebest/fernflower
synced 2024-11-17 14:55:14 -05:00
Annotation parsing (Java 8)
This commit is contained in:
parent
4f879b36b4
commit
c9c426ded7
@ -135,6 +135,19 @@ public interface CodeConstants {
|
||||
public final static int CONSTANT_MethodType = 16;
|
||||
public final static int CONSTANT_InvokeDynamic = 18;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// MethodHandle reference_kind values
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public final static int CONSTANT_MethodHandle_REF_getField = 1;
|
||||
public final static int CONSTANT_MethodHandle_REF_getStatic = 2;
|
||||
public final static int CONSTANT_MethodHandle_REF_putField = 3;
|
||||
public final static int CONSTANT_MethodHandle_REF_putStatic = 4;
|
||||
public final static int CONSTANT_MethodHandle_REF_invokeVirtual = 5;
|
||||
public final static int CONSTANT_MethodHandle_REF_invokeStatic = 6;
|
||||
public final static int CONSTANT_MethodHandle_REF_invokeSpecial = 7;
|
||||
public final static int CONSTANT_MethodHandle_REF_newInvokeSpecial = 8;
|
||||
public final static int CONSTANT_MethodHandle_REF_invokeInterface = 9;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// VM OPCODES
|
||||
|
@ -23,7 +23,7 @@ import java.util.List;
|
||||
import de.fernflower.modules.decompiler.exps.AnnotationExprent;
|
||||
import de.fernflower.struct.consts.ConstantPool;
|
||||
|
||||
public class StructAnnotationParameterAttribute extends StructGeneralAttribute {
|
||||
public class StructAnnotationParameterAttribute extends StructGeneralAttribute {
|
||||
|
||||
private List<List<AnnotationExprent>> paramAnnotations;
|
||||
|
||||
|
188
src/de/fernflower/struct/attr/StructAnnotationTypeAttribute.java
Normal file
188
src/de/fernflower/struct/attr/StructAnnotationTypeAttribute.java
Normal file
@ -0,0 +1,188 @@
|
||||
package de.fernflower.struct.attr;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.fernflower.modules.decompiler.exps.AnnotationExprent;
|
||||
import de.fernflower.struct.consts.ConstantPool;
|
||||
|
||||
public class StructAnnotationTypeAttribute extends StructGeneralAttribute {
|
||||
|
||||
public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS = 0x00;
|
||||
public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD = 0x01;
|
||||
public static final int ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS = 0x10;
|
||||
public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND = 0x11;
|
||||
public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND = 0x12;
|
||||
public static final int ANNOTATION_TARGET_TYPE_FIELD = 0x13;
|
||||
public static final int ANNOTATION_TARGET_TYPE_RETURN = 0x14;
|
||||
public static final int ANNOTATION_TARGET_TYPE_RECEIVER = 0x15;
|
||||
public static final int ANNOTATION_TARGET_TYPE_FORMAL = 0x16;
|
||||
public static final int ANNOTATION_TARGET_TYPE_THROWS = 0x17;
|
||||
public static final int ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE = 0x40;
|
||||
public static final int ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE = 0x41;
|
||||
public static final int ANNOTATION_TARGET_TYPE_EXCEPTION = 0x42;
|
||||
public static final int ANNOTATION_TARGET_TYPE_INSTANCEOF = 0x43;
|
||||
public static final int ANNOTATION_TARGET_TYPE_NEW = 0x44;
|
||||
public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW = 0x45;
|
||||
public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID = 0x46;
|
||||
public static final int ANNOTATION_TARGET_TYPE_CAST = 0x47;
|
||||
public static final int ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR = 0x48;
|
||||
public static final int ANNOTATION_TARGET_TYPE_INVOKATION_METHOD = 0x49;
|
||||
public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW = 0x4A;
|
||||
public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID = 0x4B;
|
||||
|
||||
public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER = 1;
|
||||
public static final int ANNOTATION_TARGET_UNION_SUPERTYPE = 2;
|
||||
public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND = 3;
|
||||
public static final int ANNOTATION_TARGET_UNION_EMPTY = 4;
|
||||
public static final int ANNOTATION_TARGET_UNION_FORMAL_PARAMETER = 5;
|
||||
public static final int ANNOTATION_TARGET_UNION_THROWS = 6;
|
||||
public static final int ANNOTATION_TARGET_UNION_LOCALVAR = 7;
|
||||
public static final int ANNOTATION_TARGET_UNION_CATCH = 8;
|
||||
public static final int ANNOTATION_TARGET_UNION_OFFSET = 9;
|
||||
public static final int ANNOTATION_TARGET_UNION_TYPE_ARGUMENT = 10;
|
||||
|
||||
|
||||
List<AnnotationLocation> locations = new ArrayList<AnnotationLocation>();
|
||||
List<AnnotationExprent> annotations = new ArrayList<AnnotationExprent>();
|
||||
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
super.initContent(pool);
|
||||
|
||||
DataInputStream data = new DataInputStream(new ByteArrayInputStream(info));
|
||||
|
||||
try {
|
||||
|
||||
int ann_number = data.readUnsignedByte();
|
||||
for(int i = 0; i < ann_number; i++) {
|
||||
locations.add(parseAnnotationLocation(data));
|
||||
annotations.add(StructAnnotationAttribute.parseAnnotation(data, pool));
|
||||
}
|
||||
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public AnnotationLocation parseAnnotationLocation(DataInputStream data) throws IOException {
|
||||
|
||||
AnnotationLocation ann_location = new AnnotationLocation();
|
||||
|
||||
// target type
|
||||
|
||||
ann_location.target_type = data.readUnsignedByte();
|
||||
|
||||
// target union
|
||||
|
||||
switch(ann_location.target_type) {
|
||||
case ANNOTATION_TARGET_TYPE_GENERIC_CLASS:
|
||||
case ANNOTATION_TARGET_TYPE_GENERIC_METHOD:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_SUPERTYPE;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND:
|
||||
case ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_FIELD:
|
||||
case ANNOTATION_TARGET_TYPE_RETURN:
|
||||
case ANNOTATION_TARGET_TYPE_RECEIVER:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_EMPTY;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_FORMAL:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_FORMAL_PARAMETER;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_THROWS:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_THROWS;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE:
|
||||
case ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_LOCALVAR;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_EXCEPTION:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_CATCH;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_INSTANCEOF:
|
||||
case ANNOTATION_TARGET_TYPE_NEW:
|
||||
case ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW:
|
||||
case ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_OFFSET;
|
||||
break;
|
||||
case ANNOTATION_TARGET_TYPE_CAST:
|
||||
case ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR:
|
||||
case ANNOTATION_TARGET_TYPE_INVOKATION_METHOD:
|
||||
case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW:
|
||||
case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID:
|
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_ARGUMENT;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown target type in a type annotation!");
|
||||
}
|
||||
|
||||
// target union data
|
||||
|
||||
switch(ann_location.target_union) {
|
||||
case ANNOTATION_TARGET_UNION_TYPE_PARAMETER:
|
||||
case ANNOTATION_TARGET_UNION_FORMAL_PARAMETER:
|
||||
ann_location.data = new int[] {data.readUnsignedByte()};
|
||||
break;
|
||||
case ANNOTATION_TARGET_UNION_SUPERTYPE:
|
||||
case ANNOTATION_TARGET_UNION_THROWS:
|
||||
case ANNOTATION_TARGET_UNION_CATCH:
|
||||
case ANNOTATION_TARGET_UNION_OFFSET:
|
||||
ann_location.data = new int[] {data.readUnsignedShort()};
|
||||
break;
|
||||
case ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND:
|
||||
ann_location.data = new int[] {data.readUnsignedByte(), data.readUnsignedByte()};
|
||||
break;
|
||||
case ANNOTATION_TARGET_UNION_EMPTY:
|
||||
break;
|
||||
case ANNOTATION_TARGET_UNION_LOCALVAR:
|
||||
int table_length = data.readUnsignedShort();
|
||||
|
||||
ann_location.data = new int[table_length * 3 + 1];
|
||||
ann_location.data[0] = table_length;
|
||||
|
||||
for(int i = 0; i < table_length; ++i) {
|
||||
ann_location.data[3 * i + 1] = data.readUnsignedShort();
|
||||
ann_location.data[3 * i + 2] = data.readUnsignedShort();
|
||||
ann_location.data[3 * i + 3] = data.readUnsignedShort();
|
||||
}
|
||||
break;
|
||||
case ANNOTATION_TARGET_UNION_TYPE_ARGUMENT:
|
||||
ann_location.data = new int[] {data.readUnsignedShort(), data.readUnsignedByte()};
|
||||
}
|
||||
|
||||
// target path
|
||||
|
||||
int path_length = data.readUnsignedByte();
|
||||
|
||||
ann_location.target_path_kind = new int[path_length];
|
||||
ann_location.target_argument_index = new int[path_length];
|
||||
|
||||
for(int i = 0; i < path_length; ++i) {
|
||||
ann_location.target_path_kind[i] = data.readUnsignedByte();
|
||||
ann_location.target_argument_index[i] = data.readUnsignedByte();
|
||||
}
|
||||
|
||||
return ann_location;
|
||||
}
|
||||
|
||||
private static class AnnotationLocation {
|
||||
|
||||
public int target_type;
|
||||
public int target_union;
|
||||
|
||||
public int[] data;
|
||||
|
||||
public int[] target_path_kind;
|
||||
public int[] target_argument_index;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package de.fernflower.struct.attr;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.fernflower.struct.consts.ConstantPool;
|
||||
import de.fernflower.struct.consts.LinkConstant;
|
||||
import de.fernflower.struct.consts.PooledConstant;
|
||||
|
||||
public class StructBootstrapMethodsAttribute extends StructGeneralAttribute {
|
||||
|
||||
private List<LinkConstant> method_refs = new ArrayList<LinkConstant>();
|
||||
private List<List<PooledConstant>> method_arguments = new ArrayList<List<PooledConstant>>();
|
||||
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
name = ATTRIBUTE_BOOTSTRAP_METHODS;
|
||||
|
||||
try {
|
||||
|
||||
DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 0, info.length));
|
||||
|
||||
int method_number = data.readUnsignedShort();
|
||||
|
||||
for(int i = 0; i < method_number; ++i) {
|
||||
int bootstrap_method_ref = data.readUnsignedShort();
|
||||
int num_bootstrap_arguments = data.readUnsignedShort();
|
||||
|
||||
List<PooledConstant> list_arguments = new ArrayList<PooledConstant>();
|
||||
|
||||
for(int j = 0; j < num_bootstrap_arguments; ++j) {
|
||||
int bootstrap_argument_ref = data.readUnsignedShort();
|
||||
|
||||
list_arguments.add(pool.getConstant(bootstrap_argument_ref));
|
||||
}
|
||||
|
||||
method_refs.add(pool.getLinkConstant(bootstrap_method_ref));
|
||||
method_arguments.add(list_arguments);
|
||||
}
|
||||
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -39,8 +39,11 @@ public class StructGeneralAttribute {
|
||||
public static final String ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
|
||||
public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
|
||||
public static final String ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
|
||||
public static final String ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
|
||||
public static final String ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
|
||||
public static final String ATTRIBUTE_LOCAL_VARIABLE_TABLE = "LocalVariableTable";
|
||||
public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue";
|
||||
public static final String ATTRIBUTE_BOOTSTRAP_METHODS = "BootstrapMethods";
|
||||
|
||||
|
||||
|
||||
@ -92,8 +95,13 @@ public class StructGeneralAttribute {
|
||||
} else if(ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS.equals(attrname) ||
|
||||
ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS.equals(attrname)) {
|
||||
attr = new StructAnnotationParameterAttribute();
|
||||
} else if(ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attrname) ||
|
||||
ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attrname)) {
|
||||
attr = new StructAnnotationTypeAttribute();
|
||||
} else if(ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname)) {
|
||||
attr = new StructLocalVariableTableAttribute();
|
||||
} else if(ATTRIBUTE_BOOTSTRAP_METHODS.equals(attrname)) {
|
||||
attr = new StructBootstrapMethodsAttribute();
|
||||
} else {
|
||||
// unsupported attribute
|
||||
return null;
|
||||
|
@ -90,6 +90,7 @@ public class ConstantPool {
|
||||
case CodeConstants.CONSTANT_Methodref:
|
||||
case CodeConstants.CONSTANT_InterfaceMethodref:
|
||||
case CodeConstants.CONSTANT_NameAndType:
|
||||
case CodeConstants.CONSTANT_InvokeDynamic:
|
||||
pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort()));
|
||||
if(tag == CodeConstants.CONSTANT_NameAndType) {
|
||||
pass[i] = 1;
|
||||
@ -101,9 +102,6 @@ public class ConstantPool {
|
||||
pool.add(new LinkConstant(tag, in.readUnsignedByte(), in.readUnsignedShort()));
|
||||
pass[i] = 3;
|
||||
break;
|
||||
case CodeConstants.CONSTANT_InvokeDynamic:
|
||||
pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort()));
|
||||
pass[i] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +149,7 @@ public class ConstantPool {
|
||||
case CodeConstants.CONSTANT_Methodref:
|
||||
case CodeConstants.CONSTANT_InterfaceMethodref:
|
||||
case CodeConstants.CONSTANT_NameAndType:
|
||||
case CodeConstants.CONSTANT_InvokeDynamic:
|
||||
in.skip(4);
|
||||
break;
|
||||
case CodeConstants.CONSTANT_Long:
|
||||
@ -160,7 +159,11 @@ public class ConstantPool {
|
||||
break;
|
||||
case CodeConstants.CONSTANT_Class:
|
||||
case CodeConstants.CONSTANT_String:
|
||||
case CodeConstants.CONSTANT_MethodType:
|
||||
in.skip(2);
|
||||
break;
|
||||
case CodeConstants.CONSTANT_MethodHandle:
|
||||
in.skip(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
||||
|
||||
/*
|
||||
* NameAndType, FieldRef, MethodRef, InterfaceMethodref
|
||||
* InvokeDynamic, MethodHandle
|
||||
*/
|
||||
|
||||
public class LinkConstant extends PooledConstant {
|
||||
@ -39,7 +40,7 @@ public class LinkConstant extends PooledConstant {
|
||||
|
||||
public boolean isVoid = false;;
|
||||
|
||||
public boolean returnCategory2 = false;;
|
||||
public boolean returnCategory2 = false;
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
@ -71,8 +72,17 @@ public class LinkConstant extends PooledConstant {
|
||||
if(type == CONSTANT_NameAndType) {
|
||||
elementname = pool.getPrimitiveConstant(index1).getString();
|
||||
descriptor = pool.getPrimitiveConstant(index2).getString();
|
||||
} else if(type == CONSTANT_MethodHandle) {
|
||||
LinkConstant ref_info = pool.getLinkConstant(index2);
|
||||
|
||||
classname = ref_info.classname;
|
||||
elementname = ref_info.elementname;
|
||||
descriptor = ref_info.descriptor;
|
||||
|
||||
} else {
|
||||
classname = pool.getPrimitiveConstant(index1).getString();
|
||||
if(type != CONSTANT_InvokeDynamic) {
|
||||
classname = pool.getPrimitiveConstant(index1).getString();
|
||||
}
|
||||
|
||||
LinkConstant nametype = pool.getLinkConstant(index2);
|
||||
elementname = nametype.elementname;
|
||||
@ -84,7 +94,11 @@ public class LinkConstant extends PooledConstant {
|
||||
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
out.writeByte(type);
|
||||
out.writeShort(index1);
|
||||
if(type == CONSTANT_MethodHandle) {
|
||||
out.writeByte(index1);
|
||||
} else {
|
||||
out.writeShort(index1);
|
||||
}
|
||||
out.writeShort(index2);
|
||||
}
|
||||
|
||||
@ -117,7 +131,7 @@ public class LinkConstant extends PooledConstant {
|
||||
|
||||
private void initConstant() {
|
||||
|
||||
if(type == CONSTANT_Methodref || type == CONSTANT_InterfaceMethodref) {
|
||||
if(type == CONSTANT_Methodref || type == CONSTANT_InterfaceMethodref || type == CONSTANT_InvokeDynamic || type == CONSTANT_MethodHandle) {
|
||||
resolveDescriptor(descriptor);
|
||||
} else if(type == CONSTANT_Fieldref) {
|
||||
returnCategory2 = ("D".equals(descriptor) || "J".equals(descriptor));
|
||||
|
@ -17,6 +17,8 @@ package de.fernflower.struct.consts;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import de.fernflower.code.CodeConstants;
|
||||
|
||||
/*
|
||||
* Integer, Long, Float, Double, String, Class, UTF8
|
||||
*/
|
||||
@ -75,7 +77,7 @@ public class PrimitiveConstant extends PooledConstant {
|
||||
|
||||
public void resolveConstant(ConstantPool pool) {
|
||||
|
||||
if(type == CONSTANT_Class || type == CONSTANT_String) {
|
||||
if(type == CONSTANT_Class || type == CONSTANT_String || type == CONSTANT_MethodType) {
|
||||
value = pool.getPrimitiveConstant(index).getString();
|
||||
initConstant();
|
||||
}
|
||||
@ -100,7 +102,7 @@ public class PrimitiveConstant extends PooledConstant {
|
||||
case CONSTANT_Utf8:
|
||||
out.writeUTF(getString());
|
||||
break;
|
||||
default: // CONSTANT_Class or CONSTANT_String
|
||||
default: // CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType
|
||||
out.writeShort(index);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user