| // 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); |
| } |
| } |