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