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

changeset 1
9a66ca7c79fa
child 12
7366066839bb
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,2280 @@
     1.4 +/*
     1.5 + * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Sun designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Sun in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.26 + * have any questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.javac.jvm;
    1.30 +
    1.31 +import java.io.*;
    1.32 +import java.net.URI;
    1.33 +import java.nio.CharBuffer;
    1.34 +import java.util.EnumSet;
    1.35 +import java.util.HashMap;
    1.36 +import java.util.Map;
    1.37 +import java.util.Set;
    1.38 +import javax.lang.model.SourceVersion;
    1.39 +import javax.tools.JavaFileObject;
    1.40 +import javax.tools.JavaFileManager;
    1.41 +import javax.tools.StandardJavaFileManager;
    1.42 +
    1.43 +import com.sun.tools.javac.comp.Annotate;
    1.44 +import com.sun.tools.javac.code.*;
    1.45 +import com.sun.tools.javac.code.Type.*;
    1.46 +import com.sun.tools.javac.code.Symbol.*;
    1.47 +import com.sun.tools.javac.code.Symtab;
    1.48 +import com.sun.tools.javac.util.*;
    1.49 +import com.sun.tools.javac.util.List;
    1.50 +
    1.51 +import static com.sun.tools.javac.code.Flags.*;
    1.52 +import static com.sun.tools.javac.code.Kinds.*;
    1.53 +import static com.sun.tools.javac.code.TypeTags.*;
    1.54 +import com.sun.tools.javac.jvm.ClassFile.NameAndType;
    1.55 +import javax.tools.JavaFileManager.Location;
    1.56 +import static javax.tools.StandardLocation.*;
    1.57 +
    1.58 +/** This class provides operations to read a classfile into an internal
    1.59 + *  representation. The internal representation is anchored in a
    1.60 + *  ClassSymbol which contains in its scope symbol representations
    1.61 + *  for all other definitions in the classfile. Top-level Classes themselves
    1.62 + *  appear as members of the scopes of PackageSymbols.
    1.63 + *
    1.64 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    1.65 + *  you write code that depends on this, you do so at your own risk.
    1.66 + *  This code and its internal interfaces are subject to change or
    1.67 + *  deletion without notice.</b>
    1.68 + */
    1.69 +public class ClassReader extends ClassFile implements Completer {
    1.70 +    /** The context key for the class reader. */
    1.71 +    protected static final Context.Key<ClassReader> classReaderKey =
    1.72 +        new Context.Key<ClassReader>();
    1.73 +
    1.74 +    Annotate annotate;
    1.75 +
    1.76 +    /** Switch: verbose output.
    1.77 +     */
    1.78 +    boolean verbose;
    1.79 +
    1.80 +    /** Switch: check class file for correct minor version, unrecognized
    1.81 +     *  attributes.
    1.82 +     */
    1.83 +    boolean checkClassFile;
    1.84 +
    1.85 +    /** Switch: read constant pool and code sections. This switch is initially
    1.86 +     *  set to false but can be turned on from outside.
    1.87 +     */
    1.88 +    public boolean readAllOfClassFile = false;
    1.89 +
    1.90 +    /** Switch: read GJ signature information.
    1.91 +     */
    1.92 +    boolean allowGenerics;
    1.93 +
    1.94 +    /** Switch: read varargs attribute.
    1.95 +     */
    1.96 +    boolean allowVarargs;
    1.97 +
    1.98 +    /** Switch: allow annotations.
    1.99 +     */
   1.100 +    boolean allowAnnotations;
   1.101 +
   1.102 +    /** Switch: preserve parameter names from the variable table.
   1.103 +     */
   1.104 +    public boolean saveParameterNames;
   1.105 +
   1.106 +    /**
   1.107 +     * Switch: cache completion failures unless -XDdev is used
   1.108 +     */
   1.109 +    private boolean cacheCompletionFailure;
   1.110 +
   1.111 +    /**
   1.112 +     * Switch: prefer source files instead of newer when both source
   1.113 +     * and class are available
   1.114 +     **/
   1.115 +    public boolean preferSource;
   1.116 +
   1.117 +    /** The log to use for verbose output
   1.118 +     */
   1.119 +    final Log log;
   1.120 +
   1.121 +    /** The symbol table. */
   1.122 +    Symtab syms;
   1.123 +
   1.124 +    Types types;
   1.125 +
   1.126 +    /** The name table. */
   1.127 +    final Name.Table names;
   1.128 +
   1.129 +    /** Force a completion failure on this name
   1.130 +     */
   1.131 +    final Name completionFailureName;
   1.132 +
   1.133 +    /** Access to files
   1.134 +     */
   1.135 +    private final JavaFileManager fileManager;
   1.136 +
   1.137 +    /** Can be reassigned from outside:
   1.138 +     *  the completer to be used for ".java" files. If this remains unassigned
   1.139 +     *  ".java" files will not be loaded.
   1.140 +     */
   1.141 +    public SourceCompleter sourceCompleter = null;
   1.142 +
   1.143 +    /** A hashtable containing the encountered top-level and member classes,
   1.144 +     *  indexed by flat names. The table does not contain local classes.
   1.145 +     */
   1.146 +    private Map<Name,ClassSymbol> classes;
   1.147 +
   1.148 +    /** A hashtable containing the encountered packages.
   1.149 +     */
   1.150 +    private Map<Name, PackageSymbol> packages;
   1.151 +
   1.152 +    /** The current scope where type variables are entered.
   1.153 +     */
   1.154 +    protected Scope typevars;
   1.155 +
   1.156 +    /** The path name of the class file currently being read.
   1.157 +     */
   1.158 +    protected JavaFileObject currentClassFile = null;
   1.159 +
   1.160 +    /** The class or method currently being read.
   1.161 +     */
   1.162 +    protected Symbol currentOwner = null;
   1.163 +
   1.164 +    /** The buffer containing the currently read class file.
   1.165 +     */
   1.166 +    byte[] buf = new byte[0x0fff0];
   1.167 +
   1.168 +    /** The current input pointer.
   1.169 +     */
   1.170 +    int bp;
   1.171 +
   1.172 +    /** The objects of the constant pool.
   1.173 +     */
   1.174 +    Object[] poolObj;
   1.175 +
   1.176 +    /** For every constant pool entry, an index into buf where the
   1.177 +     *  defining section of the entry is found.
   1.178 +     */
   1.179 +    int[] poolIdx;
   1.180 +
   1.181 +    /** Get the ClassReader instance for this invocation. */
   1.182 +    public static ClassReader instance(Context context) {
   1.183 +        ClassReader instance = context.get(classReaderKey);
   1.184 +        if (instance == null)
   1.185 +            instance = new ClassReader(context, true);
   1.186 +        return instance;
   1.187 +    }
   1.188 +
   1.189 +    /** Initialize classes and packages, treating this as the definitive classreader. */
   1.190 +    public void init(Symtab syms) {
   1.191 +        init(syms, true);
   1.192 +    }
   1.193 +
   1.194 +    /** Initialize classes and packages, optionally treating this as
   1.195 +     *  the definitive classreader.
   1.196 +     */
   1.197 +    private void init(Symtab syms, boolean definitive) {
   1.198 +        if (classes != null) return;
   1.199 +
   1.200 +        if (definitive) {
   1.201 +            assert packages == null || packages == syms.packages;
   1.202 +            packages = syms.packages;
   1.203 +            assert classes == null || classes == syms.classes;
   1.204 +            classes = syms.classes;
   1.205 +        } else {
   1.206 +            packages = new HashMap<Name, PackageSymbol>();
   1.207 +            classes = new HashMap<Name, ClassSymbol>();
   1.208 +        }
   1.209 +
   1.210 +        packages.put(names.empty, syms.rootPackage);
   1.211 +        syms.rootPackage.completer = this;
   1.212 +        syms.unnamedPackage.completer = this;
   1.213 +    }
   1.214 +
   1.215 +    /** Construct a new class reader, optionally treated as the
   1.216 +     *  definitive classreader for this invocation.
   1.217 +     */
   1.218 +    protected ClassReader(Context context, boolean definitive) {
   1.219 +        if (definitive) context.put(classReaderKey, this);
   1.220 +
   1.221 +        names = Name.Table.instance(context);
   1.222 +        syms = Symtab.instance(context);
   1.223 +        types = Types.instance(context);
   1.224 +        fileManager = context.get(JavaFileManager.class);
   1.225 +        if (fileManager == null)
   1.226 +            throw new AssertionError("FileManager initialization error");
   1.227 +
   1.228 +        init(syms, definitive);
   1.229 +        log = Log.instance(context);
   1.230 +
   1.231 +        Options options = Options.instance(context);
   1.232 +        annotate = Annotate.instance(context);
   1.233 +        verbose        = options.get("-verbose")        != null;
   1.234 +        checkClassFile = options.get("-checkclassfile") != null;
   1.235 +        Source source = Source.instance(context);
   1.236 +        allowGenerics    = source.allowGenerics();
   1.237 +        allowVarargs     = source.allowVarargs();
   1.238 +        allowAnnotations = source.allowAnnotations();
   1.239 +        saveParameterNames = options.get("save-parameter-names") != null;
   1.240 +        cacheCompletionFailure = options.get("dev") == null;
   1.241 +        preferSource = "source".equals(options.get("-Xprefer"));
   1.242 +
   1.243 +        completionFailureName =
   1.244 +            (options.get("failcomplete") != null)
   1.245 +            ? names.fromString(options.get("failcomplete"))
   1.246 +            : null;
   1.247 +
   1.248 +        typevars = new Scope(syms.noSymbol);
   1.249 +    }
   1.250 +
   1.251 +    /** Add member to class unless it is synthetic.
   1.252 +     */
   1.253 +    private void enterMember(ClassSymbol c, Symbol sym) {
   1.254 +        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC)
   1.255 +            c.members_field.enter(sym);
   1.256 +    }
   1.257 +
   1.258 +/************************************************************************
   1.259 + * Error Diagnoses
   1.260 + ***********************************************************************/
   1.261 +
   1.262 +    public static class BadClassFile extends CompletionFailure {
   1.263 +        private static final long serialVersionUID = 0;
   1.264 +
   1.265 +        /**
   1.266 +         * @param msg A localized message.
   1.267 +         */
   1.268 +        public BadClassFile(ClassSymbol c, Object cname, Object msg) {
   1.269 +            super(c, Log.getLocalizedString("bad.class.file.header",
   1.270 +                                            cname, msg));
   1.271 +        }
   1.272 +    }
   1.273 +
   1.274 +    public BadClassFile badClassFile(String key, Object... args) {
   1.275 +        return new BadClassFile (
   1.276 +            currentOwner.enclClass(),
   1.277 +            currentClassFile,
   1.278 +            Log.getLocalizedString(key, args));
   1.279 +    }
   1.280 +
   1.281 +/************************************************************************
   1.282 + * Buffer Access
   1.283 + ***********************************************************************/
   1.284 +
   1.285 +    /** Read a character.
   1.286 +     */
   1.287 +    char nextChar() {
   1.288 +        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
   1.289 +    }
   1.290 +
   1.291 +    /** Read an integer.
   1.292 +     */
   1.293 +    int nextInt() {
   1.294 +        return
   1.295 +            ((buf[bp++] & 0xFF) << 24) +
   1.296 +            ((buf[bp++] & 0xFF) << 16) +
   1.297 +            ((buf[bp++] & 0xFF) << 8) +
   1.298 +            (buf[bp++] & 0xFF);
   1.299 +    }
   1.300 +
   1.301 +    /** Extract a character at position bp from buf.
   1.302 +     */
   1.303 +    char getChar(int bp) {
   1.304 +        return
   1.305 +            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
   1.306 +    }
   1.307 +
   1.308 +    /** Extract an integer at position bp from buf.
   1.309 +     */
   1.310 +    int getInt(int bp) {
   1.311 +        return
   1.312 +            ((buf[bp] & 0xFF) << 24) +
   1.313 +            ((buf[bp+1] & 0xFF) << 16) +
   1.314 +            ((buf[bp+2] & 0xFF) << 8) +
   1.315 +            (buf[bp+3] & 0xFF);
   1.316 +    }
   1.317 +
   1.318 +
   1.319 +    /** Extract a long integer at position bp from buf.
   1.320 +     */
   1.321 +    long getLong(int bp) {
   1.322 +        DataInputStream bufin =
   1.323 +            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
   1.324 +        try {
   1.325 +            return bufin.readLong();
   1.326 +        } catch (IOException e) {
   1.327 +            throw new AssertionError(e);
   1.328 +        }
   1.329 +    }
   1.330 +
   1.331 +    /** Extract a float at position bp from buf.
   1.332 +     */
   1.333 +    float getFloat(int bp) {
   1.334 +        DataInputStream bufin =
   1.335 +            new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
   1.336 +        try {
   1.337 +            return bufin.readFloat();
   1.338 +        } catch (IOException e) {
   1.339 +            throw new AssertionError(e);
   1.340 +        }
   1.341 +    }
   1.342 +
   1.343 +    /** Extract a double at position bp from buf.
   1.344 +     */
   1.345 +    double getDouble(int bp) {
   1.346 +        DataInputStream bufin =
   1.347 +            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
   1.348 +        try {
   1.349 +            return bufin.readDouble();
   1.350 +        } catch (IOException e) {
   1.351 +            throw new AssertionError(e);
   1.352 +        }
   1.353 +    }
   1.354 +
   1.355 +/************************************************************************
   1.356 + * Constant Pool Access
   1.357 + ***********************************************************************/
   1.358 +
   1.359 +    /** Index all constant pool entries, writing their start addresses into
   1.360 +     *  poolIdx.
   1.361 +     */
   1.362 +    void indexPool() {
   1.363 +        poolIdx = new int[nextChar()];
   1.364 +        poolObj = new Object[poolIdx.length];
   1.365 +        int i = 1;
   1.366 +        while (i < poolIdx.length) {
   1.367 +            poolIdx[i++] = bp;
   1.368 +            byte tag = buf[bp++];
   1.369 +            switch (tag) {
   1.370 +            case CONSTANT_Utf8: case CONSTANT_Unicode: {
   1.371 +                int len = nextChar();
   1.372 +                bp = bp + len;
   1.373 +                break;
   1.374 +            }
   1.375 +            case CONSTANT_Class:
   1.376 +            case CONSTANT_String:
   1.377 +                bp = bp + 2;
   1.378 +                break;
   1.379 +            case CONSTANT_Fieldref:
   1.380 +            case CONSTANT_Methodref:
   1.381 +            case CONSTANT_InterfaceMethodref:
   1.382 +            case CONSTANT_NameandType:
   1.383 +            case CONSTANT_Integer:
   1.384 +            case CONSTANT_Float:
   1.385 +                bp = bp + 4;
   1.386 +                break;
   1.387 +            case CONSTANT_Long:
   1.388 +            case CONSTANT_Double:
   1.389 +                bp = bp + 8;
   1.390 +                i++;
   1.391 +                break;
   1.392 +            default:
   1.393 +                throw badClassFile("bad.const.pool.tag.at",
   1.394 +                                   Byte.toString(tag),
   1.395 +                                   Integer.toString(bp -1));
   1.396 +            }
   1.397 +        }
   1.398 +    }
   1.399 +
   1.400 +    /** Read constant pool entry at start address i, use pool as a cache.
   1.401 +     */
   1.402 +    Object readPool(int i) {
   1.403 +        Object result = poolObj[i];
   1.404 +        if (result != null) return result;
   1.405 +
   1.406 +        int index = poolIdx[i];
   1.407 +        if (index == 0) return null;
   1.408 +
   1.409 +        byte tag = buf[index];
   1.410 +        switch (tag) {
   1.411 +        case CONSTANT_Utf8:
   1.412 +            poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
   1.413 +            break;
   1.414 +        case CONSTANT_Unicode:
   1.415 +            throw badClassFile("unicode.str.not.supported");
   1.416 +        case CONSTANT_Class:
   1.417 +            poolObj[i] = readClassOrType(getChar(index + 1));
   1.418 +            break;
   1.419 +        case CONSTANT_String:
   1.420 +            // FIXME: (footprint) do not use toString here
   1.421 +            poolObj[i] = readName(getChar(index + 1)).toString();
   1.422 +            break;
   1.423 +        case CONSTANT_Fieldref: {
   1.424 +            ClassSymbol owner = readClassSymbol(getChar(index + 1));
   1.425 +            NameAndType nt = (NameAndType)readPool(getChar(index + 3));
   1.426 +            poolObj[i] = new VarSymbol(0, nt.name, nt.type, owner);
   1.427 +            break;
   1.428 +        }
   1.429 +        case CONSTANT_Methodref:
   1.430 +        case CONSTANT_InterfaceMethodref: {
   1.431 +            ClassSymbol owner = readClassSymbol(getChar(index + 1));
   1.432 +            NameAndType nt = (NameAndType)readPool(getChar(index + 3));
   1.433 +            poolObj[i] = new MethodSymbol(0, nt.name, nt.type, owner);
   1.434 +            break;
   1.435 +        }
   1.436 +        case CONSTANT_NameandType:
   1.437 +            poolObj[i] = new NameAndType(
   1.438 +                readName(getChar(index + 1)),
   1.439 +                readType(getChar(index + 3)));
   1.440 +            break;
   1.441 +        case CONSTANT_Integer:
   1.442 +            poolObj[i] = getInt(index + 1);
   1.443 +            break;
   1.444 +        case CONSTANT_Float:
   1.445 +            poolObj[i] = new Float(getFloat(index + 1));
   1.446 +            break;
   1.447 +        case CONSTANT_Long:
   1.448 +            poolObj[i] = new Long(getLong(index + 1));
   1.449 +            break;
   1.450 +        case CONSTANT_Double:
   1.451 +            poolObj[i] = new Double(getDouble(index + 1));
   1.452 +            break;
   1.453 +        default:
   1.454 +            throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
   1.455 +        }
   1.456 +        return poolObj[i];
   1.457 +    }
   1.458 +
   1.459 +    /** Read signature and convert to type.
   1.460 +     */
   1.461 +    Type readType(int i) {
   1.462 +        int index = poolIdx[i];
   1.463 +        return sigToType(buf, index + 3, getChar(index + 1));
   1.464 +    }
   1.465 +
   1.466 +    /** If name is an array type or class signature, return the
   1.467 +     *  corresponding type; otherwise return a ClassSymbol with given name.
   1.468 +     */
   1.469 +    Object readClassOrType(int i) {
   1.470 +        int index =  poolIdx[i];
   1.471 +        int len = getChar(index + 1);
   1.472 +        int start = index + 3;
   1.473 +        assert buf[start] == '[' || buf[start + len - 1] != ';';
   1.474 +        // by the above assertion, the following test can be
   1.475 +        // simplified to (buf[start] == '[')
   1.476 +        return (buf[start] == '[' || buf[start + len - 1] == ';')
   1.477 +            ? (Object)sigToType(buf, start, len)
   1.478 +            : (Object)enterClass(names.fromUtf(internalize(buf, start,
   1.479 +                                                           len)));
   1.480 +    }
   1.481 +
   1.482 +    /** Read signature and convert to type parameters.
   1.483 +     */
   1.484 +    List<Type> readTypeParams(int i) {
   1.485 +        int index = poolIdx[i];
   1.486 +        return sigToTypeParams(buf, index + 3, getChar(index + 1));
   1.487 +    }
   1.488 +
   1.489 +    /** Read class entry.
   1.490 +     */
   1.491 +    ClassSymbol readClassSymbol(int i) {
   1.492 +        return (ClassSymbol) (readPool(i));
   1.493 +    }
   1.494 +
   1.495 +    /** Read name.
   1.496 +     */
   1.497 +    Name readName(int i) {
   1.498 +        return (Name) (readPool(i));
   1.499 +    }
   1.500 +
   1.501 +/************************************************************************
   1.502 + * Reading Types
   1.503 + ***********************************************************************/
   1.504 +
   1.505 +    /** The unread portion of the currently read type is
   1.506 +     *  signature[sigp..siglimit-1].
   1.507 +     */
   1.508 +    byte[] signature;
   1.509 +    int sigp;
   1.510 +    int siglimit;
   1.511 +    boolean sigEnterPhase = false;
   1.512 +
   1.513 +    /** Convert signature to type, where signature is a name.
   1.514 +     */
   1.515 +    Type sigToType(Name sig) {
   1.516 +        return sig == null
   1.517 +            ? null
   1.518 +            : sigToType(sig.table.names, sig.index, sig.len);
   1.519 +    }
   1.520 +
   1.521 +    /** Convert signature to type, where signature is a byte array segment.
   1.522 +     */
   1.523 +    Type sigToType(byte[] sig, int offset, int len) {
   1.524 +        signature = sig;
   1.525 +        sigp = offset;
   1.526 +        siglimit = offset + len;
   1.527 +        return sigToType();
   1.528 +    }
   1.529 +
   1.530 +    /** Convert signature to type, where signature is implicit.
   1.531 +     */
   1.532 +    Type sigToType() {
   1.533 +        switch ((char) signature[sigp]) {
   1.534 +        case 'T':
   1.535 +            sigp++;
   1.536 +            int start = sigp;
   1.537 +            while (signature[sigp] != ';') sigp++;
   1.538 +            sigp++;
   1.539 +            return sigEnterPhase
   1.540 +                ? Type.noType
   1.541 +                : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start));
   1.542 +        case '+': {
   1.543 +            sigp++;
   1.544 +            Type t = sigToType();
   1.545 +            return new WildcardType(t, BoundKind.EXTENDS,
   1.546 +                                    syms.boundClass);
   1.547 +        }
   1.548 +        case '*':
   1.549 +            sigp++;
   1.550 +            return new WildcardType(syms.objectType, BoundKind.UNBOUND,
   1.551 +                                    syms.boundClass);
   1.552 +        case '-': {
   1.553 +            sigp++;
   1.554 +            Type t = sigToType();
   1.555 +            return new WildcardType(t, BoundKind.SUPER,
   1.556 +                                    syms.boundClass);
   1.557 +        }
   1.558 +        case 'B':
   1.559 +            sigp++;
   1.560 +            return syms.byteType;
   1.561 +        case 'C':
   1.562 +            sigp++;
   1.563 +            return syms.charType;
   1.564 +        case 'D':
   1.565 +            sigp++;
   1.566 +            return syms.doubleType;
   1.567 +        case 'F':
   1.568 +            sigp++;
   1.569 +            return syms.floatType;
   1.570 +        case 'I':
   1.571 +            sigp++;
   1.572 +            return syms.intType;
   1.573 +        case 'J':
   1.574 +            sigp++;
   1.575 +            return syms.longType;
   1.576 +        case 'L':
   1.577 +            {
   1.578 +                // int oldsigp = sigp;
   1.579 +                Type t = classSigToType();
   1.580 +                if (sigp < siglimit && signature[sigp] == '.')
   1.581 +                    throw badClassFile("deprecated inner class signature syntax " +
   1.582 +                                       "(please recompile from source)");
   1.583 +                /*
   1.584 +                System.err.println(" decoded " +
   1.585 +                                   new String(signature, oldsigp, sigp-oldsigp) +
   1.586 +                                   " => " + t + " outer " + t.outer());
   1.587 +                */
   1.588 +                return t;
   1.589 +            }
   1.590 +        case 'S':
   1.591 +            sigp++;
   1.592 +            return syms.shortType;
   1.593 +        case 'V':
   1.594 +            sigp++;
   1.595 +            return syms.voidType;
   1.596 +        case 'Z':
   1.597 +            sigp++;
   1.598 +            return syms.booleanType;
   1.599 +        case '[':
   1.600 +            sigp++;
   1.601 +            return new ArrayType(sigToType(), syms.arrayClass);
   1.602 +        case '(':
   1.603 +            sigp++;
   1.604 +            List<Type> argtypes = sigToTypes(')');
   1.605 +            Type restype = sigToType();
   1.606 +            List<Type> thrown = List.nil();
   1.607 +            while (signature[sigp] == '^') {
   1.608 +                sigp++;
   1.609 +                thrown = thrown.prepend(sigToType());
   1.610 +            }
   1.611 +            return new MethodType(argtypes,
   1.612 +                                  restype,
   1.613 +                                  thrown.reverse(),
   1.614 +                                  syms.methodClass);
   1.615 +        case '<':
   1.616 +            typevars = typevars.dup(currentOwner);
   1.617 +            Type poly = new ForAll(sigToTypeParams(), sigToType());
   1.618 +            typevars = typevars.leave();
   1.619 +            return poly;
   1.620 +        default:
   1.621 +            throw badClassFile("bad.signature",
   1.622 +                               Convert.utf2string(signature, sigp, 10));
   1.623 +        }
   1.624 +    }
   1.625 +
   1.626 +    byte[] signatureBuffer = new byte[0];
   1.627 +    int sbp = 0;
   1.628 +    /** Convert class signature to type, where signature is implicit.
   1.629 +     */
   1.630 +    Type classSigToType() {
   1.631 +        if (signature[sigp] != 'L')
   1.632 +            throw badClassFile("bad.class.signature",
   1.633 +                               Convert.utf2string(signature, sigp, 10));
   1.634 +        sigp++;
   1.635 +        Type outer = Type.noType;
   1.636 +        int startSbp = sbp;
   1.637 +
   1.638 +        while (true) {
   1.639 +            final byte c = signature[sigp++];
   1.640 +            switch (c) {
   1.641 +
   1.642 +            case ';': {         // end
   1.643 +                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
   1.644 +                                                         startSbp,
   1.645 +                                                         sbp - startSbp));
   1.646 +                if (outer == Type.noType)
   1.647 +                    outer = t.erasure(types);
   1.648 +                else
   1.649 +                    outer = new ClassType(outer, List.<Type>nil(), t);
   1.650 +                sbp = startSbp;
   1.651 +                return outer;
   1.652 +            }
   1.653 +
   1.654 +            case '<':           // generic arguments
   1.655 +                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
   1.656 +                                                         startSbp,
   1.657 +                                                         sbp - startSbp));
   1.658 +                outer = new ClassType(outer, sigToTypes('>'), t) {
   1.659 +                        boolean completed = false;
   1.660 +                        public Type getEnclosingType() {
   1.661 +                            if (!completed) {
   1.662 +                                completed = true;
   1.663 +                                tsym.complete();
   1.664 +                                Type enclosingType = tsym.type.getEnclosingType();
   1.665 +                                if (enclosingType != Type.noType) {
   1.666 +                                    List<Type> typeArgs =
   1.667 +                                        super.getEnclosingType().allparams();
   1.668 +                                    List<Type> typeParams =
   1.669 +                                        enclosingType.allparams();
   1.670 +                                    if (typeParams.length() != typeArgs.length()) {
   1.671 +                                        // no "rare" types
   1.672 +                                        super.setEnclosingType(types.erasure(enclosingType));
   1.673 +                                    } else {
   1.674 +                                        super.setEnclosingType(types.subst(enclosingType,
   1.675 +                                                                           typeParams,
   1.676 +                                                                           typeArgs));
   1.677 +                                    }
   1.678 +                                } else {
   1.679 +                                    super.setEnclosingType(Type.noType);
   1.680 +                                }
   1.681 +                            }
   1.682 +                            return super.getEnclosingType();
   1.683 +                        }
   1.684 +                        public void setEnclosingType(Type outer) {
   1.685 +                            throw new UnsupportedOperationException();
   1.686 +                        }
   1.687 +                    };
   1.688 +                switch (signature[sigp++]) {
   1.689 +                case ';':
   1.690 +                    if (sigp < signature.length && signature[sigp] == '.') {
   1.691 +                        // support old-style GJC signatures
   1.692 +                        // The signature produced was
   1.693 +                        // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
   1.694 +                        // rather than say
   1.695 +                        // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
   1.696 +                        // so we skip past ".Lfoo/Outer$"
   1.697 +                        sigp += (sbp - startSbp) + // "foo/Outer"
   1.698 +                            3;  // ".L" and "$"
   1.699 +                        signatureBuffer[sbp++] = (byte)'$';
   1.700 +                        break;
   1.701 +                    } else {
   1.702 +                        sbp = startSbp;
   1.703 +                        return outer;
   1.704 +                    }
   1.705 +                case '.':
   1.706 +                    signatureBuffer[sbp++] = (byte)'$';
   1.707 +                    break;
   1.708 +                default:
   1.709 +                    throw new AssertionError(signature[sigp-1]);
   1.710 +                }
   1.711 +                continue;
   1.712 +
   1.713 +            case '.':
   1.714 +                signatureBuffer[sbp++] = (byte)'$';
   1.715 +                continue;
   1.716 +            case '/':
   1.717 +                signatureBuffer[sbp++] = (byte)'.';
   1.718 +                continue;
   1.719 +            default:
   1.720 +                signatureBuffer[sbp++] = c;
   1.721 +                continue;
   1.722 +            }
   1.723 +        }
   1.724 +    }
   1.725 +
   1.726 +    /** Convert (implicit) signature to list of types
   1.727 +     *  until `terminator' is encountered.
   1.728 +     */
   1.729 +    List<Type> sigToTypes(char terminator) {
   1.730 +        List<Type> head = List.of(null);
   1.731 +        List<Type> tail = head;
   1.732 +        while (signature[sigp] != terminator)
   1.733 +            tail = tail.setTail(List.of(sigToType()));
   1.734 +        sigp++;
   1.735 +        return head.tail;
   1.736 +    }
   1.737 +
   1.738 +    /** Convert signature to type parameters, where signature is a name.
   1.739 +     */
   1.740 +    List<Type> sigToTypeParams(Name name) {
   1.741 +        return sigToTypeParams(name.table.names, name.index, name.len);
   1.742 +    }
   1.743 +
   1.744 +    /** Convert signature to type parameters, where signature is a byte
   1.745 +     *  array segment.
   1.746 +     */
   1.747 +    List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
   1.748 +        signature = sig;
   1.749 +        sigp = offset;
   1.750 +        siglimit = offset + len;
   1.751 +        return sigToTypeParams();
   1.752 +    }
   1.753 +
   1.754 +    /** Convert signature to type parameters, where signature is implicit.
   1.755 +     */
   1.756 +    List<Type> sigToTypeParams() {
   1.757 +        List<Type> tvars = List.nil();
   1.758 +        if (signature[sigp] == '<') {
   1.759 +            sigp++;
   1.760 +            int start = sigp;
   1.761 +            sigEnterPhase = true;
   1.762 +            while (signature[sigp] != '>')
   1.763 +                tvars = tvars.prepend(sigToTypeParam());
   1.764 +            sigEnterPhase = false;
   1.765 +            sigp = start;
   1.766 +            while (signature[sigp] != '>')
   1.767 +                sigToTypeParam();
   1.768 +            sigp++;
   1.769 +        }
   1.770 +        return tvars.reverse();
   1.771 +    }
   1.772 +
   1.773 +    /** Convert (implicit) signature to type parameter.
   1.774 +     */
   1.775 +    Type sigToTypeParam() {
   1.776 +        int start = sigp;
   1.777 +        while (signature[sigp] != ':') sigp++;
   1.778 +        Name name = names.fromUtf(signature, start, sigp - start);
   1.779 +        TypeVar tvar;
   1.780 +        if (sigEnterPhase) {
   1.781 +            tvar = new TypeVar(name, currentOwner, syms.botType);
   1.782 +            typevars.enter(tvar.tsym);
   1.783 +        } else {
   1.784 +            tvar = (TypeVar)findTypeVar(name);
   1.785 +        }
   1.786 +        List<Type> bounds = List.nil();
   1.787 +        Type st = null;
   1.788 +        if (signature[sigp] == ':' && signature[sigp+1] == ':') {
   1.789 +            sigp++;
   1.790 +            st = syms.objectType;
   1.791 +        }
   1.792 +        while (signature[sigp] == ':') {
   1.793 +            sigp++;
   1.794 +            bounds = bounds.prepend(sigToType());
   1.795 +        }
   1.796 +        if (!sigEnterPhase) {
   1.797 +            types.setBounds(tvar, bounds.reverse(), st);
   1.798 +        }
   1.799 +        return tvar;
   1.800 +    }
   1.801 +
   1.802 +    /** Find type variable with given name in `typevars' scope.
   1.803 +     */
   1.804 +    Type findTypeVar(Name name) {
   1.805 +        Scope.Entry e = typevars.lookup(name);
   1.806 +        if (e.scope != null) {
   1.807 +            return e.sym.type;
   1.808 +        } else {
   1.809 +            if (readingClassAttr) {
   1.810 +                // While reading the class attribute, the supertypes
   1.811 +                // might refer to a type variable from an enclosing element
   1.812 +                // (method or class).
   1.813 +                // If the type variable is defined in the enclosing class,
   1.814 +                // we can actually find it in
   1.815 +                // currentOwner.owner.type.getTypeArguments()
   1.816 +                // However, until we have read the enclosing method attribute
   1.817 +                // we don't know for sure if this owner is correct.  It could
   1.818 +                // be a method and there is no way to tell before reading the
   1.819 +                // enclosing method attribute.
   1.820 +                TypeVar t = new TypeVar(name, currentOwner, syms.botType);
   1.821 +                missingTypeVariables = missingTypeVariables.prepend(t);
   1.822 +                // System.err.println("Missing type var " + name);
   1.823 +                return t;
   1.824 +            }
   1.825 +            throw badClassFile("undecl.type.var", name);
   1.826 +        }
   1.827 +    }
   1.828 +
   1.829 +/************************************************************************
   1.830 + * Reading Attributes
   1.831 + ***********************************************************************/
   1.832 +
   1.833 +    /** Report unrecognized attribute.
   1.834 +     */
   1.835 +    void unrecognized(Name attrName) {
   1.836 +        if (checkClassFile)
   1.837 +            printCCF("ccf.unrecognized.attribute", attrName);
   1.838 +    }
   1.839 +
   1.840 +    /** Read member attribute.
   1.841 +     */
   1.842 +    void readMemberAttr(Symbol sym, Name attrName, int attrLen) {
   1.843 +        //- System.err.println(" z " + sym + ", " + attrName + ", " + attrLen);
   1.844 +        if (attrName == names.ConstantValue) {
   1.845 +            Object v = readPool(nextChar());
   1.846 +            // Ignore ConstantValue attribute if field not final.
   1.847 +            if ((sym.flags() & FINAL) != 0)
   1.848 +                ((VarSymbol)sym).setData(v);
   1.849 +        } else if (attrName == names.Code) {
   1.850 +            if (readAllOfClassFile || saveParameterNames)
   1.851 +                ((MethodSymbol)sym).code = readCode(sym);
   1.852 +            else
   1.853 +                bp = bp + attrLen;
   1.854 +        } else if (attrName == names.Exceptions) {
   1.855 +            int nexceptions = nextChar();
   1.856 +            List<Type> thrown = List.nil();
   1.857 +            for (int j = 0; j < nexceptions; j++)
   1.858 +                thrown = thrown.prepend(readClassSymbol(nextChar()).type);
   1.859 +            if (sym.type.getThrownTypes().isEmpty())
   1.860 +                sym.type.asMethodType().thrown = thrown.reverse();
   1.861 +        } else if (attrName == names.Synthetic) {
   1.862 +            // bridge methods are visible when generics not enabled
   1.863 +            if (allowGenerics || (sym.flags_field & BRIDGE) == 0)
   1.864 +                sym.flags_field |= SYNTHETIC;
   1.865 +        } else if (attrName == names.Bridge) {
   1.866 +            sym.flags_field |= BRIDGE;
   1.867 +            if (!allowGenerics)
   1.868 +                sym.flags_field &= ~SYNTHETIC;
   1.869 +        } else if (attrName == names.Deprecated) {
   1.870 +            sym.flags_field |= DEPRECATED;
   1.871 +        } else if (attrName == names.Varargs) {
   1.872 +            if (allowVarargs) sym.flags_field |= VARARGS;
   1.873 +        } else if (attrName == names.Annotation) {
   1.874 +            if (allowAnnotations) sym.flags_field |= ANNOTATION;
   1.875 +        } else if (attrName == names.Enum) {
   1.876 +            sym.flags_field |= ENUM;
   1.877 +        } else if (allowGenerics && attrName == names.Signature) {
   1.878 +            List<Type> thrown = sym.type.getThrownTypes();
   1.879 +            sym.type = readType(nextChar());
   1.880 +            //- System.err.println(" # " + sym.type);
   1.881 +            if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
   1.882 +                sym.type.asMethodType().thrown = thrown;
   1.883 +        } else if (attrName == names.RuntimeVisibleAnnotations) {
   1.884 +            attachAnnotations(sym);
   1.885 +        } else if (attrName == names.RuntimeInvisibleAnnotations) {
   1.886 +            attachAnnotations(sym);
   1.887 +        } else if (attrName == names.RuntimeVisibleParameterAnnotations) {
   1.888 +            attachParameterAnnotations(sym);
   1.889 +        } else if (attrName == names.RuntimeInvisibleParameterAnnotations) {
   1.890 +            attachParameterAnnotations(sym);
   1.891 +        } else if (attrName == names.LocalVariableTable) {
   1.892 +            int newbp = bp + attrLen;
   1.893 +            if (saveParameterNames) {
   1.894 +                // pick up parameter names from the variable table
   1.895 +                List<Name> parameterNames = List.nil();
   1.896 +                int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
   1.897 +                int endParam = firstParam + Code.width(sym.type.getParameterTypes());
   1.898 +                int numEntries = nextChar();
   1.899 +                for (int i=0; i<numEntries; i++) {
   1.900 +                    int start_pc = nextChar();
   1.901 +                    int length = nextChar();
   1.902 +                    int nameIndex = nextChar();
   1.903 +                    int sigIndex = nextChar();
   1.904 +                    int register = nextChar();
   1.905 +                    if (start_pc == 0 &&
   1.906 +                        firstParam <= register &&
   1.907 +                        register < endParam) {
   1.908 +                        int index = firstParam;
   1.909 +                        for (Type t : sym.type.getParameterTypes()) {
   1.910 +                            if (index == register) {
   1.911 +                                parameterNames = parameterNames.prepend(readName(nameIndex));
   1.912 +                                break;
   1.913 +                            }
   1.914 +                            index += Code.width(t);
   1.915 +                        }
   1.916 +                    }
   1.917 +                }
   1.918 +                parameterNames = parameterNames.reverse();
   1.919 +                ((MethodSymbol)sym).savedParameterNames = parameterNames;
   1.920 +            }
   1.921 +            bp = newbp;
   1.922 +        } else if (attrName == names.AnnotationDefault) {
   1.923 +            attachAnnotationDefault(sym);
   1.924 +        } else if (attrName == names.EnclosingMethod) {
   1.925 +            int newbp = bp + attrLen;
   1.926 +            readEnclosingMethodAttr(sym);
   1.927 +            bp = newbp;
   1.928 +        } else {
   1.929 +            unrecognized(attrName);
   1.930 +            bp = bp + attrLen;
   1.931 +        }
   1.932 +    }
   1.933 +
   1.934 +    void readEnclosingMethodAttr(Symbol sym) {
   1.935 +        // sym is a nested class with an "Enclosing Method" attribute
   1.936 +        // remove sym from it's current owners scope and place it in
   1.937 +        // the scope specified by the attribute
   1.938 +        sym.owner.members().remove(sym);
   1.939 +        ClassSymbol self = (ClassSymbol)sym;
   1.940 +        ClassSymbol c = readClassSymbol(nextChar());
   1.941 +        NameAndType nt = (NameAndType)readPool(nextChar());
   1.942 +
   1.943 +        MethodSymbol m = findMethod(nt, c.members_field, self.flags());
   1.944 +        if (nt != null && m == null)
   1.945 +            throw badClassFile("bad.enclosing.method", self);
   1.946 +
   1.947 +        self.name = simpleBinaryName(self.flatname, c.flatname) ;
   1.948 +        self.owner = m != null ? m : c;
   1.949 +        if (self.name.len == 0)
   1.950 +            self.fullname = null;
   1.951 +        else
   1.952 +            self.fullname = ClassSymbol.formFullName(self.name, self.owner);
   1.953 +
   1.954 +        if (m != null) {
   1.955 +            ((ClassType)sym.type).setEnclosingType(m.type);
   1.956 +        } else if ((self.flags_field & STATIC) == 0) {
   1.957 +            ((ClassType)sym.type).setEnclosingType(c.type);
   1.958 +        } else {
   1.959 +            ((ClassType)sym.type).setEnclosingType(Type.noType);
   1.960 +        }
   1.961 +        enterTypevars(self);
   1.962 +        if (!missingTypeVariables.isEmpty()) {
   1.963 +            ListBuffer<Type> typeVars =  new ListBuffer<Type>();
   1.964 +            for (Type typevar : missingTypeVariables) {
   1.965 +                typeVars.append(findTypeVar(typevar.tsym.name));
   1.966 +            }
   1.967 +            foundTypeVariables = typeVars.toList();
   1.968 +        } else {
   1.969 +            foundTypeVariables = List.nil();
   1.970 +        }
   1.971 +    }
   1.972 +
   1.973 +    // See java.lang.Class
   1.974 +    private Name simpleBinaryName(Name self, Name enclosing) {
   1.975 +        String simpleBinaryName = self.toString().substring(enclosing.toString().length());
   1.976 +        if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
   1.977 +            throw badClassFile("bad.enclosing.method", self);
   1.978 +        int index = 1;
   1.979 +        while (index < simpleBinaryName.length() &&
   1.980 +               isAsciiDigit(simpleBinaryName.charAt(index)))
   1.981 +            index++;
   1.982 +        return names.fromString(simpleBinaryName.substring(index));
   1.983 +    }
   1.984 +
   1.985 +    private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
   1.986 +        if (nt == null)
   1.987 +            return null;
   1.988 +
   1.989 +        MethodType type = nt.type.asMethodType();
   1.990 +
   1.991 +        for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next())
   1.992 +            if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
   1.993 +                return (MethodSymbol)e.sym;
   1.994 +
   1.995 +        if (nt.name != names.init)
   1.996 +            // not a constructor
   1.997 +            return null;
   1.998 +        if ((flags & INTERFACE) != 0)
   1.999 +            // no enclosing instance
  1.1000 +            return null;
  1.1001 +        if (nt.type.getParameterTypes().isEmpty())
  1.1002 +            // no parameters
  1.1003 +            return null;
  1.1004 +
  1.1005 +        // A constructor of an inner class.
  1.1006 +        // Remove the first argument (the enclosing instance)
  1.1007 +        nt.type = new MethodType(nt.type.getParameterTypes().tail,
  1.1008 +                                 nt.type.getReturnType(),
  1.1009 +                                 nt.type.getThrownTypes(),
  1.1010 +                                 syms.methodClass);
  1.1011 +        // Try searching again
  1.1012 +        return findMethod(nt, scope, flags);
  1.1013 +    }
  1.1014 +
  1.1015 +    /** Similar to Types.isSameType but avoids completion */
  1.1016 +    private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
  1.1017 +        List<Type> types1 = types.erasure(mt1.getParameterTypes())
  1.1018 +            .prepend(types.erasure(mt1.getReturnType()));
  1.1019 +        List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
  1.1020 +        while (!types1.isEmpty() && !types2.isEmpty()) {
  1.1021 +            if (types1.head.tsym != types2.head.tsym)
  1.1022 +                return false;
  1.1023 +            types1 = types1.tail;
  1.1024 +            types2 = types2.tail;
  1.1025 +        }
  1.1026 +        return types1.isEmpty() && types2.isEmpty();
  1.1027 +    }
  1.1028 +
  1.1029 +    /**
  1.1030 +     * Character.isDigit answers <tt>true</tt> to some non-ascii
  1.1031 +     * digits.  This one does not.  <b>copied from java.lang.Class</b>
  1.1032 +     */
  1.1033 +    private static boolean isAsciiDigit(char c) {
  1.1034 +        return '0' <= c && c <= '9';
  1.1035 +    }
  1.1036 +
  1.1037 +    /** Read member attributes.
  1.1038 +     */
  1.1039 +    void readMemberAttrs(Symbol sym) {
  1.1040 +        char ac = nextChar();
  1.1041 +        for (int i = 0; i < ac; i++) {
  1.1042 +            Name attrName = readName(nextChar());
  1.1043 +            int attrLen = nextInt();
  1.1044 +            readMemberAttr(sym, attrName, attrLen);
  1.1045 +        }
  1.1046 +    }
  1.1047 +
  1.1048 +    /** Read class attribute.
  1.1049 +     */
  1.1050 +    void readClassAttr(ClassSymbol c, Name attrName, int attrLen) {
  1.1051 +        if (attrName == names.SourceFile) {
  1.1052 +            Name n = readName(nextChar());
  1.1053 +            c.sourcefile = new SourceFileObject(n);
  1.1054 +        } else if (attrName == names.InnerClasses) {
  1.1055 +            readInnerClasses(c);
  1.1056 +        } else if (allowGenerics && attrName == names.Signature) {
  1.1057 +            readingClassAttr = true;
  1.1058 +            try {
  1.1059 +                ClassType ct1 = (ClassType)c.type;
  1.1060 +                assert c == currentOwner;
  1.1061 +                ct1.typarams_field = readTypeParams(nextChar());
  1.1062 +                ct1.supertype_field = sigToType();
  1.1063 +                ListBuffer<Type> is = new ListBuffer<Type>();
  1.1064 +                while (sigp != siglimit) is.append(sigToType());
  1.1065 +                ct1.interfaces_field = is.toList();
  1.1066 +            } finally {
  1.1067 +                readingClassAttr = false;
  1.1068 +            }
  1.1069 +        } else {
  1.1070 +            readMemberAttr(c, attrName, attrLen);
  1.1071 +        }
  1.1072 +    }
  1.1073 +    private boolean readingClassAttr = false;
  1.1074 +    private List<Type> missingTypeVariables = List.nil();
  1.1075 +    private List<Type> foundTypeVariables = List.nil();
  1.1076 +
  1.1077 +    /** Read class attributes.
  1.1078 +     */
  1.1079 +    void readClassAttrs(ClassSymbol c) {
  1.1080 +        char ac = nextChar();
  1.1081 +        for (int i = 0; i < ac; i++) {
  1.1082 +            Name attrName = readName(nextChar());
  1.1083 +            int attrLen = nextInt();
  1.1084 +            readClassAttr(c, attrName, attrLen);
  1.1085 +        }
  1.1086 +    }
  1.1087 +
  1.1088 +    /** Read code block.
  1.1089 +     */
  1.1090 +    Code readCode(Symbol owner) {
  1.1091 +        nextChar(); // max_stack
  1.1092 +        nextChar(); // max_locals
  1.1093 +        final int  code_length = nextInt();
  1.1094 +        bp += code_length;
  1.1095 +        final char exception_table_length = nextChar();
  1.1096 +        bp += exception_table_length * 8;
  1.1097 +        readMemberAttrs(owner);
  1.1098 +        return null;
  1.1099 +    }
  1.1100 +
  1.1101 +/************************************************************************
  1.1102 + * Reading Java-language annotations
  1.1103 + ***********************************************************************/
  1.1104 +
  1.1105 +    /** Attach annotations.
  1.1106 +     */
  1.1107 +    void attachAnnotations(final Symbol sym) {
  1.1108 +        int numAttributes = nextChar();
  1.1109 +        if (numAttributes != 0) {
  1.1110 +            ListBuffer<CompoundAnnotationProxy> proxies =
  1.1111 +                new ListBuffer<CompoundAnnotationProxy>();
  1.1112 +            for (int i = 0; i<numAttributes; i++) {
  1.1113 +                CompoundAnnotationProxy proxy = readCompoundAnnotation();
  1.1114 +                if (proxy.type.tsym == syms.proprietaryType.tsym)
  1.1115 +                    sym.flags_field |= PROPRIETARY;
  1.1116 +                else
  1.1117 +                    proxies.append(proxy);
  1.1118 +            }
  1.1119 +            annotate.later(new AnnotationCompleter(sym, proxies.toList()));
  1.1120 +        }
  1.1121 +    }
  1.1122 +
  1.1123 +    /** Attach parameter annotations.
  1.1124 +     */
  1.1125 +    void attachParameterAnnotations(final Symbol method) {
  1.1126 +        final MethodSymbol meth = (MethodSymbol)method;
  1.1127 +        int numParameters = buf[bp++] & 0xFF;
  1.1128 +        List<VarSymbol> parameters = meth.params();
  1.1129 +        int pnum = 0;
  1.1130 +        while (parameters.tail != null) {
  1.1131 +            attachAnnotations(parameters.head);
  1.1132 +            parameters = parameters.tail;
  1.1133 +            pnum++;
  1.1134 +        }
  1.1135 +        if (pnum != numParameters) {
  1.1136 +            throw badClassFile("bad.runtime.invisible.param.annotations", meth);
  1.1137 +        }
  1.1138 +    }
  1.1139 +
  1.1140 +    /** Attach the default value for an annotation element.
  1.1141 +     */
  1.1142 +    void attachAnnotationDefault(final Symbol sym) {
  1.1143 +        final MethodSymbol meth = (MethodSymbol)sym; // only on methods
  1.1144 +        final Attribute value = readAttributeValue();
  1.1145 +        annotate.later(new AnnotationDefaultCompleter(meth, value));
  1.1146 +    }
  1.1147 +
  1.1148 +    Type readTypeOrClassSymbol(int i) {
  1.1149 +        // support preliminary jsr175-format class files
  1.1150 +        if (buf[poolIdx[i]] == CONSTANT_Class)
  1.1151 +            return readClassSymbol(i).type;
  1.1152 +        return readType(i);
  1.1153 +    }
  1.1154 +    Type readEnumType(int i) {
  1.1155 +        // support preliminary jsr175-format class files
  1.1156 +        int index = poolIdx[i];
  1.1157 +        int length = getChar(index + 1);
  1.1158 +        if (buf[index + length + 2] != ';')
  1.1159 +            return enterClass(readName(i)).type;
  1.1160 +        return readType(i);
  1.1161 +    }
  1.1162 +
  1.1163 +    CompoundAnnotationProxy readCompoundAnnotation() {
  1.1164 +        Type t = readTypeOrClassSymbol(nextChar());
  1.1165 +        int numFields = nextChar();
  1.1166 +        ListBuffer<Pair<Name,Attribute>> pairs =
  1.1167 +            new ListBuffer<Pair<Name,Attribute>>();
  1.1168 +        for (int i=0; i<numFields; i++) {
  1.1169 +            Name name = readName(nextChar());
  1.1170 +            Attribute value = readAttributeValue();
  1.1171 +            pairs.append(new Pair<Name,Attribute>(name, value));
  1.1172 +        }
  1.1173 +        return new CompoundAnnotationProxy(t, pairs.toList());
  1.1174 +    }
  1.1175 +
  1.1176 +    Attribute readAttributeValue() {
  1.1177 +        char c = (char) buf[bp++];
  1.1178 +        switch (c) {
  1.1179 +        case 'B':
  1.1180 +            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
  1.1181 +        case 'C':
  1.1182 +            return new Attribute.Constant(syms.charType, readPool(nextChar()));
  1.1183 +        case 'D':
  1.1184 +            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
  1.1185 +        case 'F':
  1.1186 +            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
  1.1187 +        case 'I':
  1.1188 +            return new Attribute.Constant(syms.intType, readPool(nextChar()));
  1.1189 +        case 'J':
  1.1190 +            return new Attribute.Constant(syms.longType, readPool(nextChar()));
  1.1191 +        case 'S':
  1.1192 +            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
  1.1193 +        case 'Z':
  1.1194 +            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
  1.1195 +        case 's':
  1.1196 +            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
  1.1197 +        case 'e':
  1.1198 +            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
  1.1199 +        case 'c':
  1.1200 +            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
  1.1201 +        case '[': {
  1.1202 +            int n = nextChar();
  1.1203 +            ListBuffer<Attribute> l = new ListBuffer<Attribute>();
  1.1204 +            for (int i=0; i<n; i++)
  1.1205 +                l.append(readAttributeValue());
  1.1206 +            return new ArrayAttributeProxy(l.toList());
  1.1207 +        }
  1.1208 +        case '@':
  1.1209 +            return readCompoundAnnotation();
  1.1210 +        default:
  1.1211 +            throw new AssertionError("unknown annotation tag '" + c + "'");
  1.1212 +        }
  1.1213 +    }
  1.1214 +
  1.1215 +    interface ProxyVisitor extends Attribute.Visitor {
  1.1216 +        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
  1.1217 +        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
  1.1218 +        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
  1.1219 +    }
  1.1220 +
  1.1221 +    static class EnumAttributeProxy extends Attribute {
  1.1222 +        Type enumType;
  1.1223 +        Name enumerator;
  1.1224 +        public EnumAttributeProxy(Type enumType, Name enumerator) {
  1.1225 +            super(null);
  1.1226 +            this.enumType = enumType;
  1.1227 +            this.enumerator = enumerator;
  1.1228 +        }
  1.1229 +        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
  1.1230 +        public String toString() {
  1.1231 +            return "/*proxy enum*/" + enumType + "." + enumerator;
  1.1232 +        }
  1.1233 +    }
  1.1234 +
  1.1235 +    static class ArrayAttributeProxy extends Attribute {
  1.1236 +        List<Attribute> values;
  1.1237 +        ArrayAttributeProxy(List<Attribute> values) {
  1.1238 +            super(null);
  1.1239 +            this.values = values;
  1.1240 +        }
  1.1241 +        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
  1.1242 +        public String toString() {
  1.1243 +            return "{" + values + "}";
  1.1244 +        }
  1.1245 +    }
  1.1246 +
  1.1247 +    /** A temporary proxy representing a compound attribute.
  1.1248 +     */
  1.1249 +    static class CompoundAnnotationProxy extends Attribute {
  1.1250 +        final List<Pair<Name,Attribute>> values;
  1.1251 +        public CompoundAnnotationProxy(Type type,
  1.1252 +                                      List<Pair<Name,Attribute>> values) {
  1.1253 +            super(type);
  1.1254 +            this.values = values;
  1.1255 +        }
  1.1256 +        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
  1.1257 +        public String toString() {
  1.1258 +            StringBuffer buf = new StringBuffer();
  1.1259 +            buf.append("@");
  1.1260 +            buf.append(type.tsym.getQualifiedName());
  1.1261 +            buf.append("/*proxy*/{");
  1.1262 +            boolean first = true;
  1.1263 +            for (List<Pair<Name,Attribute>> v = values;
  1.1264 +                 v.nonEmpty(); v = v.tail) {
  1.1265 +                Pair<Name,Attribute> value = v.head;
  1.1266 +                if (!first) buf.append(",");
  1.1267 +                first = false;
  1.1268 +                buf.append(value.fst);
  1.1269 +                buf.append("=");
  1.1270 +                buf.append(value.snd);
  1.1271 +            }
  1.1272 +            buf.append("}");
  1.1273 +            return buf.toString();
  1.1274 +        }
  1.1275 +    }
  1.1276 +
  1.1277 +    class AnnotationDeproxy implements ProxyVisitor {
  1.1278 +        private ClassSymbol requestingOwner = currentOwner.kind == MTH
  1.1279 +            ? currentOwner.enclClass() : (ClassSymbol)currentOwner;
  1.1280 +
  1.1281 +        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
  1.1282 +            // also must fill in types!!!!
  1.1283 +            ListBuffer<Attribute.Compound> buf =
  1.1284 +                new ListBuffer<Attribute.Compound>();
  1.1285 +            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
  1.1286 +                buf.append(deproxyCompound(l.head));
  1.1287 +            }
  1.1288 +            return buf.toList();
  1.1289 +        }
  1.1290 +
  1.1291 +        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
  1.1292 +            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf =
  1.1293 +                new ListBuffer<Pair<Symbol.MethodSymbol,Attribute>>();
  1.1294 +            for (List<Pair<Name,Attribute>> l = a.values;
  1.1295 +                 l.nonEmpty();
  1.1296 +                 l = l.tail) {
  1.1297 +                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
  1.1298 +                buf.append(new Pair<Symbol.MethodSymbol,Attribute>
  1.1299 +                           (meth, deproxy(meth.type.getReturnType(), l.head.snd)));
  1.1300 +            }
  1.1301 +            return new Attribute.Compound(a.type, buf.toList());
  1.1302 +        }
  1.1303 +
  1.1304 +        MethodSymbol findAccessMethod(Type container, Name name) {
  1.1305 +            CompletionFailure failure = null;
  1.1306 +            try {
  1.1307 +                for (Scope.Entry e = container.tsym.members().lookup(name);
  1.1308 +                     e.scope != null;
  1.1309 +                     e = e.next()) {
  1.1310 +                    Symbol sym = e.sym;
  1.1311 +                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
  1.1312 +                        return (MethodSymbol) sym;
  1.1313 +                }
  1.1314 +            } catch (CompletionFailure ex) {
  1.1315 +                failure = ex;
  1.1316 +            }
  1.1317 +            // The method wasn't found: emit a warning and recover
  1.1318 +            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
  1.1319 +            try {
  1.1320 +                if (failure == null) {
  1.1321 +                    log.warning("annotation.method.not.found",
  1.1322 +                                container,
  1.1323 +                                name);
  1.1324 +                } else {
  1.1325 +                    log.warning("annotation.method.not.found.reason",
  1.1326 +                                container,
  1.1327 +                                name,
  1.1328 +                                failure.getMessage());
  1.1329 +                }
  1.1330 +            } finally {
  1.1331 +                log.useSource(prevSource);
  1.1332 +            }
  1.1333 +            // Construct a new method type and symbol.  Use bottom
  1.1334 +            // type (typeof null) as return type because this type is
  1.1335 +            // a subtype of all reference types and can be converted
  1.1336 +            // to primitive types by unboxing.
  1.1337 +            MethodType mt = new MethodType(List.<Type>nil(),
  1.1338 +                                           syms.botType,
  1.1339 +                                           List.<Type>nil(),
  1.1340 +                                           syms.methodClass);
  1.1341 +            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
  1.1342 +        }
  1.1343 +
  1.1344 +        Attribute result;
  1.1345 +        Type type;
  1.1346 +        Attribute deproxy(Type t, Attribute a) {
  1.1347 +            Type oldType = type;
  1.1348 +            try {
  1.1349 +                type = t;
  1.1350 +                a.accept(this);
  1.1351 +                return result;
  1.1352 +            } finally {
  1.1353 +                type = oldType;
  1.1354 +            }
  1.1355 +        }
  1.1356 +
  1.1357 +        // implement Attribute.Visitor below
  1.1358 +
  1.1359 +        public void visitConstant(Attribute.Constant value) {
  1.1360 +            // assert value.type == type;
  1.1361 +            result = value;
  1.1362 +        }
  1.1363 +
  1.1364 +        public void visitClass(Attribute.Class clazz) {
  1.1365 +            result = clazz;
  1.1366 +        }
  1.1367 +
  1.1368 +        public void visitEnum(Attribute.Enum e) {
  1.1369 +            throw new AssertionError(); // shouldn't happen
  1.1370 +        }
  1.1371 +
  1.1372 +        public void visitCompound(Attribute.Compound compound) {
  1.1373 +            throw new AssertionError(); // shouldn't happen
  1.1374 +        }
  1.1375 +
  1.1376 +        public void visitArray(Attribute.Array array) {
  1.1377 +            throw new AssertionError(); // shouldn't happen
  1.1378 +        }
  1.1379 +
  1.1380 +        public void visitError(Attribute.Error e) {
  1.1381 +            throw new AssertionError(); // shouldn't happen
  1.1382 +        }
  1.1383 +
  1.1384 +        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
  1.1385 +            // type.tsym.flatName() should == proxy.enumFlatName
  1.1386 +            TypeSymbol enumTypeSym = proxy.enumType.tsym;
  1.1387 +            VarSymbol enumerator = null;
  1.1388 +            for (Scope.Entry e = enumTypeSym.members().lookup(proxy.enumerator);
  1.1389 +                 e.scope != null;
  1.1390 +                 e = e.next()) {
  1.1391 +                if (e.sym.kind == VAR) {
  1.1392 +                    enumerator = (VarSymbol)e.sym;
  1.1393 +                    break;
  1.1394 +                }
  1.1395 +            }
  1.1396 +            if (enumerator == null) {
  1.1397 +                log.error("unknown.enum.constant",
  1.1398 +                          currentClassFile, enumTypeSym, proxy.enumerator);
  1.1399 +                result = new Attribute.Error(enumTypeSym.type);
  1.1400 +            } else {
  1.1401 +                result = new Attribute.Enum(enumTypeSym.type, enumerator);
  1.1402 +            }
  1.1403 +        }
  1.1404 +
  1.1405 +        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
  1.1406 +            int length = proxy.values.length();
  1.1407 +            Attribute[] ats = new Attribute[length];
  1.1408 +            Type elemtype = types.elemtype(type);
  1.1409 +            int i = 0;
  1.1410 +            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
  1.1411 +                ats[i++] = deproxy(elemtype, p.head);
  1.1412 +            }
  1.1413 +            result = new Attribute.Array(type, ats);
  1.1414 +        }
  1.1415 +
  1.1416 +        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
  1.1417 +            result = deproxyCompound(proxy);
  1.1418 +        }
  1.1419 +    }
  1.1420 +
  1.1421 +    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Annotator {
  1.1422 +        final MethodSymbol sym;
  1.1423 +        final Attribute value;
  1.1424 +        final JavaFileObject classFile = currentClassFile;
  1.1425 +        public String toString() {
  1.1426 +            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
  1.1427 +        }
  1.1428 +        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
  1.1429 +            this.sym = sym;
  1.1430 +            this.value = value;
  1.1431 +        }
  1.1432 +        // implement Annotate.Annotator.enterAnnotation()
  1.1433 +        public void enterAnnotation() {
  1.1434 +            JavaFileObject previousClassFile = currentClassFile;
  1.1435 +            try {
  1.1436 +                currentClassFile = classFile;
  1.1437 +                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
  1.1438 +            } finally {
  1.1439 +                currentClassFile = previousClassFile;
  1.1440 +            }
  1.1441 +        }
  1.1442 +    }
  1.1443 +
  1.1444 +    class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Annotator {
  1.1445 +        final Symbol sym;
  1.1446 +        final List<CompoundAnnotationProxy> l;
  1.1447 +        final JavaFileObject classFile;
  1.1448 +        public String toString() {
  1.1449 +            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
  1.1450 +        }
  1.1451 +        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
  1.1452 +            this.sym = sym;
  1.1453 +            this.l = l;
  1.1454 +            this.classFile = currentClassFile;
  1.1455 +        }
  1.1456 +        // implement Annotate.Annotator.enterAnnotation()
  1.1457 +        public void enterAnnotation() {
  1.1458 +            JavaFileObject previousClassFile = currentClassFile;
  1.1459 +            try {
  1.1460 +                currentClassFile = classFile;
  1.1461 +                List<Attribute.Compound> newList = deproxyCompoundList(l);
  1.1462 +                sym.attributes_field = ((sym.attributes_field == null)
  1.1463 +                                        ? newList
  1.1464 +                                        : newList.prependList(sym.attributes_field));
  1.1465 +            } finally {
  1.1466 +                currentClassFile = previousClassFile;
  1.1467 +            }
  1.1468 +        }
  1.1469 +    }
  1.1470 +
  1.1471 +
  1.1472 +/************************************************************************
  1.1473 + * Reading Symbols
  1.1474 + ***********************************************************************/
  1.1475 +
  1.1476 +    /** Read a field.
  1.1477 +     */
  1.1478 +    VarSymbol readField() {
  1.1479 +        long flags = adjustFieldFlags(nextChar());
  1.1480 +        Name name = readName(nextChar());
  1.1481 +        Type type = readType(nextChar());
  1.1482 +        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
  1.1483 +        readMemberAttrs(v);
  1.1484 +        return v;
  1.1485 +    }
  1.1486 +
  1.1487 +    /** Read a method.
  1.1488 +     */
  1.1489 +    MethodSymbol readMethod() {
  1.1490 +        long flags = adjustMethodFlags(nextChar());
  1.1491 +        Name name = readName(nextChar());
  1.1492 +        Type type = readType(nextChar());
  1.1493 +        if (name == names.init && currentOwner.hasOuterInstance()) {
  1.1494 +            // Sometimes anonymous classes don't have an outer
  1.1495 +            // instance, however, there is no reliable way to tell so
  1.1496 +            // we never strip this$n
  1.1497 +            if (currentOwner.name.len != 0)
  1.1498 +                type = new MethodType(type.getParameterTypes().tail,
  1.1499 +                                      type.getReturnType(),
  1.1500 +                                      type.getThrownTypes(),
  1.1501 +                                      syms.methodClass);
  1.1502 +        }
  1.1503 +        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
  1.1504 +        Symbol prevOwner = currentOwner;
  1.1505 +        currentOwner = m;
  1.1506 +        try {
  1.1507 +            readMemberAttrs(m);
  1.1508 +        } finally {
  1.1509 +            currentOwner = prevOwner;
  1.1510 +        }
  1.1511 +        return m;
  1.1512 +    }
  1.1513 +
  1.1514 +    /** Skip a field or method
  1.1515 +     */
  1.1516 +    void skipMember() {
  1.1517 +        bp = bp + 6;
  1.1518 +        char ac = nextChar();
  1.1519 +        for (int i = 0; i < ac; i++) {
  1.1520 +            bp = bp + 2;
  1.1521 +            int attrLen = nextInt();
  1.1522 +            bp = bp + attrLen;
  1.1523 +        }
  1.1524 +    }
  1.1525 +
  1.1526 +    /** Enter type variables of this classtype and all enclosing ones in
  1.1527 +     *  `typevars'.
  1.1528 +     */
  1.1529 +    protected void enterTypevars(Type t) {
  1.1530 +        if (t.getEnclosingType() != null && t.getEnclosingType().tag == CLASS)
  1.1531 +            enterTypevars(t.getEnclosingType());
  1.1532 +        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
  1.1533 +            typevars.enter(xs.head.tsym);
  1.1534 +    }
  1.1535 +
  1.1536 +    protected void enterTypevars(Symbol sym) {
  1.1537 +        if (sym.owner.kind == MTH) {
  1.1538 +            enterTypevars(sym.owner);
  1.1539 +            enterTypevars(sym.owner.owner);
  1.1540 +        }
  1.1541 +        enterTypevars(sym.type);
  1.1542 +    }
  1.1543 +
  1.1544 +    /** Read contents of a given class symbol `c'. Both external and internal
  1.1545 +     *  versions of an inner class are read.
  1.1546 +     */
  1.1547 +    void readClass(ClassSymbol c) {
  1.1548 +        ClassType ct = (ClassType)c.type;
  1.1549 +
  1.1550 +        // allocate scope for members
  1.1551 +        c.members_field = new Scope(c);
  1.1552 +
  1.1553 +        // prepare type variable table
  1.1554 +        typevars = typevars.dup(currentOwner);
  1.1555 +        if (ct.getEnclosingType().tag == CLASS) enterTypevars(ct.getEnclosingType());
  1.1556 +
  1.1557 +        // read flags, or skip if this is an inner class
  1.1558 +        long flags = adjustClassFlags(nextChar());
  1.1559 +        if (c.owner.kind == PCK) c.flags_field = flags;
  1.1560 +
  1.1561 +        // read own class name and check that it matches
  1.1562 +        ClassSymbol self = readClassSymbol(nextChar());
  1.1563 +        if (c != self)
  1.1564 +            throw badClassFile("class.file.wrong.class",
  1.1565 +                               self.flatname);
  1.1566 +
  1.1567 +        // class attributes must be read before class
  1.1568 +        // skip ahead to read class attributes
  1.1569 +        int startbp = bp;
  1.1570 +        nextChar();
  1.1571 +        char interfaceCount = nextChar();
  1.1572 +        bp += interfaceCount * 2;
  1.1573 +        char fieldCount = nextChar();
  1.1574 +        for (int i = 0; i < fieldCount; i++) skipMember();
  1.1575 +        char methodCount = nextChar();
  1.1576 +        for (int i = 0; i < methodCount; i++) skipMember();
  1.1577 +        readClassAttrs(c);
  1.1578 +
  1.1579 +        if (readAllOfClassFile) {
  1.1580 +            for (int i = 1; i < poolObj.length; i++) readPool(i);
  1.1581 +            c.pool = new Pool(poolObj.length, poolObj);
  1.1582 +        }
  1.1583 +
  1.1584 +        // reset and read rest of classinfo
  1.1585 +        bp = startbp;
  1.1586 +        int n = nextChar();
  1.1587 +        if (ct.supertype_field == null)
  1.1588 +            ct.supertype_field = (n == 0)
  1.1589 +                ? Type.noType
  1.1590 +                : readClassSymbol(n).erasure(types);
  1.1591 +        n = nextChar();
  1.1592 +        List<Type> is = List.nil();
  1.1593 +        for (int i = 0; i < n; i++) {
  1.1594 +            Type _inter = readClassSymbol(nextChar()).erasure(types);
  1.1595 +            is = is.prepend(_inter);
  1.1596 +        }
  1.1597 +        if (ct.interfaces_field == null)
  1.1598 +            ct.interfaces_field = is.reverse();
  1.1599 +
  1.1600 +        if (fieldCount != nextChar()) assert false;
  1.1601 +        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
  1.1602 +        if (methodCount != nextChar()) assert false;
  1.1603 +        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
  1.1604 +
  1.1605 +        typevars = typevars.leave();
  1.1606 +    }
  1.1607 +
  1.1608 +    /** Read inner class info. For each inner/outer pair allocate a
  1.1609 +     *  member class.
  1.1610 +     */
  1.1611 +    void readInnerClasses(ClassSymbol c) {
  1.1612 +        int n = nextChar();
  1.1613 +        for (int i = 0; i < n; i++) {
  1.1614 +            nextChar(); // skip inner class symbol
  1.1615 +            ClassSymbol outer = readClassSymbol(nextChar());
  1.1616 +            Name name = readName(nextChar());
  1.1617 +            if (name == null) name = names.empty;
  1.1618 +            long flags = adjustClassFlags(nextChar());
  1.1619 +            if (outer != null) { // we have a member class
  1.1620 +                if (name == names.empty)
  1.1621 +                    name = names.one;
  1.1622 +                ClassSymbol member = enterClass(name, outer);
  1.1623 +                if ((flags & STATIC) == 0) {
  1.1624 +                    ((ClassType)member.type).setEnclosingType(outer.type);
  1.1625 +                    if (member.erasure_field != null)
  1.1626 +                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
  1.1627 +                }
  1.1628 +                if (c == outer) {
  1.1629 +                    member.flags_field = flags;
  1.1630 +                    enterMember(c, member);
  1.1631 +                }
  1.1632 +            }
  1.1633 +        }
  1.1634 +    }
  1.1635 +
  1.1636 +    /** Read a class file.
  1.1637 +     */
  1.1638 +    private void readClassFile(ClassSymbol c) throws IOException {
  1.1639 +        int magic = nextInt();
  1.1640 +        if (magic != JAVA_MAGIC)
  1.1641 +            throw badClassFile("illegal.start.of.class.file");
  1.1642 +
  1.1643 +        int minorVersion = nextChar();
  1.1644 +        int majorVersion = nextChar();
  1.1645 +        int maxMajor = Target.MAX().majorVersion;
  1.1646 +        int maxMinor = Target.MAX().minorVersion;
  1.1647 +        if (majorVersion > maxMajor ||
  1.1648 +            majorVersion * 1000 + minorVersion <
  1.1649 +            Target.MIN().majorVersion * 1000 + Target.MIN().minorVersion)
  1.1650 +        {
  1.1651 +            if (majorVersion == (maxMajor + 1))
  1.1652 +                log.warning("big.major.version",
  1.1653 +                            currentClassFile,
  1.1654 +                            majorVersion,
  1.1655 +                            maxMajor);
  1.1656 +            else
  1.1657 +                throw badClassFile("wrong.version",
  1.1658 +                                   Integer.toString(majorVersion),
  1.1659 +                                   Integer.toString(minorVersion),
  1.1660 +                                   Integer.toString(maxMajor),
  1.1661 +                                   Integer.toString(maxMinor));
  1.1662 +        }
  1.1663 +        else if (checkClassFile &&
  1.1664 +                 majorVersion == maxMajor &&
  1.1665 +                 minorVersion > maxMinor)
  1.1666 +        {
  1.1667 +            printCCF("found.later.version",
  1.1668 +                     Integer.toString(minorVersion));
  1.1669 +        }
  1.1670 +        indexPool();
  1.1671 +        if (signatureBuffer.length < bp) {
  1.1672 +            int ns = Integer.highestOneBit(bp) << 1;
  1.1673 +            signatureBuffer = new byte[ns];
  1.1674 +        }
  1.1675 +        readClass(c);
  1.1676 +    }
  1.1677 +
  1.1678 +/************************************************************************
  1.1679 + * Adjusting flags
  1.1680 + ***********************************************************************/
  1.1681 +
  1.1682 +    long adjustFieldFlags(long flags) {
  1.1683 +        return flags;
  1.1684 +    }
  1.1685 +    long adjustMethodFlags(long flags) {
  1.1686 +        if ((flags & ACC_BRIDGE) != 0) {
  1.1687 +            flags &= ~ACC_BRIDGE;
  1.1688 +            flags |= BRIDGE;
  1.1689 +            if (!allowGenerics)
  1.1690 +                flags &= ~SYNTHETIC;
  1.1691 +        }
  1.1692 +        if ((flags & ACC_VARARGS) != 0) {
  1.1693 +            flags &= ~ACC_VARARGS;
  1.1694 +            flags |= VARARGS;
  1.1695 +        }
  1.1696 +        return flags;
  1.1697 +    }
  1.1698 +    long adjustClassFlags(long flags) {
  1.1699 +        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
  1.1700 +    }
  1.1701 +
  1.1702 +/************************************************************************
  1.1703 + * Loading Classes
  1.1704 + ***********************************************************************/
  1.1705 +
  1.1706 +    /** Define a new class given its name and owner.
  1.1707 +     */
  1.1708 +    public ClassSymbol defineClass(Name name, Symbol owner) {
  1.1709 +        ClassSymbol c = new ClassSymbol(0, name, owner);
  1.1710 +        if (owner.kind == PCK)
  1.1711 +            assert classes.get(c.flatname) == null : c;
  1.1712 +        c.completer = this;
  1.1713 +        return c;
  1.1714 +    }
  1.1715 +
  1.1716 +    /** Create a new toplevel or member class symbol with given name
  1.1717 +     *  and owner and enter in `classes' unless already there.
  1.1718 +     */
  1.1719 +    public ClassSymbol enterClass(Name name, TypeSymbol owner) {
  1.1720 +        Name flatname = TypeSymbol.formFlatName(name, owner);
  1.1721 +        ClassSymbol c = classes.get(flatname);
  1.1722 +        if (c == null) {
  1.1723 +            c = defineClass(name, owner);
  1.1724 +            classes.put(flatname, c);
  1.1725 +        } else if ((c.name != name || c.owner != owner) && owner.kind == TYP && c.owner.kind == PCK) {
  1.1726 +            // reassign fields of classes that might have been loaded with
  1.1727 +            // their flat names.
  1.1728 +            c.owner.members().remove(c);
  1.1729 +            c.name = name;
  1.1730 +            c.owner = owner;
  1.1731 +            c.fullname = ClassSymbol.formFullName(name, owner);
  1.1732 +        }
  1.1733 +        return c;
  1.1734 +    }
  1.1735 +
  1.1736 +    /**
  1.1737 +     * Creates a new toplevel class symbol with given flat name and
  1.1738 +     * given class (or source) file.
  1.1739 +     *
  1.1740 +     * @param flatName a fully qualified binary class name
  1.1741 +     * @param classFile the class file or compilation unit defining
  1.1742 +     * the class (may be {@code null})
  1.1743 +     * @return a newly created class symbol
  1.1744 +     * @throws AssertionError if the class symbol already exists
  1.1745 +     */
  1.1746 +    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
  1.1747 +        ClassSymbol cs = classes.get(flatName);
  1.1748 +        if (cs != null) {
  1.1749 +            String msg = Log.format("%s: completer = %s; class file = %s; source file = %s",
  1.1750 +                                    cs.fullname,
  1.1751 +                                    cs.completer,
  1.1752 +                                    cs.classfile,
  1.1753 +                                    cs.sourcefile);
  1.1754 +            throw new AssertionError(msg);
  1.1755 +        }
  1.1756 +        Name packageName = Convert.packagePart(flatName);
  1.1757 +        PackageSymbol owner = packageName.isEmpty()
  1.1758 +                                ? syms.unnamedPackage
  1.1759 +                                : enterPackage(packageName);
  1.1760 +        cs = defineClass(Convert.shortName(flatName), owner);
  1.1761 +        cs.classfile = classFile;
  1.1762 +        classes.put(flatName, cs);
  1.1763 +        return cs;
  1.1764 +    }
  1.1765 +
  1.1766 +    /** Create a new member or toplevel class symbol with given flat name
  1.1767 +     *  and enter in `classes' unless already there.
  1.1768 +     */
  1.1769 +    public ClassSymbol enterClass(Name flatname) {
  1.1770 +        ClassSymbol c = classes.get(flatname);
  1.1771 +        if (c == null)
  1.1772 +            return enterClass(flatname, (JavaFileObject)null);
  1.1773 +        else
  1.1774 +            return c;
  1.1775 +    }
  1.1776 +
  1.1777 +    private boolean suppressFlush = false;
  1.1778 +
  1.1779 +    /** Completion for classes to be loaded. Before a class is loaded
  1.1780 +     *  we make sure its enclosing class (if any) is loaded.
  1.1781 +     */
  1.1782 +    public void complete(Symbol sym) throws CompletionFailure {
  1.1783 +        if (sym.kind == TYP) {
  1.1784 +            ClassSymbol c = (ClassSymbol)sym;
  1.1785 +            c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
  1.1786 +            boolean suppressFlush = this.suppressFlush;
  1.1787 +            this.suppressFlush = true;
  1.1788 +            try {
  1.1789 +                completeOwners(c.owner);
  1.1790 +                completeEnclosing(c);
  1.1791 +            } finally {
  1.1792 +                this.suppressFlush = suppressFlush;
  1.1793 +            }
  1.1794 +            fillIn(c);
  1.1795 +        } else if (sym.kind == PCK) {
  1.1796 +            PackageSymbol p = (PackageSymbol)sym;
  1.1797 +            try {
  1.1798 +                fillIn(p);
  1.1799 +            } catch (IOException ex) {
  1.1800 +                throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
  1.1801 +            }
  1.1802 +        }
  1.1803 +        if (!filling && !suppressFlush)
  1.1804 +            annotate.flush(); // finish attaching annotations
  1.1805 +    }
  1.1806 +
  1.1807 +    /** complete up through the enclosing package. */
  1.1808 +    private void completeOwners(Symbol o) {
  1.1809 +        if (o.kind != PCK) completeOwners(o.owner);
  1.1810 +        o.complete();
  1.1811 +    }
  1.1812 +
  1.1813 +    /**
  1.1814 +     * Tries to complete lexically enclosing classes if c looks like a
  1.1815 +     * nested class.  This is similar to completeOwners but handles
  1.1816 +     * the situation when a nested class is accessed directly as it is
  1.1817 +     * possible with the Tree API or javax.lang.model.*.
  1.1818 +     */
  1.1819 +    private void completeEnclosing(ClassSymbol c) {
  1.1820 +        if (c.owner.kind == PCK) {
  1.1821 +            Symbol owner = c.owner;
  1.1822 +            for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
  1.1823 +                Symbol encl = owner.members().lookup(name).sym;
  1.1824 +                if (encl == null)
  1.1825 +                    encl = classes.get(TypeSymbol.formFlatName(name, owner));
  1.1826 +                if (encl != null)
  1.1827 +                    encl.complete();
  1.1828 +            }
  1.1829 +        }
  1.1830 +    }
  1.1831 +
  1.1832 +    /** We can only read a single class file at a time; this
  1.1833 +     *  flag keeps track of when we are currently reading a class
  1.1834 +     *  file.
  1.1835 +     */
  1.1836 +    private boolean filling = false;
  1.1837 +
  1.1838 +    /** Fill in definition of class `c' from corresponding class or
  1.1839 +     *  source file.
  1.1840 +     */
  1.1841 +    private void fillIn(ClassSymbol c) {
  1.1842 +        if (completionFailureName == c.fullname) {
  1.1843 +            throw new CompletionFailure(c, "user-selected completion failure by class name");
  1.1844 +        }
  1.1845 +        currentOwner = c;
  1.1846 +        JavaFileObject classfile = c.classfile;
  1.1847 +        if (classfile != null) {
  1.1848 +            JavaFileObject previousClassFile = currentClassFile;
  1.1849 +            try {
  1.1850 +                assert !filling :
  1.1851 +                    "Filling " + classfile.toUri() +
  1.1852 +                    " during " + previousClassFile;
  1.1853 +                currentClassFile = classfile;
  1.1854 +                if (verbose) {
  1.1855 +                    printVerbose("loading", currentClassFile.toString());
  1.1856 +                }
  1.1857 +                if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
  1.1858 +                    filling = true;
  1.1859 +                    try {
  1.1860 +                        bp = 0;
  1.1861 +                        buf = readInputStream(buf, classfile.openInputStream());
  1.1862 +                        readClassFile(c);
  1.1863 +                        if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
  1.1864 +                            List<Type> missing = missingTypeVariables;
  1.1865 +                            List<Type> found = foundTypeVariables;
  1.1866 +                            missingTypeVariables = List.nil();
  1.1867 +                            foundTypeVariables = List.nil();
  1.1868 +                            filling = false;
  1.1869 +                            ClassType ct = (ClassType)currentOwner.type;
  1.1870 +                            ct.supertype_field =
  1.1871 +                                types.subst(ct.supertype_field, missing, found);
  1.1872 +                            ct.interfaces_field =
  1.1873 +                                types.subst(ct.interfaces_field, missing, found);
  1.1874 +                        } else if (missingTypeVariables.isEmpty() !=
  1.1875 +                                   foundTypeVariables.isEmpty()) {
  1.1876 +                            Name name = missingTypeVariables.head.tsym.name;
  1.1877 +                            throw badClassFile("undecl.type.var", name);
  1.1878 +                        }
  1.1879 +                    } finally {
  1.1880 +                        missingTypeVariables = List.nil();
  1.1881 +                        foundTypeVariables = List.nil();
  1.1882 +                        filling = false;
  1.1883 +                    }
  1.1884 +                } else {
  1.1885 +                    if (sourceCompleter != null) {
  1.1886 +                        sourceCompleter.complete(c);
  1.1887 +                    } else {
  1.1888 +                        throw new IllegalStateException("Source completer required to read "
  1.1889 +                                                        + classfile.toUri());
  1.1890 +                    }
  1.1891 +                }
  1.1892 +                return;
  1.1893 +            } catch (IOException ex) {
  1.1894 +                throw badClassFile("unable.to.access.file", ex.getMessage());
  1.1895 +            } finally {
  1.1896 +                currentClassFile = previousClassFile;
  1.1897 +            }
  1.1898 +        } else {
  1.1899 +            throw
  1.1900 +                newCompletionFailure(c,
  1.1901 +                                     Log.getLocalizedString("class.file.not.found",
  1.1902 +                                                            c.flatname));
  1.1903 +        }
  1.1904 +    }
  1.1905 +    // where
  1.1906 +        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
  1.1907 +            try {
  1.1908 +                buf = ensureCapacity(buf, s.available());
  1.1909 +                int r = s.read(buf);
  1.1910 +                int bp = 0;
  1.1911 +                while (r != -1) {
  1.1912 +                    bp += r;
  1.1913 +                    buf = ensureCapacity(buf, bp);
  1.1914 +                    r = s.read(buf, bp, buf.length - bp);
  1.1915 +                }
  1.1916 +                return buf;
  1.1917 +            } finally {
  1.1918 +                try {
  1.1919 +                    s.close();
  1.1920 +                } catch (IOException e) {
  1.1921 +                    /* Ignore any errors, as this stream may have already
  1.1922 +                     * thrown a related exception which is the one that
  1.1923 +                     * should be reported.
  1.1924 +                     */
  1.1925 +                }
  1.1926 +            }
  1.1927 +        }
  1.1928 +        private static byte[] ensureCapacity(byte[] buf, int needed) {
  1.1929 +            if (buf.length < needed) {
  1.1930 +                byte[] old = buf;
  1.1931 +                buf = new byte[Integer.highestOneBit(needed) << 1];
  1.1932 +                System.arraycopy(old, 0, buf, 0, old.length);
  1.1933 +            }
  1.1934 +            return buf;
  1.1935 +        }
  1.1936 +        /** Static factory for CompletionFailure objects.
  1.1937 +         *  In practice, only one can be used at a time, so we share one
  1.1938 +         *  to reduce the expense of allocating new exception objects.
  1.1939 +         */
  1.1940 +        private CompletionFailure newCompletionFailure(ClassSymbol c,
  1.1941 +                                                       String localized) {
  1.1942 +            if (!cacheCompletionFailure) {
  1.1943 +                // log.warning("proc.messager",
  1.1944 +                //             Log.getLocalizedString("class.file.not.found", c.flatname));
  1.1945 +                // c.debug.printStackTrace();
  1.1946 +                return new CompletionFailure(c, localized);
  1.1947 +            } else {
  1.1948 +                CompletionFailure result = cachedCompletionFailure;
  1.1949 +                result.sym = c;
  1.1950 +                result.errmsg = localized;
  1.1951 +                return result;
  1.1952 +            }
  1.1953 +        }
  1.1954 +        private CompletionFailure cachedCompletionFailure =
  1.1955 +            new CompletionFailure(null, null);
  1.1956 +        {
  1.1957 +            cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
  1.1958 +        }
  1.1959 +
  1.1960 +    /** Load a toplevel class with given fully qualified name
  1.1961 +     *  The class is entered into `classes' only if load was successful.
  1.1962 +     */
  1.1963 +    public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
  1.1964 +        boolean absent = classes.get(flatname) == null;
  1.1965 +        ClassSymbol c = enterClass(flatname);
  1.1966 +        if (c.members_field == null && c.completer != null) {
  1.1967 +            try {
  1.1968 +                c.complete();
  1.1969 +            } catch (CompletionFailure ex) {
  1.1970 +                if (absent) classes.remove(flatname);
  1.1971 +                throw ex;
  1.1972 +            }
  1.1973 +        }
  1.1974 +        return c;
  1.1975 +    }
  1.1976 +
  1.1977 +/************************************************************************
  1.1978 + * Loading Packages
  1.1979 + ***********************************************************************/
  1.1980 +
  1.1981 +    /** Check to see if a package exists, given its fully qualified name.
  1.1982 +     */
  1.1983 +    public boolean packageExists(Name fullname) {
  1.1984 +        return enterPackage(fullname).exists();
  1.1985 +    }
  1.1986 +
  1.1987 +    /** Make a package, given its fully qualified name.
  1.1988 +     */
  1.1989 +    public PackageSymbol enterPackage(Name fullname) {
  1.1990 +        PackageSymbol p = packages.get(fullname);
  1.1991 +        if (p == null) {
  1.1992 +            assert !fullname.isEmpty() : "rootPackage missing!";
  1.1993 +            p = new PackageSymbol(
  1.1994 +                Convert.shortName(fullname),
  1.1995 +                enterPackage(Convert.packagePart(fullname)));
  1.1996 +            p.completer = this;
  1.1997 +            packages.put(fullname, p);
  1.1998 +        }
  1.1999 +        return p;
  1.2000 +    }
  1.2001 +
  1.2002 +    /** Make a package, given its unqualified name and enclosing package.
  1.2003 +     */
  1.2004 +    public PackageSymbol enterPackage(Name name, PackageSymbol owner) {
  1.2005 +        return enterPackage(TypeSymbol.formFullName(name, owner));
  1.2006 +    }
  1.2007 +
  1.2008 +    /** Include class corresponding to given class file in package,
  1.2009 +     *  unless (1) we already have one the same kind (.class or .java), or
  1.2010 +     *         (2) we have one of the other kind, and the given class file
  1.2011 +     *             is older.
  1.2012 +     */
  1.2013 +    protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
  1.2014 +        if ((p.flags_field & EXISTS) == 0)
  1.2015 +            for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
  1.2016 +                q.flags_field |= EXISTS;
  1.2017 +        JavaFileObject.Kind kind = file.getKind();
  1.2018 +        int seen;
  1.2019 +        if (kind == JavaFileObject.Kind.CLASS)
  1.2020 +            seen = CLASS_SEEN;
  1.2021 +        else
  1.2022 +            seen = SOURCE_SEEN;
  1.2023 +        String binaryName = fileManager.inferBinaryName(currentLoc, file);
  1.2024 +        int lastDot = binaryName.lastIndexOf(".");
  1.2025 +        Name classname = names.fromString(binaryName.substring(lastDot + 1));
  1.2026 +        boolean isPkgInfo = classname == names.package_info;
  1.2027 +        ClassSymbol c = isPkgInfo
  1.2028 +            ? p.package_info
  1.2029 +            : (ClassSymbol) p.members_field.lookup(classname).sym;
  1.2030 +        if (c == null) {
  1.2031 +            c = enterClass(classname, p);
  1.2032 +            if (c.classfile == null) // only update the file if's it's newly created
  1.2033 +                c.classfile = file;
  1.2034 +            if (isPkgInfo) {
  1.2035 +                p.package_info = c;
  1.2036 +            } else {
  1.2037 +                if (c.owner == p)  // it might be an inner class
  1.2038 +                    p.members_field.enter(c);
  1.2039 +            }
  1.2040 +        } else if (c.classfile != null && (c.flags_field & seen) == 0) {
  1.2041 +            // if c.classfile == null, we are currently compiling this class
  1.2042 +            // and no further action is necessary.
  1.2043 +            // if (c.flags_field & seen) != 0, we have already encountered
  1.2044 +            // a file of the same kind; again no further action is necessary.
  1.2045 +            if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
  1.2046 +                c.classfile = preferredFileObject(file, c.classfile);
  1.2047 +        }
  1.2048 +        c.flags_field |= seen;
  1.2049 +    }
  1.2050 +
  1.2051 +    /** Implement policy to choose to derive information from a source
  1.2052 +     *  file or a class file when both are present.  May be overridden
  1.2053 +     *  by subclasses.
  1.2054 +     */
  1.2055 +    protected JavaFileObject preferredFileObject(JavaFileObject a,
  1.2056 +                                           JavaFileObject b) {
  1.2057 +
  1.2058 +        if (preferSource)
  1.2059 +            return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
  1.2060 +        else {
  1.2061 +            long adate = a.getLastModified();
  1.2062 +            long bdate = b.getLastModified();
  1.2063 +            // 6449326: policy for bad lastModifiedTime in ClassReader
  1.2064 +            //assert adate >= 0 && bdate >= 0;
  1.2065 +            return (adate > bdate) ? a : b;
  1.2066 +        }
  1.2067 +    }
  1.2068 +
  1.2069 +    /**
  1.2070 +     * specifies types of files to be read when filling in a package symbol
  1.2071 +     */
  1.2072 +    protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
  1.2073 +        return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
  1.2074 +    }
  1.2075 +
  1.2076 +    /**
  1.2077 +     * this is used to support javadoc
  1.2078 +     */
  1.2079 +    protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) {
  1.2080 +    }
  1.2081 +
  1.2082 +    protected Location currentLoc; // FIXME
  1.2083 +
  1.2084 +    private boolean verbosePath = true;
  1.2085 +
  1.2086 +    /** Load directory of package into members scope.
  1.2087 +     */
  1.2088 +    private void fillIn(PackageSymbol p) throws IOException {
  1.2089 +        if (p.members_field == null) p.members_field = new Scope(p);
  1.2090 +        String packageName = p.fullname.toString();
  1.2091 +
  1.2092 +        Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
  1.2093 +
  1.2094 +        fillIn(p, PLATFORM_CLASS_PATH,
  1.2095 +               fileManager.list(PLATFORM_CLASS_PATH,
  1.2096 +                                packageName,
  1.2097 +                                EnumSet.of(JavaFileObject.Kind.CLASS),
  1.2098 +                                false));
  1.2099 +
  1.2100 +        Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
  1.2101 +        classKinds.remove(JavaFileObject.Kind.SOURCE);
  1.2102 +        boolean wantClassFiles = !classKinds.isEmpty();
  1.2103 +
  1.2104 +        Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
  1.2105 +        sourceKinds.remove(JavaFileObject.Kind.CLASS);
  1.2106 +        boolean wantSourceFiles = !sourceKinds.isEmpty();
  1.2107 +
  1.2108 +        boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
  1.2109 +
  1.2110 +        if (verbose && verbosePath) {
  1.2111 +            if (fileManager instanceof StandardJavaFileManager) {
  1.2112 +                StandardJavaFileManager fm = (StandardJavaFileManager)fileManager;
  1.2113 +                if (haveSourcePath && wantSourceFiles) {
  1.2114 +                    List<File> path = List.nil();
  1.2115 +                    for (File file : fm.getLocation(SOURCE_PATH)) {
  1.2116 +                        path = path.prepend(file);
  1.2117 +                    }
  1.2118 +                    printVerbose("sourcepath", path.reverse().toString());
  1.2119 +                } else if (wantSourceFiles) {
  1.2120 +                    List<File> path = List.nil();
  1.2121 +                    for (File file : fm.getLocation(CLASS_PATH)) {
  1.2122 +                        path = path.prepend(file);
  1.2123 +                    }
  1.2124 +                    printVerbose("sourcepath", path.reverse().toString());
  1.2125 +                }
  1.2126 +                if (wantClassFiles) {
  1.2127 +                    List<File> path = List.nil();
  1.2128 +                    for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) {
  1.2129 +                        path = path.prepend(file);
  1.2130 +                    }
  1.2131 +                    for (File file : fm.getLocation(CLASS_PATH)) {
  1.2132 +                        path = path.prepend(file);
  1.2133 +                    }
  1.2134 +                    printVerbose("classpath",  path.reverse().toString());
  1.2135 +                }
  1.2136 +            }
  1.2137 +        }
  1.2138 +
  1.2139 +        if (wantSourceFiles && !haveSourcePath) {
  1.2140 +            fillIn(p, CLASS_PATH,
  1.2141 +                   fileManager.list(CLASS_PATH,
  1.2142 +                                    packageName,
  1.2143 +                                    kinds,
  1.2144 +                                    false));
  1.2145 +        } else {
  1.2146 +            if (wantClassFiles)
  1.2147 +                fillIn(p, CLASS_PATH,
  1.2148 +                       fileManager.list(CLASS_PATH,
  1.2149 +                                        packageName,
  1.2150 +                                        classKinds,
  1.2151 +                                        false));
  1.2152 +            if (wantSourceFiles)
  1.2153 +                fillIn(p, SOURCE_PATH,
  1.2154 +                       fileManager.list(SOURCE_PATH,
  1.2155 +                                        packageName,
  1.2156 +                                        sourceKinds,
  1.2157 +                                        false));
  1.2158 +        }
  1.2159 +        verbosePath = false;
  1.2160 +    }
  1.2161 +    // where
  1.2162 +        private void fillIn(PackageSymbol p,
  1.2163 +                            Location location,
  1.2164 +                            Iterable<JavaFileObject> files)
  1.2165 +        {
  1.2166 +            currentLoc = location;
  1.2167 +            for (JavaFileObject fo : files) {
  1.2168 +                switch (fo.getKind()) {
  1.2169 +                case CLASS:
  1.2170 +                case SOURCE: {
  1.2171 +                    // TODO pass binaryName to includeClassFile
  1.2172 +                    String binaryName = fileManager.inferBinaryName(currentLoc, fo);
  1.2173 +                    String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
  1.2174 +                    if (SourceVersion.isIdentifier(simpleName) ||
  1.2175 +                        simpleName.equals("package-info"))
  1.2176 +                        includeClassFile(p, fo);
  1.2177 +                    break;
  1.2178 +                }
  1.2179 +                default:
  1.2180 +                    extraFileActions(p, fo);
  1.2181 +                }
  1.2182 +            }
  1.2183 +        }
  1.2184 +
  1.2185 +    /** Output for "-verbose" option.
  1.2186 +     *  @param key The key to look up the correct internationalized string.
  1.2187 +     *  @param arg An argument for substitution into the output string.
  1.2188 +     */
  1.2189 +    private void printVerbose(String key, CharSequence arg) {
  1.2190 +        Log.printLines(log.noticeWriter, Log.getLocalizedString("verbose." + key, arg));
  1.2191 +    }
  1.2192 +
  1.2193 +    /** Output for "-checkclassfile" option.
  1.2194 +     *  @param key The key to look up the correct internationalized string.
  1.2195 +     *  @param arg An argument for substitution into the output string.
  1.2196 +     */
  1.2197 +    private void printCCF(String key, Object arg) {
  1.2198 +        Log.printLines(log.noticeWriter, Log.getLocalizedString(key, arg));
  1.2199 +    }
  1.2200 +
  1.2201 +
  1.2202 +    public interface SourceCompleter {
  1.2203 +        void complete(ClassSymbol sym)
  1.2204 +            throws CompletionFailure;
  1.2205 +    }
  1.2206 +
  1.2207 +    /**
  1.2208 +     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
  1.2209 +     * The attribute is only the last component of the original filename, so is unlikely
  1.2210 +     * to be valid as is, so operations other than those to access the name throw
  1.2211 +     * UnsupportedOperationException
  1.2212 +     */
  1.2213 +    private static class SourceFileObject extends BaseFileObject {
  1.2214 +
  1.2215 +        /** The file's name.
  1.2216 +         */
  1.2217 +        private Name name;
  1.2218 +
  1.2219 +        public SourceFileObject(Name name) {
  1.2220 +            this.name = name;
  1.2221 +        }
  1.2222 +
  1.2223 +        public InputStream openInputStream() {
  1.2224 +            throw new UnsupportedOperationException();
  1.2225 +        }
  1.2226 +
  1.2227 +        public OutputStream openOutputStream() {
  1.2228 +            throw new UnsupportedOperationException();
  1.2229 +        }
  1.2230 +
  1.2231 +        public Reader openReader() {
  1.2232 +            throw new UnsupportedOperationException();
  1.2233 +        }
  1.2234 +
  1.2235 +        public Writer openWriter() {
  1.2236 +            throw new UnsupportedOperationException();
  1.2237 +        }
  1.2238 +
  1.2239 +        /** @deprecated see bug 6410637 */
  1.2240 +        @Deprecated
  1.2241 +        public String getName() {
  1.2242 +            return name.toString();
  1.2243 +        }
  1.2244 +
  1.2245 +        public long getLastModified() {
  1.2246 +            throw new UnsupportedOperationException();
  1.2247 +        }
  1.2248 +
  1.2249 +        public boolean delete() {
  1.2250 +            throw new UnsupportedOperationException();
  1.2251 +        }
  1.2252 +
  1.2253 +        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
  1.2254 +            throw new UnsupportedOperationException();
  1.2255 +        }
  1.2256 +
  1.2257 +        @Override
  1.2258 +        public boolean equals(Object other) {
  1.2259 +            if (!(other instanceof SourceFileObject))
  1.2260 +                return false;
  1.2261 +            SourceFileObject o = (SourceFileObject) other;
  1.2262 +            return name.equals(o.name);
  1.2263 +        }
  1.2264 +
  1.2265 +        @Override
  1.2266 +        public int hashCode() {
  1.2267 +            return name.hashCode();
  1.2268 +        }
  1.2269 +
  1.2270 +        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
  1.2271 +            return true; // fail-safe mode
  1.2272 +        }
  1.2273 +
  1.2274 +        public URI toUri() {
  1.2275 +            return URI.create(name.toString());
  1.2276 +        }
  1.2277 +
  1.2278 +        public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
  1.2279 +            throw new UnsupportedOperationException();
  1.2280 +        }
  1.2281 +
  1.2282 +    }
  1.2283 +}

mercurial