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