ClassFile.java revision 4a9a664dd17b17d4ca4641f6267a59f644f20a07
1/* 2 * Copyright 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.turbine.bytecode; 18 19import static java.util.Objects.requireNonNull; 20 21import com.google.common.collect.ImmutableList; 22import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; 23import com.google.turbine.model.Const; 24import com.google.turbine.model.Const.Value; 25import java.util.ArrayDeque; 26import java.util.Deque; 27import java.util.List; 28import java.util.Map; 29import javax.annotation.Nullable; 30 31/** A JVMS §4.1 ClassFile. */ 32public class ClassFile { 33 34 private final int access; 35 private final String name; 36 private final String signature; 37 private final String superClass; 38 private final List<String> interfaces; 39 private final List<MethodInfo> methods; 40 private final List<FieldInfo> fields; 41 private final List<AnnotationInfo> annotations; 42 private final List<InnerClass> innerClasses; 43 private final ImmutableList<TypeAnnotationInfo> typeAnnotations; 44 45 public ClassFile( 46 int access, 47 String name, 48 String signature, 49 String superClass, 50 List<String> interfaces, 51 List<MethodInfo> methods, 52 List<FieldInfo> fields, 53 List<AnnotationInfo> annotations, 54 List<InnerClass> innerClasses, 55 ImmutableList<TypeAnnotationInfo> typeAnnotations) { 56 this.access = access; 57 this.name = name; 58 this.signature = signature; 59 this.superClass = superClass; 60 this.interfaces = interfaces; 61 this.methods = methods; 62 this.fields = fields; 63 this.annotations = annotations; 64 this.innerClasses = innerClasses; 65 this.typeAnnotations = typeAnnotations; 66 } 67 68 /** Class access and property flags. */ 69 public int access() { 70 return access; 71 } 72 73 /** The name of the class or interface. */ 74 public String name() { 75 return name; 76 } 77 78 /** The value of the Signature attribute. */ 79 public String signature() { 80 return signature; 81 } 82 83 /** The super class. */ 84 public String superName() { 85 return superClass; 86 } 87 88 /** The direct superinterfaces. */ 89 public List<String> interfaces() { 90 return interfaces; 91 } 92 93 /** Methods declared by this class or interfaces type. */ 94 public List<MethodInfo> methods() { 95 return methods; 96 } 97 98 /** Fields declared by this class or interfaces type. */ 99 public List<FieldInfo> fields() { 100 return fields; 101 } 102 103 /** Declaration annotations of the class. */ 104 public List<AnnotationInfo> annotations() { 105 return annotations; 106 } 107 108 /** Inner class information. */ 109 public List<InnerClass> innerClasses() { 110 return innerClasses; 111 } 112 113 /** Type annotations. */ 114 public ImmutableList<TypeAnnotationInfo> typeAnnotations() { 115 return typeAnnotations; 116 } 117 118 /** The contents of a JVMS §4.5 field_info structure. */ 119 public static class FieldInfo { 120 121 private final int access; 122 private final String name; 123 private final String descriptor; 124 @Nullable private final String signature; 125 @Nullable private final Const.Value value; 126 private final List<AnnotationInfo> annotations; 127 private final ImmutableList<TypeAnnotationInfo> typeAnnotations; 128 129 public FieldInfo( 130 int access, 131 String name, 132 String descriptor, 133 @Nullable String signature, 134 Value value, 135 List<AnnotationInfo> annotations, 136 ImmutableList<TypeAnnotationInfo> typeAnnotations) { 137 this.access = access; 138 this.name = name; 139 this.descriptor = descriptor; 140 this.signature = signature; 141 this.value = value; 142 this.annotations = annotations; 143 this.typeAnnotations = typeAnnotations; 144 } 145 146 /** Field access and property flags. */ 147 public int access() { 148 return access; 149 } 150 151 /** The name of the field. */ 152 public String name() { 153 return name; 154 } 155 156 /** The descriptor. */ 157 public String descriptor() { 158 return descriptor; 159 } 160 161 /** The value of Signature attribute. */ 162 @Nullable 163 public String signature() { 164 return signature; 165 } 166 167 /** The compile-time constant value. */ 168 @Nullable 169 public Const.Value value() { 170 return value; 171 } 172 173 /** Declaration annotations of the field. */ 174 public List<AnnotationInfo> annotations() { 175 return annotations; 176 } 177 178 /** Type annotations. */ 179 public ImmutableList<TypeAnnotationInfo> typeAnnotations() { 180 return typeAnnotations; 181 } 182 } 183 184 /** A JVMS §4.7.6 InnerClasses attribute. */ 185 public static class InnerClass { 186 187 private final String innerClass; 188 private final String outerClass; 189 private final String innerName; 190 private final int access; 191 192 public InnerClass(String innerClass, String outerClass, String innerName, int access) { 193 this.innerClass = requireNonNull(innerClass); 194 this.outerClass = requireNonNull(outerClass); 195 this.innerName = requireNonNull(innerName); 196 this.access = access; 197 } 198 199 /** The binary name of the inner class. */ 200 public String innerClass() { 201 return innerClass; 202 } 203 204 /** The binary name of the enclosing class. */ 205 public String outerClass() { 206 return outerClass; 207 } 208 209 /** The simple name of the inner class. */ 210 public String innerName() { 211 return innerName; 212 } 213 214 /** Access and property flags of the inner class; see JVMS table 4.8. */ 215 public int access() { 216 return access; 217 } 218 } 219 220 /** The contents of a JVMS §4.6 method_info structure. */ 221 public static class MethodInfo { 222 223 private final int access; 224 private final String name; 225 private final String descriptor; 226 @Nullable private final String signature; 227 private final List<String> exceptions; 228 @Nullable private final AnnotationInfo.ElementValue defaultValue; 229 private final List<AnnotationInfo> annotations; 230 private final ImmutableList<ImmutableList<AnnotationInfo>> parameterAnnotations; 231 private final ImmutableList<TypeAnnotationInfo> typeAnnotations; 232 private final ImmutableList<ParameterInfo> parameters; 233 234 public MethodInfo( 235 int access, 236 String name, 237 String descriptor, 238 @Nullable String signature, 239 List<String> exceptions, 240 @Nullable ElementValue defaultValue, 241 List<AnnotationInfo> annotations, 242 ImmutableList<ImmutableList<AnnotationInfo>> parameterAnnotations, 243 ImmutableList<TypeAnnotationInfo> typeAnnotations, 244 ImmutableList<ParameterInfo> parameters) { 245 this.access = access; 246 this.name = name; 247 this.descriptor = descriptor; 248 this.signature = signature; 249 this.exceptions = exceptions; 250 this.defaultValue = defaultValue; 251 this.annotations = annotations; 252 this.parameterAnnotations = parameterAnnotations; 253 this.typeAnnotations = typeAnnotations; 254 this.parameters = parameters; 255 } 256 257 /** Method access and property flags. */ 258 public int access() { 259 return access; 260 } 261 262 /** The name of the method. */ 263 public String name() { 264 return name; 265 } 266 267 /** The descriptor. */ 268 public String descriptor() { 269 return descriptor; 270 } 271 272 /** The value of Signature attribute. */ 273 @Nullable 274 public String signature() { 275 return signature; 276 } 277 278 /** The value of Exceptions attribute. */ 279 public List<String> exceptions() { 280 return exceptions; 281 } 282 283 /** The value of the AnnotationDefault attribute. */ 284 @Nullable 285 public AnnotationInfo.ElementValue defaultValue() { 286 return defaultValue; 287 } 288 289 /** Declaration annotations of the method. */ 290 public List<AnnotationInfo> annotations() { 291 return annotations; 292 } 293 294 /** Declaration annotations of the formal parameters. */ 295 public ImmutableList<ImmutableList<AnnotationInfo>> parameterAnnotations() { 296 return parameterAnnotations; 297 } 298 299 /** Type annotations. */ 300 public ImmutableList<TypeAnnotationInfo> typeAnnotations() { 301 return typeAnnotations; 302 } 303 304 /** Formal parameters. */ 305 public ImmutableList<ParameterInfo> parameters() { 306 return parameters; 307 } 308 309 /** A formal parameter. */ 310 public static class ParameterInfo { 311 private final String name; 312 private final int access; 313 314 public ParameterInfo(String name, int access) { 315 this.name = name; 316 this.access = access; 317 } 318 319 /** Returns the parameter's name. */ 320 public String name() { 321 return name; 322 } 323 324 /** Returns the parameter's modifiers. */ 325 public int access() { 326 return access; 327 } 328 } 329 } 330 331 /** The contents of a JVMS §4.7.16 annotation structure. */ 332 public static class AnnotationInfo { 333 334 private final String typeName; 335 private final boolean runtimeVisible; 336 private final Map<String, ElementValue> elementValuePairs; 337 338 public AnnotationInfo( 339 String typeName, boolean runtimeVisible, Map<String, ElementValue> elementValuePairs) { 340 this.typeName = typeName; 341 this.runtimeVisible = runtimeVisible; 342 this.elementValuePairs = elementValuePairs; 343 } 344 345 /** The JVMS §4.3.2 field descriptor for the type of the annotation. */ 346 public String typeName() { 347 return typeName; 348 } 349 350 /** Returns true if the annotation is visible at runtime. */ 351 public boolean isRuntimeVisible() { 352 return runtimeVisible; 353 } 354 355 /** The element-value pairs of the annotation. */ 356 public Map<String, ElementValue> elementValuePairs() { 357 return elementValuePairs; 358 } 359 360 /** A value of a JVMS §4.7.16.1 element-value pair. */ 361 public interface ElementValue { 362 363 /** The value kind. */ 364 Kind kind(); 365 366 /** Element value kinds. */ 367 enum Kind { 368 ENUM, 369 CONST, 370 ARRAY, 371 CLASS, 372 ANNOTATION 373 } 374 375 /** An enum constant value. */ 376 class EnumConstValue implements ElementValue { 377 378 private final String typeName; 379 private final String constName; 380 381 public EnumConstValue(String typeName, String constName) { 382 this.typeName = typeName; 383 this.constName = constName; 384 } 385 386 @Override 387 public Kind kind() { 388 return Kind.ENUM; 389 } 390 391 /** The type of the enum. */ 392 public String typeName() { 393 return typeName; 394 } 395 396 /** The name of the enum constant. */ 397 public String constName() { 398 return constName; 399 } 400 } 401 402 /** A primitive or string constant value. */ 403 class ConstValue implements ElementValue { 404 405 private final Const.Value value; 406 407 public ConstValue(Const.Value value) { 408 409 this.value = value; 410 } 411 412 @Override 413 public Kind kind() { 414 return Kind.CONST; 415 } 416 417 /** The constant value. */ 418 public Const.Value value() { 419 return value; 420 } 421 } 422 423 /** A constant array value. */ 424 class ArrayValue implements ElementValue { 425 426 private final List<ElementValue> elements; 427 428 public ArrayValue(List<ElementValue> elements) { 429 this.elements = elements; 430 } 431 432 @Override 433 public Kind kind() { 434 return Kind.ARRAY; 435 } 436 437 /** The elements of the array. */ 438 public List<ElementValue> elements() { 439 return elements; 440 } 441 } 442 443 /** A constant class literal value. */ 444 class ConstClassValue implements ElementValue { 445 446 private final String className; 447 448 public ConstClassValue(String className) { 449 this.className = className; 450 } 451 452 @Override 453 public Kind kind() { 454 return Kind.CLASS; 455 } 456 457 /** The class name. */ 458 public String className() { 459 return className; 460 } 461 } 462 463 /** A nested annotation value. */ 464 class AnnotationValue implements ElementValue { 465 466 private final AnnotationInfo annotation; 467 468 public AnnotationValue(AnnotationInfo annotation) { 469 this.annotation = annotation; 470 } 471 472 @Override 473 public Kind kind() { 474 return Kind.ANNOTATION; 475 } 476 477 /** The annotation. */ 478 public AnnotationInfo annotation() { 479 return annotation; 480 } 481 } 482 } 483 } 484 485 /** The contents of a JVMS §4.7.20 type annotation structure. */ 486 public static class TypeAnnotationInfo { 487 private final TargetType targetType; 488 private final Target target; 489 private final TypePath path; 490 private final AnnotationInfo anno; 491 492 public TypeAnnotationInfo( 493 TargetType targetType, Target target, TypePath path, AnnotationInfo anno) { 494 this.targetType = targetType; 495 this.target = target; 496 this.path = path; 497 this.anno = anno; 498 } 499 500 /** 501 * The underlying annotation info (type, visibility, element-value pairs); shared with 502 * declaration annotations. 503 */ 504 public AnnotationInfo anno() { 505 return anno; 506 } 507 508 /** A JVMS 4.7.20 target_type kind, denotes the type context where the annotation appears. */ 509 public TargetType targetType() { 510 return targetType; 511 } 512 513 /** A JVMS 4.7.20 target_info structure. */ 514 public Target target() { 515 return target; 516 } 517 518 /** 519 * A JVMS 4.7.20 type_path structure, denotes which part of the type the annotation applies to. 520 */ 521 public TypePath path() { 522 return path; 523 } 524 525 /** A JVMS 4.7.20 target_type kind. */ 526 public enum TargetType { 527 CLASS_TYPE_PARAMETER(0x00), 528 METHOD_TYPE_PARAMETER(0x01), 529 SUPERTYPE(0x10), 530 CLASS_TYPE_PARAMETER_BOUND(0x11), 531 METHOD_TYPE_PARAMETER_BOUND(0x12), 532 FIELD(0x13), 533 METHOD_RETURN(0x14), 534 METHOD_RECEIVER_PARAMETER(0x15), 535 METHOD_FORMAL_PARAMETER(0x16), 536 METHOD_THROWS(0x17); 537 538 private final int tag; 539 540 TargetType(int tag) { 541 this.tag = tag; 542 } 543 544 public int tag() { 545 return tag; 546 } 547 } 548 549 /** A JVMS 4.7.20 target_info. */ 550 public abstract static class Target { 551 /** Target info kind. */ 552 public enum Kind { 553 TYPE_PARAMETER, 554 SUPERTYPE, 555 TYPE_PARAMETER_BOUND, 556 EMPTY, 557 FORMAL_PARAMETER, 558 THROWS; 559 } 560 561 /** Returns the target info kind. */ 562 public abstract Kind kind(); 563 } 564 565 /** A JVMS 4.7.20.1 type_parameter_target. */ 566 public static class TypeParameterTarget extends Target { 567 private final int index; 568 569 public TypeParameterTarget(int index) { 570 this.index = index; 571 } 572 573 public int index() { 574 return index; 575 } 576 577 @Override 578 public Kind kind() { 579 return Kind.TYPE_PARAMETER; 580 } 581 } 582 583 /** A JVMS 4.7.20.1 supertype_target. */ 584 public static class SuperTypeTarget extends Target { 585 private final int index; 586 587 public SuperTypeTarget(int index) { 588 this.index = index; 589 } 590 591 @Override 592 public Kind kind() { 593 return Kind.SUPERTYPE; 594 } 595 596 public int index() { 597 return index; 598 } 599 } 600 601 /** A JVMS 4.7.20.1 type_parameter_bound_target. */ 602 public static class TypeParameterBoundTarget extends Target { 603 private final int typeParameterIndex; 604 private final int boundIndex; 605 606 public TypeParameterBoundTarget(int typeParameterIndex, int boundIndex) { 607 this.typeParameterIndex = typeParameterIndex; 608 this.boundIndex = boundIndex; 609 } 610 611 @Override 612 public Kind kind() { 613 return Kind.TYPE_PARAMETER_BOUND; 614 } 615 616 public int typeParameterIndex() { 617 return typeParameterIndex; 618 } 619 620 public int boundIndex() { 621 return boundIndex; 622 } 623 } 624 625 /** A JVMS 4.7.20.1 empty_target. */ 626 public static final Target EMPTY_TARGET = 627 new Target() { 628 @Override 629 public Kind kind() { 630 return Kind.EMPTY; 631 } 632 }; 633 634 /** A JVMS 4.7.20.1 formal_parameter_target. */ 635 public static class FormalParameterTarget extends Target { 636 private final int index; 637 638 public FormalParameterTarget(int index) { 639 this.index = index; 640 } 641 642 @Override 643 public Kind kind() { 644 return Kind.FORMAL_PARAMETER; 645 } 646 647 public int index() { 648 return index; 649 } 650 } 651 652 /** A JVMS 4.7.20.1 throws_target. */ 653 public static class ThrowsTarget extends Target { 654 private final int index; 655 656 public ThrowsTarget(int index) { 657 this.index = index; 658 } 659 660 @Override 661 public Kind kind() { 662 return Kind.THROWS; 663 } 664 665 public int index() { 666 return index; 667 } 668 } 669 670 /** 671 * A JVMS 4.7.20.2 type_path. 672 * 673 * <p>Represented as an immutable linked-list of nodes, which is built out by {@code Lower} 674 * while recursively searching for type annotations to process. 675 */ 676 public static class TypePath { 677 678 /** The root type_path_kind, used for initialization. */ 679 public static TypePath root() { 680 return new TypePath(null, null); 681 } 682 683 /** Adds an array type_path_kind entry. */ 684 public TypePath array() { 685 return new TypePath(Kind.ARRAY, this); 686 } 687 688 /** Adds a nested type type_path_kind entry. */ 689 public TypePath nested() { 690 return new TypePath(Kind.NESTED, this); 691 } 692 693 /** Adds a wildcard bound type_path_kind entry. */ 694 public TypePath wild() { 695 return new TypePath(Kind.WILDCARD_BOUND, this); 696 } 697 698 /** Adds a type argument type_path_kind entry. */ 699 public TypePath typeArgument(int idx) { 700 return new TypePath(idx, Kind.TYPE_ARGUMENT, this); 701 } 702 703 /** A type_path_kind. */ 704 enum Kind { 705 ARRAY(0), 706 NESTED(1), 707 WILDCARD_BOUND(2), 708 TYPE_ARGUMENT(3); 709 710 final int tag; 711 712 Kind(int tag) { 713 this.tag = tag; 714 } 715 } 716 717 private final TypePath parent; 718 private final Kind kind; 719 private final int index; 720 721 private TypePath(Kind kind, TypePath parent) { 722 // JVMS 4.7.20.2: type_argument_index is 0 if the bound kind is not TYPE_ARGUMENT 723 this(0, kind, parent); 724 } 725 726 private TypePath(int index, Kind kind, TypePath parent) { 727 this.index = index; 728 this.kind = kind; 729 this.parent = parent; 730 } 731 732 /** The type argument index; set only if the kind is {@code TYPE_ARGUMENT}. */ 733 public int typeArgumentIndex() { 734 return index; 735 } 736 737 /** The JVMS 4.7.20.2-A serialized value of the type_path_kind. */ 738 public byte tag() { 739 return (byte) kind.tag; 740 } 741 742 /** Returns a flattened view of the type path. */ 743 public ImmutableList<TypePath> flatten() { 744 Deque<TypePath> flat = new ArrayDeque<>(); 745 for (TypePath curr = this; curr.kind != null; curr = curr.parent) { 746 flat.addFirst(curr); 747 } 748 return ImmutableList.copyOf(flat); 749 } 750 } 751 } 752} 753