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

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 1755
ddb4a2bfcd82
parent 0
959103a6100f
permissions
-rw-r--r--

merge

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

mercurial