Home » openjdk-7 » com.sun.tools » javac » jvm » [javadoc | source]

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

Home » openjdk-7 » com.sun.tools » javac » jvm » [javadoc | source]