src/share/classes/com/sun/tools/classfile/TypeAnnotation.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

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. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.classfile;
aoqi@0 27
aoqi@0 28 import java.io.IOException;
aoqi@0 29 import java.util.ArrayList;
aoqi@0 30 import java.util.List;
aoqi@0 31
aoqi@0 32 import com.sun.tools.classfile.TypeAnnotation.Position.TypePathEntry;
aoqi@0 33
aoqi@0 34 /**
aoqi@0 35 * See JSR 308 specification, Section 3.
aoqi@0 36 *
aoqi@0 37 * <p><b>This is NOT part of any supported API.
aoqi@0 38 * If you write code that depends on this, you do so at your own risk.
aoqi@0 39 * This code and its internal interfaces are subject to change or
aoqi@0 40 * deletion without notice.</b>
aoqi@0 41 */
aoqi@0 42 public class TypeAnnotation {
aoqi@0 43 TypeAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
aoqi@0 44 constant_pool = cr.getConstantPool();
aoqi@0 45 position = read_position(cr);
aoqi@0 46 annotation = new Annotation(cr);
aoqi@0 47 }
aoqi@0 48
aoqi@0 49 public TypeAnnotation(ConstantPool constant_pool,
aoqi@0 50 Annotation annotation, Position position) {
aoqi@0 51 this.constant_pool = constant_pool;
aoqi@0 52 this.position = position;
aoqi@0 53 this.annotation = annotation;
aoqi@0 54 }
aoqi@0 55
aoqi@0 56 public int length() {
aoqi@0 57 int n = annotation.length();
aoqi@0 58 n += position_length(position);
aoqi@0 59 return n;
aoqi@0 60 }
aoqi@0 61
aoqi@0 62 @Override
aoqi@0 63 public String toString() {
aoqi@0 64 try {
aoqi@0 65 return "@" + constant_pool.getUTF8Value(annotation.type_index).toString().substring(1) +
aoqi@0 66 " pos: " + position.toString();
aoqi@0 67 } catch (Exception e) {
aoqi@0 68 e.printStackTrace();
aoqi@0 69 return e.toString();
aoqi@0 70 }
aoqi@0 71 }
aoqi@0 72
aoqi@0 73 public final ConstantPool constant_pool;
aoqi@0 74 public final Position position;
aoqi@0 75 public final Annotation annotation;
aoqi@0 76
aoqi@0 77 private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
aoqi@0 78 // Copied from ClassReader
aoqi@0 79 int tag = cr.readUnsignedByte(); // TargetType tag is a byte
aoqi@0 80 if (!TargetType.isValidTargetTypeValue(tag))
aoqi@0 81 throw new Annotation.InvalidAnnotation("TypeAnnotation: Invalid type annotation target type value: " + String.format("0x%02X", tag));
aoqi@0 82
aoqi@0 83 TargetType type = TargetType.fromTargetTypeValue(tag);
aoqi@0 84
aoqi@0 85 Position position = new Position();
aoqi@0 86 position.type = type;
aoqi@0 87
aoqi@0 88 switch (type) {
aoqi@0 89 // instanceof
aoqi@0 90 case INSTANCEOF:
aoqi@0 91 // new expression
aoqi@0 92 case NEW:
aoqi@0 93 // constructor/method reference receiver
aoqi@0 94 case CONSTRUCTOR_REFERENCE:
aoqi@0 95 case METHOD_REFERENCE:
aoqi@0 96 position.offset = cr.readUnsignedShort();
aoqi@0 97 break;
aoqi@0 98 // local variable
aoqi@0 99 case LOCAL_VARIABLE:
aoqi@0 100 // resource variable
aoqi@0 101 case RESOURCE_VARIABLE:
aoqi@0 102 int table_length = cr.readUnsignedShort();
aoqi@0 103 position.lvarOffset = new int[table_length];
aoqi@0 104 position.lvarLength = new int[table_length];
aoqi@0 105 position.lvarIndex = new int[table_length];
aoqi@0 106 for (int i = 0; i < table_length; ++i) {
aoqi@0 107 position.lvarOffset[i] = cr.readUnsignedShort();
aoqi@0 108 position.lvarLength[i] = cr.readUnsignedShort();
aoqi@0 109 position.lvarIndex[i] = cr.readUnsignedShort();
aoqi@0 110 }
aoqi@0 111 break;
aoqi@0 112 // exception parameter
aoqi@0 113 case EXCEPTION_PARAMETER:
aoqi@0 114 position.exception_index = cr.readUnsignedShort();
aoqi@0 115 break;
aoqi@0 116 // method receiver
aoqi@0 117 case METHOD_RECEIVER:
aoqi@0 118 // Do nothing
aoqi@0 119 break;
aoqi@0 120 // type parameter
aoqi@0 121 case CLASS_TYPE_PARAMETER:
aoqi@0 122 case METHOD_TYPE_PARAMETER:
aoqi@0 123 position.parameter_index = cr.readUnsignedByte();
aoqi@0 124 break;
aoqi@0 125 // type parameter bound
aoqi@0 126 case CLASS_TYPE_PARAMETER_BOUND:
aoqi@0 127 case METHOD_TYPE_PARAMETER_BOUND:
aoqi@0 128 position.parameter_index = cr.readUnsignedByte();
aoqi@0 129 position.bound_index = cr.readUnsignedByte();
aoqi@0 130 break;
aoqi@0 131 // class extends or implements clause
aoqi@0 132 case CLASS_EXTENDS:
aoqi@0 133 int in = cr.readUnsignedShort();
aoqi@0 134 if (in == 0xFFFF)
aoqi@0 135 in = -1;
aoqi@0 136 position.type_index = in;
aoqi@0 137 break;
aoqi@0 138 // throws
aoqi@0 139 case THROWS:
aoqi@0 140 position.type_index = cr.readUnsignedShort();
aoqi@0 141 break;
aoqi@0 142 // method parameter
aoqi@0 143 case METHOD_FORMAL_PARAMETER:
aoqi@0 144 position.parameter_index = cr.readUnsignedByte();
aoqi@0 145 break;
aoqi@0 146 // type cast
aoqi@0 147 case CAST:
aoqi@0 148 // method/constructor/reference type argument
aoqi@0 149 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
aoqi@0 150 case METHOD_INVOCATION_TYPE_ARGUMENT:
aoqi@0 151 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
aoqi@0 152 case METHOD_REFERENCE_TYPE_ARGUMENT:
aoqi@0 153 position.offset = cr.readUnsignedShort();
aoqi@0 154 position.type_index = cr.readUnsignedByte();
aoqi@0 155 break;
aoqi@0 156 // We don't need to worry about these
aoqi@0 157 case METHOD_RETURN:
aoqi@0 158 case FIELD:
aoqi@0 159 break;
aoqi@0 160 case UNKNOWN:
aoqi@0 161 throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!");
aoqi@0 162 default:
aoqi@0 163 throw new AssertionError("TypeAnnotation: Unknown target type: " + type);
aoqi@0 164 }
aoqi@0 165
aoqi@0 166 { // Write type path
aoqi@0 167 int len = cr.readUnsignedByte();
aoqi@0 168 List<Integer> loc = new ArrayList<Integer>(len);
aoqi@0 169 for (int i = 0; i < len * TypePathEntry.bytesPerEntry; ++i)
aoqi@0 170 loc.add(cr.readUnsignedByte());
aoqi@0 171 position.location = Position.getTypePathFromBinary(loc);
aoqi@0 172 }
aoqi@0 173 return position;
aoqi@0 174 }
aoqi@0 175
aoqi@0 176 private static int position_length(Position pos) {
aoqi@0 177 int n = 0;
aoqi@0 178 n += 1; // TargetType tag is a byte
aoqi@0 179 switch (pos.type) {
aoqi@0 180 // instanceof
aoqi@0 181 case INSTANCEOF:
aoqi@0 182 // new expression
aoqi@0 183 case NEW:
aoqi@0 184 // constructor/method reference receiver
aoqi@0 185 case CONSTRUCTOR_REFERENCE:
aoqi@0 186 case METHOD_REFERENCE:
aoqi@0 187 n += 2; // offset
aoqi@0 188 break;
aoqi@0 189 // local variable
aoqi@0 190 case LOCAL_VARIABLE:
aoqi@0 191 // resource variable
aoqi@0 192 case RESOURCE_VARIABLE:
aoqi@0 193 n += 2; // table_length;
aoqi@0 194 int table_length = pos.lvarOffset.length;
aoqi@0 195 n += 2 * table_length; // offset
aoqi@0 196 n += 2 * table_length; // length
aoqi@0 197 n += 2 * table_length; // index
aoqi@0 198 break;
aoqi@0 199 // exception parameter
aoqi@0 200 case EXCEPTION_PARAMETER:
aoqi@0 201 n += 2; // exception_index
aoqi@0 202 break;
aoqi@0 203 // method receiver
aoqi@0 204 case METHOD_RECEIVER:
aoqi@0 205 // Do nothing
aoqi@0 206 break;
aoqi@0 207 // type parameter
aoqi@0 208 case CLASS_TYPE_PARAMETER:
aoqi@0 209 case METHOD_TYPE_PARAMETER:
aoqi@0 210 n += 1; // parameter_index
aoqi@0 211 break;
aoqi@0 212 // type parameter bound
aoqi@0 213 case CLASS_TYPE_PARAMETER_BOUND:
aoqi@0 214 case METHOD_TYPE_PARAMETER_BOUND:
aoqi@0 215 n += 1; // parameter_index
aoqi@0 216 n += 1; // bound_index
aoqi@0 217 break;
aoqi@0 218 // class extends or implements clause
aoqi@0 219 case CLASS_EXTENDS:
aoqi@0 220 n += 2; // type_index
aoqi@0 221 break;
aoqi@0 222 // throws
aoqi@0 223 case THROWS:
aoqi@0 224 n += 2; // type_index
aoqi@0 225 break;
aoqi@0 226 // method parameter
aoqi@0 227 case METHOD_FORMAL_PARAMETER:
aoqi@0 228 n += 1; // parameter_index
aoqi@0 229 break;
aoqi@0 230 // type cast
aoqi@0 231 case CAST:
aoqi@0 232 // method/constructor/reference type argument
aoqi@0 233 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
aoqi@0 234 case METHOD_INVOCATION_TYPE_ARGUMENT:
aoqi@0 235 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
aoqi@0 236 case METHOD_REFERENCE_TYPE_ARGUMENT:
aoqi@0 237 n += 2; // offset
aoqi@0 238 n += 1; // type index
aoqi@0 239 break;
aoqi@0 240 // We don't need to worry about these
aoqi@0 241 case METHOD_RETURN:
aoqi@0 242 case FIELD:
aoqi@0 243 break;
aoqi@0 244 case UNKNOWN:
aoqi@0 245 throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!");
aoqi@0 246 default:
aoqi@0 247 throw new AssertionError("TypeAnnotation: Unknown target type: " + pos.type);
aoqi@0 248 }
aoqi@0 249
aoqi@0 250 {
aoqi@0 251 n += 1; // length
aoqi@0 252 n += TypePathEntry.bytesPerEntry * pos.location.size(); // bytes for actual array
aoqi@0 253 }
aoqi@0 254
aoqi@0 255 return n;
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 // Code duplicated from com.sun.tools.javac.code.TypeAnnotationPosition
aoqi@0 259 public static class Position {
aoqi@0 260 public enum TypePathEntryKind {
aoqi@0 261 ARRAY(0),
aoqi@0 262 INNER_TYPE(1),
aoqi@0 263 WILDCARD(2),
aoqi@0 264 TYPE_ARGUMENT(3);
aoqi@0 265
aoqi@0 266 public final int tag;
aoqi@0 267
aoqi@0 268 private TypePathEntryKind(int tag) {
aoqi@0 269 this.tag = tag;
aoqi@0 270 }
aoqi@0 271 }
aoqi@0 272
aoqi@0 273 public static class TypePathEntry {
aoqi@0 274 /** The fixed number of bytes per TypePathEntry. */
aoqi@0 275 public static final int bytesPerEntry = 2;
aoqi@0 276
aoqi@0 277 public final TypePathEntryKind tag;
aoqi@0 278 public final int arg;
aoqi@0 279
aoqi@0 280 public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
aoqi@0 281 public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
aoqi@0 282 public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
aoqi@0 283
aoqi@0 284 private TypePathEntry(TypePathEntryKind tag) {
aoqi@0 285 if (!(tag == TypePathEntryKind.ARRAY ||
aoqi@0 286 tag == TypePathEntryKind.INNER_TYPE ||
aoqi@0 287 tag == TypePathEntryKind.WILDCARD)) {
aoqi@0 288 throw new AssertionError("Invalid TypePathEntryKind: " + tag);
aoqi@0 289 }
aoqi@0 290 this.tag = tag;
aoqi@0 291 this.arg = 0;
aoqi@0 292 }
aoqi@0 293
aoqi@0 294 public TypePathEntry(TypePathEntryKind tag, int arg) {
aoqi@0 295 if (tag != TypePathEntryKind.TYPE_ARGUMENT) {
aoqi@0 296 throw new AssertionError("Invalid TypePathEntryKind: " + tag);
aoqi@0 297 }
aoqi@0 298 this.tag = tag;
aoqi@0 299 this.arg = arg;
aoqi@0 300 }
aoqi@0 301
aoqi@0 302 public static TypePathEntry fromBinary(int tag, int arg) {
aoqi@0 303 if (arg != 0 && tag != TypePathEntryKind.TYPE_ARGUMENT.tag) {
aoqi@0 304 throw new AssertionError("Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
aoqi@0 305 }
aoqi@0 306 switch (tag) {
aoqi@0 307 case 0:
aoqi@0 308 return ARRAY;
aoqi@0 309 case 1:
aoqi@0 310 return INNER_TYPE;
aoqi@0 311 case 2:
aoqi@0 312 return WILDCARD;
aoqi@0 313 case 3:
aoqi@0 314 return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
aoqi@0 315 default:
aoqi@0 316 throw new AssertionError("Invalid TypePathEntryKind tag: " + tag);
aoqi@0 317 }
aoqi@0 318 }
aoqi@0 319
aoqi@0 320 @Override
aoqi@0 321 public String toString() {
aoqi@0 322 return tag.toString() +
aoqi@0 323 (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
aoqi@0 324 }
aoqi@0 325
aoqi@0 326 @Override
aoqi@0 327 public boolean equals(Object other) {
aoqi@0 328 if (! (other instanceof TypePathEntry)) {
aoqi@0 329 return false;
aoqi@0 330 }
aoqi@0 331 TypePathEntry tpe = (TypePathEntry) other;
aoqi@0 332 return this.tag == tpe.tag && this.arg == tpe.arg;
aoqi@0 333 }
aoqi@0 334
aoqi@0 335 @Override
aoqi@0 336 public int hashCode() {
aoqi@0 337 return this.tag.hashCode() * 17 + this.arg;
aoqi@0 338 }
aoqi@0 339 }
aoqi@0 340
aoqi@0 341 public TargetType type = TargetType.UNKNOWN;
aoqi@0 342
aoqi@0 343 // For generic/array types.
aoqi@0 344 // TODO: or should we use null? Noone will use this object.
aoqi@0 345 public List<TypePathEntry> location = new ArrayList<TypePathEntry>(0);
aoqi@0 346
aoqi@0 347 // Tree position.
aoqi@0 348 public int pos = -1;
aoqi@0 349
aoqi@0 350 // For typecasts, type tests, new (and locals, as start_pc).
aoqi@0 351 public boolean isValidOffset = false;
aoqi@0 352 public int offset = -1;
aoqi@0 353
aoqi@0 354 // For locals. arrays same length
aoqi@0 355 public int[] lvarOffset = null;
aoqi@0 356 public int[] lvarLength = null;
aoqi@0 357 public int[] lvarIndex = null;
aoqi@0 358
aoqi@0 359 // For type parameter bound
aoqi@0 360 public int bound_index = Integer.MIN_VALUE;
aoqi@0 361
aoqi@0 362 // For type parameter and method parameter
aoqi@0 363 public int parameter_index = Integer.MIN_VALUE;
aoqi@0 364
aoqi@0 365 // For class extends, implements, and throws clauses
aoqi@0 366 public int type_index = Integer.MIN_VALUE;
aoqi@0 367
aoqi@0 368 // For exception parameters, index into exception table
aoqi@0 369 public int exception_index = Integer.MIN_VALUE;
aoqi@0 370
aoqi@0 371 public Position() {}
aoqi@0 372
aoqi@0 373 @Override
aoqi@0 374 public String toString() {
aoqi@0 375 StringBuilder sb = new StringBuilder();
aoqi@0 376 sb.append('[');
aoqi@0 377 sb.append(type);
aoqi@0 378
aoqi@0 379 switch (type) {
aoqi@0 380 // instanceof
aoqi@0 381 case INSTANCEOF:
aoqi@0 382 // new expression
aoqi@0 383 case NEW:
aoqi@0 384 // constructor/method reference receiver
aoqi@0 385 case CONSTRUCTOR_REFERENCE:
aoqi@0 386 case METHOD_REFERENCE:
aoqi@0 387 sb.append(", offset = ");
aoqi@0 388 sb.append(offset);
aoqi@0 389 break;
aoqi@0 390 // local variable
aoqi@0 391 case LOCAL_VARIABLE:
aoqi@0 392 // resource variable
aoqi@0 393 case RESOURCE_VARIABLE:
aoqi@0 394 if (lvarOffset == null) {
aoqi@0 395 sb.append(", lvarOffset is null!");
aoqi@0 396 break;
aoqi@0 397 }
aoqi@0 398 sb.append(", {");
aoqi@0 399 for (int i = 0; i < lvarOffset.length; ++i) {
aoqi@0 400 if (i != 0) sb.append("; ");
aoqi@0 401 sb.append("start_pc = ");
aoqi@0 402 sb.append(lvarOffset[i]);
aoqi@0 403 sb.append(", length = ");
aoqi@0 404 sb.append(lvarLength[i]);
aoqi@0 405 sb.append(", index = ");
aoqi@0 406 sb.append(lvarIndex[i]);
aoqi@0 407 }
aoqi@0 408 sb.append("}");
aoqi@0 409 break;
aoqi@0 410 // method receiver
aoqi@0 411 case METHOD_RECEIVER:
aoqi@0 412 // Do nothing
aoqi@0 413 break;
aoqi@0 414 // type parameter
aoqi@0 415 case CLASS_TYPE_PARAMETER:
aoqi@0 416 case METHOD_TYPE_PARAMETER:
aoqi@0 417 sb.append(", param_index = ");
aoqi@0 418 sb.append(parameter_index);
aoqi@0 419 break;
aoqi@0 420 // type parameter bound
aoqi@0 421 case CLASS_TYPE_PARAMETER_BOUND:
aoqi@0 422 case METHOD_TYPE_PARAMETER_BOUND:
aoqi@0 423 sb.append(", param_index = ");
aoqi@0 424 sb.append(parameter_index);
aoqi@0 425 sb.append(", bound_index = ");
aoqi@0 426 sb.append(bound_index);
aoqi@0 427 break;
aoqi@0 428 // class extends or implements clause
aoqi@0 429 case CLASS_EXTENDS:
aoqi@0 430 sb.append(", type_index = ");
aoqi@0 431 sb.append(type_index);
aoqi@0 432 break;
aoqi@0 433 // throws
aoqi@0 434 case THROWS:
aoqi@0 435 sb.append(", type_index = ");
aoqi@0 436 sb.append(type_index);
aoqi@0 437 break;
aoqi@0 438 // exception parameter
aoqi@0 439 case EXCEPTION_PARAMETER:
aoqi@0 440 sb.append(", exception_index = ");
aoqi@0 441 sb.append(exception_index);
aoqi@0 442 break;
aoqi@0 443 // method parameter
aoqi@0 444 case METHOD_FORMAL_PARAMETER:
aoqi@0 445 sb.append(", param_index = ");
aoqi@0 446 sb.append(parameter_index);
aoqi@0 447 break;
aoqi@0 448 // type cast
aoqi@0 449 case CAST:
aoqi@0 450 // method/constructor/reference type argument
aoqi@0 451 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
aoqi@0 452 case METHOD_INVOCATION_TYPE_ARGUMENT:
aoqi@0 453 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
aoqi@0 454 case METHOD_REFERENCE_TYPE_ARGUMENT:
aoqi@0 455 sb.append(", offset = ");
aoqi@0 456 sb.append(offset);
aoqi@0 457 sb.append(", type_index = ");
aoqi@0 458 sb.append(type_index);
aoqi@0 459 break;
aoqi@0 460 // We don't need to worry about these
aoqi@0 461 case METHOD_RETURN:
aoqi@0 462 case FIELD:
aoqi@0 463 break;
aoqi@0 464 case UNKNOWN:
aoqi@0 465 sb.append(", position UNKNOWN!");
aoqi@0 466 break;
aoqi@0 467 default:
aoqi@0 468 throw new AssertionError("Unknown target type: " + type);
aoqi@0 469 }
aoqi@0 470
aoqi@0 471 // Append location data for generics/arrays.
aoqi@0 472 if (!location.isEmpty()) {
aoqi@0 473 sb.append(", location = (");
aoqi@0 474 sb.append(location);
aoqi@0 475 sb.append(")");
aoqi@0 476 }
aoqi@0 477
aoqi@0 478 sb.append(", pos = ");
aoqi@0 479 sb.append(pos);
aoqi@0 480
aoqi@0 481 sb.append(']');
aoqi@0 482 return sb.toString();
aoqi@0 483 }
aoqi@0 484
aoqi@0 485 /**
aoqi@0 486 * Indicates whether the target tree of the annotation has been optimized
aoqi@0 487 * away from classfile or not.
aoqi@0 488 * @return true if the target has not been optimized away
aoqi@0 489 */
aoqi@0 490 public boolean emitToClassfile() {
aoqi@0 491 return !type.isLocal() || isValidOffset;
aoqi@0 492 }
aoqi@0 493
aoqi@0 494 /**
aoqi@0 495 * Decode the binary representation for a type path and set
aoqi@0 496 * the {@code location} field.
aoqi@0 497 *
aoqi@0 498 * @param list The bytecode representation of the type path.
aoqi@0 499 */
aoqi@0 500 public static List<TypePathEntry> getTypePathFromBinary(List<Integer> list) {
aoqi@0 501 List<TypePathEntry> loc = new ArrayList<TypePathEntry>(list.size() / TypePathEntry.bytesPerEntry);
aoqi@0 502 int idx = 0;
aoqi@0 503 while (idx < list.size()) {
aoqi@0 504 if (idx + 1 == list.size()) {
aoqi@0 505 throw new AssertionError("Could not decode type path: " + list);
aoqi@0 506 }
aoqi@0 507 loc.add(TypePathEntry.fromBinary(list.get(idx), list.get(idx + 1)));
aoqi@0 508 idx += 2;
aoqi@0 509 }
aoqi@0 510 return loc;
aoqi@0 511 }
aoqi@0 512
aoqi@0 513 public static List<Integer> getBinaryFromTypePath(List<TypePathEntry> locs) {
aoqi@0 514 List<Integer> loc = new ArrayList<Integer>(locs.size() * TypePathEntry.bytesPerEntry);
aoqi@0 515 for (TypePathEntry tpe : locs) {
aoqi@0 516 loc.add(tpe.tag.tag);
aoqi@0 517 loc.add(tpe.arg);
aoqi@0 518 }
aoqi@0 519 return loc;
aoqi@0 520 }
aoqi@0 521 }
aoqi@0 522
aoqi@0 523 // Code duplicated from com.sun.tools.javac.code.TargetType
aoqi@0 524 // The IsLocal flag could be removed here.
aoqi@0 525 public enum TargetType {
aoqi@0 526 /** For annotations on a class type parameter declaration. */
aoqi@0 527 CLASS_TYPE_PARAMETER(0x00),
aoqi@0 528
aoqi@0 529 /** For annotations on a method type parameter declaration. */
aoqi@0 530 METHOD_TYPE_PARAMETER(0x01),
aoqi@0 531
aoqi@0 532 /** For annotations on the type of an "extends" or "implements" clause. */
aoqi@0 533 CLASS_EXTENDS(0x10),
aoqi@0 534
aoqi@0 535 /** For annotations on a bound of a type parameter of a class. */
aoqi@0 536 CLASS_TYPE_PARAMETER_BOUND(0x11),
aoqi@0 537
aoqi@0 538 /** For annotations on a bound of a type parameter of a method. */
aoqi@0 539 METHOD_TYPE_PARAMETER_BOUND(0x12),
aoqi@0 540
aoqi@0 541 /** For annotations on a field. */
aoqi@0 542 FIELD(0x13),
aoqi@0 543
aoqi@0 544 /** For annotations on a method return type. */
aoqi@0 545 METHOD_RETURN(0x14),
aoqi@0 546
aoqi@0 547 /** For annotations on the method receiver. */
aoqi@0 548 METHOD_RECEIVER(0x15),
aoqi@0 549
aoqi@0 550 /** For annotations on a method parameter. */
aoqi@0 551 METHOD_FORMAL_PARAMETER(0x16),
aoqi@0 552
aoqi@0 553 /** For annotations on a throws clause in a method declaration. */
aoqi@0 554 THROWS(0x17),
aoqi@0 555
aoqi@0 556 /** For annotations on a local variable. */
aoqi@0 557 LOCAL_VARIABLE(0x40, true),
aoqi@0 558
aoqi@0 559 /** For annotations on a resource variable. */
aoqi@0 560 RESOURCE_VARIABLE(0x41, true),
aoqi@0 561
aoqi@0 562 /** For annotations on an exception parameter. */
aoqi@0 563 EXCEPTION_PARAMETER(0x42, true),
aoqi@0 564
aoqi@0 565 /** For annotations on a type test. */
aoqi@0 566 INSTANCEOF(0x43, true),
aoqi@0 567
aoqi@0 568 /** For annotations on an object creation expression. */
aoqi@0 569 NEW(0x44, true),
aoqi@0 570
aoqi@0 571 /** For annotations on a constructor reference receiver. */
aoqi@0 572 CONSTRUCTOR_REFERENCE(0x45, true),
aoqi@0 573
aoqi@0 574 /** For annotations on a method reference receiver. */
aoqi@0 575 METHOD_REFERENCE(0x46, true),
aoqi@0 576
aoqi@0 577 /** For annotations on a typecast. */
aoqi@0 578 CAST(0x47, true),
aoqi@0 579
aoqi@0 580 /** For annotations on a type argument of an object creation expression. */
aoqi@0 581 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x48, true),
aoqi@0 582
aoqi@0 583 /** For annotations on a type argument of a method call. */
aoqi@0 584 METHOD_INVOCATION_TYPE_ARGUMENT(0x49, true),
aoqi@0 585
aoqi@0 586 /** For annotations on a type argument of a constructor reference. */
aoqi@0 587 CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(0x4A, true),
aoqi@0 588
aoqi@0 589 /** For annotations on a type argument of a method reference. */
aoqi@0 590 METHOD_REFERENCE_TYPE_ARGUMENT(0x4B, true),
aoqi@0 591
aoqi@0 592 /** For annotations with an unknown target. */
aoqi@0 593 UNKNOWN(0xFF);
aoqi@0 594
aoqi@0 595 private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x4B;
aoqi@0 596
aoqi@0 597 private final int targetTypeValue;
aoqi@0 598 private final boolean isLocal;
aoqi@0 599
aoqi@0 600 private TargetType(int targetTypeValue) {
aoqi@0 601 this(targetTypeValue, false);
aoqi@0 602 }
aoqi@0 603
aoqi@0 604 private TargetType(int targetTypeValue, boolean isLocal) {
aoqi@0 605 if (targetTypeValue < 0
aoqi@0 606 || targetTypeValue > 255)
aoqi@0 607 throw new AssertionError("Attribute type value needs to be an unsigned byte: " + String.format("0x%02X", targetTypeValue));
aoqi@0 608 this.targetTypeValue = targetTypeValue;
aoqi@0 609 this.isLocal = isLocal;
aoqi@0 610 }
aoqi@0 611
aoqi@0 612 /**
aoqi@0 613 * Returns whether or not this TargetType represents an annotation whose
aoqi@0 614 * target is exclusively a tree in a method body
aoqi@0 615 *
aoqi@0 616 * Note: wildcard bound targets could target a local tree and a class
aoqi@0 617 * member declaration signature tree
aoqi@0 618 */
aoqi@0 619 public boolean isLocal() {
aoqi@0 620 return isLocal;
aoqi@0 621 }
aoqi@0 622
aoqi@0 623 public int targetTypeValue() {
aoqi@0 624 return this.targetTypeValue;
aoqi@0 625 }
aoqi@0 626
aoqi@0 627 private static final TargetType[] targets;
aoqi@0 628
aoqi@0 629 static {
aoqi@0 630 targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
aoqi@0 631 TargetType[] alltargets = values();
aoqi@0 632 for (TargetType target : alltargets) {
aoqi@0 633 if (target.targetTypeValue != UNKNOWN.targetTypeValue)
aoqi@0 634 targets[target.targetTypeValue] = target;
aoqi@0 635 }
aoqi@0 636 for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i) {
aoqi@0 637 if (targets[i] == null)
aoqi@0 638 targets[i] = UNKNOWN;
aoqi@0 639 }
aoqi@0 640 }
aoqi@0 641
aoqi@0 642 public static boolean isValidTargetTypeValue(int tag) {
aoqi@0 643 if (tag == UNKNOWN.targetTypeValue)
aoqi@0 644 return true;
aoqi@0 645 return (tag >= 0 && tag < targets.length);
aoqi@0 646 }
aoqi@0 647
aoqi@0 648 public static TargetType fromTargetTypeValue(int tag) {
aoqi@0 649 if (tag == UNKNOWN.targetTypeValue)
aoqi@0 650 return UNKNOWN;
aoqi@0 651
aoqi@0 652 if (tag < 0 || tag >= targets.length)
aoqi@0 653 throw new AssertionError("Unknown TargetType: " + tag);
aoqi@0 654 return targets[tag];
aoqi@0 655 }
aoqi@0 656 }
aoqi@0 657 }

mercurial