langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
changeset 41254 08f8dbf7741e
parent 40835 6ab9ed1abc46
child 42827 36468b5fa7f4
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Oct 04 13:41:52 2016 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Oct 04 16:25:19 2016 +0200
@@ -37,6 +37,7 @@
 import java.util.Queue;
 import java.util.ResourceBundle;
 import java.util.Set;
+import java.util.function.Function;
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
@@ -67,7 +68,9 @@
 import com.sun.tools.javac.tree.JCTree.JCLambda;
 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.tree.JCTree.Tag;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.JCDiagnostic.Factory;
@@ -341,6 +344,13 @@
                 }
             };
 
+    protected final ModuleFinder.ModuleInfoSourceFileCompleter moduleInfoSourceFileCompleter =
+            fo -> (ModuleSymbol) readSourceFile(parseImplicitFile(fo), null, tl -> {
+                return tl.defs.nonEmpty() && tl.defs.head.hasTag(Tag.MODULEDEF) ?
+                        ((JCModuleDecl) tl.defs.head).sym.module_info :
+                        syms.defineClass(names.module_info, syms.errModule);
+            }).owner;
+
     /**
      * Command line options.
      */
@@ -411,6 +421,7 @@
         diags = Factory.instance(context);
 
         finder.sourceCompleter = sourceCompleter;
+        moduleFinder.sourceFileCompleter = moduleInfoSourceFileCompleter;
 
         options = Options.instance(context);
 
@@ -779,6 +790,19 @@
         readSourceFile(null, c);
     }
 
+    private JCTree.JCCompilationUnit parseImplicitFile(JavaFileObject filename) {
+        JavaFileObject prev = log.useSource(filename);
+        try {
+            JCTree.JCCompilationUnit t = parse(filename, filename.getCharContent(false));
+            return t;
+        } catch (IOException e) {
+            log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
+            return make.TopLevel(List.<JCTree>nil());
+        } finally {
+            log.useSource(prev);
+        }
+    }
+
     /** Compile a ClassSymbol from source, optionally using the given compilation unit as
      *  the source tree.
      *  @param tree the compilation unit in which the given ClassSymbol resides,
@@ -789,20 +813,20 @@
         if (completionFailureName == c.fullname) {
             throw new CompletionFailure(c, "user-selected completion failure by class name");
         }
-        JavaFileObject filename = c.classfile;
-        JavaFileObject prev = log.useSource(filename);
 
         if (tree == null) {
-            try {
-                tree = parse(filename, filename.getCharContent(false));
-            } catch (IOException e) {
-                log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
-                tree = make.TopLevel(List.<JCTree>nil());
-            } finally {
-                log.useSource(prev);
-            }
+            tree = parseImplicitFile(c.classfile);
         }
 
+        readSourceFile(tree, c, cut -> c);
+    }
+
+    private ClassSymbol readSourceFile(JCCompilationUnit tree,
+                                       ClassSymbol expectedSymbol,
+                                       Function<JCCompilationUnit, ClassSymbol> symbolGetter)
+                                           throws CompletionFailure {
+        Assert.checkNonNull(tree);
+
         if (!taskListener.isEmpty()) {
             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
             taskListener.started(e);
@@ -814,18 +838,20 @@
         // 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"));
+        if (!modules.enter(List.of(tree), expectedSymbol)) {
+            throw new CompletionFailure(symbolGetter.apply(tree),
+                                        diags.fragment("cant.resolve.modules"));
         }
 
-        enter.complete(List.of(tree), c);
+        enter.complete(List.of(tree), expectedSymbol);
 
         if (!taskListener.isEmpty()) {
             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
             taskListener.finished(e);
         }
 
-        if (enter.getEnv(c) == null) {
+        ClassSymbol sym = symbolGetter.apply(tree);
+        if (sym == null || enter.getEnv(sym) == null) {
             boolean isPkgInfo =
                 tree.sourcefile.isNameCompatible("package-info",
                                                  JavaFileObject.Kind.SOURCE);
@@ -836,24 +862,26 @@
                 if (enter.getEnv(tree.modle) == null) {
                     JCDiagnostic diag =
                         diagFactory.fragment("file.does.not.contain.module");
-                    throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+                    throw new ClassFinder.BadClassFile(sym, tree.sourcefile, diag, diagFactory);
                 }
             } else if (isPkgInfo) {
                 if (enter.getEnv(tree.packge) == null) {
                     JCDiagnostic diag =
                         diagFactory.fragment("file.does.not.contain.package",
-                                                 c.location());
-                    throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+                                                 sym.location());
+                    throw new ClassFinder.BadClassFile(sym, tree.sourcefile, diag, diagFactory);
                 }
             } else {
                 JCDiagnostic diag =
                         diagFactory.fragment("file.doesnt.contain.class",
-                                            c.getQualifiedName());
-                throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+                                            sym.getQualifiedName());
+                throw new ClassFinder.BadClassFile(sym, tree.sourcefile, diag, diagFactory);
             }
         }
 
         implicitSourceFilesRead = true;
+
+        return sym;
     }
 
     /** Track when the JavaCompiler has been used to compile something. */