support for reading method parameter annotations from Java bytecodes
This commit is contained in:
parent
31d3bf835e
commit
b984760100
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2013 IBM Corporation.
|
||||
* 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package annotations;
|
||||
|
||||
public class ParameterAnnotations1 {
|
||||
|
||||
public static void foo(@RuntimeVisableAnnotation String s) {
|
||||
}
|
||||
|
||||
public static void bar(@AnnotationWithParams(enumParam=AnnotationEnum.VAL1,strArrParam={"biz","boz"},annotParam=@AnnotationWithSingleParam("sdfevs"),strParam="sdfsevs",intParam=25,klassParam=Integer.class) Integer i) {
|
||||
|
||||
}
|
||||
|
||||
public static void foo2(@RuntimeVisableAnnotation String s, @RuntimeInvisableAnnotation Integer i) {
|
||||
}
|
||||
|
||||
public void foo3(@RuntimeVisableAnnotation String s, @RuntimeInvisableAnnotation Integer i) {
|
||||
}
|
||||
|
||||
public void foo4(@RuntimeInvisableAnnotation @RuntimeVisableAnnotation String s, Integer i) {
|
||||
|
||||
}
|
||||
}
|
|
@ -172,4 +172,43 @@ public class AnnotationTest extends WalaTestCase {
|
|||
annots.toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParamAnnotations1() throws Exception {
|
||||
|
||||
TypeReference typeRef = TypeReference.findOrCreate(ClassLoaderReference.Application, "Lannotations/ParameterAnnotations1");
|
||||
|
||||
checkParameterAnnots(typeRef, "foo(Ljava/lang/String;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]");
|
||||
checkParameterAnnots(
|
||||
typeRef,
|
||||
"bar(Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/AnnotationWithParams> {enumParam=EnumElementValue [type=Lannotations/AnnotationEnum;, val=VAL1], strArrParam=ArrayElementValue [vals=[biz, boz]], annotParam=AnnotationElementValue [type=Lannotations/AnnotationWithSingleParam;, elementValues={value=sdfevs}], strParam=sdfsevs, intParam=25, klassParam=Ljava/lang/Integer;}]");
|
||||
checkParameterAnnots(typeRef, "foo2(Ljava/lang/String;Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]",
|
||||
"[Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>]");
|
||||
checkParameterAnnots(typeRef, "foo3(Ljava/lang/String;Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]",
|
||||
"[Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>]");
|
||||
checkParameterAnnots(typeRef, "foo4(Ljava/lang/String;Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>, Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]",
|
||||
"[]");
|
||||
|
||||
}
|
||||
|
||||
protected void checkParameterAnnots(TypeReference typeRef, String selector, String... expected) {
|
||||
MethodReference methodRefUnderTest = MethodReference.findOrCreate(typeRef, Selector.make(selector));
|
||||
|
||||
IMethod methodUnderTest = cha.resolveMethod(methodRefUnderTest);
|
||||
Assert.assertNotNull(methodRefUnderTest.toString() + " not found", methodUnderTest);
|
||||
Assert.assertTrue(methodUnderTest instanceof ShrikeCTMethod);
|
||||
ShrikeCTMethod shrikeCTMethodUnderTest = (ShrikeCTMethod) methodUnderTest;
|
||||
|
||||
Collection<Annotation>[] parameterAnnotations = shrikeCTMethodUnderTest.getParameterAnnotations();
|
||||
Assert.assertEquals(expected.length, parameterAnnotations.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
Assert.assertEquals(expected[i], parameterAnnotations[i].toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import com.ibm.wala.shrikeBT.Decoder;
|
|||
import com.ibm.wala.shrikeBT.IndirectionData;
|
||||
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.AnnotationType;
|
||||
import com.ibm.wala.shrikeCT.ClassReader;
|
||||
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
|
||||
import com.ibm.wala.shrikeCT.CodeReader;
|
||||
|
@ -24,9 +25,8 @@ import com.ibm.wala.shrikeCT.ExceptionsReader;
|
|||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.shrikeCT.LineNumberTableReader;
|
||||
import com.ibm.wala.shrikeCT.LocalVariableTableReader;
|
||||
import com.ibm.wala.shrikeCT.RuntimeInvisibleAnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.RuntimeVisibleAnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.SignatureReader;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.types.generics.MethodTypeSignature;
|
||||
|
@ -273,30 +273,11 @@ public final class ShrikeCTMethod extends ShrikeBTMethod implements IBytecodeMet
|
|||
return result;
|
||||
}
|
||||
|
||||
private AnnotationsReader getAnnotationsReader(boolean runtimeInvisible) {
|
||||
private AnnotationsReader getAnnotationsReader(AnnotationType type) {
|
||||
ClassReader.AttrIterator iter = new AttrIterator();
|
||||
getClassReader().initMethodAttributeIterator(shrikeMethodIndex, iter);
|
||||
|
||||
// search for the desired attribute
|
||||
AnnotationsReader result = null;
|
||||
try {
|
||||
for (; iter.isValid(); iter.advance()) {
|
||||
if (runtimeInvisible) {
|
||||
if (iter.getName().equals(RuntimeInvisibleAnnotationsReader.attrName)) {
|
||||
result = new RuntimeInvisibleAnnotationsReader(iter);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (iter.getName().equals(RuntimeVisibleAnnotationsReader.attrName)) {
|
||||
result = new RuntimeVisibleAnnotationsReader(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return result;
|
||||
return AnnotationsReader.getReaderForAnnotation(type, iter);
|
||||
}
|
||||
|
||||
private String computeGenericsSignature() throws InvalidClassFileException {
|
||||
|
@ -353,7 +334,8 @@ public final class ShrikeCTMethod extends ShrikeBTMethod implements IBytecodeMet
|
|||
}
|
||||
|
||||
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) throws InvalidClassFileException {
|
||||
AnnotationsReader r = getAnnotationsReader(runtimeInvisible);
|
||||
AnnotationsReader r = getAnnotationsReader(runtimeInvisible ? AnnotationType.RuntimeInvisibleAnnotations
|
||||
: AnnotationType.RuntimeVisibleAnnotations);
|
||||
return Annotation.getAnnotationsFromReader(r, getDeclaringClass().getClassLoader().getReference());
|
||||
}
|
||||
|
||||
|
@ -369,6 +351,42 @@ public final class ShrikeCTMethod extends ShrikeBTMethod implements IBytecodeMet
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get annotations on parameters as an array of Collections, where each array
|
||||
* element gives the annotations on the corresponding parameter. Note that the
|
||||
* 'this' parameter for an instance method cannot have annotations.
|
||||
*/
|
||||
public Collection<Annotation>[] getParameterAnnotations() {
|
||||
int numAnnotatedParams = isStatic() ? getNumberOfParameters() : getNumberOfParameters() - 1;
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Annotation>[] result = new Collection[numAnnotatedParams];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = HashSetFactory.make();
|
||||
}
|
||||
try {
|
||||
ClassLoaderReference reference = getDeclaringClass().getClassLoader().getReference();
|
||||
AnnotationsReader r = getAnnotationsReader(AnnotationType.RuntimeInvisibleParameterAnnotations);
|
||||
Collection<Annotation>[] paramAnnots = Annotation.getParameterAnnotationsFromReader(r, reference);
|
||||
if (paramAnnots != null) {
|
||||
assert paramAnnots.length == result.length : paramAnnots.length + " != " + result.length;
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i].addAll(paramAnnots[i]);
|
||||
}
|
||||
}
|
||||
r = getAnnotationsReader(AnnotationType.RuntimeVisibleParameterAnnotations);
|
||||
paramAnnots = Annotation.getParameterAnnotationsFromReader(r, reference);
|
||||
if (paramAnnots != null) {
|
||||
assert paramAnnots.length == result.length;
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i].addAll(paramAnnots[i]);
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final IndirectionData NO_INDIRECTIONS = new IndirectionData() {
|
||||
|
||||
private final int[] NOTHING = new int[0];
|
||||
|
|
|
@ -18,13 +18,12 @@ import java.util.List;
|
|||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.AnnotationType;
|
||||
import com.ibm.wala.shrikeCT.ClassConstants;
|
||||
import com.ibm.wala.shrikeCT.ClassReader;
|
||||
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
|
||||
import com.ibm.wala.shrikeCT.InnerClassesReader;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.shrikeCT.RuntimeInvisibleAnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.RuntimeVisibleAnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.SignatureReader;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
@ -47,9 +46,10 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
* The Shrike object that knows how to read the class file
|
||||
*/
|
||||
private final ShrikeClassReaderHandle reader;
|
||||
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if reader is null
|
||||
* @throws IllegalArgumentException
|
||||
* if reader is null
|
||||
*/
|
||||
public ShrikeClass(ShrikeClassReaderHandle reader, IClassLoader loader, IClassHierarchy cha) throws InvalidClassFileException {
|
||||
super(loader, cha);
|
||||
|
@ -70,7 +70,8 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
/**
|
||||
* Compute the fields declared by this class
|
||||
*
|
||||
* @throws InvalidClassFileException iff Shrike fails to read the class file correctly
|
||||
* @throws InvalidClassFileException
|
||||
* iff Shrike fails to read the class file correctly
|
||||
*/
|
||||
private void computeFields() throws InvalidClassFileException {
|
||||
ClassReader cr = reader.get();
|
||||
|
@ -82,7 +83,7 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
int accessFlags = cr.getFieldAccessFlags(i);
|
||||
Atom name = Atom.findOrCreateUnicodeAtom(cr.getFieldName(i));
|
||||
ImmutableByteArray b = ImmutableByteArray.make(cr.getFieldType(i));
|
||||
Collection<Annotation> annotations = HashSetFactory.make();
|
||||
Collection<Annotation> annotations = HashSetFactory.make();
|
||||
annotations.addAll(getRuntimeInvisibleAnnotations(i));
|
||||
annotations.addAll(getRuntimeVisibleAnnotations(i));
|
||||
annotations = annotations.isEmpty() ? null : annotations;
|
||||
|
@ -111,9 +112,11 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
modifiers = reader.get().getAccessFlags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is not yet ready to actually load the superclass.
|
||||
* Instead, we pull out the name of the superclass and cache it here, to avoid hitting the reader later.
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is
|
||||
* not yet ready to actually load the superclass. Instead, we pull out the
|
||||
* name of the superclass and cache it here, to avoid hitting the reader
|
||||
* later.
|
||||
*/
|
||||
private void computeSuperName() {
|
||||
try {
|
||||
|
@ -127,8 +130,10 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is not yet ready to actually load the interfaces.
|
||||
* Instead, we pull out the name of the interfaces and cache it here, to avoid hitting the reader later.
|
||||
* Note that this is called from the constructor, at which point this class is
|
||||
* not yet ready to actually load the interfaces. Instead, we pull out the
|
||||
* name of the interfaces and cache it here, to avoid hitting the reader
|
||||
* later.
|
||||
*/
|
||||
private void computeInterfaceNames() {
|
||||
try {
|
||||
|
@ -161,11 +166,11 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* initialize the TypeReference field for this instance
|
||||
*
|
||||
* @throws InvalidClassFileException iff Shrike can't read this class
|
||||
* @throws InvalidClassFileException
|
||||
* iff Shrike can't read this class
|
||||
*/
|
||||
private void computeTypeReference() throws InvalidClassFileException {
|
||||
String className = "L" + reader.get().getName();
|
||||
|
@ -174,7 +179,6 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
typeReference = TypeReference.findOrCreate(getClassLoader().getReference(), TypeName.findOrCreate(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
|
@ -198,7 +202,7 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear all optional cached data associated with this class
|
||||
*/
|
||||
|
@ -227,7 +231,7 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
public Collection<Annotation> getRuntimeVisibleAnnotations() throws InvalidClassFileException {
|
||||
return getAnnotations(false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
Collection<Annotation> result = HashSetFactory.make();
|
||||
|
@ -235,7 +239,7 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
result.addAll(getAnnotations(true));
|
||||
result.addAll(getAnnotations(false));
|
||||
} catch (InvalidClassFileException e) {
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -250,29 +254,10 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
ClassReader.AttrIterator attrs = new ClassReader.AttrIterator();
|
||||
r.initClassAttributeIterator(attrs);
|
||||
|
||||
// search for the desired attribute
|
||||
AnnotationsReader result = null;
|
||||
try {
|
||||
for (; attrs.isValid(); attrs.advance()) {
|
||||
if (runtimeInvisable){
|
||||
if (attrs.getName().equals(RuntimeInvisibleAnnotationsReader.attrName)) {
|
||||
result = new RuntimeInvisibleAnnotationsReader(attrs);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (attrs.getName().equals(RuntimeVisibleAnnotationsReader.attrName)) {
|
||||
result = new RuntimeVisibleAnnotationsReader(attrs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return result;
|
||||
return AnnotationsReader.getReaderForAnnotation(runtimeInvisable ? AnnotationType.RuntimeInvisibleAnnotations
|
||||
: AnnotationType.RuntimeVisibleAnnotations, attrs);
|
||||
}
|
||||
|
||||
|
||||
private InnerClassesReader getInnerClassesReader() throws InvalidClassFileException {
|
||||
ClassReader r = reader.get();
|
||||
ClassReader.AttrIterator attrs = new ClassReader.AttrIterator();
|
||||
|
@ -297,26 +282,8 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
ClassReader.AttrIterator iter = new AttrIterator();
|
||||
reader.get().initFieldAttributeIterator(fieldIndex, iter);
|
||||
|
||||
// search for the desired attribute
|
||||
AnnotationsReader result = null;
|
||||
try {
|
||||
for (; iter.isValid(); iter.advance()) {
|
||||
if (runtimeInvisible) {
|
||||
if (iter.getName().equals(RuntimeInvisibleAnnotationsReader.attrName)) {
|
||||
result = new RuntimeInvisibleAnnotationsReader(iter);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (iter.getName().equals(RuntimeVisibleAnnotationsReader.attrName)) {
|
||||
result = new RuntimeVisibleAnnotationsReader(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return result;
|
||||
return AnnotationsReader.getReaderForAnnotation(runtimeInvisible ? AnnotationType.RuntimeInvisibleAnnotations
|
||||
: AnnotationType.RuntimeVisibleAnnotations, iter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,7 +299,7 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
public Collection<Annotation> getRuntimeVisibleAnnotations(int fieldIndex) throws InvalidClassFileException {
|
||||
return getFieldAnnotations(fieldIndex, false);
|
||||
}
|
||||
|
||||
|
||||
protected Collection<Annotation> getFieldAnnotations(int fieldIndex, boolean runtimeInvisible) throws InvalidClassFileException {
|
||||
AnnotationsReader r = getFieldAnnotationsReader(runtimeInvisible, fieldIndex);
|
||||
return Annotation.getAnnotationsFromReader(r, getClassLoader().getReference());
|
||||
|
@ -373,7 +340,8 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Does the class file indicate that this class is a member of some other class?
|
||||
* Does the class file indicate that this class is a member of some other
|
||||
* class?
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
|
@ -411,10 +379,11 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If this is an inner class, return the outer class. Else return null.
|
||||
* @throws InvalidClassFileException
|
||||
* If this is an inner class, return the outer class. Else return null.
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public TypeReference getOuterClass() throws InvalidClassFileException {
|
||||
if (!isInnerClass()) {
|
||||
|
@ -431,7 +400,8 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Module getContainer() {
|
||||
return reader.getModuleEntry().getContainer();
|
||||
}
|
||||
|
|
|
@ -73,13 +73,7 @@ public class Annotation {
|
|||
public static Collection<Annotation> getAnnotationsFromReader(AnnotationsReader r, ClassLoaderReference clRef) throws InvalidClassFileException {
|
||||
if (r != null) {
|
||||
AnnotationAttribute[] allAnnotations = r.getAllAnnotations();
|
||||
Collection<Annotation> result = HashSetFactory.make();
|
||||
for (AnnotationAttribute annot : allAnnotations) {
|
||||
String type = annot.type;
|
||||
type = type.replaceAll(";", "");
|
||||
TypeReference t = TypeReference.findOrCreate(clRef, type);
|
||||
result.add(makeWithNamed(t, annot.elementValues));
|
||||
}
|
||||
Collection<Annotation> result = convertToAnnotations(clRef, allAnnotations);
|
||||
return result;
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
|
@ -87,6 +81,35 @@ public class Annotation {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* If r != null, return parameter annotations as an array with length equal to
|
||||
* number of annotatable parameters. Otherwise, return null.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Collection<Annotation>[] getParameterAnnotationsFromReader(AnnotationsReader r, ClassLoaderReference clRef) throws InvalidClassFileException {
|
||||
if (r != null) {
|
||||
AnnotationAttribute[][] allAnnots = r.getAllParameterAnnotations();
|
||||
Collection<Annotation>[] result = new Collection[allAnnots.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = convertToAnnotations(clRef, allAnnots[i]);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static Collection<Annotation> convertToAnnotations(ClassLoaderReference clRef, AnnotationAttribute[] allAnnotations) {
|
||||
Collection<Annotation> result = HashSetFactory.make();
|
||||
for (AnnotationAttribute annot : allAnnotations) {
|
||||
String type = annot.type;
|
||||
type = type.replaceAll(";", "");
|
||||
TypeReference t = TypeReference.findOrCreate(clRef, type);
|
||||
result.add(makeWithNamed(t, annot.elementValues));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer("Annotation type " + type);
|
||||
|
|
|
@ -32,8 +32,6 @@ import com.ibm.wala.shrikeCT.ConstantValueReader;
|
|||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.shrikeCT.LineNumberTableReader;
|
||||
import com.ibm.wala.shrikeCT.LocalVariableTableReader;
|
||||
import com.ibm.wala.shrikeCT.RuntimeInvisibleAnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.RuntimeVisibleAnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.SignatureReader;
|
||||
import com.ibm.wala.shrikeCT.SourceFileReader;
|
||||
|
||||
|
@ -266,11 +264,8 @@ public class ClassPrinter {
|
|||
} else if (name.equals("Signature")) {
|
||||
SignatureReader sr = new SignatureReader(attrs);
|
||||
w.write(" signature: " + cr.getCP().getCPUtf8(sr.getSignatureCPIndex()) + "\n");
|
||||
} else if (name.equals(RuntimeInvisibleAnnotationsReader.attrName)) {
|
||||
AnnotationsReader r = new RuntimeInvisibleAnnotationsReader(attrs);
|
||||
printAnnotations(cr, attrs, r);
|
||||
} else if (name.equals(RuntimeVisibleAnnotationsReader.attrName)) {
|
||||
AnnotationsReader r = new RuntimeVisibleAnnotationsReader(attrs);
|
||||
} else if (AnnotationsReader.isKnownAnnotation(name)) {
|
||||
AnnotationsReader r = new AnnotationsReader(attrs, name);
|
||||
printAnnotations(cr, attrs, r);
|
||||
} else {
|
||||
int len = attrs.getDataSize();
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Map;
|
|||
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
* This class reads Annotations attributes, e.g., RuntimeInvisibleAnnotations.
|
||||
|
@ -74,6 +75,7 @@ public class AnnotationsReader extends AttributeReader {
|
|||
* @see AnnotationsReader#readElementValueAndSize(int)
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public static interface ElementValue {
|
||||
}
|
||||
|
||||
|
@ -104,12 +106,12 @@ public class AnnotationsReader extends AttributeReader {
|
|||
* Represents enum constant annotation arguments.
|
||||
*/
|
||||
public static class EnumElementValue implements ElementValue {
|
||||
|
||||
|
||||
/**
|
||||
* the name of the enum type
|
||||
*/
|
||||
public final String enumType;
|
||||
|
||||
|
||||
/**
|
||||
* the enum value
|
||||
*/
|
||||
|
@ -151,7 +153,7 @@ public class AnnotationsReader extends AttributeReader {
|
|||
}
|
||||
|
||||
/**
|
||||
* get all the annotations declared in this attribute.
|
||||
* get all the annotations declared in this attribute.
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
|
@ -167,6 +169,37 @@ public class AnnotationsReader extends AttributeReader {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* param_annotations {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u1 num_parameters;
|
||||
* {
|
||||
* u2 num_annotations;
|
||||
* annotation annotations[num_annotations];
|
||||
* } parameter_annotations[num_parameters];
|
||||
* </pre>
|
||||
*/
|
||||
public AnnotationAttribute[][] getAllParameterAnnotations() throws InvalidClassFileException {
|
||||
int numParamOffset = beginOffset + 6;
|
||||
checkSize(numParamOffset, 1);
|
||||
int paramCount = cr.getByte(numParamOffset);
|
||||
AnnotationAttribute[][] result = new AnnotationAttribute[paramCount][];
|
||||
// skip attribute_name_index, attribute_length, and num_parameters
|
||||
int offset = beginOffset + 7;
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
checkSize(offset, 2);
|
||||
result[i] = new AnnotationAttribute[cr.getUShort(offset)];
|
||||
offset += 2;
|
||||
for (int j = 0; j < result[i].length; j++) {
|
||||
Pair<AnnotationAttribute, Integer> attributeAndSize = getAttributeAndSize(offset);
|
||||
result[i][j] = attributeAndSize.fst;
|
||||
offset += attributeAndSize.snd;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* <pre>
|
||||
* annotation {
|
||||
|
@ -302,7 +335,7 @@ public class AnnotationsReader extends AttributeReader {
|
|||
}
|
||||
return Pair.<ElementValue, Integer> make(new ArrayElementValue(vals), numArrayBytes);
|
||||
case '@': // annotation
|
||||
Pair<AnnotationAttribute,Integer> attributeAndSize = getAttributeAndSize(offset+1);
|
||||
Pair<AnnotationAttribute, Integer> attributeAndSize = getAttributeAndSize(offset + 1);
|
||||
// add 1 to size for the tag
|
||||
return Pair.<ElementValue, Integer> make(attributeAndSize.fst, attributeAndSize.snd + 1);
|
||||
default:
|
||||
|
@ -311,4 +344,35 @@ public class AnnotationsReader extends AttributeReader {
|
|||
}
|
||||
}
|
||||
|
||||
// //////////////
|
||||
// utility methods for reading well-known annotation types
|
||||
// //////////////
|
||||
|
||||
public static enum AnnotationType {
|
||||
RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations,RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations
|
||||
}
|
||||
|
||||
public static boolean isKnownAnnotation(String name) {
|
||||
for (AnnotationType t : AnnotationType.values()) {
|
||||
if (t.name().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static AnnotationsReader getReaderForAnnotation(AnnotationType type, ClassReader.AttrIterator iter) {
|
||||
// search for the desired attribute
|
||||
final String attrName = type.toString();
|
||||
try {
|
||||
for (; iter.isValid(); iter.advance()) {
|
||||
if (iter.getName().equals(attrName)) {
|
||||
return new AnnotationsReader(iter, attrName);
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002,2006 IBM Corporation.
|
||||
* 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.shrikeCT;
|
||||
|
||||
/**
|
||||
* This class reads RuntimeInvisibleAnnotations attributes.
|
||||
*
|
||||
* @author sjfink
|
||||
*/
|
||||
public final class RuntimeInvisibleAnnotationsReader extends AnnotationsReader {
|
||||
|
||||
public static final String attrName = "RuntimeInvisibleAnnotations";
|
||||
|
||||
public RuntimeInvisibleAnnotationsReader(ClassReader.AttrIterator iter) throws InvalidClassFileException {
|
||||
super(iter, attrName);
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002,2006 IBM Corporation.
|
||||
* 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.shrikeCT;
|
||||
|
||||
/**
|
||||
* This class reads RuntimeVisibleAnnotations attributes.
|
||||
*
|
||||
* @author sjfink
|
||||
*/
|
||||
public final class RuntimeVisibleAnnotationsReader extends AnnotationsReader {
|
||||
|
||||
public final static String attrName = "RuntimeVisibleAnnotations";
|
||||
|
||||
public RuntimeVisibleAnnotationsReader(ClassReader.AttrIterator iter) throws InvalidClassFileException {
|
||||
super(iter, attrName);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue