@@ -0,0 +1,104 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2013 VMware | |||
* | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.apache.bcel.classfile; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import org.aspectj.apache.bcel.Constants; | |||
// see http://cr.openjdk.java.net/~abuckley/8misc.pdf | |||
public class MethodParameters extends Attribute { | |||
public final static int[] NO_PARAMETER_NAME_INDEXES = new int[0]; | |||
public final static int[] NO_PARAMETER_ACCESS_FLAGS = new int[0]; | |||
public final static int ACCESS_FLAGS_FINAL = 0x0010; | |||
public final static int ACCESS_FLAGS_SYNTHETIC = 0x1000; | |||
public final static int ACCESS_FLAGS_MANDATED = 0x8000; | |||
private byte[] data; | |||
private int[] names; | |||
private int[] accessFlags; | |||
public MethodParameters(int index, int length, DataInputStream dis, ConstantPool cpool) throws IOException { | |||
super(Constants.ATTR_METHOD_PARAMETERS,index,length,cpool); | |||
data = new byte[length]; | |||
dis.read(data,0,length); | |||
} | |||
private void ensureInflated() { | |||
if (names!=null) return; | |||
try { | |||
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data)); | |||
int parametersCount = dis.readUnsignedByte(); | |||
if (parametersCount == 0) { | |||
names = NO_PARAMETER_NAME_INDEXES; | |||
accessFlags = NO_PARAMETER_ACCESS_FLAGS; | |||
} else { | |||
names = new int[parametersCount]; | |||
accessFlags = new int[parametersCount]; | |||
for (int i=0;i<parametersCount;i++) { | |||
names[i] = dis.readUnsignedShort(); | |||
accessFlags[i] = dis.readUnsignedShort(); | |||
} | |||
} | |||
} catch (IOException ioe) { | |||
throw new RuntimeException("Unabled to inflate type annotation data, badly formed?"); | |||
} | |||
} | |||
public void dump(DataOutputStream dos) throws IOException { | |||
super.dump(dos); | |||
dos.writeByte(names.length); | |||
for (int i=0;i<names.length;i++) { | |||
dos.writeShort(names[i]); | |||
dos.writeShort(accessFlags[i]); | |||
} | |||
} | |||
public int getParametersCount() { | |||
ensureInflated(); | |||
return names.length; | |||
} | |||
public String getParameterName(int parameter) { | |||
ensureInflated(); | |||
ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(names[parameter], Constants.CONSTANT_Utf8); | |||
return c.getValue(); | |||
} | |||
public int getAccessFlags(int parameter) { | |||
ensureInflated(); | |||
return accessFlags[parameter]; | |||
} | |||
public boolean isFinal(int parameter) { | |||
return (getAccessFlags(parameter) & ACCESS_FLAGS_FINAL)!=0; | |||
} | |||
public boolean isSynthetic(int parameter) { | |||
return (getAccessFlags(parameter) & ACCESS_FLAGS_SYNTHETIC)!=0; | |||
} | |||
public boolean isMandated(int parameter) { | |||
return (getAccessFlags(parameter) & ACCESS_FLAGS_MANDATED)!=0; | |||
} | |||
@Override | |||
public void accept(ClassVisitor v) { | |||
v.visitMethodParameters(this); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2013 VMware | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial implementation {date} | |||
* ******************************************************************/ | |||
package org.aspectj.apache.bcel.classfile.annotation; | |||
import java.io.DataInputStream; | |||
import java.io.IOException; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.ConstantPool; | |||
import org.aspectj.apache.bcel.classfile.ClassVisitor; | |||
public class RuntimeInvisTypeAnnos extends RuntimeTypeAnnos { | |||
public RuntimeInvisTypeAnnos(int nameIdx, int len, DataInputStream dis, | |||
ConstantPool cpool) throws IOException { | |||
this(nameIdx, len, cpool); | |||
readTypeAnnotations(dis, cpool); | |||
} | |||
public RuntimeInvisTypeAnnos(int nameIdx, int len, ConstantPool cpool) { | |||
super(Constants.ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, true, nameIdx, len, cpool); | |||
} | |||
public void accept(ClassVisitor v) { | |||
v.visitRuntimeInvisibleTypeAnnotations(this); | |||
} | |||
} |
@@ -0,0 +1,105 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2013 VMware | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial implementation {date} | |||
* ******************************************************************/ | |||
package org.aspectj.apache.bcel.classfile.annotation; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import org.aspectj.apache.bcel.classfile.Attribute; | |||
import org.aspectj.apache.bcel.classfile.ConstantPool; | |||
public abstract class RuntimeTypeAnnos extends Attribute { | |||
private boolean visible; | |||
private TypeAnnotationGen[] typeAnnotations; // null until inflated | |||
// Keep just a byte stream of the data until someone actually asks for the information within | |||
private byte[] annotation_data; | |||
public RuntimeTypeAnnos(byte attrid, boolean visible, int nameIdx, int len, ConstantPool cpool) { | |||
super(attrid,nameIdx,len,cpool); | |||
this.visible = visible; | |||
} | |||
protected void readTypeAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException { | |||
annotation_data = new byte[length]; | |||
dis.read(annotation_data,0,length); | |||
} | |||
public final void dump(DataOutputStream dos) throws IOException { | |||
super.dump(dos); | |||
writeTypeAnnotations(dos); | |||
} | |||
protected void writeTypeAnnotations(DataOutputStream dos) throws IOException { | |||
if (typeAnnotations == null) { | |||
dos.write(annotation_data,0,length); | |||
} else { | |||
dos.writeShort(typeAnnotations.length); | |||
for (int i=0; i<typeAnnotations.length; i++) { | |||
typeAnnotations[i].dump(dos); | |||
} | |||
} | |||
} | |||
// public RuntimeTypeAnnos(byte attrid,boolean visible,int nameIdx,int len,byte[] data,ConstantPool cpool) { | |||
// super(attrid,nameIdx,len,cpool); | |||
// this.visible = visible; | |||
// parameterAnnotations = new ArrayList<AnnotationGen[]>(); | |||
// annotation_data = data; | |||
// } | |||
public Attribute copy(ConstantPool constant_pool) { | |||
throw new RuntimeException("Not implemented yet!"); | |||
} | |||
public TypeAnnotationGen[] getTypeAnnotations() { | |||
ensureInflated(); | |||
return typeAnnotations; | |||
} | |||
public boolean areVisible() { | |||
return visible; | |||
} | |||
private void ensureInflated() { | |||
if (typeAnnotations !=null) { | |||
return; | |||
} | |||
try { | |||
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data)); | |||
int numTypeAnnotations = dis.readUnsignedShort(); | |||
if (numTypeAnnotations == 0) { | |||
typeAnnotations = TypeAnnotationGen.NO_TYPE_ANNOTATIONS; | |||
} else { | |||
typeAnnotations = new TypeAnnotationGen[numTypeAnnotations]; | |||
for (int i=0; i<numTypeAnnotations; i++) { | |||
typeAnnotations[i] = TypeAnnotationGen.read(dis,getConstantPool(),visible); | |||
} | |||
} | |||
} catch (IOException ioe) { | |||
throw new RuntimeException("Unabled to inflate type annotation data, badly formed?"); | |||
} | |||
} | |||
public String toString() { | |||
return "Runtime"+(visible?"Visible":"Invisible")+"TypeAnnotations ["+(isInflated()?"inflated":"not yet inflated")+"]"; | |||
} | |||
public boolean isInflated() { | |||
return typeAnnotations != null; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2013 VMware | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial implementation {date} | |||
* ******************************************************************/ | |||
package org.aspectj.apache.bcel.classfile.annotation; | |||
import java.io.DataInputStream; | |||
import java.io.IOException; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.Attribute; | |||
import org.aspectj.apache.bcel.classfile.ConstantPool; | |||
import org.aspectj.apache.bcel.classfile.ClassVisitor; | |||
public class RuntimeVisTypeAnnos extends RuntimeTypeAnnos { | |||
public RuntimeVisTypeAnnos(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException { | |||
this(nameIdx, len, cpool); | |||
readTypeAnnotations(dis,cpool); | |||
} | |||
public RuntimeVisTypeAnnos(int nameIdx, int len, ConstantPool cpool) { | |||
super(Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, true, nameIdx, len, cpool); | |||
} | |||
// public RuntimeVisTypeAnnos(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) { | |||
// super(Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS,true,nameIndex,len,rvaData,cpool); | |||
// } | |||
public void accept(ClassVisitor v) { | |||
v.visitRuntimeVisibleTypeAnnotations(this); | |||
} | |||
// public Attribute copy(ConstantPool constant_pool) { | |||
// throw new RuntimeException("Not implemented yet!"); | |||
// } | |||
} |
@@ -0,0 +1,405 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2013 VMware | |||
* | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.apache.bcel.classfile.annotation; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import org.aspectj.apache.bcel.classfile.ConstantPool; | |||
public class TypeAnnotationGen { | |||
public static final TypeAnnotationGen[] NO_TYPE_ANNOTATIONS = new TypeAnnotationGen[0]; | |||
public static final int[] NO_TYPE_PATH = new int[0]; | |||
private ConstantPool cpool; | |||
private TypeAnnotationGen(ConstantPool cpool) { | |||
this.cpool = cpool; | |||
} | |||
private int targetType; | |||
private int[] typePath; | |||
private AnnotationGen annotation; | |||
private int info; // meaning varies depending on target type | |||
private int info2; // meaning varies depending on target type | |||
private int[] localVarTarget; | |||
// target type constants | |||
public final static int CLASS_TYPE_PARAMETER = 0x00; | |||
public final static int METHOD_TYPE_PARAMETER = 0x01; | |||
public final static int CLASS_EXTENDS = 0x10; | |||
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; | |||
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; | |||
public final static int FIELD = 0x13; | |||
public final static int METHOD_RETURN = 0x14; | |||
public final static int METHOD_RECEIVER = 0x15; | |||
public final static int METHOD_FORMAL_PARAMETER = 0x16; | |||
public final static int THROWS = 0x17; | |||
public final static int LOCAL_VARIABLE = 0x40; | |||
public final static int RESOURCE_VARIABLE = 0x41; | |||
public final static int EXCEPTION_PARAMETER = 0x42; | |||
public final static int INSTANCEOF = 0x43; | |||
public final static int NEW = 0x44; | |||
public final static int CONSTRUCTOR_REFERENCE = 0x45; | |||
public final static int METHOD_REFERENCE = 0x46; | |||
public final static int CAST = 0x47; | |||
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; | |||
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; | |||
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; | |||
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; | |||
// type path entry kinds | |||
public final static int TYPE_PATH_ENTRY_KIND_ARRAY = 0; | |||
public final static int TYPE_PATH_ENTRY_KIND_INNER_TYPE = 1; | |||
public final static int TYPE_PATH_ENTRY_KIND_WILDCARD = 2; | |||
public final static int TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT = 3; | |||
public static TypeAnnotationGen read(DataInputStream dis, ConstantPool cpool, boolean isVisible) throws IOException { | |||
TypeAnnotationGen typeAnno = new TypeAnnotationGen(cpool); | |||
typeAnno.targetType = dis.readUnsignedByte(); | |||
// read target_info | |||
switch (typeAnno.targetType) { | |||
case CLASS_TYPE_PARAMETER: | |||
typeAnno.info = dis.readUnsignedByte();// type_parameter_index | |||
break; | |||
case METHOD_TYPE_PARAMETER: | |||
typeAnno.info = dis.readUnsignedByte(); // type_parameter_index | |||
break; | |||
case CLASS_EXTENDS: | |||
int superTypeIndex = dis.readUnsignedShort(); | |||
if (superTypeIndex == 65535) { | |||
typeAnno.info = -1; | |||
} else { | |||
typeAnno.info = superTypeIndex; | |||
} | |||
break; | |||
case CLASS_TYPE_PARAMETER_BOUND: | |||
case METHOD_TYPE_PARAMETER_BOUND: | |||
typeAnno.info = dis.readUnsignedByte(); // type_parameter_index | |||
typeAnno.info2 = dis.readUnsignedByte(); // bound_index; | |||
break; | |||
case FIELD: | |||
case METHOD_RETURN: | |||
case METHOD_RECEIVER: | |||
break; | |||
case METHOD_FORMAL_PARAMETER: | |||
typeAnno.info = dis.readUnsignedByte(); // method_formal_parameter_index | |||
break; | |||
case THROWS: | |||
typeAnno.info = dis.readUnsignedShort(); // throws_type_index | |||
break; | |||
case LOCAL_VARIABLE: | |||
case RESOURCE_VARIABLE: | |||
typeAnno.localVarTarget = readLocalVarTarget(dis); | |||
break; | |||
case EXCEPTION_PARAMETER: | |||
// TODO should be a SHORT according to the spec but byte for now because of javac (b90) | |||
typeAnno.info = dis.readUnsignedByte(); // exception_table_index | |||
break; | |||
case INSTANCEOF: | |||
case NEW: | |||
case CONSTRUCTOR_REFERENCE: | |||
case METHOD_REFERENCE: | |||
typeAnno.info = dis.readUnsignedShort(); // offset | |||
break; | |||
case CAST: | |||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: | |||
case METHOD_INVOCATION_TYPE_ARGUMENT: | |||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: | |||
case METHOD_REFERENCE_TYPE_ARGUMENT: | |||
typeAnno.info = dis.readUnsignedShort(); // offset | |||
typeAnno.info2 = dis.readUnsignedByte(); // type_argument_index | |||
break; | |||
default: | |||
throw new IllegalStateException("nyi "+typeAnno.targetType); | |||
} | |||
int typepathlength = dis.readUnsignedByte(); | |||
if (typepathlength==0) { | |||
typeAnno.typePath = NO_TYPE_PATH; | |||
} else { | |||
typeAnno.typePath = new int[typepathlength*2]; | |||
for (int i=0, max = typepathlength*2; i<max; i++) { | |||
typeAnno.typePath[i] = dis.readUnsignedByte(); | |||
} | |||
} | |||
typeAnno.annotation = AnnotationGen.read(dis, cpool, isVisible); | |||
return typeAnno; | |||
} | |||
public static int[] readLocalVarTarget(DataInputStream dis) throws IOException { | |||
int tableLength = dis.readUnsignedShort(); | |||
int[] table = new int[tableLength*3]; | |||
int count = 0; | |||
for (int i=0;i<tableLength;i++) { | |||
table[count++]=dis.readUnsignedShort(); // start_pc | |||
table[count++]=dis.readUnsignedShort(); // length | |||
table[count++]=dis.readUnsignedShort(); // index | |||
} | |||
return table; | |||
} | |||
public void dump(DataOutputStream dos) throws IOException { | |||
dos.writeByte(targetType); | |||
switch (targetType) { | |||
case CLASS_TYPE_PARAMETER: | |||
dos.writeByte(this.info); // type_parameter_index | |||
break; | |||
case METHOD_TYPE_PARAMETER: | |||
dos.writeByte(info); // type_parameter_index | |||
break; | |||
case CLASS_EXTENDS: | |||
dos.writeShort(info); // supertype_index | |||
break; | |||
case CLASS_TYPE_PARAMETER_BOUND: | |||
case METHOD_TYPE_PARAMETER_BOUND: | |||
dos.writeByte(info); // type_parameter_index | |||
dos.writeByte(info2); // bound_index; | |||
break; | |||
case FIELD: | |||
case METHOD_RETURN: | |||
case METHOD_RECEIVER: | |||
break; | |||
case METHOD_FORMAL_PARAMETER: | |||
dos.writeByte(info); // method_formal_parameter_index | |||
break; | |||
case THROWS: | |||
dos.writeShort(info); // throws_type_index | |||
break; | |||
case LOCAL_VARIABLE: | |||
case RESOURCE_VARIABLE: | |||
dos.writeShort(localVarTarget.length/3); | |||
for (int i=0;i<localVarTarget.length;i++) { | |||
dos.writeShort(localVarTarget[i]); | |||
} | |||
break; | |||
case EXCEPTION_PARAMETER: | |||
// TODO should be a SHORT according to the spec but byte for now because of javac (b90) | |||
dos.writeByte(info); // exception_table_index | |||
break; | |||
case INSTANCEOF: | |||
case NEW: | |||
case CONSTRUCTOR_REFERENCE: | |||
case METHOD_REFERENCE: | |||
dos.writeShort(info); // offset | |||
break; | |||
case CAST: | |||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: | |||
case METHOD_INVOCATION_TYPE_ARGUMENT: | |||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: | |||
case METHOD_REFERENCE_TYPE_ARGUMENT: | |||
dos.writeShort(info); // offset | |||
dos.writeByte(info); // type_argument_index | |||
break; | |||
default: | |||
throw new IllegalStateException("nyi "+targetType); | |||
} | |||
dos.writeByte(typePath.length); | |||
for (int i=0;i<typePath.length;i++) { | |||
dos.writeByte(typePath[i]); | |||
} | |||
annotation.dump(dos); | |||
} | |||
public int getSupertypeIndex() { | |||
assert (targetType==CLASS_EXTENDS); | |||
return info; | |||
} | |||
public int getOffset() { | |||
assert (targetType==INSTANCEOF || targetType==NEW || targetType==CONSTRUCTOR_REFERENCE || targetType==METHOD_REFERENCE || | |||
targetType==CAST || targetType==CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT || | |||
targetType==METHOD_INVOCATION_TYPE_ARGUMENT || targetType==CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT || | |||
targetType==METHOD_REFERENCE_TYPE_ARGUMENT); | |||
return info; | |||
} | |||
public int getTypeParameterIndex() { | |||
assert (targetType==CLASS_TYPE_PARAMETER || targetType==METHOD_TYPE_PARAMETER || | |||
targetType==CLASS_TYPE_PARAMETER_BOUND || targetType==METHOD_TYPE_PARAMETER_BOUND); | |||
return info; | |||
} | |||
public int getTypeArgumentIndex() { | |||
assert (targetType==CAST || targetType==CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT || | |||
targetType==METHOD_INVOCATION_TYPE_ARGUMENT || targetType==CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT || targetType==METHOD_REFERENCE_TYPE_ARGUMENT); | |||
return info2; | |||
} | |||
public int getBoundIndex() { | |||
assert (targetType==CLASS_TYPE_PARAMETER_BOUND || targetType==METHOD_TYPE_PARAMETER_BOUND); | |||
return info2; | |||
} | |||
public int getMethodFormalParameterIndex() { | |||
assert (targetType==METHOD_FORMAL_PARAMETER); | |||
return info; | |||
} | |||
public int getThrowsTypeIndex() { | |||
assert (targetType==THROWS); | |||
return info; | |||
} | |||
public int[] getLocalVarTarget() { | |||
assert (targetType==LOCAL_VARIABLE||targetType==RESOURCE_VARIABLE); | |||
return localVarTarget; | |||
} | |||
public int getExceptionTableIndex() { | |||
assert (targetType==EXCEPTION_PARAMETER); | |||
return info; | |||
} | |||
public int getTargetType() { | |||
return targetType; | |||
} | |||
public AnnotationGen getAnnotation() { | |||
return annotation; | |||
} | |||
// @Override | |||
// public String toString() { | |||
// StringBuffer s = new StringBuffer(); | |||
// s.append("AnnotationGen:[" + getTypeName() + " #" + pairs.size() + " {"); | |||
// for (int i = 0; i < pairs.size(); i++) { | |||
// s.append(pairs.get(i)); | |||
// if (i + 1 < pairs.size()) | |||
// s.append(","); | |||
// } | |||
// s.append("}]"); | |||
// return s.toString(); | |||
// } | |||
// | |||
// public String toShortString() { | |||
// StringBuffer s = new StringBuffer(); | |||
// s.append("@" + getTypeName() + "("); | |||
// for (int i = 0; i < pairs.size(); i++) { | |||
// s.append(pairs.get(i)); | |||
// if (i + 1 < pairs.size()) | |||
// s.append(","); | |||
// } | |||
// s.append(")"); | |||
// return s.toString(); | |||
// } | |||
// | |||
// private void isRuntimeVisible(boolean b) { | |||
// isRuntimeVisible = b; | |||
// } | |||
// | |||
// public boolean isRuntimeVisible() { | |||
// return isRuntimeVisible; | |||
// } | |||
// | |||
// /** | |||
// * @return true if the annotation has a value with the specified name and (toString'd) value | |||
// */ | |||
// public boolean hasNameValuePair(String name, String value) { | |||
// for (NameValuePair pair : pairs) { | |||
// if (pair.getNameString().equals(name)) { | |||
// if (pair.getValue().stringifyValue().equals(value)) { | |||
// return true; | |||
// } | |||
// } | |||
// } | |||
// return false; | |||
// } | |||
// | |||
// /** | |||
// * @return true if the annotation has a value with the specified name | |||
// */ | |||
// public boolean hasNamedValue(String name) { | |||
// for (NameValuePair pair : pairs) { | |||
// if (pair.getNameString().equals(name)) { | |||
// return true; | |||
// } | |||
// } | |||
// return false; | |||
// } | |||
// public TypeAnnotationGen(TypeAnnotationGen a, ConstantPool cpool, boolean copyPoolEntries) { | |||
// this.cpool = cpool; | |||
// if (copyPoolEntries) { | |||
// typeIndex = cpool.addUtf8(a.getTypeSignature()); | |||
// } else { | |||
// typeIndex = a.getTypeIndex(); | |||
// } | |||
// isRuntimeVisible = a.isRuntimeVisible(); | |||
// pairs = copyValues(a.getValues(), cpool, copyPoolEntries); | |||
// } | |||
// | |||
// private List<NameValuePair> copyValues(List<NameValuePair> in, ConstantPool cpool, boolean copyPoolEntries) { | |||
// List<NameValuePair> out = new ArrayList<NameValuePair>(); | |||
// for (NameValuePair nvp : in) { | |||
// out.add(new NameValuePair(nvp, cpool, copyPoolEntries)); | |||
// } | |||
// return out; | |||
// } | |||
// | |||
// | |||
// /** | |||
// * Retrieve an immutable version of this AnnotationGen | |||
// */ | |||
// public TypeAnnotationGen(ObjectType type, List<NameValuePair> pairs, boolean runtimeVisible, ConstantPool cpool) { | |||
// this.cpool = cpool; | |||
// if (type != null) { | |||
// this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects | |||
// } | |||
// this.pairs = pairs; | |||
// isRuntimeVisible = runtimeVisible; | |||
// } | |||
// | |||
public int[] getTypePath() { | |||
return typePath; | |||
} | |||
public String getTypePathString() { | |||
return toTypePathString(typePath); | |||
} | |||
public static String toTypePathString(int[] typepath) { | |||
StringBuilder sb = new StringBuilder(); | |||
int count = 0; | |||
sb.append("["); | |||
while (count < typepath.length) { | |||
if (count>0) sb.append(","); | |||
switch (typepath[count++]) { | |||
case TYPE_PATH_ENTRY_KIND_ARRAY: | |||
sb.append("ARRAY"); | |||
count++; | |||
break; | |||
case TYPE_PATH_ENTRY_KIND_INNER_TYPE: | |||
sb.append("INNER_TYPE"); | |||
count++; | |||
break; | |||
case TYPE_PATH_ENTRY_KIND_WILDCARD: | |||
sb.append("WILDCARD"); | |||
count++; | |||
break; | |||
case TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT: | |||
sb.append("TYPE_ARGUMENT(").append(typepath[count++]).append(")"); | |||
break; | |||
} | |||
} | |||
sb.append("]"); | |||
return sb.toString(); | |||
} | |||
} |
@@ -0,0 +1,86 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2013 VMware | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.apache.bcel.classfile.tests; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.JavaClass; | |||
import org.aspectj.apache.bcel.classfile.Method; | |||
import org.aspectj.apache.bcel.classfile.MethodParameters; | |||
public class MethodParametersTest extends BcelTestCase { | |||
protected void setUp() throws Exception { | |||
super.setUp(); | |||
} | |||
public void testMethodParameters1() throws Exception { | |||
JavaClass jc = getClassFromJava8Jar("Parameters"); | |||
Method m = getMethod(jc, "foo"); | |||
MethodParameters mp = (MethodParameters)getAttribute(m.getAttributes(),Constants.ATTR_METHOD_PARAMETERS); | |||
assertEquals(3,mp.getParametersCount()); | |||
assertEquals("abc",mp.getParameterName(0)); | |||
assertEquals("def",mp.getParameterName(1)); | |||
assertEquals("ghi",mp.getParameterName(2)); | |||
assertFalse(mp.isFinal(0)); | |||
assertFalse(mp.isSynthetic(0)); | |||
assertFalse(mp.isMandated(0)); | |||
} | |||
// this method specifies the receiver | |||
public void testMethodParameters2() throws Exception { | |||
JavaClass jc = getClassFromJava8Jar("Parameters"); | |||
Method m = getMethod(jc, "bar"); | |||
MethodParameters mp = (MethodParameters)getAttribute(m.getAttributes(),Constants.ATTR_METHOD_PARAMETERS); | |||
assertEquals(1,mp.getParametersCount()); | |||
assertEquals("abc",mp.getParameterName(0)); | |||
assertFalse(mp.isFinal(0)); | |||
assertFalse(mp.isSynthetic(0)); | |||
assertFalse(mp.isMandated(0)); | |||
} | |||
// access flags | |||
public void testMethodParameters3() throws Exception { | |||
JavaClass jc = getClassFromJava8Jar("Parameters$Inner"); | |||
Method m = getMethod(jc, "<init>"); | |||
MethodParameters mp = (MethodParameters)getAttribute(m.getAttributes(),Constants.ATTR_METHOD_PARAMETERS); | |||
assertEquals(2,mp.getParametersCount()); | |||
assertEquals("this$0",mp.getParameterName(0)); | |||
assertTrue(mp.isFinal(0)); | |||
assertFalse(mp.isSynthetic(0)); | |||
assertTrue(mp.isMandated(0)); | |||
assertEquals("x",mp.getParameterName(1)); | |||
assertFalse(mp.isFinal(1)); | |||
assertFalse(mp.isSynthetic(1)); | |||
assertFalse(mp.isMandated(1)); | |||
} | |||
// access flags | |||
public void testMethodParameters4() throws Exception { | |||
JavaClass jc = getClassFromJava8Jar("Parameters$Color"); | |||
Method m = getMethod(jc, "<init>"); | |||
MethodParameters mp = (MethodParameters)getAttribute(m.getAttributes(),Constants.ATTR_METHOD_PARAMETERS); | |||
assertEquals(2,mp.getParametersCount()); | |||
assertEquals("$enum$name",mp.getParameterName(0)); | |||
assertFalse(mp.isFinal(0)); | |||
assertTrue(mp.isSynthetic(0)); | |||
assertFalse(mp.isMandated(0)); | |||
assertEquals("$enum$ordinal",mp.getParameterName(1)); | |||
assertFalse(mp.isFinal(1)); | |||
assertTrue(mp.isSynthetic(1)); | |||
assertFalse(mp.isMandated(1)); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
import java.lang.annotation.*; | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE_USE) | |||
@interface Anno { | |||
int value() default 0; | |||
} |
@@ -0,0 +1 @@ | |||
interface Intface {} |
@@ -0,0 +1 @@ | |||
interface Intface2 {} |
@@ -0,0 +1,13 @@ | |||
public class Parameters { | |||
public void foo(String abc,int def, String... ghi) { | |||
} | |||
public void bar(Parameters this, String abc) { | |||
} | |||
class Inner { | |||
public Inner(String x) { | |||
} | |||
} | |||
enum Color { RED, GREEN, BLUE; } | |||
} |
@@ -0,0 +1 @@ | |||
class TypeAnnoOnClassTypeParameter<@Anno T,@Anno(2) Q> { } |
@@ -0,0 +1 @@ | |||
class TypeAnnoOnClassTypeParameterBound<T extends @Anno String & java.util.@Anno(2) List<@Anno(3) String>> { } |
@@ -0,0 +1,11 @@ | |||
public class TypeAnnoOnExceptionParameter { | |||
class Throwable2 extends Throwable {} | |||
class Throwable3 extends Throwable {} | |||
public void m() { | |||
try { | |||
foo(); | |||
} catch (@Anno Throwable3 | @Anno(99) Throwable2 t) { | |||
} | |||
} | |||
public void foo() throws Throwable2,Throwable3 {} | |||
} |
@@ -0,0 +1,9 @@ | |||
public class TypeAnnoOnField { | |||
@Anno int f1; | |||
java.util.List<@Anno String> f2; | |||
java.util.@Anno List[] f3; | |||
java.util.List<@Anno String>[] f4; | |||
} |
@@ -0,0 +1,11 @@ | |||
public class TypeAnnoOnInstanceOf { | |||
public void m() { | |||
Object o = "abc"; | |||
if (o instanceof @Anno(1) String) { | |||
String s = (String) o; | |||
} | |||
if (o instanceof @Anno(1) Integer) { | |||
Integer s = (Integer) o; | |||
} | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
public class TypeAnnoOnLocalVariable { | |||
public void m() { | |||
System.out.println("Hello"); | |||
@Anno String s = "abc"; | |||
System.out.println(s); | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
public class TypeAnnoOnMethodFormalParameter { | |||
void m(@Anno String s, @Anno(2) int i) {} | |||
} |
@@ -0,0 +1,3 @@ | |||
public class TypeAnnoOnMethodReceiver { | |||
void m(@Anno TypeAnnoOnMethodReceiver this) {} | |||
} |
@@ -0,0 +1,3 @@ | |||
public class TypeAnnoOnMethodReturn { | |||
@Anno String m() {return null;} | |||
} |
@@ -0,0 +1,3 @@ | |||
class TypeAnnoOnMethodTypeParameter { | |||
<@Anno T> void m() {} | |||
} |
@@ -0,0 +1,3 @@ | |||
class TypeAnnoOnMethodTypeParameterBound { | |||
<T extends @Anno String & java.util.@Anno(2) Map<Integer, @Anno(3) String>> void m() {} | |||
} |
@@ -0,0 +1,7 @@ | |||
public class TypeAnnoOnNew { | |||
public void m() { | |||
Object o = new @Anno String(); | |||
Object o2= new @Anno(2) String[1]; | |||
Object o3 = new @Anno(3) int @Anno(4)[3][3]; | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
import java.io.*; | |||
public class TypeAnnoOnResourceVariable { | |||
public void m() throws Exception { | |||
try (@Anno BufferedReader br1 = new BufferedReader(new FileReader("a")); | |||
@Anno(99) BufferedReader br2 = new BufferedReader(new FileReader("b"))) { | |||
System.out.println(br1.readLine()+br2.readLine()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,2 @@ | |||
class TypeAnnoOnSuperinterface1 implements @Anno Intface { | |||
} |
@@ -0,0 +1,3 @@ | |||
class TypeAnnoOnSupertypes extends @Anno(1) Object implements @Anno Intface, @Anno(2) Intface2 { | |||
} |
@@ -0,0 +1,3 @@ | |||
public class TypeAnnoOnThrows { | |||
void m() throws @Anno Exception, @Anno(2) Throwable {} | |||
} |
@@ -0,0 +1 @@ | |||
jar -cvMf ../testdata/java8testcode.jar *.class |
@@ -0,0 +1,2 @@ | |||
Notes: | |||
- build Parameters.java with -parameters option |