1 /* 2 * Copyright (c) 2020, 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 */ 23 package org.openjdk.asmtools.jasm; 24 25 import java.io.IOException; 26 import java.io.PrintWriter; 27 import java.util.ArrayList; 28 29 /** 30 * TargetInfo (4.7.20.1. The target_info union) 31 * 32 * BaseClass for any Type Annotation Target-Info. 33 */ 34 public abstract class TypeAnnotationTargetInfoData implements Data { 35 36 protected TypeAnnotationTypes.ETargetType targettype = null; 37 38 public TypeAnnotationTargetInfoData(TypeAnnotationTypes.ETargetType tt) { 39 targettype = tt; 40 } 41 42 public TypeAnnotationTypes.ETargetType getTargetType() { 43 return targettype; 44 } 45 46 public void print(PrintWriter out, String tab) { 47 // print the TargetType and TargetInfo 48 out.print(tab + " {"); 49 targettype.print(out); 50 _print(out, tab); 51 out.print(tab + "} "); 52 } 53 54 public abstract void _print(PrintWriter out, String tab); 55 56 public abstract void write(CheckedDataOutputStream out) throws IOException; 57 58 @Override 59 public String toString() { 60 return toString(0); 61 } 62 63 protected abstract void _toString(StringBuilder sb, int tabLevel); 64 65 public String toString(int tabLevel) { 66 StringBuilder sb = new StringBuilder(tabString(tabLevel)); 67 // first print the target info name ( 68 sb.append(targettype.targetInfo().printValue()).append("_target "); 69 // get the sub-classes parts 70 _toString(sb, tabLevel); 71 return sb.toString(); 72 } 73 74 /** 75 * type_parameter_target (4.7.20.1. The target_info union) 76 * 77 * The type_parameter_target item indicates that an annotation appears on the declaration of the i'th type parameter 78 * of a generic class, generic interface, generic method, or generic constructor. 79 * 80 * type_parameter_target { 81 * u1 type_parameter_index; 82 * } 83 */ 84 public static class type_parameter_target extends TypeAnnotationTargetInfoData { 85 86 int typeParamIndex; 87 88 public type_parameter_target(TypeAnnotationTypes.ETargetType tt, int index) { 89 super(tt); 90 typeParamIndex = index; 91 } 92 93 @Override 94 public void write(CheckedDataOutputStream out) throws IOException { 95 out.writeByte(typeParamIndex); 96 } 97 98 @Override 99 public void _print(PrintWriter out, String tab) { 100 out.print(" "); 101 out.print(typeParamIndex); 102 } 103 104 @Override 105 public int getLength() { 106 return 1; 107 } 108 109 @Override 110 protected void _toString(StringBuilder sb, int tabLevel) { 111 sb.append(tabString(tabLevel)).append(String.format("{ type_parameter_index: %d; }",typeParamIndex)); 112 } 113 } 114 115 /** 116 * supertype_target (4.7.20.1. The target_info union) 117 * 118 * The supertype_target item indicates that an annotation appears on a type in the extends or implements clause of 119 * a class or interface declaration. 120 * 121 * supertype_target { 122 * u2 supertype_index; 123 * } 124 */ 125 public static class supertype_target extends TypeAnnotationTargetInfoData { 126 127 int superTypeIndex; 128 129 public supertype_target(TypeAnnotationTypes.ETargetType tt, int index) { 130 super(tt); 131 superTypeIndex = index; 132 } 133 134 @Override 135 public void write(CheckedDataOutputStream out) throws IOException { 136 out.writeShort(superTypeIndex); 137 } 138 139 @Override 140 public void _print(PrintWriter out, String tab) { 141 out.print(" "); 142 out.print(superTypeIndex); 143 } 144 145 @Override 146 public int getLength() { 147 return 2; 148 } 149 150 @Override 151 protected void _toString(StringBuilder sb, int tabLevel) { 152 sb.append(tabString(tabLevel)).append(String.format("{ supertype_index: %d; }",superTypeIndex)); 153 } 154 } 155 156 /** 157 * type_parameter_bound_target (4.7.20.1. The target_info union) 158 * 159 * The type_parameter_bound_target item indicates that an annotation appears on the i'th bound of the j'th type parameter 160 * declaration of a generic class, interface, method, or constructor. 161 * 162 * type_parameter_bound_target { 163 * u1 type_parameter_index; 164 * u1 bound_index; 165 * } 166 */ 167 public static class type_parameter_bound_target extends TypeAnnotationTargetInfoData { 168 169 int typeParamIndex; 170 int boundIndex; 171 172 public type_parameter_bound_target(TypeAnnotationTypes.ETargetType tt, int pindx, int bindx) { 173 super(tt); 174 typeParamIndex = pindx; 175 boundIndex = bindx; 176 } 177 178 @Override 179 public void write(CheckedDataOutputStream out) throws IOException { 180 out.writeByte(typeParamIndex); 181 out.writeByte(boundIndex); 182 } 183 184 @Override 185 public void _print(PrintWriter out, String tab) { 186 out.print(" "); 187 out.print(typeParamIndex); 188 out.print(" "); 189 out.print(boundIndex); 190 } 191 192 @Override 193 public int getLength() { 194 return 2; 195 } 196 197 @Override 198 protected void _toString(StringBuilder sb, int tabLevel) { 199 sb.append(tabString(tabLevel)).append(String.format("{ type_parameter_index: %d; bound_index: %d; }", 200 typeParamIndex, boundIndex)); 201 } 202 } 203 204 /** 205 * empty_target (4.7.20.1. The target_info union) 206 * 207 * The empty_target item indicates that an annotation appears on either the type in a field declaration, 208 * the return type of a method, the type of a newly constructed object, or the receiver type of a method or constructor. 209 * 210 * empty_target { 211 * } 212 */ 213 public static class empty_target extends TypeAnnotationTargetInfoData { 214 215 public empty_target(TypeAnnotationTypes.ETargetType tt) { 216 super(tt); 217 } 218 219 @Override 220 public void _print(PrintWriter out, String tab) { 221 // do nothing 222 } 223 224 @Override 225 public void write(CheckedDataOutputStream out) throws IOException { 226 // do nothing 227 } 228 229 @Override 230 public int getLength() { return 0; } 231 232 @Override 233 protected void _toString(StringBuilder sb, int tabLevel) { 234 sb.append(tabString(tabLevel)).append("{ }"); 235 } 236 } 237 238 /** 239 * formal_parameter_target (4.7.20.1. The target_info union) 240 * 241 * The formal_parameter_target item indicates that an annotation appears on the type in a formal parameter 242 * declaration of a method, constructor, or lambda expression. 243 * 244 * formal_parameter_target { 245 * u1 formal_parameter_index; 246 * } 247 */ 248 public static class formal_parameter_target extends TypeAnnotationTargetInfoData { 249 250 int formalParamIndex; 251 252 public formal_parameter_target(TypeAnnotationTypes.ETargetType tt, int index) { 253 super(tt); 254 formalParamIndex = index; 255 } 256 257 @Override 258 public void write(CheckedDataOutputStream out) throws IOException { 259 out.writeByte(formalParamIndex); 260 } 261 262 @Override 263 public void _print(PrintWriter out, String tab) { 264 out.print(" "); 265 out.print(formalParamIndex); 266 } 267 268 @Override 269 public int getLength() { 270 return 1; 271 } 272 273 @Override 274 protected void _toString(StringBuilder sb, int tabLevel) { 275 sb.append(tabString(tabLevel)).append(String.format("{ formal_parameter_index: %d; }",formalParamIndex)); 276 } 277 } 278 279 /** 280 * throws_target (4.7.20.1. The target_info union) 281 * 282 * The throws_target item indicates that an annotation appears on the i'th type in the throws clause of a method or 283 * constructor declaration. 284 * 285 * throws_target { 286 * u2 throws_type_index; 287 * } 288 */ 289 public static class throws_target extends TypeAnnotationTargetInfoData { 290 291 int throwsTypeIndex; 292 293 public throws_target(TypeAnnotationTypes.ETargetType tt, int index) { 294 super(tt); 295 throwsTypeIndex = index; 296 } 297 298 @Override 299 public void write(CheckedDataOutputStream out) throws IOException { 300 out.writeShort(throwsTypeIndex); 301 } 302 303 @Override 304 public void _print(PrintWriter out, String tab) { 305 out.print(" "); 306 out.print(throwsTypeIndex); 307 } 308 309 @Override 310 public int getLength() { 311 return 2; 312 } 313 314 @Override 315 protected void _toString(StringBuilder sb, int tabLevel) { 316 sb.append(tabString(tabLevel)).append(String.format("{ throws_type_index: %d; }",throwsTypeIndex)); 317 } 318 } 319 320 /** 321 * localvar_target (4.7.20.1. The target_info union) 322 * 323 * The localvar_target item indicates that an annotation appears on the type in a local variable declaration, 324 * including a variable declared as a resource in a try-with-resources statement. 325 * 326 * localvar_target { 327 * u2 table_length; 328 * { u2 start_pc; 329 * u2 length; 330 * u2 index; 331 * } table[table_length]; 332 * } 333 */ 334 public static class localvar_target extends TypeAnnotationTargetInfoData { 335 336 public class LocalVar_Entry { 337 338 public int startPC; 339 public int length; 340 public int cpx; 341 342 public LocalVar_Entry(int st, int len, int index) { 343 startPC = st; 344 length = len; 345 cpx = index; 346 } 347 348 void write(CheckedDataOutputStream out) throws IOException { 349 out.writeShort(startPC); 350 out.writeShort(length); 351 out.writeShort(cpx); 352 } 353 354 public void _print(PrintWriter out, String tab) { 355 out.print(tab + "{"); 356 out.print(startPC); 357 out.print(" "); 358 out.print(length); 359 out.print(" "); 360 out.print(cpx); 361 out.print("}"); 362 } 363 364 public String toString() { 365 return String.format("start_pc: %d, length: %d, index: %d", startPC, length, cpx); 366 } 367 } 368 369 ArrayList<LocalVar_Entry> table = null; 370 371 public localvar_target(TypeAnnotationTypes.ETargetType tt, int size) { 372 super(tt); 373 table = new ArrayList<>(size); 374 } 375 376 public void addEntry(int startPC, int length, int cpx) { 377 LocalVar_Entry entry = new LocalVar_Entry(startPC, length, cpx); 378 table.add(entry); 379 } 380 381 @Override 382 public void write(CheckedDataOutputStream out) throws IOException { 383 out.writeShort(table.size()); 384 for (LocalVar_Entry entry : table) { 385 entry.write(out); 386 } 387 } 388 389 @Override 390 public void _print(PrintWriter out, String tab) { 391 String innerTab = tab + " "; 392 for (LocalVar_Entry entry : table) { 393 entry._print(out, innerTab); 394 } 395 out.print(tab); 396 } 397 398 @Override 399 public int getLength() { 400 return 2 + // U2 for table size 401 (6 * table.size()); // (3 * U2) for each table entry 402 } 403 404 @Override 405 protected void _toString(StringBuilder sb, int tabLevel) { 406 int i = 0; 407 sb.append(tabString(tabLevel)).append(String.format("{ %d {", table.size())); 408 for (LocalVar_Entry entry : table) { 409 sb.append(String.format(" [%d]: %s;", i++, entry.toString())); 410 } 411 sb.append(" } }"); 412 } 413 } 414 415 /** 416 * catch_target (4.7.20.1. The target_info union) 417 * 418 * The catch_target item indicates that an annotation appears on the i'th type in an exception parameter declaration. 419 * 420 * catch_target { 421 * u2 exception_table_index; 422 * } 423 */ 424 public static class catch_target extends TypeAnnotationTargetInfoData { 425 426 int exceptionTableIndex; 427 428 public catch_target(TypeAnnotationTypes.ETargetType tt, int index) { 429 super(tt); 430 exceptionTableIndex = index; 431 } 432 433 @Override 434 public void write(CheckedDataOutputStream out) throws IOException { 435 out.writeShort(exceptionTableIndex); 436 } 437 438 @Override 439 public void _print(PrintWriter out, String tab) { 440 out.print(" "); 441 out.print(exceptionTableIndex); 442 } 443 444 @Override 445 public int getLength() { 446 return 2; 447 } 448 449 @Override 450 protected void _toString(StringBuilder sb, int tabLevel) { 451 sb.append(tabString(tabLevel)).append(String.format("{ exception_table_index: %d; }",exceptionTableIndex)); 452 } 453 } 454 455 /** 456 * offset_target (4.7.20.1. The target_info union) 457 * 458 * The offset_target item indicates that an annotation appears on either the type in an instanceof expression or 459 * a new expression, or the type before the :: in a method reference expression. 460 * 461 * offset_target { 462 * u2 offset; 463 * } 464 */ 465 public static class offset_target extends TypeAnnotationTargetInfoData { 466 467 int offset; 468 469 public offset_target(TypeAnnotationTypes.ETargetType tt, int offset) { 470 super(tt); 471 this.offset = offset; 472 } 473 474 @Override 475 public void write(CheckedDataOutputStream out) throws IOException { 476 out.writeShort(offset); 477 } 478 479 @Override 480 public void _print(PrintWriter out, String tab) { 481 out.print(" "); 482 out.print(offset); 483 } 484 485 @Override 486 public int getLength() { 487 return 2; 488 } 489 490 @Override 491 protected void _toString(StringBuilder sb, int tabLevel) { 492 sb.append(tabString(tabLevel)).append(String.format("{ offset: %d; }", offset)); 493 } 494 } 495 496 /** 497 * type_argument_target (4.7.20.1. The target_info union) 498 * 499 * The type_argument_target item indicates that an annotation appears either on the i'th type in a cast expression, 500 * or on the i'th type argument in the explicit type argument list for any of the following: a new expression, 501 * an explicit constructor invocation statement, a method invocation expression, or a method reference expression 502 * 503 * type_argument_target { 504 * u2 offset; 505 * u1 type_argument_index; 506 * } 507 */ 508 public static class type_argument_target extends TypeAnnotationTargetInfoData { 509 510 int offset; 511 int typeArgumentIndex; 512 513 public type_argument_target(TypeAnnotationTypes.ETargetType tt, int offset, int index) { 514 super(tt); 515 this.offset = offset; 516 typeArgumentIndex = index; 517 } 518 519 @Override 520 public void write(CheckedDataOutputStream out) throws IOException { 521 out.writeShort(offset); 522 out.writeByte(typeArgumentIndex); 523 } 524 525 @Override 526 public void _print(PrintWriter out, String tab) { 527 out.print(" "); 528 out.print(offset); 529 out.print(" "); 530 out.print(typeArgumentIndex); 531 } 532 533 @Override 534 public int getLength() { 535 return 3; 536 } 537 538 @Override 539 protected void _toString(StringBuilder sb, int tabLevel) { 540 sb.append(tabString(tabLevel)).append(String.format("{ offset: %d; type_argument_index: %d; }", 541 offset, typeArgumentIndex)); 542 } 543 } 544 545 } 546