test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

     1 /*
     2  * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 import java.util.ArrayList;
    25 import java.util.Arrays;
    26 import java.util.List;
    27 import java.util.Map;
    29 import com.sun.tools.classfile.Attribute;
    30 import com.sun.tools.classfile.ClassFile;
    31 import com.sun.tools.classfile.Code_attribute;
    32 import com.sun.tools.classfile.TypeAnnotation;
    33 import com.sun.tools.classfile.Field;
    34 import com.sun.tools.classfile.Method;
    35 import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute;
    36 import com.sun.tools.classfile.ConstantPool.InvalidIndex;
    37 import com.sun.tools.classfile.ConstantPool.UnexpectedEntry;
    39 public class ReferenceInfoUtil {
    41     public static final int IGNORE_VALUE = -321;
    43     public static List<TypeAnnotation> extendedAnnotationsOf(ClassFile cf) {
    44         List<TypeAnnotation> annos = new ArrayList<TypeAnnotation>();
    45         findAnnotations(cf, annos);
    46         return annos;
    47     }
    49     /////////////////// Extract type annotations //////////////////
    50     private static void findAnnotations(ClassFile cf, List<TypeAnnotation> annos) {
    51         findAnnotations(cf, Attribute.RuntimeVisibleTypeAnnotations, annos);
    52         findAnnotations(cf, Attribute.RuntimeInvisibleTypeAnnotations, annos);
    54         for (Field f : cf.fields) {
    55             findAnnotations(cf, f, annos);
    56         }
    57         for (Method m: cf.methods) {
    58             findAnnotations(cf, m, annos);
    59         }
    60     }
    62     private static void findAnnotations(ClassFile cf, Method m, List<TypeAnnotation> annos) {
    63         findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos);
    64         findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos);
    65     }
    67     private static void findAnnotations(ClassFile cf, Field m, List<TypeAnnotation> annos) {
    68         findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos);
    69         findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos);
    70     }
    72     // test the result of Attributes.getIndex according to expectations
    73     // encoded in the method's name
    74     private static void findAnnotations(ClassFile cf, String name, List<TypeAnnotation> annos) {
    75         int index = cf.attributes.getIndex(cf.constant_pool, name);
    76         if (index != -1) {
    77             Attribute attr = cf.attributes.get(index);
    78             assert attr instanceof RuntimeTypeAnnotations_attribute;
    79             RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
    80             annos.addAll(Arrays.asList(tAttr.annotations));
    81         }
    82     }
    84     // test the result of Attributes.getIndex according to expectations
    85     // encoded in the method's name
    86     private static void findAnnotations(ClassFile cf, Method m, String name, List<TypeAnnotation> annos) {
    87         int index = m.attributes.getIndex(cf.constant_pool, name);
    88         if (index != -1) {
    89             Attribute attr = m.attributes.get(index);
    90             assert attr instanceof RuntimeTypeAnnotations_attribute;
    91             RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
    92             annos.addAll(Arrays.asList(tAttr.annotations));
    93         }
    95         int cindex = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
    96         if (cindex != -1) {
    97             Attribute cattr = m.attributes.get(cindex);
    98             assert cattr instanceof Code_attribute;
    99             Code_attribute cAttr = (Code_attribute)cattr;
   100             index = cAttr.attributes.getIndex(cf.constant_pool, name);
   101             if (index != -1) {
   102                 Attribute attr = cAttr.attributes.get(index);
   103                 assert attr instanceof RuntimeTypeAnnotations_attribute;
   104                 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
   105                 annos.addAll(Arrays.asList(tAttr.annotations));
   106             }
   107         }
   108     }
   110     // test the result of Attributes.getIndex according to expectations
   111     // encoded in the method's name
   112     private static void findAnnotations(ClassFile cf, Field m, String name, List<TypeAnnotation> annos) {
   113         int index = m.attributes.getIndex(cf.constant_pool, name);
   114         if (index != -1) {
   115             Attribute attr = m.attributes.get(index);
   116             assert attr instanceof RuntimeTypeAnnotations_attribute;
   117             RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
   118             annos.addAll(Arrays.asList(tAttr.annotations));
   119         }
   120     }
   122     /////////////////// TA Position Builder ///////////////////////
   123     /* TODO: comment out this dead code. Was this unfinished code that was
   124      * supposed to be used somewhere? The tests pass without this.
   125     private static class TAPositionBuilder {
   126         private TypeAnnotation.Position pos = new TypeAnnotation.Position();
   128         private TAPositionBuilder() { }
   130         public TypeAnnotation.Position build() { return pos; }
   132         public static TAPositionBuilder ofType(TypeAnnotation.TargetType type) {
   133             TAPositionBuilder builder = new TAPositionBuilder();
   134             builder.pos.type = type;
   135             return builder;
   136         }
   138         public TAPositionBuilder atOffset(int offset) {
   139             switch (pos.type) {
   140             // type cast
   141             case TYPECAST:
   142             // instanceof
   143             case INSTANCEOF:
   144             // new expression
   145             case NEW:
   146                 pos.offset = offset;
   147                 break;
   148             default:
   149                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   150             }
   151             return this;
   152         }
   154         public TAPositionBuilder atLocalPosition(int offset, int length, int index) {
   155             switch (pos.type) {
   156             // local variable
   157             case LOCAL_VARIABLE:
   158                 pos.lvarOffset = new int[] { offset };
   159                 pos.lvarLength = new int[] { length };
   160                 pos.lvarIndex  = new int[] { index  };
   161                 break;
   162             default:
   163                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   164             }
   165             return this;
   166         }
   168         public TAPositionBuilder atParameterIndex(int index) {
   169             switch (pos.type) {
   170             // type parameters
   171             case CLASS_TYPE_PARAMETER:
   172             case METHOD_TYPE_PARAMETER:
   173             // method parameter
   174             case METHOD_FORMAL_PARAMETER:
   175                 pos.parameter_index = index;
   176                 break;
   177             default:
   178                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   179             }
   180             return this;
   181         }
   183         public TAPositionBuilder atParamBound(int param, int bound) {
   184             switch (pos.type) {
   185             // type parameters bounds
   186             case CLASS_TYPE_PARAMETER_BOUND:
   187             case METHOD_TYPE_PARAMETER_BOUND:
   188                 pos.parameter_index = param;
   189                 pos.bound_index = bound;
   190                 break;
   191             default:
   192                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   193             }
   194             return this;
   195         }
   197         public TAPositionBuilder atWildcardPosition(TypeAnnotation.Position pos) {
   198             switch (pos.type) {
   199             // wildcards
   200             case WILDCARD_BOUND:
   201                 pos.wildcard_position = pos;
   202                 break;
   203             default:
   204                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   205             }
   206             return this;
   207         }
   209         public TAPositionBuilder atTypeIndex(int index) {
   210             switch (pos.type) {
   211             // class extends or implements clauses
   212             case CLASS_EXTENDS:
   213             // throws
   214             case THROWS:
   215                 pos.type_index = index;
   216                 break;
   217             default:
   218                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   219             }
   220             return this;
   221         }
   223         public TAPositionBuilder atOffsetWithIndex(int offset, int index) {
   224             switch (pos.type) {
   225             // method type argument: wasn't specified
   226             case NEW_TYPE_ARGUMENT:
   227             case METHOD_TYPE_ARGUMENT:
   228                 pos.offset = offset;
   229                 pos.type_index = index;
   230                 break;
   231             default:
   232                 throw new IllegalArgumentException("invalid field for given type: " + pos.type);
   233             }
   234             return this;
   235         }
   237         public TAPositionBuilder atGenericLocation(Integer ...loc) {
   238             pos.location = Arrays.asList(loc);
   239             pos.type = pos.type.getGenericComplement();
   240             return this;
   241         }
   242     }*/
   244     /////////////////////// Equality testing /////////////////////
   245     private static boolean areEquals(int a, int b) {
   246         return a == b || a == IGNORE_VALUE || b == IGNORE_VALUE;
   247     }
   249     private static boolean areEquals(int[] a, int[] a2) {
   250         if (a==a2)
   251             return true;
   252         if (a==null || a2==null)
   253             return false;
   255         int length = a.length;
   256         if (a2.length != length)
   257             return false;
   259         for (int i=0; i<length; i++)
   260             if (a[i] != a2[i] && a[i] != IGNORE_VALUE && a2[i] != IGNORE_VALUE)
   261                 return false;
   263         return true;
   264     }
   266     public static boolean areEquals(TypeAnnotation.Position p1, TypeAnnotation.Position p2) {
   267         if (p1 == p2)
   268             return true;
   269         if (p1 == null || p2 == null)
   270             return false;
   272         return ((p1.type == p2.type)
   273                 && (p1.location.equals(p2.location))
   274                 && areEquals(p1.offset, p2.offset)
   275                 && areEquals(p1.lvarOffset, p2.lvarOffset)
   276                 && areEquals(p1.lvarLength, p2.lvarLength)
   277                 && areEquals(p1.lvarIndex, p2.lvarIndex)
   278                 && areEquals(p1.bound_index, p2.bound_index)
   279                 && areEquals(p1.parameter_index, p2.parameter_index)
   280                 && areEquals(p1.type_index, p2.type_index)
   281                 && areEquals(p1.exception_index, p2.exception_index));
   282     }
   284     private static TypeAnnotation findAnnotation(String name, List<TypeAnnotation> annotations, ClassFile cf) throws InvalidIndex, UnexpectedEntry {
   285         String properName = "L" + name + ";";
   286         for (TypeAnnotation anno : annotations) {
   287             String actualName = cf.constant_pool.getUTF8Value(anno.annotation.type_index);
   288             if (properName.equals(actualName))
   289                 return anno;
   290         }
   291         return null;
   292     }
   294     public static boolean compare(Map<String, TypeAnnotation.Position> expectedAnnos,
   295             List<TypeAnnotation> actualAnnos, ClassFile cf) throws InvalidIndex, UnexpectedEntry {
   296         if (actualAnnos.size() != expectedAnnos.size()) {
   297             throw new ComparisionException("Wrong number of annotations",
   298                     expectedAnnos,
   299                     actualAnnos);
   300         }
   302         for (Map.Entry<String, TypeAnnotation.Position> e : expectedAnnos.entrySet()) {
   303             String aName = e.getKey();
   304             TypeAnnotation.Position expected = e.getValue();
   305             TypeAnnotation actual = findAnnotation(aName, actualAnnos, cf);
   306             if (actual == null)
   307                 throw new ComparisionException("Expected annotation not found: " + aName);
   309             // TODO: you currently get an exception if the test case does not use all necessary
   310             // annotation attributes, e.g. forgetting the offset for a local variable.
   311             // It would be nicer to give an understandable warning instead.
   312             if (!areEquals(expected, actual.position)) {
   313                 throw new ComparisionException("Unexpected position for annotation : " + aName +
   314                         "\n  Expected: " + expected.toString() +
   315                         "\n  Found: " + actual.position.toString());
   316             }
   317         }
   318         return true;
   319     }
   320 }
   322 class ComparisionException extends RuntimeException {
   323     private static final long serialVersionUID = -3930499712333815821L;
   325     public final Map<String, TypeAnnotation.Position> expected;
   326     public final List<TypeAnnotation> found;
   328     public ComparisionException(String message) {
   329         this(message, null, null);
   330     }
   332     public ComparisionException(String message, Map<String, TypeAnnotation.Position> expected, List<TypeAnnotation> found) {
   333         super(message);
   334         this.expected = expected;
   335         this.found = found;
   336     }
   338     public String toString() {
   339         String str = super.toString();
   340         if (expected != null && found != null) {
   341             str += "\n\tExpected: " + expected.size() + " annotations; but found: " + found.size() + " annotations\n" +
   342                    "  Expected: " + expected +
   343                    "\n  Found: " + found;
   344         }
   345         return str;
   346     }
   347 }

mercurial