langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
changeset 24604 7f68545b5128
parent 24403 f2ce14657001
child 24606 12c0ca21f8dc
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri May 16 10:52:07 2014 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Sun May 18 19:59:10 2014 -0700
@@ -35,13 +35,8 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileManager;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.StandardJavaFileManager;
-
-import static javax.tools.StandardLocation.*;
 
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.code.*;
@@ -120,23 +115,6 @@
     public boolean saveParameterNames;
 
     /**
-     * Switch: cache completion failures unless -XDdev is used
-     */
-    private boolean cacheCompletionFailure;
-
-    /**
-     * Switch: prefer source files instead of newer when both source
-     * and class are available
-     **/
-    public boolean preferSource;
-
-    /**
-     * Switch: Search classpath and sourcepath for classes before the
-     * bootclasspath
-     */
-    public boolean userPathsFirst;
-
-    /**
      * The currently selected profile.
      */
     public final Profile profile;
@@ -153,10 +131,6 @@
     /** The name table. */
     final Names names;
 
-    /** Force a completion failure on this name
-     */
-    final Name completionFailureName;
-
     /** Access to files
      */
     private final JavaFileManager fileManager;
@@ -165,12 +139,6 @@
      */
     JCDiagnostic.Factory diagFactory;
 
-    /** Can be reassigned from outside:
-     *  the completer to be used for ".java" files. If this remains unassigned
-     *  ".java" files will not be loaded.
-     */
-    public SourceCompleter sourceCompleter = null;
-
     /** The current scope where type variables are entered.
      */
     protected Scope typevars;
@@ -227,20 +195,6 @@
      */
     Set<Name> warnedAttrs = new HashSet<>();
 
-    /**
-     * Completer that delegates to the complete-method of this class.
-     */
-    private final Completer thisCompleter = new Completer() {
-        @Override
-        public void complete(Symbol sym) throws CompletionFailure {
-            ClassReader.this.complete(sym);
-        }
-    };
-
-    public Completer getCompleter() {
-        return thisCompleter;
-    }
-
     /** Get the ClassReader instance for this invocation. */
     public static ClassReader instance(Context context) {
         ClassReader instance = context.get(classReaderKey);
@@ -274,17 +228,9 @@
         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
 
         saveParameterNames = options.isSet("save-parameter-names");
-        cacheCompletionFailure = options.isUnset("dev");
-        preferSource = "source".equals(options.get("-Xprefer"));
-        userPathsFirst = options.isSet(XXUSERPATHSFIRST);
 
         profile = Profile.instance(context);
 
-        completionFailureName =
-            options.isSet("failcomplete")
-            ? names.fromString(options.get("failcomplete"))
-            : null;
-
         typevars = new Scope(syms.noSymbol);
 
         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
@@ -305,26 +251,12 @@
  * Error Diagnoses
  ***********************************************************************/
 
-
-    public class BadClassFile extends CompletionFailure {
-        private static final long serialVersionUID = 0;
-
-        public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag) {
-            super(sym, createBadClassFileDiagnostic(file, diag));
-        }
-    }
-    // where
-    private JCDiagnostic createBadClassFileDiagnostic(JavaFileObject file, JCDiagnostic diag) {
-        String key = (file.getKind() == JavaFileObject.Kind.SOURCE
-                    ? "bad.source.file.header" : "bad.class.file.header");
-        return diagFactory.fragment(key, file, diag);
-    }
-
-    public BadClassFile badClassFile(String key, Object... args) {
-        return new BadClassFile (
+    public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
+        return new ClassFinder.BadClassFile (
             currentOwner.enclClass(),
             currentClassFile,
-            diagFactory.fragment(key, args));
+            diagFactory.fragment(key, args),
+            diagFactory);
     }
 
 /************************************************************************
@@ -1501,7 +1433,7 @@
         int tag = nextByte(); // TargetType tag is a byte
 
         if (!TargetType.isValidTargetTypeValue(tag))
-            throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
+            throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
 
         TargetType type = TargetType.fromTargetTypeValue(tag);
 
@@ -2353,9 +2285,9 @@
         }
     }
 
-    /** Read a class file.
+    /** Read a class definition from the bytes in buf.
      */
-    private void readClassFile(ClassSymbol c) throws IOException {
+    private void readClassBuffer(ClassSymbol c) throws IOException {
         int magic = nextInt();
         if (magic != JAVA_MAGIC)
             throw badClassFile("illegal.start.of.class.file");
@@ -2395,162 +2327,39 @@
         readClass(c);
     }
 
-/************************************************************************
- * Adjusting flags
- ***********************************************************************/
-
-    long adjustFieldFlags(long flags) {
-        return flags;
-    }
-    long adjustMethodFlags(long flags) {
-        if ((flags & ACC_BRIDGE) != 0) {
-            flags &= ~ACC_BRIDGE;
-            flags |= BRIDGE;
-            if (!allowGenerics)
-                flags &= ~SYNTHETIC;
-        }
-        if ((flags & ACC_VARARGS) != 0) {
-            flags &= ~ACC_VARARGS;
-            flags |= VARARGS;
-        }
-        return flags;
-    }
-    long adjustClassFlags(long flags) {
-        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
-    }
-
-/************************************************************************
- * Loading Classes
- ***********************************************************************/
-
-    /** Completion for classes to be loaded. Before a class is loaded
-     *  we make sure its enclosing class (if any) is loaded.
-     */
-    private void complete(Symbol sym) throws CompletionFailure {
-        if (sym.kind == TYP) {
-            ClassSymbol c = (ClassSymbol)sym;
-            c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
-            annotate.enterStart();
-            try {
-                completeOwners(c.owner);
-                completeEnclosing(c);
-            } finally {
-                // The flush needs to happen only after annotations
-                // are filled in.
-                annotate.enterDoneWithoutFlush();
-            }
-            fillIn(c);
-        } else if (sym.kind == PCK) {
-            PackageSymbol p = (PackageSymbol)sym;
-            try {
-                fillIn(p);
-            } catch (IOException ex) {
-                throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
+    public void readClassFile(ClassSymbol c) {
+        currentOwner = c;
+        currentClassFile = c.classfile;
+        warnedAttrs.clear();
+        filling = true;
+        try {
+            bp = 0;
+            buf = readInputStream(buf, c.classfile.openInputStream());
+            readClassBuffer(c);
+            if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
+                List<Type> missing = missingTypeVariables;
+                List<Type> found = foundTypeVariables;
+                missingTypeVariables = List.nil();
+                foundTypeVariables = List.nil();
+                filling = false;
+                ClassType ct = (ClassType)currentOwner.type;
+                ct.supertype_field =
+                    types.subst(ct.supertype_field, missing, found);
+                ct.interfaces_field =
+                    types.subst(ct.interfaces_field, missing, found);
+            } else if (missingTypeVariables.isEmpty() !=
+                       foundTypeVariables.isEmpty()) {
+                Name name = missingTypeVariables.head.tsym.name;
+                throw badClassFile("undecl.type.var", name);
             }
-        }
-        if (!filling)
-            annotate.flush(); // finish attaching annotations
-    }
-
-    /** complete up through the enclosing package. */
-    private void completeOwners(Symbol o) {
-        if (o.kind != PCK) completeOwners(o.owner);
-        o.complete();
-    }
-
-    /**
-     * Tries to complete lexically enclosing classes if c looks like a
-     * nested class.  This is similar to completeOwners but handles
-     * the situation when a nested class is accessed directly as it is
-     * possible with the Tree API or javax.lang.model.*.
-     */
-    private void completeEnclosing(ClassSymbol c) {
-        if (c.owner.kind == PCK) {
-            Symbol owner = c.owner;
-            for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
-                Symbol encl = owner.members().lookup(name).sym;
-                if (encl == null)
-                    encl = syms.classes.get(TypeSymbol.formFlatName(name, owner));
-                if (encl != null)
-                    encl.complete();
-            }
-        }
-    }
-
-    /** We can only read a single class file at a time; this
-     *  flag keeps track of when we are currently reading a class
-     *  file.
-     */
-    private boolean filling = false;
-
-    /** Fill in definition of class `c' from corresponding class or
-     *  source file.
-     */
-    private void fillIn(ClassSymbol c) {
-        if (completionFailureName == c.fullname) {
-            throw new CompletionFailure(c, "user-selected completion failure by class name");
-        }
-        currentOwner = c;
-        warnedAttrs.clear();
-        JavaFileObject classfile = c.classfile;
-        if (classfile != null) {
-            JavaFileObject previousClassFile = currentClassFile;
-            try {
-                if (filling) {
-                    Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
-                }
-                currentClassFile = classfile;
-                if (verbose) {
-                    log.printVerbose("loading", currentClassFile.toString());
-                }
-                if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
-                    filling = true;
-                    try {
-                        bp = 0;
-                        buf = readInputStream(buf, classfile.openInputStream());
-                        readClassFile(c);
-                        if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
-                            List<Type> missing = missingTypeVariables;
-                            List<Type> found = foundTypeVariables;
-                            missingTypeVariables = List.nil();
-                            foundTypeVariables = List.nil();
-                            filling = false;
-                            ClassType ct = (ClassType)currentOwner.type;
-                            ct.supertype_field =
-                                types.subst(ct.supertype_field, missing, found);
-                            ct.interfaces_field =
-                                types.subst(ct.interfaces_field, missing, found);
-                        } else if (missingTypeVariables.isEmpty() !=
-                                   foundTypeVariables.isEmpty()) {
-                            Name name = missingTypeVariables.head.tsym.name;
-                            throw badClassFile("undecl.type.var", name);
-                        }
-                    } finally {
-                        missingTypeVariables = List.nil();
-                        foundTypeVariables = List.nil();
-                        filling = false;
-                    }
-                } else {
-                    if (sourceCompleter != null) {
-                        sourceCompleter.complete(c);
-                    } else {
-                        throw new IllegalStateException("Source completer required to read "
-                                                        + classfile.toUri());
-                    }
-                }
-                return;
-            } catch (IOException ex) {
-                throw badClassFile("unable.to.access.file", ex.getMessage());
-            } catch (ArrayIndexOutOfBoundsException ex) {
-                throw badClassFile("bad.class.file", c.flatname);
-            } finally {
-                currentClassFile = previousClassFile;
-            }
-        } else {
-            JCDiagnostic diag =
-                diagFactory.fragment("class.file.not.found", c.flatname);
-            throw
-                newCompletionFailure(c, diag);
+        } catch (IOException ex) {
+            throw badClassFile("unable.to.access.file", ex.getMessage());
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            throw badClassFile("bad.class.file", c.flatname);
+        } finally {
+            missingTypeVariables = List.nil();
+            foundTypeVariables = List.nil();
+            filling = false;
         }
     }
     // where
@@ -2590,253 +2399,39 @@
             }
             return buf;
         }
-        /** Static factory for CompletionFailure objects.
-         *  In practice, only one can be used at a time, so we share one
-         *  to reduce the expense of allocating new exception objects.
-         */
-        private CompletionFailure newCompletionFailure(TypeSymbol c,
-                                                       JCDiagnostic diag) {
-            if (!cacheCompletionFailure) {
-                // log.warning("proc.messager",
-                //             Log.getLocalizedString("class.file.not.found", c.flatname));
-                // c.debug.printStackTrace();
-                return new CompletionFailure(c, diag);
-            } else {
-                CompletionFailure result = cachedCompletionFailure;
-                result.sym = c;
-                result.diag = diag;
-                return result;
-            }
-        }
-        private CompletionFailure cachedCompletionFailure =
-            new CompletionFailure(null, (JCDiagnostic) null);
-        {
-            cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
-        }
 
-
-    /** Load a toplevel class with given fully qualified name
-     *  The class is entered into `classes' only if load was successful.
+    /** We can only read a single class file at a time; this
+     *  flag keeps track of when we are currently reading a class
+     *  file.
      */
-    public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
-        boolean absent = syms.classes.get(flatname) == null;
-        ClassSymbol c = syms.enterClass(flatname);
-        if (c.members_field == null && c.completer != null) {
-            try {
-                c.complete();
-            } catch (CompletionFailure ex) {
-                if (absent) syms.classes.remove(flatname);
-                throw ex;
-            }
-        }
-        return c;
-    }
+    public boolean filling = false;
 
 /************************************************************************
- * Loading Packages
+ * Adjusting flags
  ***********************************************************************/
 
-    /** Include class corresponding to given class file in package,
-     *  unless (1) we already have one the same kind (.class or .java), or
-     *         (2) we have one of the other kind, and the given class file
-     *             is older.
-     */
-    protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
-        if ((p.flags_field & EXISTS) == 0)
-            for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
-                q.flags_field |= EXISTS;
-        JavaFileObject.Kind kind = file.getKind();
-        int seen;
-        if (kind == JavaFileObject.Kind.CLASS)
-            seen = CLASS_SEEN;
-        else
-            seen = SOURCE_SEEN;
-        String binaryName = fileManager.inferBinaryName(currentLoc, file);
-        int lastDot = binaryName.lastIndexOf(".");
-        Name classname = names.fromString(binaryName.substring(lastDot + 1));
-        boolean isPkgInfo = classname == names.package_info;
-        ClassSymbol c = isPkgInfo
-            ? p.package_info
-            : (ClassSymbol) p.members_field.lookup(classname).sym;
-        if (c == null) {
-            c = syms.enterClass(classname, p);
-            if (c.classfile == null) // only update the file if's it's newly created
-                c.classfile = file;
-            if (isPkgInfo) {
-                p.package_info = c;
-            } else {
-                if (c.owner == p)  // it might be an inner class
-                    p.members_field.enter(c);
-            }
-        } else if (!preferCurrent && c.classfile != null && (c.flags_field & seen) == 0) {
-            // if c.classfile == null, we are currently compiling this class
-            // and no further action is necessary.
-            // if (c.flags_field & seen) != 0, we have already encountered
-            // a file of the same kind; again no further action is necessary.
-            if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
-                c.classfile = preferredFileObject(file, c.classfile);
-        }
-        c.flags_field |= seen;
-    }
-
-    /** Implement policy to choose to derive information from a source
-     *  file or a class file when both are present.  May be overridden
-     *  by subclasses.
-     */
-    protected JavaFileObject preferredFileObject(JavaFileObject a,
-                                           JavaFileObject b) {
-
-        if (preferSource)
-            return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
-        else {
-            long adate = a.getLastModified();
-            long bdate = b.getLastModified();
-            // 6449326: policy for bad lastModifiedTime in ClassReader
-            //assert adate >= 0 && bdate >= 0;
-            return (adate > bdate) ? a : b;
-        }
-    }
-
-    /**
-     * specifies types of files to be read when filling in a package symbol
-     */
-    protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
-        return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
-    }
-
-    /**
-     * this is used to support javadoc
-     */
-    protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) {
+    long adjustFieldFlags(long flags) {
+        return flags;
     }
 
-    protected Location currentLoc; // FIXME
-
-    private boolean verbosePath = true;
-
-    // Set to true when the currently selected file should be kept
-    private boolean preferCurrent;
-
-    /** Load directory of package into members scope.
-     */
-    private void fillIn(PackageSymbol p) throws IOException {
-        if (p.members_field == null)
-            p.members_field = new Scope(p);
-
-        preferCurrent = false;
-        if (userPathsFirst) {
-            scanUserPaths(p);
-            preferCurrent = true;
-            scanPlatformPath(p);
-        } else {
-            scanPlatformPath(p);
-            scanUserPaths(p);
+    long adjustMethodFlags(long flags) {
+        if ((flags & ACC_BRIDGE) != 0) {
+            flags &= ~ACC_BRIDGE;
+            flags |= BRIDGE;
+            if (!allowGenerics)
+                flags &= ~SYNTHETIC;
         }
-        verbosePath = false;
+        if ((flags & ACC_VARARGS) != 0) {
+            flags &= ~ACC_VARARGS;
+            flags |= VARARGS;
+        }
+        return flags;
     }
 
-    /**
-     * Scans class path and source path for files in given package.
-     */
-    private void scanUserPaths(PackageSymbol p) throws IOException {
-        Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
-
-        Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
-        classKinds.remove(JavaFileObject.Kind.SOURCE);
-        boolean wantClassFiles = !classKinds.isEmpty();
-
-        Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
-        sourceKinds.remove(JavaFileObject.Kind.CLASS);
-        boolean wantSourceFiles = !sourceKinds.isEmpty();
-
-        boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
-
-        if (verbose && verbosePath) {
-            if (fileManager instanceof StandardJavaFileManager) {
-                StandardJavaFileManager fm = (StandardJavaFileManager)fileManager;
-                if (haveSourcePath && wantSourceFiles) {
-                    List<File> path = List.nil();
-                    for (File file : fm.getLocation(SOURCE_PATH)) {
-                        path = path.prepend(file);
-                    }
-                    log.printVerbose("sourcepath", path.reverse().toString());
-                } else if (wantSourceFiles) {
-                    List<File> path = List.nil();
-                    for (File file : fm.getLocation(CLASS_PATH)) {
-                        path = path.prepend(file);
-                    }
-                    log.printVerbose("sourcepath", path.reverse().toString());
-                }
-                if (wantClassFiles) {
-                    List<File> path = List.nil();
-                    for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) {
-                        path = path.prepend(file);
-                    }
-                    for (File file : fm.getLocation(CLASS_PATH)) {
-                        path = path.prepend(file);
-                    }
-                    log.printVerbose("classpath",  path.reverse().toString());
-                }
-            }
-        }
-
-        String packageName = p.fullname.toString();
-        if (wantSourceFiles && !haveSourcePath) {
-            fillIn(p, CLASS_PATH,
-                   fileManager.list(CLASS_PATH,
-                                    packageName,
-                                    kinds,
-                                    false));
-        } else {
-            if (wantClassFiles)
-                fillIn(p, CLASS_PATH,
-                       fileManager.list(CLASS_PATH,
-                                        packageName,
-                                        classKinds,
-                                        false));
-            if (wantSourceFiles)
-                fillIn(p, SOURCE_PATH,
-                       fileManager.list(SOURCE_PATH,
-                                        packageName,
-                                        sourceKinds,
-                                        false));
-        }
+    long adjustClassFlags(long flags) {
+        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
     }
 
-    /**
-     * Scans platform class path for files in given package.
-     */
-    private void scanPlatformPath(PackageSymbol p) throws IOException {
-        fillIn(p, PLATFORM_CLASS_PATH,
-               fileManager.list(PLATFORM_CLASS_PATH,
-                                p.fullname.toString(),
-                                EnumSet.of(JavaFileObject.Kind.CLASS),
-                                false));
-    }
-    // where
-        private void fillIn(PackageSymbol p,
-                            Location location,
-                            Iterable<JavaFileObject> files)
-        {
-            currentLoc = location;
-            for (JavaFileObject fo : files) {
-                switch (fo.getKind()) {
-                case CLASS:
-                case SOURCE: {
-                    // TODO pass binaryName to includeClassFile
-                    String binaryName = fileManager.inferBinaryName(currentLoc, fo);
-                    String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
-                    if (SourceVersion.isIdentifier(simpleName) ||
-                        simpleName.equals("package-info"))
-                        includeClassFile(p, fo);
-                    break;
-                }
-                default:
-                    extraFileActions(p, fo);
-                }
-            }
-        }
-
     /** Output for "-checkclassfile" option.
      *  @param key The key to look up the correct internationalized string.
      *  @param arg An argument for substitution into the output string.
@@ -2845,12 +2440,6 @@
         log.printLines(key, arg);
     }
 
-
-    public interface SourceCompleter {
-        void complete(ClassSymbol sym)
-            throws CompletionFailure;
-    }
-
     /**
      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
      * The attribute is only the last component of the original filename, so is unlikely