blob: 032fc576ba2b0e69b610cddec07eeb65ee6c649e [file] [log] [blame]
// Keep somewhat in sync with
// langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java
// Adapted to handled the same type qualifier appearing multiple times.
import com.sun.tools.classfile.Annotation;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPool.InvalidIndex;
import com.sun.tools.classfile.ConstantPool.UnexpectedEntry;
import com.sun.tools.classfile.Method;
import com.sun.tools.classfile.RuntimeAnnotations_attribute;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
public class ReferenceInfoUtil {
public static final int IGNORE_VALUE = -321;
public static List<Annotation> extendedAnnotationsOf(ClassFile cf) {
List<Annotation> annos = new ArrayList<>();
findAnnotations(cf, annos);
return annos;
}
/////////////////// Extract annotations //////////////////
private static void findAnnotations(ClassFile cf, List<Annotation> annos) {
for (Method m : cf.methods) {
findAnnotations(cf, m, Attribute.RuntimeVisibleAnnotations, annos);
}
}
/**
* Test the result of Attributes.getIndex according to expectations encoded in the method's name.
*/
private static void findAnnotations(ClassFile cf, Method m, String name, List<Annotation> annos) {
int index = m.attributes.getIndex(cf.constant_pool, name);
if (index != -1) {
Attribute attr = m.attributes.get(index);
assert attr instanceof RuntimeAnnotations_attribute;
RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute) attr;
for (Annotation an : tAttr.annotations) {
if (!containsName(annos, an, cf)) {
annos.add(an);
}
}
}
}
private static Annotation findAnnotation(String name, List<Annotation> annotations, ClassFile cf)
throws InvalidIndex, UnexpectedEntry {
String properName = "L" + name + ";";
for (Annotation anno : annotations) {
String actualName = cf.constant_pool.getUTF8Value(anno.type_index);
if (properName.equals(actualName)) {
return anno;
}
}
return null;
}
public static boolean compare(
List<String> expectedAnnos, List<Annotation> actualAnnos, ClassFile cf)
throws InvalidIndex, UnexpectedEntry {
if (actualAnnos.size() != expectedAnnos.size()) {
throw new ComparisonException("Wrong number of annotations", expectedAnnos, actualAnnos, cf);
}
for (String annoName : expectedAnnos) {
Annotation anno = findAnnotation(annoName, actualAnnos, cf);
if (anno == null) {
throw new ComparisonException(
"Expected annotation not found: " + annoName, expectedAnnos, actualAnnos, cf);
}
}
return true;
}
private static boolean containsName(List<Annotation> annos, Annotation anno, ClassFile cf) {
try {
for (Annotation an : annos) {
if (cf.constant_pool
.getUTF8Value(an.type_index)
.equals(cf.constant_pool.getUTF8Value(anno.type_index))) {
return true;
}
}
} catch (Exception e) {
throw new RuntimeException();
}
return false;
}
}
class ComparisonException extends RuntimeException {
private static final long serialVersionUID = -3930499712333815821L;
public final List<String> expected;
public final List<Annotation> found;
public final ClassFile cf;
public ComparisonException(
String message, List<String> expected, List<Annotation> found, ClassFile cf) {
super(message);
this.expected = expected;
this.found = found;
this.cf = cf;
}
public String toString() {
StringJoiner foundString = new StringJoiner(",");
for (Annotation anno : found) {
try {
foundString.add(cf.constant_pool.getUTF8Value(anno.type_index));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return String.join(
System.lineSeparator(),
super.toString(),
"\tExpected: "
+ expected.size()
+ " annotations; but found: "
+ found.size()
+ " annotations",
" Expected: " + expected,
" Found: " + foundString);
}
}