langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
changeset 36526 3b41f1c69604
parent 36155 1555ce1fcb4f
child 39587 76c453568ffa
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Mar 15 13:48:30 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Mar 17 19:04:28 2016 +0000
@@ -39,6 +39,7 @@
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ElementVisitor;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
@@ -67,12 +68,20 @@
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.JCDiagnostic.Factory;
 import com.sun.tools.javac.util.Log.WriterKind;
 
 import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+
 import static com.sun.tools.javac.code.TypeTag.CLASS;
 import static com.sun.tools.javac.main.Option.*;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
+
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 /** This class could be the main entry point for GJC when GJC is used as a
@@ -276,6 +285,18 @@
      */
     protected Flow flow;
 
+    /** The modules visitor
+     */
+    protected Modules modules;
+
+    /** The module finder
+     */
+    protected ModuleFinder moduleFinder;
+
+    /** The diagnostics factory
+     */
+    protected JCDiagnostic.Factory diags;
+
     /** The type eraser.
      */
     protected TransTypes transTypes;
@@ -336,6 +357,8 @@
      **/
     protected boolean implicitSourceFilesRead;
 
+    protected boolean enterDone;
+
     protected CompileStates compileStates;
 
     /** Construct a new compiler using a shared context.
@@ -382,6 +405,9 @@
         annotate = Annotate.instance(context);
         types = Types.instance(context);
         taskListener = MultiTaskListener.instance(context);
+        modules = Modules.instance(context);
+        moduleFinder = ModuleFinder.instance(context);
+        diags = Factory.instance(context);
 
         finder.sourceCompleter = sourceCompleter;
 
@@ -430,6 +456,18 @@
 
         if (platformProvider != null)
             closeables = closeables.prepend(platformProvider);
+
+        silentFail = new Symbol(ABSENT_TYP, 0, names.empty, Type.noType, syms.rootPackage) {
+            @DefinedBy(Api.LANGUAGE_MODEL)
+            public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+                return v.visitUnknown(this, p);
+            }
+            @Override
+            public boolean exists() {
+                return false;
+            }
+        };
+
     }
 
     /* Switches:
@@ -512,6 +550,11 @@
      */
     protected Set<JavaFileObject> inputFiles = new HashSet<>();
 
+    /** Used by the resolveBinaryNameOrIdent to say that the given type cannot be found, and that
+     *  an error has already been produced about that.
+     */
+    private final Symbol silentFail;
+
     protected boolean shouldStop(CompileState cs) {
         CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
             ? shouldStopPolicyIfError
@@ -625,18 +668,44 @@
      * @param name      The name to resolve
      */
     public Symbol resolveBinaryNameOrIdent(String name) {
+        ModuleSymbol msym;
+        String typeName;
+        int sep = name.indexOf('/');
+        if (sep == -1) {
+            msym = modules.getDefaultModule();
+            typeName = name;
+        } else if (source.allowModules() && !options.isSet("noModules")) {
+            Name modName = names.fromString(name.substring(0, sep));
+
+            msym = moduleFinder.findModule(modName);
+            typeName = name.substring(sep + 1);
+        } else {
+            log.error(Errors.InvalidModuleSpecifier(name));
+            return silentFail;
+        }
+
+        return resolveBinaryNameOrIdent(msym, typeName);
+    }
+
+    /** Resolve an identifier which may be the binary name of a class or
+     * the Java name of a class or package.
+     * @param msym      The module in which the search should be performed
+     * @param name      The name to resolve
+     */
+    public Symbol resolveBinaryNameOrIdent(ModuleSymbol msym, String name) {
         try {
             Name flatname = names.fromString(name.replace("/", "."));
-            return finder.loadClass(flatname);
+            return finder.loadClass(msym, flatname);
         } catch (CompletionFailure ignore) {
-            return resolveIdent(name);
+            return resolveIdent(msym, name);
         }
     }
 
     /** Resolve an identifier.
+     * @param msym      The module in which the search should be performed
      * @param name      The identifier to resolve
      */
-    public Symbol resolveIdent(String name) {
+    public Symbol resolveIdent(ModuleSymbol msym, String name) {
         if (name.equals(""))
             return syms.errSymbol;
         JavaFileObject prev = log.useSource(null);
@@ -650,7 +719,8 @@
             }
             JCCompilationUnit toplevel =
                 make.TopLevel(List.<JCTree>nil());
-            toplevel.packge = syms.unnamedPackage;
+            toplevel.modle = msym;
+            toplevel.packge = msym.unnamedPackage;
             return attr.attribIdent(tree, toplevel);
         } finally {
             log.useSource(prev);
@@ -737,6 +807,16 @@
             taskListener.started(e);
         }
 
+        // Process module declarations.
+        // If module resolution fails, ignore trees, and if trying to
+        // complete a specific symbol, throw CompletionFailure.
+        // Note that if module resolution failed, we may not even
+        // have enough modules available to access java.lang, and
+        // so risk getting FatalError("no.java.lang") from MemberEnter.
+        if (!modules.enter(List.of(tree), c)) {
+            throw new CompletionFailure(c, diags.fragment("cant.resolve.modules"));
+        }
+
         enter.complete(List.of(tree), c);
 
         if (!taskListener.isEmpty()) {
@@ -748,7 +828,16 @@
             boolean isPkgInfo =
                 tree.sourcefile.isNameCompatible("package-info",
                                                  JavaFileObject.Kind.SOURCE);
-            if (isPkgInfo) {
+            boolean isModuleInfo =
+                tree.sourcefile.isNameCompatible("module-info",
+                                                 JavaFileObject.Kind.SOURCE);
+            if (isModuleInfo) {
+                if (enter.getEnv(tree.modle) == null) {
+                    JCDiagnostic diag =
+                        diagFactory.fragment("file.does.not.contain.module");
+                    throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+                }
+            } else if (isPkgInfo) {
                 if (enter.getEnv(tree.packge) == null) {
                     JCDiagnostic diag =
                         diagFactory.fragment("file.does.not.contain.package",
@@ -812,8 +901,12 @@
 
             // These method calls must be chained to avoid memory leaks
             processAnnotations(
-                enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))),
-                classnames);
+                enterTrees(
+                        stopIfError(CompileState.PARSE,
+                                initModules(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))))
+                ),
+                classnames
+            );
 
             // If it's safe to do so, skip attr / flow / gen for implicit classes
             if (taskListener.isEmpty() &&
@@ -912,7 +1005,20 @@
     public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
        if (shouldStop(CompileState.ATTR))
            return List.nil();
-        return enterTrees(roots);
+        return enterTrees(initModules(roots));
+    }
+
+    public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
+        List<JCCompilationUnit> result = initModules(roots, null);
+        if (roots.isEmpty()) {
+            enterDone = true;
+        }
+        return result;
+    }
+
+    List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots, ClassSymbol c) {
+        modules.enter(roots, c);
+        return roots;
     }
 
     /**
@@ -931,6 +1037,8 @@
 
         enter.main(roots);
 
+        enterDone = true;
+
         if (!taskListener.isEmpty()) {
             for (JCCompilationUnit unit: roots) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
@@ -1085,7 +1193,8 @@
                         if (sym == null ||
                             (sym.kind == PCK && !processPcks) ||
                             sym.kind == ABSENT_TYP) {
-                            log.error("proc.cant.find.class", nameStr);
+                            if (sym != silentFail)
+                                log.error(Errors.ProcCantFindClass(nameStr));
                             errors = true;
                             continue;
                         }
@@ -1100,10 +1209,10 @@
                                 continue;
                             }
                             Assert.check(sym.kind == PCK);
-                            log.warning("proc.package.does.not.exist", nameStr);
+                            log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
                             pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
                         } catch (CompletionFailure e) {
-                            log.error("proc.cant.find.class", nameStr);
+                            log.error(Errors.ProcCantFindClass(nameStr));
                             errors = true;
                             continue;
                         }
@@ -1154,6 +1263,7 @@
         return
             options.isSet(PROCESSOR) ||
             options.isSet(PROCESSORPATH) ||
+            options.isSet(PROCESSORMODULEPATH) ||
             options.isSet(PROC, "only") ||
             options.isSet(XPRINT);
     }
@@ -1388,14 +1498,14 @@
             make.at(Position.FIRSTPOS);
             TreeMaker localMake = make.forToplevel(env.toplevel);
 
-            if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
+            if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
                 if (!(sourceOutput)) {
                     if (shouldStop(CompileState.LOWER))
-                       return;
-                    List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
-                    if (pdef.head != null) {
-                        Assert.check(pdef.tail.isEmpty());
-                        results.add(new Pair<>(env, (JCClassDecl)pdef.head));
+                        return;
+                    List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
+                    if (def.head != null) {
+                        Assert.check(def.tail.isEmpty());
+                        results.add(new Pair<>(env, (JCClassDecl)def.head));
                     }
                 }
                 return;
@@ -1589,6 +1699,10 @@
         }
     }
 
+    public boolean isEnterDone() {
+        return enterDone;
+    }
+
     /** Close the compiler, flushing the logs
      */
     public void close() {