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