src/share/classes/com/sun/tools/javac/jvm/ClassReader.java

Tue, 04 Jan 2011 17:10:35 -0800

author
lana
date
Tue, 04 Jan 2011 17:10:35 -0800
changeset 809
e63b1f8341ce
parent 804
3131e664558d
parent 798
4868a36f6fd8
child 815
d17f37522154
permissions
-rw-r--r--

Merge

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

mercurial