ClassReader.java revision 3755:d4deb115da83
1/* 2 * Copyright (c) 1999, 2016, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.jvm; 27 28import java.io.*; 29import java.net.URI; 30import java.net.URISyntaxException; 31import java.nio.CharBuffer; 32import java.util.Arrays; 33import java.util.EnumSet; 34import java.util.HashMap; 35import java.util.HashSet; 36import java.util.Map; 37import java.util.Set; 38 39import javax.lang.model.element.Modifier; 40import javax.lang.model.element.NestingKind; 41import javax.tools.JavaFileManager; 42import javax.tools.JavaFileObject; 43 44import com.sun.tools.javac.comp.Annotate; 45import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter; 46import com.sun.tools.javac.code.*; 47import com.sun.tools.javac.code.Directive.*; 48import com.sun.tools.javac.code.Lint.LintCategory; 49import com.sun.tools.javac.code.Scope.WriteableScope; 50import com.sun.tools.javac.code.Symbol.*; 51import com.sun.tools.javac.code.Symtab; 52import com.sun.tools.javac.code.Type.*; 53import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; 54import com.sun.tools.javac.file.BaseFileManager; 55import com.sun.tools.javac.file.PathFileObject; 56import com.sun.tools.javac.jvm.ClassFile.NameAndType; 57import com.sun.tools.javac.jvm.ClassFile.Version; 58import com.sun.tools.javac.main.Option; 59import com.sun.tools.javac.util.*; 60import com.sun.tools.javac.util.DefinedBy.Api; 61import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 62 63import static com.sun.tools.javac.code.Flags.*; 64import static com.sun.tools.javac.code.Kinds.Kind.*; 65import com.sun.tools.javac.code.Scope.LookupKind; 66import static com.sun.tools.javac.code.TypeTag.ARRAY; 67import static com.sun.tools.javac.code.TypeTag.CLASS; 68import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 69import static com.sun.tools.javac.jvm.ClassFile.*; 70import static com.sun.tools.javac.jvm.ClassFile.Version.*; 71 72import static com.sun.tools.javac.main.Option.PARAMETERS; 73 74/** This class provides operations to read a classfile into an internal 75 * representation. The internal representation is anchored in a 76 * ClassSymbol which contains in its scope symbol representations 77 * for all other definitions in the classfile. Top-level Classes themselves 78 * appear as members of the scopes of PackageSymbols. 79 * 80 * <p><b>This is NOT part of any supported API. 81 * If you write code that depends on this, you do so at your own risk. 82 * This code and its internal interfaces are subject to change or 83 * deletion without notice.</b> 84 */ 85public class ClassReader { 86 /** The context key for the class reader. */ 87 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>(); 88 89 public static final int INITIAL_BUFFER_SIZE = 0x0fff0; 90 91 private final Annotate annotate; 92 93 /** Switch: verbose output. 94 */ 95 boolean verbose; 96 97 /** Switch: read constant pool and code sections. This switch is initially 98 * set to false but can be turned on from outside. 99 */ 100 public boolean readAllOfClassFile = false; 101 102 /** Switch: allow simplified varargs. 103 */ 104 boolean allowSimplifiedVarargs; 105 106 /** Switch: allow modules. 107 */ 108 boolean allowModules; 109 110 /** Lint option: warn about classfile issues 111 */ 112 boolean lintClassfile; 113 114 /** Switch: preserve parameter names from the variable table. 115 */ 116 public boolean saveParameterNames; 117 118 /** 119 * The currently selected profile. 120 */ 121 public final Profile profile; 122 123 /** The log to use for verbose output 124 */ 125 final Log log; 126 127 /** The symbol table. */ 128 Symtab syms; 129 130 Types types; 131 132 /** The name table. */ 133 final Names names; 134 135 /** Access to files 136 */ 137 private final JavaFileManager fileManager; 138 139 /** Factory for diagnostics 140 */ 141 JCDiagnostic.Factory diagFactory; 142 143 /** The current scope where type variables are entered. 144 */ 145 protected WriteableScope typevars; 146 147 private List<InterimUsesDirective> interimUses = List.nil(); 148 private List<InterimProvidesDirective> interimProvides = List.nil(); 149 150 /** The path name of the class file currently being read. 151 */ 152 protected JavaFileObject currentClassFile = null; 153 154 /** The class or method currently being read. 155 */ 156 protected Symbol currentOwner = null; 157 158 /** The module containing the class currently being read. 159 */ 160 protected ModuleSymbol currentModule = null; 161 162 /** The buffer containing the currently read class file. 163 */ 164 byte[] buf = new byte[INITIAL_BUFFER_SIZE]; 165 166 /** The current input pointer. 167 */ 168 protected int bp; 169 170 /** The objects of the constant pool. 171 */ 172 Object[] poolObj; 173 174 /** For every constant pool entry, an index into buf where the 175 * defining section of the entry is found. 176 */ 177 int[] poolIdx; 178 179 /** The major version number of the class file being read. */ 180 int majorVersion; 181 /** The minor version number of the class file being read. */ 182 int minorVersion; 183 184 /** A table to hold the constant pool indices for method parameter 185 * names, as given in LocalVariableTable attributes. 186 */ 187 int[] parameterNameIndices; 188 189 /** 190 * Whether or not any parameter names have been found. 191 */ 192 boolean haveParameterNameIndices; 193 194 /** Set this to false every time we start reading a method 195 * and are saving parameter names. Set it to true when we see 196 * MethodParameters, if it's set when we see a LocalVariableTable, 197 * then we ignore the parameter names from the LVT. 198 */ 199 boolean sawMethodParameters; 200 201 /** 202 * The set of attribute names for which warnings have been generated for the current class 203 */ 204 Set<Name> warnedAttrs = new HashSet<>(); 205 206 /** 207 * The prototype @Target Attribute.Compound if this class is an annotation annotated with 208 * @Target 209 */ 210 CompoundAnnotationProxy target; 211 212 /** 213 * The prototype @Repetable Attribute.Compound if this class is an annotation annotated with 214 * @Repeatable 215 */ 216 CompoundAnnotationProxy repeatable; 217 218 /** Get the ClassReader instance for this invocation. */ 219 public static ClassReader instance(Context context) { 220 ClassReader instance = context.get(classReaderKey); 221 if (instance == null) 222 instance = new ClassReader(context); 223 return instance; 224 } 225 226 /** Construct a new class reader. */ 227 protected ClassReader(Context context) { 228 context.put(classReaderKey, this); 229 annotate = Annotate.instance(context); 230 names = Names.instance(context); 231 syms = Symtab.instance(context); 232 types = Types.instance(context); 233 fileManager = context.get(JavaFileManager.class); 234 if (fileManager == null) 235 throw new AssertionError("FileManager initialization error"); 236 diagFactory = JCDiagnostic.Factory.instance(context); 237 238 log = Log.instance(context); 239 240 Options options = Options.instance(context); 241 verbose = options.isSet(Option.VERBOSE); 242 243 Source source = Source.instance(context); 244 allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 245 allowModules = source.allowModules(); 246 247 saveParameterNames = options.isSet(PARAMETERS); 248 249 profile = Profile.instance(context); 250 251 typevars = WriteableScope.create(syms.noSymbol); 252 253 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE); 254 255 initAttributeReaders(); 256 } 257 258 /** Add member to class unless it is synthetic. 259 */ 260 private void enterMember(ClassSymbol c, Symbol sym) { 261 // Synthetic members are not entered -- reason lost to history (optimization?). 262 // Lambda methods must be entered because they may have inner classes (which reference them) 263 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) 264 c.members_field.enter(sym); 265 } 266 267/************************************************************************ 268 * Error Diagnoses 269 ***********************************************************************/ 270 271 public ClassFinder.BadClassFile badClassFile(String key, Object... args) { 272 return new ClassFinder.BadClassFile ( 273 currentOwner.enclClass(), 274 currentClassFile, 275 diagFactory.fragment(key, args), 276 diagFactory); 277 } 278 279 public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Object... args) { 280 return new ClassFinder.BadEnclosingMethodAttr ( 281 currentOwner.enclClass(), 282 currentClassFile, 283 diagFactory.fragment("bad.enclosing.method", args), 284 diagFactory); 285 } 286 287/************************************************************************ 288 * Buffer Access 289 ***********************************************************************/ 290 291 /** Read a character. 292 */ 293 char nextChar() { 294 return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF)); 295 } 296 297 /** Read a byte. 298 */ 299 int nextByte() { 300 return buf[bp++] & 0xFF; 301 } 302 303 /** Read an integer. 304 */ 305 int nextInt() { 306 return 307 ((buf[bp++] & 0xFF) << 24) + 308 ((buf[bp++] & 0xFF) << 16) + 309 ((buf[bp++] & 0xFF) << 8) + 310 (buf[bp++] & 0xFF); 311 } 312 313 /** Extract a character at position bp from buf. 314 */ 315 char getChar(int bp) { 316 return 317 (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF)); 318 } 319 320 /** Extract an integer at position bp from buf. 321 */ 322 int getInt(int bp) { 323 return 324 ((buf[bp] & 0xFF) << 24) + 325 ((buf[bp+1] & 0xFF) << 16) + 326 ((buf[bp+2] & 0xFF) << 8) + 327 (buf[bp+3] & 0xFF); 328 } 329 330 331 /** Extract a long integer at position bp from buf. 332 */ 333 long getLong(int bp) { 334 DataInputStream bufin = 335 new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 336 try { 337 return bufin.readLong(); 338 } catch (IOException e) { 339 throw new AssertionError(e); 340 } 341 } 342 343 /** Extract a float at position bp from buf. 344 */ 345 float getFloat(int bp) { 346 DataInputStream bufin = 347 new DataInputStream(new ByteArrayInputStream(buf, bp, 4)); 348 try { 349 return bufin.readFloat(); 350 } catch (IOException e) { 351 throw new AssertionError(e); 352 } 353 } 354 355 /** Extract a double at position bp from buf. 356 */ 357 double getDouble(int bp) { 358 DataInputStream bufin = 359 new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 360 try { 361 return bufin.readDouble(); 362 } catch (IOException e) { 363 throw new AssertionError(e); 364 } 365 } 366 367/************************************************************************ 368 * Constant Pool Access 369 ***********************************************************************/ 370 371 /** Index all constant pool entries, writing their start addresses into 372 * poolIdx. 373 */ 374 void indexPool() { 375 poolIdx = new int[nextChar()]; 376 poolObj = new Object[poolIdx.length]; 377 int i = 1; 378 while (i < poolIdx.length) { 379 poolIdx[i++] = bp; 380 byte tag = buf[bp++]; 381 switch (tag) { 382 case CONSTANT_Utf8: case CONSTANT_Unicode: { 383 int len = nextChar(); 384 bp = bp + len; 385 break; 386 } 387 case CONSTANT_Class: 388 case CONSTANT_String: 389 case CONSTANT_MethodType: 390 bp = bp + 2; 391 break; 392 case CONSTANT_MethodHandle: 393 bp = bp + 3; 394 break; 395 case CONSTANT_Fieldref: 396 case CONSTANT_Methodref: 397 case CONSTANT_InterfaceMethodref: 398 case CONSTANT_NameandType: 399 case CONSTANT_Integer: 400 case CONSTANT_Float: 401 case CONSTANT_InvokeDynamic: 402 bp = bp + 4; 403 break; 404 case CONSTANT_Long: 405 case CONSTANT_Double: 406 bp = bp + 8; 407 i++; 408 break; 409 default: 410 throw badClassFile("bad.const.pool.tag.at", 411 Byte.toString(tag), 412 Integer.toString(bp -1)); 413 } 414 } 415 } 416 417 /** Read constant pool entry at start address i, use pool as a cache. 418 */ 419 Object readPool(int i) { 420 Object result = poolObj[i]; 421 if (result != null) return result; 422 423 int index = poolIdx[i]; 424 if (index == 0) return null; 425 426 byte tag = buf[index]; 427 switch (tag) { 428 case CONSTANT_Utf8: 429 poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1)); 430 break; 431 case CONSTANT_Unicode: 432 throw badClassFile("unicode.str.not.supported"); 433 case CONSTANT_Class: 434 poolObj[i] = readClassOrType(getChar(index + 1)); 435 break; 436 case CONSTANT_String: 437 // FIXME: (footprint) do not use toString here 438 poolObj[i] = readName(getChar(index + 1)).toString(); 439 break; 440 case CONSTANT_Fieldref: { 441 ClassSymbol owner = readClassSymbol(getChar(index + 1)); 442 NameAndType nt = readNameAndType(getChar(index + 3)); 443 poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner); 444 break; 445 } 446 case CONSTANT_Methodref: 447 case CONSTANT_InterfaceMethodref: { 448 ClassSymbol owner = readClassSymbol(getChar(index + 1)); 449 NameAndType nt = readNameAndType(getChar(index + 3)); 450 poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner); 451 break; 452 } 453 case CONSTANT_NameandType: 454 poolObj[i] = new NameAndType( 455 readName(getChar(index + 1)), 456 readType(getChar(index + 3)), types); 457 break; 458 case CONSTANT_Integer: 459 poolObj[i] = getInt(index + 1); 460 break; 461 case CONSTANT_Float: 462 poolObj[i] = Float.valueOf(getFloat(index + 1)); 463 break; 464 case CONSTANT_Long: 465 poolObj[i] = Long.valueOf(getLong(index + 1)); 466 break; 467 case CONSTANT_Double: 468 poolObj[i] = Double.valueOf(getDouble(index + 1)); 469 break; 470 case CONSTANT_MethodHandle: 471 skipBytes(4); 472 break; 473 case CONSTANT_MethodType: 474 skipBytes(3); 475 break; 476 case CONSTANT_InvokeDynamic: 477 skipBytes(5); 478 break; 479 default: 480 throw badClassFile("bad.const.pool.tag", Byte.toString(tag)); 481 } 482 return poolObj[i]; 483 } 484 485 /** Read signature and convert to type. 486 */ 487 Type readType(int i) { 488 int index = poolIdx[i]; 489 return sigToType(buf, index + 3, getChar(index + 1)); 490 } 491 492 /** If name is an array type or class signature, return the 493 * corresponding type; otherwise return a ClassSymbol with given name. 494 */ 495 Object readClassOrType(int i) { 496 int index = poolIdx[i]; 497 int len = getChar(index + 1); 498 int start = index + 3; 499 Assert.check(buf[start] == '[' || buf[start + len - 1] != ';'); 500 // by the above assertion, the following test can be 501 // simplified to (buf[start] == '[') 502 return (buf[start] == '[' || buf[start + len - 1] == ';') 503 ? (Object)sigToType(buf, start, len) 504 : (Object)enterClass(names.fromUtf(internalize(buf, start, 505 len))); 506 } 507 508 /** Read signature and convert to type parameters. 509 */ 510 List<Type> readTypeParams(int i) { 511 int index = poolIdx[i]; 512 return sigToTypeParams(buf, index + 3, getChar(index + 1)); 513 } 514 515 /** Read class entry. 516 */ 517 ClassSymbol readClassSymbol(int i) { 518 Object obj = readPool(i); 519 if (obj != null && !(obj instanceof ClassSymbol)) 520 throw badClassFile("bad.const.pool.entry", 521 currentClassFile.toString(), 522 "CONSTANT_Class_info", i); 523 return (ClassSymbol)obj; 524 } 525 526 Name readClassName(int i) { 527 int index = poolIdx[i]; 528 if (index == 0) return null; 529 byte tag = buf[index]; 530 if (tag != CONSTANT_Class) { 531 throw badClassFile("bad.const.pool.entry", 532 currentClassFile.toString(), 533 "CONSTANT_Class_info", i); 534 } 535 int nameIndex = poolIdx[getChar(index + 1)]; 536 int len = getChar(nameIndex + 1); 537 int start = nameIndex + 3; 538 if (buf[start] == '[' || buf[start + len - 1] == ';') 539 throw badClassFile("wrong class name"); //TODO: proper diagnostics 540 return names.fromUtf(internalize(buf, start, len)); 541 } 542 543 /** Read name. 544 */ 545 Name readName(int i) { 546 Object obj = readPool(i); 547 if (obj != null && !(obj instanceof Name)) 548 throw badClassFile("bad.const.pool.entry", 549 currentClassFile.toString(), 550 "CONSTANT_Utf8_info or CONSTANT_String_info", i); 551 return (Name)obj; 552 } 553 554 /** Read name and type. 555 */ 556 NameAndType readNameAndType(int i) { 557 Object obj = readPool(i); 558 if (obj != null && !(obj instanceof NameAndType)) 559 throw badClassFile("bad.const.pool.entry", 560 currentClassFile.toString(), 561 "CONSTANT_NameAndType_info", i); 562 return (NameAndType)obj; 563 } 564 565 /** Read the class name of a module-info.class file. 566 * The name is stored in a CONSTANT_Class entry, where the 567 * class name is of the form module-name.module-info. 568 */ 569 Name readModuleInfoName(int i) { 570 if (majorVersion < Version.V53.major) { 571 throw badClassFile("anachronistic.module.info", 572 Integer.toString(majorVersion), 573 Integer.toString(minorVersion)); 574 } 575 int classIndex = poolIdx[i]; 576 if (buf[classIndex] == CONSTANT_Class) { 577 int utf8Index = poolIdx[getChar(classIndex + 1)]; 578 if (buf[utf8Index] == CONSTANT_Utf8) { 579 int len = getChar(utf8Index + 1); 580 int start = utf8Index + 3; 581 return names.fromUtf(internalize(buf, start, len)); 582 } 583 } 584 throw badClassFile("bad.module-info.name"); 585 } 586 587 /** Read requires_flags. 588 */ 589 Set<RequiresFlag> readRequiresFlags(int flags) { 590 Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class); 591 for (RequiresFlag f: RequiresFlag.values()) { 592 if ((flags & f.value) != 0) 593 set.add(f); 594 } 595 return set; 596 } 597 598/************************************************************************ 599 * Reading Types 600 ***********************************************************************/ 601 602 /** The unread portion of the currently read type is 603 * signature[sigp..siglimit-1]. 604 */ 605 byte[] signature; 606 int sigp; 607 int siglimit; 608 boolean sigEnterPhase = false; 609 610 /** Convert signature to type, where signature is a byte array segment. 611 */ 612 Type sigToType(byte[] sig, int offset, int len) { 613 signature = sig; 614 sigp = offset; 615 siglimit = offset + len; 616 return sigToType(); 617 } 618 619 /** Convert signature to type, where signature is implicit. 620 */ 621 Type sigToType() { 622 switch ((char) signature[sigp]) { 623 case 'T': 624 sigp++; 625 int start = sigp; 626 while (signature[sigp] != ';') sigp++; 627 sigp++; 628 return sigEnterPhase 629 ? Type.noType 630 : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start)); 631 case '+': { 632 sigp++; 633 Type t = sigToType(); 634 return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass); 635 } 636 case '*': 637 sigp++; 638 return new WildcardType(syms.objectType, BoundKind.UNBOUND, 639 syms.boundClass); 640 case '-': { 641 sigp++; 642 Type t = sigToType(); 643 return new WildcardType(t, BoundKind.SUPER, syms.boundClass); 644 } 645 case 'B': 646 sigp++; 647 return syms.byteType; 648 case 'C': 649 sigp++; 650 return syms.charType; 651 case 'D': 652 sigp++; 653 return syms.doubleType; 654 case 'F': 655 sigp++; 656 return syms.floatType; 657 case 'I': 658 sigp++; 659 return syms.intType; 660 case 'J': 661 sigp++; 662 return syms.longType; 663 case 'L': 664 { 665 // int oldsigp = sigp; 666 Type t = classSigToType(); 667 if (sigp < siglimit && signature[sigp] == '.') 668 throw badClassFile("deprecated inner class signature syntax " + 669 "(please recompile from source)"); 670 /* 671 System.err.println(" decoded " + 672 new String(signature, oldsigp, sigp-oldsigp) + 673 " => " + t + " outer " + t.outer()); 674 */ 675 return t; 676 } 677 case 'S': 678 sigp++; 679 return syms.shortType; 680 case 'V': 681 sigp++; 682 return syms.voidType; 683 case 'Z': 684 sigp++; 685 return syms.booleanType; 686 case '[': 687 sigp++; 688 return new ArrayType(sigToType(), syms.arrayClass); 689 case '(': 690 sigp++; 691 List<Type> argtypes = sigToTypes(')'); 692 Type restype = sigToType(); 693 List<Type> thrown = List.nil(); 694 while (signature[sigp] == '^') { 695 sigp++; 696 thrown = thrown.prepend(sigToType()); 697 } 698 // if there is a typevar in the throws clause we should state it. 699 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) { 700 if (l.head.hasTag(TYPEVAR)) { 701 l.head.tsym.flags_field |= THROWS; 702 } 703 } 704 return new MethodType(argtypes, 705 restype, 706 thrown.reverse(), 707 syms.methodClass); 708 case '<': 709 typevars = typevars.dup(currentOwner); 710 Type poly = new ForAll(sigToTypeParams(), sigToType()); 711 typevars = typevars.leave(); 712 return poly; 713 default: 714 throw badClassFile("bad.signature", 715 Convert.utf2string(signature, sigp, 10)); 716 } 717 } 718 719 byte[] signatureBuffer = new byte[0]; 720 int sbp = 0; 721 /** Convert class signature to type, where signature is implicit. 722 */ 723 Type classSigToType() { 724 if (signature[sigp] != 'L') 725 throw badClassFile("bad.class.signature", 726 Convert.utf2string(signature, sigp, 10)); 727 sigp++; 728 Type outer = Type.noType; 729 int startSbp = sbp; 730 731 while (true) { 732 final byte c = signature[sigp++]; 733 switch (c) { 734 735 case ';': { // end 736 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, 737 startSbp, 738 sbp - startSbp)); 739 740 try { 741 return (outer == Type.noType) ? 742 t.erasure(types) : 743 new ClassType(outer, List.<Type>nil(), t); 744 } finally { 745 sbp = startSbp; 746 } 747 } 748 749 case '<': // generic arguments 750 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, 751 startSbp, 752 sbp - startSbp)); 753 outer = new ClassType(outer, sigToTypes('>'), t) { 754 boolean completed = false; 755 @Override @DefinedBy(Api.LANGUAGE_MODEL) 756 public Type getEnclosingType() { 757 if (!completed) { 758 completed = true; 759 tsym.complete(); 760 Type enclosingType = tsym.type.getEnclosingType(); 761 if (enclosingType != Type.noType) { 762 List<Type> typeArgs = 763 super.getEnclosingType().allparams(); 764 List<Type> typeParams = 765 enclosingType.allparams(); 766 if (typeParams.length() != typeArgs.length()) { 767 // no "rare" types 768 super.setEnclosingType(types.erasure(enclosingType)); 769 } else { 770 super.setEnclosingType(types.subst(enclosingType, 771 typeParams, 772 typeArgs)); 773 } 774 } else { 775 super.setEnclosingType(Type.noType); 776 } 777 } 778 return super.getEnclosingType(); 779 } 780 @Override 781 public void setEnclosingType(Type outer) { 782 throw new UnsupportedOperationException(); 783 } 784 }; 785 switch (signature[sigp++]) { 786 case ';': 787 if (sigp < signature.length && signature[sigp] == '.') { 788 // support old-style GJC signatures 789 // The signature produced was 790 // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>; 791 // rather than say 792 // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>; 793 // so we skip past ".Lfoo/Outer$" 794 sigp += (sbp - startSbp) + // "foo/Outer" 795 3; // ".L" and "$" 796 signatureBuffer[sbp++] = (byte)'$'; 797 break; 798 } else { 799 sbp = startSbp; 800 return outer; 801 } 802 case '.': 803 signatureBuffer[sbp++] = (byte)'$'; 804 break; 805 default: 806 throw new AssertionError(signature[sigp-1]); 807 } 808 continue; 809 810 case '.': 811 //we have seen an enclosing non-generic class 812 if (outer != Type.noType) { 813 t = enterClass(names.fromUtf(signatureBuffer, 814 startSbp, 815 sbp - startSbp)); 816 outer = new ClassType(outer, List.<Type>nil(), t); 817 } 818 signatureBuffer[sbp++] = (byte)'$'; 819 continue; 820 case '/': 821 signatureBuffer[sbp++] = (byte)'.'; 822 continue; 823 default: 824 signatureBuffer[sbp++] = c; 825 continue; 826 } 827 } 828 } 829 830 /** Convert (implicit) signature to list of types 831 * until `terminator' is encountered. 832 */ 833 List<Type> sigToTypes(char terminator) { 834 List<Type> head = List.of(null); 835 List<Type> tail = head; 836 while (signature[sigp] != terminator) 837 tail = tail.setTail(List.of(sigToType())); 838 sigp++; 839 return head.tail; 840 } 841 842 /** Convert signature to type parameters, where signature is a byte 843 * array segment. 844 */ 845 List<Type> sigToTypeParams(byte[] sig, int offset, int len) { 846 signature = sig; 847 sigp = offset; 848 siglimit = offset + len; 849 return sigToTypeParams(); 850 } 851 852 /** Convert signature to type parameters, where signature is implicit. 853 */ 854 List<Type> sigToTypeParams() { 855 List<Type> tvars = List.nil(); 856 if (signature[sigp] == '<') { 857 sigp++; 858 int start = sigp; 859 sigEnterPhase = true; 860 while (signature[sigp] != '>') 861 tvars = tvars.prepend(sigToTypeParam()); 862 sigEnterPhase = false; 863 sigp = start; 864 while (signature[sigp] != '>') 865 sigToTypeParam(); 866 sigp++; 867 } 868 return tvars.reverse(); 869 } 870 871 /** Convert (implicit) signature to type parameter. 872 */ 873 Type sigToTypeParam() { 874 int start = sigp; 875 while (signature[sigp] != ':') sigp++; 876 Name name = names.fromUtf(signature, start, sigp - start); 877 TypeVar tvar; 878 if (sigEnterPhase) { 879 tvar = new TypeVar(name, currentOwner, syms.botType); 880 typevars.enter(tvar.tsym); 881 } else { 882 tvar = (TypeVar)findTypeVar(name); 883 } 884 List<Type> bounds = List.nil(); 885 boolean allInterfaces = false; 886 if (signature[sigp] == ':' && signature[sigp+1] == ':') { 887 sigp++; 888 allInterfaces = true; 889 } 890 while (signature[sigp] == ':') { 891 sigp++; 892 bounds = bounds.prepend(sigToType()); 893 } 894 if (!sigEnterPhase) { 895 types.setBounds(tvar, bounds.reverse(), allInterfaces); 896 } 897 return tvar; 898 } 899 900 /** Find type variable with given name in `typevars' scope. 901 */ 902 Type findTypeVar(Name name) { 903 Symbol s = typevars.findFirst(name); 904 if (s != null) { 905 return s.type; 906 } else { 907 if (readingClassAttr) { 908 // While reading the class attribute, the supertypes 909 // might refer to a type variable from an enclosing element 910 // (method or class). 911 // If the type variable is defined in the enclosing class, 912 // we can actually find it in 913 // currentOwner.owner.type.getTypeArguments() 914 // However, until we have read the enclosing method attribute 915 // we don't know for sure if this owner is correct. It could 916 // be a method and there is no way to tell before reading the 917 // enclosing method attribute. 918 TypeVar t = new TypeVar(name, currentOwner, syms.botType); 919 missingTypeVariables = missingTypeVariables.prepend(t); 920 // System.err.println("Missing type var " + name); 921 return t; 922 } 923 throw badClassFile("undecl.type.var", name); 924 } 925 } 926 927/************************************************************************ 928 * Reading Attributes 929 ***********************************************************************/ 930 931 protected enum AttributeKind { CLASS, MEMBER } 932 933 protected abstract class AttributeReader { 934 protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { 935 this.name = name; 936 this.version = version; 937 this.kinds = kinds; 938 } 939 940 protected boolean accepts(AttributeKind kind) { 941 if (kinds.contains(kind)) { 942 if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor)) 943 return true; 944 945 if (lintClassfile && !warnedAttrs.contains(name)) { 946 JavaFileObject prev = log.useSource(currentClassFile); 947 try { 948 log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr", 949 name, version.major, version.minor, majorVersion, minorVersion); 950 } finally { 951 log.useSource(prev); 952 } 953 warnedAttrs.add(name); 954 } 955 } 956 return false; 957 } 958 959 protected abstract void read(Symbol sym, int attrLen); 960 961 protected final Name name; 962 protected final ClassFile.Version version; 963 protected final Set<AttributeKind> kinds; 964 } 965 966 protected Set<AttributeKind> CLASS_ATTRIBUTE = 967 EnumSet.of(AttributeKind.CLASS); 968 protected Set<AttributeKind> MEMBER_ATTRIBUTE = 969 EnumSet.of(AttributeKind.MEMBER); 970 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE = 971 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER); 972 973 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>(); 974 975 private void initAttributeReaders() { 976 AttributeReader[] readers = { 977 // v45.3 attributes 978 979 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) { 980 protected void read(Symbol sym, int attrLen) { 981 if (readAllOfClassFile || saveParameterNames) 982 ((MethodSymbol)sym).code = readCode(sym); 983 else 984 bp = bp + attrLen; 985 } 986 }, 987 988 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) { 989 protected void read(Symbol sym, int attrLen) { 990 Object v = readPool(nextChar()); 991 // Ignore ConstantValue attribute if field not final. 992 if ((sym.flags() & FINAL) != 0) 993 ((VarSymbol) sym).setData(v); 994 } 995 }, 996 997 new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 998 protected void read(Symbol sym, int attrLen) { 999 sym.flags_field |= DEPRECATED; 1000 } 1001 }, 1002 1003 new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1004 protected void read(Symbol sym, int attrLen) { 1005 int nexceptions = nextChar(); 1006 List<Type> thrown = List.nil(); 1007 for (int j = 0; j < nexceptions; j++) 1008 thrown = thrown.prepend(readClassSymbol(nextChar()).type); 1009 if (sym.type.getThrownTypes().isEmpty()) 1010 sym.type.asMethodType().thrown = thrown.reverse(); 1011 } 1012 }, 1013 1014 new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) { 1015 protected void read(Symbol sym, int attrLen) { 1016 ClassSymbol c = (ClassSymbol) sym; 1017 if (currentModule.module_info == c) { 1018 //prevent entering the classes too soon: 1019 skipInnerClasses(); 1020 } else { 1021 readInnerClasses(c); 1022 } 1023 } 1024 }, 1025 1026 new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1027 protected void read(Symbol sym, int attrLen) { 1028 int newbp = bp + attrLen; 1029 if (saveParameterNames && !sawMethodParameters) { 1030 // Pick up parameter names from the variable table. 1031 // Parameter names are not explicitly identified as such, 1032 // but all parameter name entries in the LocalVariableTable 1033 // have a start_pc of 0. Therefore, we record the name 1034 // indicies of all slots with a start_pc of zero in the 1035 // parameterNameIndicies array. 1036 // Note that this implicitly honors the JVMS spec that 1037 // there may be more than one LocalVariableTable, and that 1038 // there is no specified ordering for the entries. 1039 int numEntries = nextChar(); 1040 for (int i = 0; i < numEntries; i++) { 1041 int start_pc = nextChar(); 1042 int length = nextChar(); 1043 int nameIndex = nextChar(); 1044 int sigIndex = nextChar(); 1045 int register = nextChar(); 1046 if (start_pc == 0) { 1047 // ensure array large enough 1048 if (register >= parameterNameIndices.length) { 1049 int newSize = 1050 Math.max(register + 1, parameterNameIndices.length + 8); 1051 parameterNameIndices = 1052 Arrays.copyOf(parameterNameIndices, newSize); 1053 } 1054 parameterNameIndices[register] = nameIndex; 1055 haveParameterNameIndices = true; 1056 } 1057 } 1058 } 1059 bp = newbp; 1060 } 1061 }, 1062 1063 new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) { 1064 protected void read(Symbol sym, int attrLen) { 1065 ClassSymbol c = (ClassSymbol) sym; 1066 Name n = readName(nextChar()); 1067 c.sourcefile = new SourceFileObject(n, c.flatname); 1068 // If the class is a toplevel class, originating from a Java source file, 1069 // but the class name does not match the file name, then it is 1070 // an auxiliary class. 1071 String sn = n.toString(); 1072 if (c.owner.kind == PCK && 1073 sn.endsWith(".java") && 1074 !sn.equals(c.name.toString()+".java")) { 1075 c.flags_field |= AUXILIARY; 1076 } 1077 } 1078 }, 1079 1080 new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1081 protected void read(Symbol sym, int attrLen) { 1082 sym.flags_field |= SYNTHETIC; 1083 } 1084 }, 1085 1086 // standard v49 attributes 1087 1088 new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) { 1089 protected void read(Symbol sym, int attrLen) { 1090 int newbp = bp + attrLen; 1091 readEnclosingMethodAttr(sym); 1092 bp = newbp; 1093 } 1094 }, 1095 1096 new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1097 protected void read(Symbol sym, int attrLen) { 1098 if (sym.kind == TYP) { 1099 ClassSymbol c = (ClassSymbol) sym; 1100 readingClassAttr = true; 1101 try { 1102 ClassType ct1 = (ClassType)c.type; 1103 Assert.check(c == currentOwner); 1104 ct1.typarams_field = readTypeParams(nextChar()); 1105 ct1.supertype_field = sigToType(); 1106 ListBuffer<Type> is = new ListBuffer<>(); 1107 while (sigp != siglimit) is.append(sigToType()); 1108 ct1.interfaces_field = is.toList(); 1109 } finally { 1110 readingClassAttr = false; 1111 } 1112 } else { 1113 List<Type> thrown = sym.type.getThrownTypes(); 1114 sym.type = readType(nextChar()); 1115 //- System.err.println(" # " + sym.type); 1116 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty()) 1117 sym.type.asMethodType().thrown = thrown; 1118 1119 } 1120 } 1121 }, 1122 1123 // v49 annotation attributes 1124 1125 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1126 protected void read(Symbol sym, int attrLen) { 1127 attachAnnotationDefault(sym); 1128 } 1129 }, 1130 1131 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1132 protected void read(Symbol sym, int attrLen) { 1133 attachAnnotations(sym); 1134 } 1135 }, 1136 1137 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1138 protected void read(Symbol sym, int attrLen) { 1139 attachParameterAnnotations(sym); 1140 } 1141 }, 1142 1143 new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1144 protected void read(Symbol sym, int attrLen) { 1145 attachAnnotations(sym); 1146 } 1147 }, 1148 1149 new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1150 protected void read(Symbol sym, int attrLen) { 1151 attachParameterAnnotations(sym); 1152 } 1153 }, 1154 1155 // additional "legacy" v49 attributes, superceded by flags 1156 1157 new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1158 protected void read(Symbol sym, int attrLen) { 1159 sym.flags_field |= ANNOTATION; 1160 } 1161 }, 1162 1163 new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) { 1164 protected void read(Symbol sym, int attrLen) { 1165 sym.flags_field |= BRIDGE; 1166 } 1167 }, 1168 1169 new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1170 protected void read(Symbol sym, int attrLen) { 1171 sym.flags_field |= ENUM; 1172 } 1173 }, 1174 1175 new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1176 protected void read(Symbol sym, int attrLen) { 1177 sym.flags_field |= VARARGS; 1178 } 1179 }, 1180 1181 new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1182 protected void read(Symbol sym, int attrLen) { 1183 attachTypeAnnotations(sym); 1184 } 1185 }, 1186 1187 new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1188 protected void read(Symbol sym, int attrLen) { 1189 attachTypeAnnotations(sym); 1190 } 1191 }, 1192 1193 // The following attributes for a Code attribute are not currently handled 1194 // StackMapTable 1195 // SourceDebugExtension 1196 // LineNumberTable 1197 // LocalVariableTypeTable 1198 1199 // standard v52 attributes 1200 1201 new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) { 1202 protected void read(Symbol sym, int attrlen) { 1203 int newbp = bp + attrlen; 1204 if (saveParameterNames) { 1205 sawMethodParameters = true; 1206 int numEntries = nextByte(); 1207 parameterNameIndices = new int[numEntries]; 1208 haveParameterNameIndices = true; 1209 for (int i = 0; i < numEntries; i++) { 1210 int nameIndex = nextChar(); 1211 int flags = nextChar(); 1212 parameterNameIndices[i] = nameIndex; 1213 } 1214 } 1215 bp = newbp; 1216 } 1217 }, 1218 1219 // standard v53 attributes 1220 1221 new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) { 1222 @Override 1223 protected boolean accepts(AttributeKind kind) { 1224 return super.accepts(kind) && allowModules; 1225 } 1226 protected void read(Symbol sym, int attrLen) { 1227 if (sym.kind == TYP && sym.owner.kind == MDL) { 1228 ModuleSymbol msym = (ModuleSymbol) sym.owner; 1229 ListBuffer<Directive> directives = new ListBuffer<>(); 1230 1231 ListBuffer<RequiresDirective> requires = new ListBuffer<>(); 1232 int nrequires = nextChar(); 1233 for (int i = 0; i < nrequires; i++) { 1234 Name name = readName(nextChar()); 1235 ModuleSymbol rsym = syms.enterModule(name); 1236 Set<RequiresFlag> flags = readRequiresFlags(nextChar()); 1237 requires.add(new RequiresDirective(rsym, flags)); 1238 } 1239 msym.requires = requires.toList(); 1240 directives.addAll(msym.requires); 1241 1242 ListBuffer<ExportsDirective> exports = new ListBuffer<>(); 1243 int nexports = nextChar(); 1244 for (int i = 0; i < nexports; i++) { 1245 Name n = readName(nextChar()); 1246 PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n))); 1247 int nto = nextChar(); 1248 List<ModuleSymbol> to; 1249 if (nto == 0) { 1250 to = null; 1251 } else { 1252 ListBuffer<ModuleSymbol> lb = new ListBuffer<>(); 1253 for (int t = 0; t < nto; t++) 1254 lb.append(syms.enterModule(readName(nextChar()))); 1255 to = lb.toList(); 1256 } 1257 exports.add(new ExportsDirective(p, to)); 1258 } 1259 msym.exports = exports.toList(); 1260 directives.addAll(msym.exports); 1261 1262 msym.directives = directives.toList(); 1263 1264 ListBuffer<InterimUsesDirective> uses = new ListBuffer<>(); 1265 int nuses = nextChar(); 1266 for (int i = 0; i < nuses; i++) { 1267 Name srvc = readClassName(nextChar()); 1268 uses.add(new InterimUsesDirective(srvc)); 1269 } 1270 interimUses = uses.toList(); 1271 1272 ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>(); 1273 int nprovides = nextChar(); 1274 for (int i = 0; i < nprovides; i++) { 1275 Name srvc = readClassName(nextChar()); 1276 Name impl = readClassName(nextChar()); 1277 provides.add(new InterimProvidesDirective(srvc, impl)); 1278 } 1279 interimProvides = provides.toList(); 1280 } 1281 } 1282 }, 1283 1284 new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) { 1285 @Override 1286 protected boolean accepts(AttributeKind kind) { 1287 return super.accepts(kind) && allowModules; 1288 } 1289 protected void read(Symbol sym, int attrLen) { 1290 if (sym.kind == TYP && sym.owner.kind == MDL) { 1291 ModuleSymbol msym = (ModuleSymbol) sym.owner; 1292 msym.version = readName(nextChar()); 1293 } 1294 } 1295 }, 1296 }; 1297 1298 for (AttributeReader r: readers) 1299 attributeReaders.put(r.name, r); 1300 } 1301 1302 protected void readEnclosingMethodAttr(Symbol sym) { 1303 // sym is a nested class with an "Enclosing Method" attribute 1304 // remove sym from it's current owners scope and place it in 1305 // the scope specified by the attribute 1306 sym.owner.members().remove(sym); 1307 ClassSymbol self = (ClassSymbol)sym; 1308 ClassSymbol c = readClassSymbol(nextChar()); 1309 NameAndType nt = readNameAndType(nextChar()); 1310 1311 if (c.members_field == null) 1312 throw badClassFile("bad.enclosing.class", self, c); 1313 1314 MethodSymbol m = findMethod(nt, c.members_field, self.flags()); 1315 if (nt != null && m == null) 1316 throw badEnclosingMethod(self); 1317 1318 self.name = simpleBinaryName(self.flatname, c.flatname) ; 1319 self.owner = m != null ? m : c; 1320 if (self.name.isEmpty()) 1321 self.fullname = names.empty; 1322 else 1323 self.fullname = ClassSymbol.formFullName(self.name, self.owner); 1324 1325 if (m != null) { 1326 ((ClassType)sym.type).setEnclosingType(m.type); 1327 } else if ((self.flags_field & STATIC) == 0) { 1328 ((ClassType)sym.type).setEnclosingType(c.type); 1329 } else { 1330 ((ClassType)sym.type).setEnclosingType(Type.noType); 1331 } 1332 enterTypevars(self, self.type); 1333 if (!missingTypeVariables.isEmpty()) { 1334 ListBuffer<Type> typeVars = new ListBuffer<>(); 1335 for (Type typevar : missingTypeVariables) { 1336 typeVars.append(findTypeVar(typevar.tsym.name)); 1337 } 1338 foundTypeVariables = typeVars.toList(); 1339 } else { 1340 foundTypeVariables = List.nil(); 1341 } 1342 } 1343 1344 // See java.lang.Class 1345 private Name simpleBinaryName(Name self, Name enclosing) { 1346 String simpleBinaryName = self.toString().substring(enclosing.toString().length()); 1347 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$') 1348 throw badClassFile("bad.enclosing.method", self); 1349 int index = 1; 1350 while (index < simpleBinaryName.length() && 1351 isAsciiDigit(simpleBinaryName.charAt(index))) 1352 index++; 1353 return names.fromString(simpleBinaryName.substring(index)); 1354 } 1355 1356 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) { 1357 if (nt == null) 1358 return null; 1359 1360 MethodType type = nt.uniqueType.type.asMethodType(); 1361 1362 for (Symbol sym : scope.getSymbolsByName(nt.name)) { 1363 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type)) 1364 return (MethodSymbol)sym; 1365 } 1366 1367 if (nt.name != names.init) 1368 // not a constructor 1369 return null; 1370 if ((flags & INTERFACE) != 0) 1371 // no enclosing instance 1372 return null; 1373 if (nt.uniqueType.type.getParameterTypes().isEmpty()) 1374 // no parameters 1375 return null; 1376 1377 // A constructor of an inner class. 1378 // Remove the first argument (the enclosing instance) 1379 nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail, 1380 nt.uniqueType.type.getReturnType(), 1381 nt.uniqueType.type.getThrownTypes(), 1382 syms.methodClass)); 1383 // Try searching again 1384 return findMethod(nt, scope, flags); 1385 } 1386 1387 /** Similar to Types.isSameType but avoids completion */ 1388 private boolean isSameBinaryType(MethodType mt1, MethodType mt2) { 1389 List<Type> types1 = types.erasure(mt1.getParameterTypes()) 1390 .prepend(types.erasure(mt1.getReturnType())); 1391 List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType()); 1392 while (!types1.isEmpty() && !types2.isEmpty()) { 1393 if (types1.head.tsym != types2.head.tsym) 1394 return false; 1395 types1 = types1.tail; 1396 types2 = types2.tail; 1397 } 1398 return types1.isEmpty() && types2.isEmpty(); 1399 } 1400 1401 /** 1402 * Character.isDigit answers <tt>true</tt> to some non-ascii 1403 * digits. This one does not. <b>copied from java.lang.Class</b> 1404 */ 1405 private static boolean isAsciiDigit(char c) { 1406 return '0' <= c && c <= '9'; 1407 } 1408 1409 /** Read member attributes. 1410 */ 1411 void readMemberAttrs(Symbol sym) { 1412 readAttrs(sym, AttributeKind.MEMBER); 1413 } 1414 1415 void readAttrs(Symbol sym, AttributeKind kind) { 1416 char ac = nextChar(); 1417 for (int i = 0; i < ac; i++) { 1418 Name attrName = readName(nextChar()); 1419 int attrLen = nextInt(); 1420 AttributeReader r = attributeReaders.get(attrName); 1421 if (r != null && r.accepts(kind)) 1422 r.read(sym, attrLen); 1423 else { 1424 bp = bp + attrLen; 1425 } 1426 } 1427 } 1428 1429 private boolean readingClassAttr = false; 1430 private List<Type> missingTypeVariables = List.nil(); 1431 private List<Type> foundTypeVariables = List.nil(); 1432 1433 /** Read class attributes. 1434 */ 1435 void readClassAttrs(ClassSymbol c) { 1436 readAttrs(c, AttributeKind.CLASS); 1437 } 1438 1439 /** Read code block. 1440 */ 1441 Code readCode(Symbol owner) { 1442 nextChar(); // max_stack 1443 nextChar(); // max_locals 1444 final int code_length = nextInt(); 1445 bp += code_length; 1446 final char exception_table_length = nextChar(); 1447 bp += exception_table_length * 8; 1448 readMemberAttrs(owner); 1449 return null; 1450 } 1451 1452/************************************************************************ 1453 * Reading Java-language annotations 1454 ***********************************************************************/ 1455 1456 /** Attach annotations. 1457 */ 1458 void attachAnnotations(final Symbol sym) { 1459 int numAttributes = nextChar(); 1460 if (numAttributes != 0) { 1461 ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>(); 1462 for (int i = 0; i<numAttributes; i++) { 1463 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1464 if (proxy.type.tsym == syms.proprietaryType.tsym) 1465 sym.flags_field |= PROPRIETARY; 1466 else if (proxy.type.tsym == syms.profileType.tsym) { 1467 if (profile != Profile.DEFAULT) { 1468 for (Pair<Name,Attribute> v: proxy.values) { 1469 if (v.fst == names.value && v.snd instanceof Attribute.Constant) { 1470 Attribute.Constant c = (Attribute.Constant) v.snd; 1471 if (c.type == syms.intType && ((Integer) c.value) > profile.value) { 1472 sym.flags_field |= NOT_IN_PROFILE; 1473 } 1474 } 1475 } 1476 } 1477 } else { 1478 if (proxy.type.tsym == syms.annotationTargetType.tsym) { 1479 target = proxy; 1480 } else if (proxy.type.tsym == syms.repeatableType.tsym) { 1481 repeatable = proxy; 1482 } else if (proxy.type.tsym == syms.deprecatedType.tsym) { 1483 sym.flags_field |= DEPRECATED; 1484 for (Pair<Name, Attribute> v : proxy.values) { 1485 if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) { 1486 Attribute.Constant c = (Attribute.Constant) v.snd; 1487 if (c.type == syms.booleanType && ((Integer) c.value) != 0) { 1488 sym.flags_field |= DEPRECATED_REMOVAL; 1489 } 1490 } 1491 } 1492 } 1493 1494 proxies.append(proxy); 1495 } 1496 } 1497 annotate.normal(new AnnotationCompleter(sym, proxies.toList())); 1498 } 1499 } 1500 1501 /** Attach parameter annotations. 1502 */ 1503 void attachParameterAnnotations(final Symbol method) { 1504 final MethodSymbol meth = (MethodSymbol)method; 1505 int numParameters = buf[bp++] & 0xFF; 1506 List<VarSymbol> parameters = meth.params(); 1507 int pnum = 0; 1508 while (parameters.tail != null) { 1509 attachAnnotations(parameters.head); 1510 parameters = parameters.tail; 1511 pnum++; 1512 } 1513 if (pnum != numParameters) { 1514 throw badClassFile("bad.runtime.invisible.param.annotations", meth); 1515 } 1516 } 1517 1518 void attachTypeAnnotations(final Symbol sym) { 1519 int numAttributes = nextChar(); 1520 if (numAttributes != 0) { 1521 ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>(); 1522 for (int i = 0; i < numAttributes; i++) 1523 proxies.append(readTypeAnnotation()); 1524 annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); 1525 } 1526 } 1527 1528 /** Attach the default value for an annotation element. 1529 */ 1530 void attachAnnotationDefault(final Symbol sym) { 1531 final MethodSymbol meth = (MethodSymbol)sym; // only on methods 1532 final Attribute value = readAttributeValue(); 1533 1534 // The default value is set later during annotation. It might 1535 // be the case that the Symbol sym is annotated _after_ the 1536 // repeating instances that depend on this default value, 1537 // because of this we set an interim value that tells us this 1538 // element (most likely) has a default. 1539 // 1540 // Set interim value for now, reset just before we do this 1541 // properly at annotate time. 1542 meth.defaultValue = value; 1543 annotate.normal(new AnnotationDefaultCompleter(meth, value)); 1544 } 1545 1546 Type readTypeOrClassSymbol(int i) { 1547 // support preliminary jsr175-format class files 1548 if (buf[poolIdx[i]] == CONSTANT_Class) 1549 return readClassSymbol(i).type; 1550 return readType(i); 1551 } 1552 Type readEnumType(int i) { 1553 // support preliminary jsr175-format class files 1554 int index = poolIdx[i]; 1555 int length = getChar(index + 1); 1556 if (buf[index + length + 2] != ';') 1557 return enterClass(readName(i)).type; 1558 return readType(i); 1559 } 1560 1561 CompoundAnnotationProxy readCompoundAnnotation() { 1562 Type t = readTypeOrClassSymbol(nextChar()); 1563 int numFields = nextChar(); 1564 ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>(); 1565 for (int i=0; i<numFields; i++) { 1566 Name name = readName(nextChar()); 1567 Attribute value = readAttributeValue(); 1568 pairs.append(new Pair<>(name, value)); 1569 } 1570 return new CompoundAnnotationProxy(t, pairs.toList()); 1571 } 1572 1573 TypeAnnotationProxy readTypeAnnotation() { 1574 TypeAnnotationPosition position = readPosition(); 1575 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1576 1577 return new TypeAnnotationProxy(proxy, position); 1578 } 1579 1580 TypeAnnotationPosition readPosition() { 1581 int tag = nextByte(); // TargetType tag is a byte 1582 1583 if (!TargetType.isValidTargetTypeValue(tag)) 1584 throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); 1585 1586 TargetType type = TargetType.fromTargetTypeValue(tag); 1587 1588 switch (type) { 1589 // instanceof 1590 case INSTANCEOF: { 1591 final int offset = nextChar(); 1592 final TypeAnnotationPosition position = 1593 TypeAnnotationPosition.instanceOf(readTypePath()); 1594 position.offset = offset; 1595 return position; 1596 } 1597 // new expression 1598 case NEW: { 1599 final int offset = nextChar(); 1600 final TypeAnnotationPosition position = 1601 TypeAnnotationPosition.newObj(readTypePath()); 1602 position.offset = offset; 1603 return position; 1604 } 1605 // constructor/method reference receiver 1606 case CONSTRUCTOR_REFERENCE: { 1607 final int offset = nextChar(); 1608 final TypeAnnotationPosition position = 1609 TypeAnnotationPosition.constructorRef(readTypePath()); 1610 position.offset = offset; 1611 return position; 1612 } 1613 case METHOD_REFERENCE: { 1614 final int offset = nextChar(); 1615 final TypeAnnotationPosition position = 1616 TypeAnnotationPosition.methodRef(readTypePath()); 1617 position.offset = offset; 1618 return position; 1619 } 1620 // local variable 1621 case LOCAL_VARIABLE: { 1622 final int table_length = nextChar(); 1623 final int[] newLvarOffset = new int[table_length]; 1624 final int[] newLvarLength = new int[table_length]; 1625 final int[] newLvarIndex = new int[table_length]; 1626 1627 for (int i = 0; i < table_length; ++i) { 1628 newLvarOffset[i] = nextChar(); 1629 newLvarLength[i] = nextChar(); 1630 newLvarIndex[i] = nextChar(); 1631 } 1632 1633 final TypeAnnotationPosition position = 1634 TypeAnnotationPosition.localVariable(readTypePath()); 1635 position.lvarOffset = newLvarOffset; 1636 position.lvarLength = newLvarLength; 1637 position.lvarIndex = newLvarIndex; 1638 return position; 1639 } 1640 // resource variable 1641 case RESOURCE_VARIABLE: { 1642 final int table_length = nextChar(); 1643 final int[] newLvarOffset = new int[table_length]; 1644 final int[] newLvarLength = new int[table_length]; 1645 final int[] newLvarIndex = new int[table_length]; 1646 1647 for (int i = 0; i < table_length; ++i) { 1648 newLvarOffset[i] = nextChar(); 1649 newLvarLength[i] = nextChar(); 1650 newLvarIndex[i] = nextChar(); 1651 } 1652 1653 final TypeAnnotationPosition position = 1654 TypeAnnotationPosition.resourceVariable(readTypePath()); 1655 position.lvarOffset = newLvarOffset; 1656 position.lvarLength = newLvarLength; 1657 position.lvarIndex = newLvarIndex; 1658 return position; 1659 } 1660 // exception parameter 1661 case EXCEPTION_PARAMETER: { 1662 final int exception_index = nextChar(); 1663 final TypeAnnotationPosition position = 1664 TypeAnnotationPosition.exceptionParameter(readTypePath()); 1665 position.setExceptionIndex(exception_index); 1666 return position; 1667 } 1668 // method receiver 1669 case METHOD_RECEIVER: 1670 return TypeAnnotationPosition.methodReceiver(readTypePath()); 1671 // type parameter 1672 case CLASS_TYPE_PARAMETER: { 1673 final int parameter_index = nextByte(); 1674 return TypeAnnotationPosition 1675 .typeParameter(readTypePath(), parameter_index); 1676 } 1677 case METHOD_TYPE_PARAMETER: { 1678 final int parameter_index = nextByte(); 1679 return TypeAnnotationPosition 1680 .methodTypeParameter(readTypePath(), parameter_index); 1681 } 1682 // type parameter bound 1683 case CLASS_TYPE_PARAMETER_BOUND: { 1684 final int parameter_index = nextByte(); 1685 final int bound_index = nextByte(); 1686 return TypeAnnotationPosition 1687 .typeParameterBound(readTypePath(), parameter_index, 1688 bound_index); 1689 } 1690 case METHOD_TYPE_PARAMETER_BOUND: { 1691 final int parameter_index = nextByte(); 1692 final int bound_index = nextByte(); 1693 return TypeAnnotationPosition 1694 .methodTypeParameterBound(readTypePath(), parameter_index, 1695 bound_index); 1696 } 1697 // class extends or implements clause 1698 case CLASS_EXTENDS: { 1699 final int type_index = nextChar(); 1700 return TypeAnnotationPosition.classExtends(readTypePath(), 1701 type_index); 1702 } 1703 // throws 1704 case THROWS: { 1705 final int type_index = nextChar(); 1706 return TypeAnnotationPosition.methodThrows(readTypePath(), 1707 type_index); 1708 } 1709 // method parameter 1710 case METHOD_FORMAL_PARAMETER: { 1711 final int parameter_index = nextByte(); 1712 return TypeAnnotationPosition.methodParameter(readTypePath(), 1713 parameter_index); 1714 } 1715 // type cast 1716 case CAST: { 1717 final int offset = nextChar(); 1718 final int type_index = nextByte(); 1719 final TypeAnnotationPosition position = 1720 TypeAnnotationPosition.typeCast(readTypePath(), type_index); 1721 position.offset = offset; 1722 return position; 1723 } 1724 // method/constructor/reference type argument 1725 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: { 1726 final int offset = nextChar(); 1727 final int type_index = nextByte(); 1728 final TypeAnnotationPosition position = TypeAnnotationPosition 1729 .constructorInvocationTypeArg(readTypePath(), type_index); 1730 position.offset = offset; 1731 return position; 1732 } 1733 case METHOD_INVOCATION_TYPE_ARGUMENT: { 1734 final int offset = nextChar(); 1735 final int type_index = nextByte(); 1736 final TypeAnnotationPosition position = TypeAnnotationPosition 1737 .methodInvocationTypeArg(readTypePath(), type_index); 1738 position.offset = offset; 1739 return position; 1740 } 1741 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: { 1742 final int offset = nextChar(); 1743 final int type_index = nextByte(); 1744 final TypeAnnotationPosition position = TypeAnnotationPosition 1745 .constructorRefTypeArg(readTypePath(), type_index); 1746 position.offset = offset; 1747 return position; 1748 } 1749 case METHOD_REFERENCE_TYPE_ARGUMENT: { 1750 final int offset = nextChar(); 1751 final int type_index = nextByte(); 1752 final TypeAnnotationPosition position = TypeAnnotationPosition 1753 .methodRefTypeArg(readTypePath(), type_index); 1754 position.offset = offset; 1755 return position; 1756 } 1757 // We don't need to worry about these 1758 case METHOD_RETURN: 1759 return TypeAnnotationPosition.methodReturn(readTypePath()); 1760 case FIELD: 1761 return TypeAnnotationPosition.field(readTypePath()); 1762 case UNKNOWN: 1763 throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); 1764 default: 1765 throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type); 1766 } 1767 } 1768 1769 List<TypeAnnotationPosition.TypePathEntry> readTypePath() { 1770 int len = nextByte(); 1771 ListBuffer<Integer> loc = new ListBuffer<>(); 1772 for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) 1773 loc = loc.append(nextByte()); 1774 1775 return TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); 1776 1777 } 1778 1779 Attribute readAttributeValue() { 1780 char c = (char) buf[bp++]; 1781 switch (c) { 1782 case 'B': 1783 return new Attribute.Constant(syms.byteType, readPool(nextChar())); 1784 case 'C': 1785 return new Attribute.Constant(syms.charType, readPool(nextChar())); 1786 case 'D': 1787 return new Attribute.Constant(syms.doubleType, readPool(nextChar())); 1788 case 'F': 1789 return new Attribute.Constant(syms.floatType, readPool(nextChar())); 1790 case 'I': 1791 return new Attribute.Constant(syms.intType, readPool(nextChar())); 1792 case 'J': 1793 return new Attribute.Constant(syms.longType, readPool(nextChar())); 1794 case 'S': 1795 return new Attribute.Constant(syms.shortType, readPool(nextChar())); 1796 case 'Z': 1797 return new Attribute.Constant(syms.booleanType, readPool(nextChar())); 1798 case 's': 1799 return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString()); 1800 case 'e': 1801 return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar())); 1802 case 'c': 1803 return new Attribute.Class(types, readTypeOrClassSymbol(nextChar())); 1804 case '[': { 1805 int n = nextChar(); 1806 ListBuffer<Attribute> l = new ListBuffer<>(); 1807 for (int i=0; i<n; i++) 1808 l.append(readAttributeValue()); 1809 return new ArrayAttributeProxy(l.toList()); 1810 } 1811 case '@': 1812 return readCompoundAnnotation(); 1813 default: 1814 throw new AssertionError("unknown annotation tag '" + c + "'"); 1815 } 1816 } 1817 1818 interface ProxyVisitor extends Attribute.Visitor { 1819 void visitEnumAttributeProxy(EnumAttributeProxy proxy); 1820 void visitArrayAttributeProxy(ArrayAttributeProxy proxy); 1821 void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy); 1822 } 1823 1824 static class EnumAttributeProxy extends Attribute { 1825 Type enumType; 1826 Name enumerator; 1827 public EnumAttributeProxy(Type enumType, Name enumerator) { 1828 super(null); 1829 this.enumType = enumType; 1830 this.enumerator = enumerator; 1831 } 1832 public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); } 1833 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1834 public String toString() { 1835 return "/*proxy enum*/" + enumType + "." + enumerator; 1836 } 1837 } 1838 1839 static class ArrayAttributeProxy extends Attribute { 1840 List<Attribute> values; 1841 ArrayAttributeProxy(List<Attribute> values) { 1842 super(null); 1843 this.values = values; 1844 } 1845 public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); } 1846 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1847 public String toString() { 1848 return "{" + values + "}"; 1849 } 1850 } 1851 1852 /** A temporary proxy representing a compound attribute. 1853 */ 1854 static class CompoundAnnotationProxy extends Attribute { 1855 final List<Pair<Name,Attribute>> values; 1856 public CompoundAnnotationProxy(Type type, 1857 List<Pair<Name,Attribute>> values) { 1858 super(type); 1859 this.values = values; 1860 } 1861 public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); } 1862 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1863 public String toString() { 1864 StringBuilder buf = new StringBuilder(); 1865 buf.append("@"); 1866 buf.append(type.tsym.getQualifiedName()); 1867 buf.append("/*proxy*/{"); 1868 boolean first = true; 1869 for (List<Pair<Name,Attribute>> v = values; 1870 v.nonEmpty(); v = v.tail) { 1871 Pair<Name,Attribute> value = v.head; 1872 if (!first) buf.append(","); 1873 first = false; 1874 buf.append(value.fst); 1875 buf.append("="); 1876 buf.append(value.snd); 1877 } 1878 buf.append("}"); 1879 return buf.toString(); 1880 } 1881 } 1882 1883 /** A temporary proxy representing a type annotation. 1884 */ 1885 static class TypeAnnotationProxy { 1886 final CompoundAnnotationProxy compound; 1887 final TypeAnnotationPosition position; 1888 public TypeAnnotationProxy(CompoundAnnotationProxy compound, 1889 TypeAnnotationPosition position) { 1890 this.compound = compound; 1891 this.position = position; 1892 } 1893 } 1894 1895 class AnnotationDeproxy implements ProxyVisitor { 1896 private ClassSymbol requestingOwner; 1897 1898 AnnotationDeproxy(ClassSymbol owner) { 1899 this.requestingOwner = owner; 1900 } 1901 1902 List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) { 1903 // also must fill in types!!!! 1904 ListBuffer<Attribute.Compound> buf = new ListBuffer<>(); 1905 for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) { 1906 buf.append(deproxyCompound(l.head)); 1907 } 1908 return buf.toList(); 1909 } 1910 1911 Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) { 1912 ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>(); 1913 for (List<Pair<Name,Attribute>> l = a.values; 1914 l.nonEmpty(); 1915 l = l.tail) { 1916 MethodSymbol meth = findAccessMethod(a.type, l.head.fst); 1917 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd))); 1918 } 1919 return new Attribute.Compound(a.type, buf.toList()); 1920 } 1921 1922 MethodSymbol findAccessMethod(Type container, Name name) { 1923 CompletionFailure failure = null; 1924 try { 1925 for (Symbol sym : container.tsym.members().getSymbolsByName(name)) { 1926 if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0) 1927 return (MethodSymbol) sym; 1928 } 1929 } catch (CompletionFailure ex) { 1930 failure = ex; 1931 } 1932 // The method wasn't found: emit a warning and recover 1933 JavaFileObject prevSource = log.useSource(requestingOwner.classfile); 1934 try { 1935 if (lintClassfile) { 1936 if (failure == null) { 1937 log.warning("annotation.method.not.found", 1938 container, 1939 name); 1940 } else { 1941 log.warning("annotation.method.not.found.reason", 1942 container, 1943 name, 1944 failure.getDetailValue());//diagnostic, if present 1945 } 1946 } 1947 } finally { 1948 log.useSource(prevSource); 1949 } 1950 // Construct a new method type and symbol. Use bottom 1951 // type (typeof null) as return type because this type is 1952 // a subtype of all reference types and can be converted 1953 // to primitive types by unboxing. 1954 MethodType mt = new MethodType(List.<Type>nil(), 1955 syms.botType, 1956 List.<Type>nil(), 1957 syms.methodClass); 1958 return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym); 1959 } 1960 1961 Attribute result; 1962 Type type; 1963 Attribute deproxy(Type t, Attribute a) { 1964 Type oldType = type; 1965 try { 1966 type = t; 1967 a.accept(this); 1968 return result; 1969 } finally { 1970 type = oldType; 1971 } 1972 } 1973 1974 // implement Attribute.Visitor below 1975 1976 public void visitConstant(Attribute.Constant value) { 1977 // assert value.type == type; 1978 result = value; 1979 } 1980 1981 public void visitClass(Attribute.Class clazz) { 1982 result = clazz; 1983 } 1984 1985 public void visitEnum(Attribute.Enum e) { 1986 throw new AssertionError(); // shouldn't happen 1987 } 1988 1989 public void visitCompound(Attribute.Compound compound) { 1990 throw new AssertionError(); // shouldn't happen 1991 } 1992 1993 public void visitArray(Attribute.Array array) { 1994 throw new AssertionError(); // shouldn't happen 1995 } 1996 1997 public void visitError(Attribute.Error e) { 1998 throw new AssertionError(); // shouldn't happen 1999 } 2000 2001 public void visitEnumAttributeProxy(EnumAttributeProxy proxy) { 2002 // type.tsym.flatName() should == proxy.enumFlatName 2003 TypeSymbol enumTypeSym = proxy.enumType.tsym; 2004 VarSymbol enumerator = null; 2005 CompletionFailure failure = null; 2006 try { 2007 for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) { 2008 if (sym.kind == VAR) { 2009 enumerator = (VarSymbol)sym; 2010 break; 2011 } 2012 } 2013 } 2014 catch (CompletionFailure ex) { 2015 failure = ex; 2016 } 2017 if (enumerator == null) { 2018 if (failure != null) { 2019 log.warning("unknown.enum.constant.reason", 2020 currentClassFile, enumTypeSym, proxy.enumerator, 2021 failure.getDiagnostic()); 2022 } else { 2023 log.warning("unknown.enum.constant", 2024 currentClassFile, enumTypeSym, proxy.enumerator); 2025 } 2026 result = new Attribute.Enum(enumTypeSym.type, 2027 new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym)); 2028 } else { 2029 result = new Attribute.Enum(enumTypeSym.type, enumerator); 2030 } 2031 } 2032 2033 public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) { 2034 int length = proxy.values.length(); 2035 Attribute[] ats = new Attribute[length]; 2036 Type elemtype = types.elemtype(type); 2037 int i = 0; 2038 for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) { 2039 ats[i++] = deproxy(elemtype, p.head); 2040 } 2041 result = new Attribute.Array(type, ats); 2042 } 2043 2044 public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) { 2045 result = deproxyCompound(proxy); 2046 } 2047 } 2048 2049 class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable { 2050 final MethodSymbol sym; 2051 final Attribute value; 2052 final JavaFileObject classFile = currentClassFile; 2053 2054 AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) { 2055 super(currentOwner.kind == MTH 2056 ? currentOwner.enclClass() : (ClassSymbol)currentOwner); 2057 this.sym = sym; 2058 this.value = value; 2059 } 2060 2061 @Override 2062 public void run() { 2063 JavaFileObject previousClassFile = currentClassFile; 2064 try { 2065 // Reset the interim value set earlier in 2066 // attachAnnotationDefault(). 2067 sym.defaultValue = null; 2068 currentClassFile = classFile; 2069 sym.defaultValue = deproxy(sym.type.getReturnType(), value); 2070 } finally { 2071 currentClassFile = previousClassFile; 2072 } 2073 } 2074 2075 @Override 2076 public String toString() { 2077 return " ClassReader store default for " + sym.owner + "." + sym + " is " + value; 2078 } 2079 } 2080 2081 class AnnotationCompleter extends AnnotationDeproxy implements Runnable { 2082 final Symbol sym; 2083 final List<CompoundAnnotationProxy> l; 2084 final JavaFileObject classFile; 2085 2086 AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) { 2087 super(currentOwner.kind == MTH 2088 ? currentOwner.enclClass() : (ClassSymbol)currentOwner); 2089 this.sym = sym; 2090 this.l = l; 2091 this.classFile = currentClassFile; 2092 } 2093 2094 @Override 2095 public void run() { 2096 JavaFileObject previousClassFile = currentClassFile; 2097 try { 2098 currentClassFile = classFile; 2099 List<Attribute.Compound> newList = deproxyCompoundList(l); 2100 if (sym.annotationsPendingCompletion()) { 2101 sym.setDeclarationAttributes(newList); 2102 } else { 2103 sym.appendAttributes(newList); 2104 } 2105 } finally { 2106 currentClassFile = previousClassFile; 2107 } 2108 } 2109 2110 @Override 2111 public String toString() { 2112 return " ClassReader annotate " + sym.owner + "." + sym + " with " + l; 2113 } 2114 } 2115 2116 class TypeAnnotationCompleter extends AnnotationCompleter { 2117 2118 List<TypeAnnotationProxy> proxies; 2119 2120 TypeAnnotationCompleter(Symbol sym, 2121 List<TypeAnnotationProxy> proxies) { 2122 super(sym, List.<CompoundAnnotationProxy>nil()); 2123 this.proxies = proxies; 2124 } 2125 2126 List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) { 2127 ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>(); 2128 for (TypeAnnotationProxy proxy: proxies) { 2129 Attribute.Compound compound = deproxyCompound(proxy.compound); 2130 Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); 2131 buf.add(typeCompound); 2132 } 2133 return buf.toList(); 2134 } 2135 2136 @Override 2137 public void run() { 2138 JavaFileObject previousClassFile = currentClassFile; 2139 try { 2140 currentClassFile = classFile; 2141 List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies); 2142 sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); 2143 } finally { 2144 currentClassFile = previousClassFile; 2145 } 2146 } 2147 } 2148 2149 2150/************************************************************************ 2151 * Reading Symbols 2152 ***********************************************************************/ 2153 2154 /** Read a field. 2155 */ 2156 VarSymbol readField() { 2157 long flags = adjustFieldFlags(nextChar()); 2158 Name name = readName(nextChar()); 2159 Type type = readType(nextChar()); 2160 VarSymbol v = new VarSymbol(flags, name, type, currentOwner); 2161 readMemberAttrs(v); 2162 return v; 2163 } 2164 2165 /** Read a method. 2166 */ 2167 MethodSymbol readMethod() { 2168 long flags = adjustMethodFlags(nextChar()); 2169 Name name = readName(nextChar()); 2170 Type type = readType(nextChar()); 2171 if (currentOwner.isInterface() && 2172 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) { 2173 if (majorVersion > Version.V52.major || 2174 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) { 2175 if ((flags & STATIC) == 0) { 2176 currentOwner.flags_field |= DEFAULT; 2177 flags |= DEFAULT | ABSTRACT; 2178 } 2179 } else { 2180 //protect against ill-formed classfiles 2181 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface", 2182 Integer.toString(majorVersion), 2183 Integer.toString(minorVersion)); 2184 } 2185 } 2186 if (name == names.init && currentOwner.hasOuterInstance()) { 2187 // Sometimes anonymous classes don't have an outer 2188 // instance, however, there is no reliable way to tell so 2189 // we never strip this$n 2190 // ditto for local classes. Local classes that have an enclosing method set 2191 // won't pass the "hasOuterInstance" check above, but those that don't have an 2192 // enclosing method (i.e. from initializers) will pass that check. 2193 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE); 2194 if (!currentOwner.name.isEmpty() && !local) 2195 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), 2196 type.getReturnType(), 2197 type.getThrownTypes(), 2198 syms.methodClass); 2199 } 2200 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); 2201 if (types.isSignaturePolymorphic(m)) { 2202 m.flags_field |= SIGNATURE_POLYMORPHIC; 2203 } 2204 if (saveParameterNames) 2205 initParameterNames(m); 2206 Symbol prevOwner = currentOwner; 2207 currentOwner = m; 2208 try { 2209 readMemberAttrs(m); 2210 } finally { 2211 currentOwner = prevOwner; 2212 } 2213 if (saveParameterNames) 2214 setParameterNames(m, type); 2215 2216 if ((flags & VARARGS) != 0) { 2217 final Type last = type.getParameterTypes().last(); 2218 if (last == null || !last.hasTag(ARRAY)) { 2219 m.flags_field &= ~VARARGS; 2220 throw badClassFile("malformed.vararg.method", m); 2221 } 2222 } 2223 2224 return m; 2225 } 2226 2227 private List<Type> adjustMethodParams(long flags, List<Type> args) { 2228 boolean isVarargs = (flags & VARARGS) != 0; 2229 if (isVarargs) { 2230 Type varargsElem = args.last(); 2231 ListBuffer<Type> adjustedArgs = new ListBuffer<>(); 2232 for (Type t : args) { 2233 adjustedArgs.append(t != varargsElem ? 2234 t : 2235 ((ArrayType)t).makeVarargs()); 2236 } 2237 args = adjustedArgs.toList(); 2238 } 2239 return args.tail; 2240 } 2241 2242 /** 2243 * Init the parameter names array. 2244 * Parameter names are currently inferred from the names in the 2245 * LocalVariableTable attributes of a Code attribute. 2246 * (Note: this means parameter names are currently not available for 2247 * methods without a Code attribute.) 2248 * This method initializes an array in which to store the name indexes 2249 * of parameter names found in LocalVariableTable attributes. It is 2250 * slightly supersized to allow for additional slots with a start_pc of 0. 2251 */ 2252 void initParameterNames(MethodSymbol sym) { 2253 // make allowance for synthetic parameters. 2254 final int excessSlots = 4; 2255 int expectedParameterSlots = 2256 Code.width(sym.type.getParameterTypes()) + excessSlots; 2257 if (parameterNameIndices == null 2258 || parameterNameIndices.length < expectedParameterSlots) { 2259 parameterNameIndices = new int[expectedParameterSlots]; 2260 } else 2261 Arrays.fill(parameterNameIndices, 0); 2262 haveParameterNameIndices = false; 2263 sawMethodParameters = false; 2264 } 2265 2266 /** 2267 * Set the parameter names for a symbol from the name index in the 2268 * parameterNameIndicies array. The type of the symbol may have changed 2269 * while reading the method attributes (see the Signature attribute). 2270 * This may be because of generic information or because anonymous 2271 * synthetic parameters were added. The original type (as read from 2272 * the method descriptor) is used to help guess the existence of 2273 * anonymous synthetic parameters. 2274 * On completion, sym.savedParameter names will either be null (if 2275 * no parameter names were found in the class file) or will be set to a 2276 * list of names, one per entry in sym.type.getParameterTypes, with 2277 * any missing names represented by the empty name. 2278 */ 2279 void setParameterNames(MethodSymbol sym, Type jvmType) { 2280 // if no names were found in the class file, there's nothing more to do 2281 if (!haveParameterNameIndices) 2282 return; 2283 // If we get parameter names from MethodParameters, then we 2284 // don't need to skip. 2285 int firstParam = 0; 2286 if (!sawMethodParameters) { 2287 firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; 2288 // the code in readMethod may have skipped the first 2289 // parameter when setting up the MethodType. If so, we 2290 // make a corresponding allowance here for the position of 2291 // the first parameter. Note that this assumes the 2292 // skipped parameter has a width of 1 -- i.e. it is not 2293 // a double width type (long or double.) 2294 if (sym.name == names.init && currentOwner.hasOuterInstance()) { 2295 // Sometimes anonymous classes don't have an outer 2296 // instance, however, there is no reliable way to tell so 2297 // we never strip this$n 2298 if (!currentOwner.name.isEmpty()) 2299 firstParam += 1; 2300 } 2301 2302 if (sym.type != jvmType) { 2303 // reading the method attributes has caused the 2304 // symbol's type to be changed. (i.e. the Signature 2305 // attribute.) This may happen if there are hidden 2306 // (synthetic) parameters in the descriptor, but not 2307 // in the Signature. The position of these hidden 2308 // parameters is unspecified; for now, assume they are 2309 // at the beginning, and so skip over them. The 2310 // primary case for this is two hidden parameters 2311 // passed into Enum constructors. 2312 int skip = Code.width(jvmType.getParameterTypes()) 2313 - Code.width(sym.type.getParameterTypes()); 2314 firstParam += skip; 2315 } 2316 } 2317 List<Name> paramNames = List.nil(); 2318 int index = firstParam; 2319 for (Type t: sym.type.getParameterTypes()) { 2320 int nameIdx = (index < parameterNameIndices.length 2321 ? parameterNameIndices[index] : 0); 2322 Name name = nameIdx == 0 ? names.empty : readName(nameIdx); 2323 paramNames = paramNames.prepend(name); 2324 index += Code.width(t); 2325 } 2326 sym.savedParameterNames = paramNames.reverse(); 2327 } 2328 2329 /** 2330 * skip n bytes 2331 */ 2332 void skipBytes(int n) { 2333 bp = bp + n; 2334 } 2335 2336 /** Skip a field or method 2337 */ 2338 void skipMember() { 2339 bp = bp + 6; 2340 char ac = nextChar(); 2341 for (int i = 0; i < ac; i++) { 2342 bp = bp + 2; 2343 int attrLen = nextInt(); 2344 bp = bp + attrLen; 2345 } 2346 } 2347 2348 void skipInnerClasses() { 2349 int n = nextChar(); 2350 for (int i = 0; i < n; i++) { 2351 nextChar(); 2352 nextChar(); 2353 nextChar(); 2354 nextChar(); 2355 } 2356 } 2357 2358 /** Enter type variables of this classtype and all enclosing ones in 2359 * `typevars'. 2360 */ 2361 protected void enterTypevars(Symbol sym, Type t) { 2362 if (t.getEnclosingType() != null) { 2363 if (!t.getEnclosingType().hasTag(TypeTag.NONE)) { 2364 enterTypevars(sym.owner, t.getEnclosingType()); 2365 } 2366 } else if (sym.kind == MTH && !sym.isStatic()) { 2367 enterTypevars(sym.owner, sym.owner.type); 2368 } 2369 for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) { 2370 typevars.enter(xs.head.tsym); 2371 } 2372 } 2373 2374 protected ClassSymbol enterClass(Name name) { 2375 return syms.enterClass(currentModule, name); 2376 } 2377 2378 protected ClassSymbol enterClass(Name name, TypeSymbol owner) { 2379 return syms.enterClass(currentModule, name, owner); 2380 } 2381 2382 /** Read contents of a given class symbol `c'. Both external and internal 2383 * versions of an inner class are read. 2384 */ 2385 void readClass(ClassSymbol c) { 2386 ClassType ct = (ClassType)c.type; 2387 2388 // allocate scope for members 2389 c.members_field = WriteableScope.create(c); 2390 2391 // prepare type variable table 2392 typevars = typevars.dup(currentOwner); 2393 if (ct.getEnclosingType().hasTag(CLASS)) 2394 enterTypevars(c.owner, ct.getEnclosingType()); 2395 2396 // read flags, or skip if this is an inner class 2397 long f = nextChar(); 2398 long flags = adjustClassFlags(f); 2399 if ((flags & MODULE) == 0) { 2400 if (c.owner.kind == PCK) c.flags_field = flags; 2401 // read own class name and check that it matches 2402 currentModule = c.packge().modle; 2403 ClassSymbol self = readClassSymbol(nextChar()); 2404 if (c != self) { 2405 throw badClassFile("class.file.wrong.class", 2406 self.flatname); 2407 } 2408 } else { 2409 c.flags_field = flags; 2410 Name modInfoName = readModuleInfoName(nextChar()); 2411 currentModule = (ModuleSymbol) c.owner; 2412 if (currentModule.name.append('.', names.module_info) != modInfoName) { 2413 //strip trailing .module-info, if exists: 2414 int modInfoStart = modInfoName.length() - names.module_info.length(); 2415 modInfoName = modInfoName.subName(modInfoStart, modInfoName.length()) == names.module_info && 2416 modInfoName.charAt(modInfoStart - 1) == '.' ? 2417 modInfoName.subName(0, modInfoStart - 1) : modInfoName; 2418 throw badClassFile("module.name.mismatch", modInfoName, currentModule.name); 2419 } 2420 } 2421 2422 // class attributes must be read before class 2423 // skip ahead to read class attributes 2424 int startbp = bp; 2425 nextChar(); 2426 char interfaceCount = nextChar(); 2427 bp += interfaceCount * 2; 2428 char fieldCount = nextChar(); 2429 for (int i = 0; i < fieldCount; i++) skipMember(); 2430 char methodCount = nextChar(); 2431 for (int i = 0; i < methodCount; i++) skipMember(); 2432 readClassAttrs(c); 2433 2434 if (readAllOfClassFile) { 2435 for (int i = 1; i < poolObj.length; i++) readPool(i); 2436 c.pool = new Pool(poolObj.length, poolObj, types); 2437 } 2438 2439 // reset and read rest of classinfo 2440 bp = startbp; 2441 int n = nextChar(); 2442 if ((flags & MODULE) != 0 && n > 0) { 2443 throw badClassFile("module.info.invalid.super.class"); 2444 } 2445 if (ct.supertype_field == null) 2446 ct.supertype_field = (n == 0) 2447 ? Type.noType 2448 : readClassSymbol(n).erasure(types); 2449 n = nextChar(); 2450 List<Type> is = List.nil(); 2451 for (int i = 0; i < n; i++) { 2452 Type _inter = readClassSymbol(nextChar()).erasure(types); 2453 is = is.prepend(_inter); 2454 } 2455 if (ct.interfaces_field == null) 2456 ct.interfaces_field = is.reverse(); 2457 2458 Assert.check(fieldCount == nextChar()); 2459 for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); 2460 Assert.check(methodCount == nextChar()); 2461 for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); 2462 2463 typevars = typevars.leave(); 2464 } 2465 2466 /** Read inner class info. For each inner/outer pair allocate a 2467 * member class. 2468 */ 2469 void readInnerClasses(ClassSymbol c) { 2470 int n = nextChar(); 2471 for (int i = 0; i < n; i++) { 2472 nextChar(); // skip inner class symbol 2473 ClassSymbol outer = readClassSymbol(nextChar()); 2474 Name name = readName(nextChar()); 2475 if (name == null) name = names.empty; 2476 long flags = adjustClassFlags(nextChar()); 2477 if (outer != null) { // we have a member class 2478 if (name == names.empty) 2479 name = names.one; 2480 ClassSymbol member = enterClass(name, outer); 2481 if ((flags & STATIC) == 0) { 2482 ((ClassType)member.type).setEnclosingType(outer.type); 2483 if (member.erasure_field != null) 2484 ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type)); 2485 } 2486 if (c == outer) { 2487 member.flags_field = flags; 2488 enterMember(c, member); 2489 } 2490 } 2491 } 2492 } 2493 2494 /** Read a class definition from the bytes in buf. 2495 */ 2496 private void readClassBuffer(ClassSymbol c) throws IOException { 2497 int magic = nextInt(); 2498 if (magic != JAVA_MAGIC) 2499 throw badClassFile("illegal.start.of.class.file"); 2500 2501 minorVersion = nextChar(); 2502 majorVersion = nextChar(); 2503 int maxMajor = Version.MAX().major; 2504 int maxMinor = Version.MAX().minor; 2505 if (majorVersion > maxMajor || 2506 majorVersion * 1000 + minorVersion < 2507 Version.MIN().major * 1000 + Version.MIN().minor) { 2508 if (majorVersion == (maxMajor + 1)) 2509 log.warning("big.major.version", 2510 currentClassFile, 2511 majorVersion, 2512 maxMajor); 2513 else 2514 throw badClassFile("wrong.version", 2515 Integer.toString(majorVersion), 2516 Integer.toString(minorVersion), 2517 Integer.toString(maxMajor), 2518 Integer.toString(maxMinor)); 2519 } 2520 2521 indexPool(); 2522 if (signatureBuffer.length < bp) { 2523 int ns = Integer.highestOneBit(bp) << 1; 2524 signatureBuffer = new byte[ns]; 2525 } 2526 readClass(c); 2527 } 2528 2529 public void readClassFile(ClassSymbol c) { 2530 currentOwner = c; 2531 currentClassFile = c.classfile; 2532 warnedAttrs.clear(); 2533 filling = true; 2534 target = null; 2535 repeatable = null; 2536 try { 2537 bp = 0; 2538 buf = readInputStream(buf, c.classfile.openInputStream()); 2539 readClassBuffer(c); 2540 if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { 2541 List<Type> missing = missingTypeVariables; 2542 List<Type> found = foundTypeVariables; 2543 missingTypeVariables = List.nil(); 2544 foundTypeVariables = List.nil(); 2545 filling = false; 2546 ClassType ct = (ClassType)currentOwner.type; 2547 ct.supertype_field = 2548 types.subst(ct.supertype_field, missing, found); 2549 ct.interfaces_field = 2550 types.subst(ct.interfaces_field, missing, found); 2551 ct.typarams_field = 2552 types.substBounds(ct.typarams_field, missing, found); 2553 for (List<Type> types = ct.typarams_field; types.nonEmpty(); types = types.tail) { 2554 types.head.tsym.type = types.head; 2555 } 2556 } else if (missingTypeVariables.isEmpty() != 2557 foundTypeVariables.isEmpty()) { 2558 Name name = missingTypeVariables.head.tsym.name; 2559 throw badClassFile("undecl.type.var", name); 2560 } 2561 2562 if ((c.flags_field & Flags.ANNOTATION) != 0) { 2563 c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable))); 2564 } else { 2565 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType()); 2566 } 2567 2568 if (c == currentModule.module_info) { 2569 if (interimUses.nonEmpty() || interimProvides.nonEmpty()) { 2570 Assert.check(currentModule.isCompleted()); 2571 currentModule.usesProvidesCompleter = 2572 new UsesProvidesCompleter(currentModule, interimUses, interimProvides); 2573 } else { 2574 currentModule.uses = List.nil(); 2575 currentModule.provides = List.nil(); 2576 } 2577 } 2578 } catch (IOException ex) { 2579 throw badClassFile("unable.to.access.file", ex.getMessage()); 2580 } catch (ArrayIndexOutOfBoundsException ex) { 2581 throw badClassFile("bad.class.file", c.flatname); 2582 } finally { 2583 interimUses = List.nil(); 2584 interimProvides = List.nil(); 2585 missingTypeVariables = List.nil(); 2586 foundTypeVariables = List.nil(); 2587 filling = false; 2588 } 2589 } 2590 // where 2591 private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException { 2592 try { 2593 buf = ensureCapacity(buf, s.available()); 2594 int r = s.read(buf); 2595 int bp = 0; 2596 while (r != -1) { 2597 bp += r; 2598 buf = ensureCapacity(buf, bp); 2599 r = s.read(buf, bp, buf.length - bp); 2600 } 2601 return buf; 2602 } finally { 2603 try { 2604 s.close(); 2605 } catch (IOException e) { 2606 /* Ignore any errors, as this stream may have already 2607 * thrown a related exception which is the one that 2608 * should be reported. 2609 */ 2610 } 2611 } 2612 } 2613 /* 2614 * ensureCapacity will increase the buffer as needed, taking note that 2615 * the new buffer will always be greater than the needed and never 2616 * exactly equal to the needed size or bp. If equal then the read (above) 2617 * will infinitely loop as buf.length - bp == 0. 2618 */ 2619 private static byte[] ensureCapacity(byte[] buf, int needed) { 2620 if (buf.length <= needed) { 2621 byte[] old = buf; 2622 buf = new byte[Integer.highestOneBit(needed) << 1]; 2623 System.arraycopy(old, 0, buf, 0, old.length); 2624 } 2625 return buf; 2626 } 2627 2628 /** We can only read a single class file at a time; this 2629 * flag keeps track of when we are currently reading a class 2630 * file. 2631 */ 2632 public boolean filling = false; 2633 2634/************************************************************************ 2635 * Adjusting flags 2636 ***********************************************************************/ 2637 2638 long adjustFieldFlags(long flags) { 2639 return flags; 2640 } 2641 2642 long adjustMethodFlags(long flags) { 2643 if ((flags & ACC_BRIDGE) != 0) { 2644 flags &= ~ACC_BRIDGE; 2645 flags |= BRIDGE; 2646 } 2647 if ((flags & ACC_VARARGS) != 0) { 2648 flags &= ~ACC_VARARGS; 2649 flags |= VARARGS; 2650 } 2651 return flags; 2652 } 2653 2654 long adjustClassFlags(long flags) { 2655 if ((flags & ACC_MODULE) != 0) { 2656 flags &= ~ACC_MODULE; 2657 flags |= MODULE; 2658 } 2659 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded 2660 } 2661 2662 /** 2663 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile. 2664 * The attribute is only the last component of the original filename, so is unlikely 2665 * to be valid as is, so operations other than those to access the name throw 2666 * UnsupportedOperationException 2667 */ 2668 private static class SourceFileObject implements JavaFileObject { 2669 2670 /** The file's name. 2671 */ 2672 private final Name name; 2673 private final Name flatname; 2674 2675 public SourceFileObject(Name name, Name flatname) { 2676 this.name = name; 2677 this.flatname = flatname; 2678 } 2679 2680 @Override @DefinedBy(Api.COMPILER) 2681 public URI toUri() { 2682 try { 2683 return new URI(null, name.toString(), null); 2684 } catch (URISyntaxException e) { 2685 throw new PathFileObject.CannotCreateUriError(name.toString(), e); 2686 } 2687 } 2688 2689 @Override @DefinedBy(Api.COMPILER) 2690 public String getName() { 2691 return name.toString(); 2692 } 2693 2694 @Override @DefinedBy(Api.COMPILER) 2695 public JavaFileObject.Kind getKind() { 2696 return BaseFileManager.getKind(getName()); 2697 } 2698 2699 @Override @DefinedBy(Api.COMPILER) 2700 public InputStream openInputStream() { 2701 throw new UnsupportedOperationException(); 2702 } 2703 2704 @Override @DefinedBy(Api.COMPILER) 2705 public OutputStream openOutputStream() { 2706 throw new UnsupportedOperationException(); 2707 } 2708 2709 @Override @DefinedBy(Api.COMPILER) 2710 public CharBuffer getCharContent(boolean ignoreEncodingErrors) { 2711 throw new UnsupportedOperationException(); 2712 } 2713 2714 @Override @DefinedBy(Api.COMPILER) 2715 public Reader openReader(boolean ignoreEncodingErrors) { 2716 throw new UnsupportedOperationException(); 2717 } 2718 2719 @Override @DefinedBy(Api.COMPILER) 2720 public Writer openWriter() { 2721 throw new UnsupportedOperationException(); 2722 } 2723 2724 @Override @DefinedBy(Api.COMPILER) 2725 public long getLastModified() { 2726 throw new UnsupportedOperationException(); 2727 } 2728 2729 @Override @DefinedBy(Api.COMPILER) 2730 public boolean delete() { 2731 throw new UnsupportedOperationException(); 2732 } 2733 2734 @Override @DefinedBy(Api.COMPILER) 2735 public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { 2736 return true; // fail-safe mode 2737 } 2738 2739 @Override @DefinedBy(Api.COMPILER) 2740 public NestingKind getNestingKind() { 2741 return null; 2742 } 2743 2744 @Override @DefinedBy(Api.COMPILER) 2745 public Modifier getAccessLevel() { 2746 return null; 2747 } 2748 2749 /** 2750 * Check if two file objects are equal. 2751 * SourceFileObjects are just placeholder objects for the value of a 2752 * SourceFile attribute, and do not directly represent specific files. 2753 * Two SourceFileObjects are equal if their names are equal. 2754 */ 2755 @Override 2756 public boolean equals(Object other) { 2757 if (this == other) 2758 return true; 2759 2760 if (!(other instanceof SourceFileObject)) 2761 return false; 2762 2763 SourceFileObject o = (SourceFileObject) other; 2764 return name.equals(o.name); 2765 } 2766 2767 @Override 2768 public int hashCode() { 2769 return name.hashCode(); 2770 } 2771 } 2772 2773 private class CompleterDeproxy implements AnnotationTypeCompleter { 2774 ClassSymbol proxyOn; 2775 CompoundAnnotationProxy target; 2776 CompoundAnnotationProxy repeatable; 2777 2778 public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target, 2779 CompoundAnnotationProxy repeatable) 2780 { 2781 this.proxyOn = c; 2782 this.target = target; 2783 this.repeatable = repeatable; 2784 } 2785 2786 @Override 2787 public void complete(ClassSymbol sym) { 2788 Assert.check(proxyOn == sym); 2789 Attribute.Compound theTarget = null, theRepeatable = null; 2790 AnnotationDeproxy deproxy; 2791 2792 try { 2793 if (target != null) { 2794 deproxy = new AnnotationDeproxy(proxyOn); 2795 theTarget = deproxy.deproxyCompound(target); 2796 } 2797 2798 if (repeatable != null) { 2799 deproxy = new AnnotationDeproxy(proxyOn); 2800 theRepeatable = deproxy.deproxyCompound(repeatable); 2801 } 2802 } catch (Exception e) { 2803 throw new CompletionFailure(sym, e.getMessage()); 2804 } 2805 2806 sym.getAnnotationTypeMetadata().setTarget(theTarget); 2807 sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable); 2808 } 2809 } 2810 2811 private static final class InterimUsesDirective { 2812 public final Name service; 2813 2814 public InterimUsesDirective(Name service) { 2815 this.service = service; 2816 } 2817 2818 } 2819 2820 private static final class InterimProvidesDirective { 2821 public final Name service; 2822 public final Name impl; 2823 2824 public InterimProvidesDirective(Name service, Name impl) { 2825 this.service = service; 2826 this.impl = impl; 2827 } 2828 2829 } 2830 2831 private final class UsesProvidesCompleter implements Completer { 2832 private final ModuleSymbol currentModule; 2833 private final List<InterimUsesDirective> interimUsesCopy; 2834 private final List<InterimProvidesDirective> interimProvidesCopy; 2835 2836 public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) { 2837 this.currentModule = currentModule; 2838 this.interimUsesCopy = interimUsesCopy; 2839 this.interimProvidesCopy = interimProvidesCopy; 2840 } 2841 2842 @Override 2843 public void complete(Symbol sym) throws CompletionFailure { 2844 ListBuffer<Directive> directives = new ListBuffer<>(); 2845 directives.addAll(currentModule.directives); 2846 ListBuffer<UsesDirective> uses = new ListBuffer<>(); 2847 for (InterimUsesDirective interim : interimUsesCopy) { 2848 UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service)); 2849 uses.add(d); 2850 directives.add(d); 2851 } 2852 currentModule.uses = uses.toList(); 2853 ListBuffer<ProvidesDirective> provides = new ListBuffer<>(); 2854 for (InterimProvidesDirective interim : interimProvidesCopy) { 2855 ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service), 2856 syms.enterClass(currentModule, interim.impl)); 2857 provides.add(d); 2858 directives.add(d); 2859 } 2860 currentModule.provides = provides.toList(); 2861 currentModule.directives = directives.toList(); 2862 } 2863 } 2864} 2865