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