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

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 1755
ddb4a2bfcd82
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

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

mercurial