8164745: javac -Xmodule compiles the module in a way that reads the unnamed module
authorjlahoda
Mon, 29 Aug 2016 15:53:03 +0200
changeset 40602 50045337b3a1
parent 40601 9af676462cbf
child 40603 a890cefaa41b
8164745: javac -Xmodule compiles the module in a way that reads the unnamed module Summary: Ensuring proper separation between named modules the unnamed module when using -Xmodule Reviewed-by: jjg
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
langtools/test/tools/javac/modules/XModuleTest.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Mon Aug 29 11:13:48 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Mon Aug 29 15:53:03 2016 +0200
@@ -119,10 +119,6 @@
      */
     final Name completionFailureName;
 
-    /** Module specified with -Xmodule:
-     */
-    final Name moduleOverride;
-
     /** Access to files
      */
     private final JavaFileManager fileManager;
@@ -210,9 +206,6 @@
             ? names.fromString(options.get("failcomplete"))
             : null;
 
-        moduleOverride = options.isSet(Option.XMODULE) ? names.fromString(options.get(Option.XMODULE))
-                                                : null;
-
         // Temporary, until more info is available from the module system.
         boolean useCtProps;
         JavaFileManager fm = context.get(JavaFileManager.class);
@@ -527,16 +520,15 @@
         if (msym == syms.noModule) {
             preferCurrent = false;
             if (userPathsFirst) {
-                scanUserPaths(p);
+                scanUserPaths(p, true);
                 preferCurrent = true;
                 scanPlatformPath(p);
             } else {
                 scanPlatformPath(p);
-                scanUserPaths(p);
+                scanUserPaths(p, true);
             }
         } else if (msym.classLocation == StandardLocation.CLASS_PATH) {
-            // assert p.modle.sourceLocation == StandardLocation.SOURCE_PATH);
-            scanUserPaths(p);
+            scanUserPaths(p, msym.sourceLocation == StandardLocation.SOURCE_PATH);
         } else {
             scanModulePaths(p, msym);
         }
@@ -561,23 +553,6 @@
 
         String packageName = p.fullname.toString();
 
-        if (msym.name == moduleOverride) {
-            if (wantClassFiles) {
-                fillIn(p, CLASS_PATH,
-                       fileManager.list(CLASS_PATH,
-                                        packageName,
-                                        classKinds,
-                                        false));
-            }
-            if (wantSourceFiles && fileManager.hasLocation(SOURCE_PATH)) {
-                fillIn(p, SOURCE_PATH,
-                        fileManager.list(SOURCE_PATH,
-                                        packageName,
-                                        sourceKinds,
-                                        false));
-            }
-        }
-
         Location classLocn = msym.classLocation;
         Location sourceLocn = msym.sourceLocation;
 
@@ -600,7 +575,7 @@
     /**
      * Scans class path and source path for files in given package.
      */
-    private void scanUserPaths(PackageSymbol p) throws IOException {
+    private void scanUserPaths(PackageSymbol p, boolean includeSourcePath) throws IOException {
         Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
 
         Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
@@ -611,7 +586,7 @@
         sourceKinds.remove(JavaFileObject.Kind.CLASS);
         boolean wantSourceFiles = !sourceKinds.isEmpty();
 
-        boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
+        boolean haveSourcePath = includeSourcePath && fileManager.hasLocation(SOURCE_PATH);
 
         if (verbose && verbosePath) {
             if (fileManager instanceof StandardJavaFileManager) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Aug 29 11:13:48 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Aug 29 15:53:03 2016 +0200
@@ -392,6 +392,7 @@
                             if (moduleOverride != null) {
                                 checkNoAllModulePath();
                                 defaultModule = moduleFinder.findModule(names.fromString(moduleOverride));
+                                defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
                             } else {
                                 // Question: why not do findAllModules and initVisiblePackages here?
                                 // i.e. body of unnamedModuleCompleter
@@ -432,7 +433,9 @@
 
             if (defaultModule != syms.unnamedModule) {
                 syms.unnamedModule.completer = getUnnamedModuleCompleter();
-                syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                if (moduleOverride == null) {
+                    syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                }
                 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
             }
 
--- a/langtools/test/tools/javac/modules/XModuleTest.java	Mon Aug 29 11:13:48 2016 +0000
+++ b/langtools/test/tools/javac/modules/XModuleTest.java	Mon Aug 29 15:53:03 2016 +0200
@@ -27,7 +27,9 @@
  * @library /tools/lib
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.code
  *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.compiler/com.sun.tools.javac.processing
  * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main XModuleTest
  */
@@ -35,12 +37,22 @@
 import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 import toolbox.JavacTask;
 import toolbox.ModuleBuilder;
 import toolbox.Task;
-import toolbox.TestRunner;
-import toolbox.ToolBox;
+import toolbox.Task.Expect;
 
 public class XModuleTest extends ModuleTestBase {
 
@@ -111,15 +123,22 @@
         Path classes = base.resolve("classes");
         tb.createDirectories(classes);
 
-        String log = new JavacTask(tb)
-                .options("-Xmodule:java.compiler", "--class-path", cpClasses.toString())
+        List<String> log = new JavacTask(tb)
+                .options("-Xmodule:java.compiler",
+                         "--class-path", cpClasses.toString(),
+                         "-XDrawDiagnostics")
                 .outdir(classes)
                 .files(src.resolve("javax/lang/model/element/Extra.java"))
-                .run()
+                .run(Expect.FAIL)
                 .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
+                .getOutputLines(Task.OutputKind.DIRECT);
 
-        if (!log.isEmpty())
+        List<String> expectedOut = Arrays.asList(
+                "Extra.java:1:76: compiler.err.doesnt.exist: p",
+                "1 error"
+        );
+
+        if (!expectedOut.equals(log))
             throw new Exception("expected output not found: " + log);
     }
 
@@ -302,4 +321,103 @@
                 .run()
                 .writeAll();
     }
+
+    @Test
+    public void testUnnamedIsolation(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path sourcePath = base.resolve("source-path");
+        tb.writeJavaFiles(sourcePath, "package src; public class Src {}");
+
+        Path classPathSrc = base.resolve("class-path-src");
+        tb.writeJavaFiles(classPathSrc, "package cp; public class CP { }");
+        Path classPath = base.resolve("classPath");
+        tb.createDirectories(classPath);
+
+        String cpLog = new JavacTask(tb)
+                .outdir(classPath)
+                .files(findJavaFiles(classPathSrc))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!cpLog.isEmpty())
+            throw new Exception("expected output not found: " + cpLog);
+
+        Path modulePathSrc = base.resolve("module-path-src");
+        tb.writeJavaFiles(modulePathSrc,
+                          "module m {}",
+                          "package m; public class M {}");
+        Path modulePath = base.resolve("modulePath");
+        tb.createDirectories(modulePath.resolve("m"));
+
+        String modLog = new JavacTask(tb)
+                .outdir(modulePath.resolve("m"))
+                .files(findJavaFiles(modulePathSrc))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!modLog.isEmpty())
+            throw new Exception("expected output not found: " + modLog);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package m; public class Extra { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-Xmodule:m",
+                         "--class-path", classPath.toString(),
+                         "--source-path", sourcePath.toString(),
+                         "--module-path", modulePath.toString(),
+                         "-XDaccessInternalAPI=true",
+                         "--processor-path", System.getProperty("test.classes"),
+                         "-processor", CheckModuleContentProcessing.class.getName())
+                .outdir(classes)
+                .files(findJavaFiles(sourcePath))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class CheckModuleContentProcessing extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            Symtab syms = Symtab.instance(((JavacProcessingEnvironment) processingEnv).getContext());
+            Elements elements = processingEnv.getElementUtils();
+            ModuleElement unnamedModule = syms.unnamedModule;
+            ModuleElement mModule = elements.getModuleElement("m");
+
+            assertNonNull("mModule found", mModule);
+            assertNonNull("src.Src from m", elements.getTypeElement(mModule, "src.Src"));
+            assertNull("cp.CP not from m", elements.getTypeElement(mModule, "cp.CP"));
+            assertNull("src.Src not from unnamed", elements.getTypeElement(unnamedModule, "src.Src"));
+            assertNonNull("cp.CP from unnamed", elements.getTypeElement(unnamedModule, "cp.CP"));
+
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    private static void assertNonNull(String msg, Object val) {
+        if (val == null) {
+            throw new AssertionError(msg);
+        }
+    }
+
+    private static void assertNull(String msg, Object val) {
+        if (val != null) {
+            throw new AssertionError(msg);
+        }
+    }
 }