[java] fixes compiler module path composition (IDEA-158385)
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Mon, 21 Nov 2016 18:38:51 +0000 (19:38 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Mon, 21 Nov 2016 18:39:07 +0000 (19:39 +0100)
jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java
jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt

index 4d21510ad72b7afbc1f02253c4018dbba597e820..fd492e073a41e391c60e7c57d973901ef02e652d 100644 (file)
@@ -33,7 +33,7 @@ import java.util.*;
 
 /**
  * @author Eugene Zhuravlev
- *         Date: 9/30/11
+ * @since 30.09.2011
  */
 public class ProjectPaths {
   private ProjectPaths() { }
@@ -56,6 +56,11 @@ public class ProjectPaths {
     return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.containsTests()), excludeMainModuleOutput, ClasspathPart.AFTER_JDK, true);
   }
 
+  @NotNull
+  public static Collection<File> getCompilationModulePath(ModuleChunk chunk, boolean excludeMainModuleOutput) {
+    return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.containsTests()), excludeMainModuleOutput, ClasspathPart.AFTER_JDK, false);
+  }
+
   @NotNull
   private static Collection<File> getClasspathFiles(ModuleChunk chunk,
                                                     JpsJavaClasspathKind kind,
index aba3a9b6e7d7c089d049f33a2869ff2eb3e6e01d..9551a6a5125c1f08af6769a6d8bad876972e4121 100644 (file)
@@ -234,8 +234,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
                            DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                            Collection<File> files,
                            OutputConsumer outputConsumer,
-                           JavaCompilingTool compilingTool)
-    throws Exception {
+                           JavaCompilingTool compilingTool) throws Exception {
     ExitCode exitCode = ExitCode.NOTHING_DONE;
 
     final boolean hasSourcesToCompile = !files.isEmpty();
@@ -247,8 +246,8 @@ public class JavaBuilder extends ModuleLevelBuilder {
     final ProjectDescriptor pd = context.getProjectDescriptor();
 
     JavaBuilderUtil.ensureModuleHasJdk(chunk.representativeTarget().getModule(), context, BUILDER_NAME);
-    final Collection<File> classpath = ProjectPaths.getCompilationClasspath(chunk, false/*context.isProjectRebuild()*/);
-    final Collection<File> platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false/*context.isProjectRebuild()*/);
+    final Collection<File> classpath = ProjectPaths.getCompilationClasspath(chunk, false);
+    final Collection<File> platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false);
 
     // begin compilation round
     final OutputFilesSink outputSink =
@@ -366,6 +365,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
     try {
       final int targetLanguageLevel = JpsJavaSdkType.parseVersion(getLanguageLevel(chunk.getModules().iterator().next()));
       final boolean shouldForkJavac = shouldForkCompilerProcess(context, targetLanguageLevel);
+      final boolean hasModules = targetLanguageLevel >= 9 && getJavaModuleIndex(context).hasJavaModules(modules);
 
       // when forking external javac, compilers from SDK 1.6 and higher are supported
       Pair<String, Integer> forkSdk = null;
@@ -377,9 +377,9 @@ public class JavaBuilder extends ModuleLevelBuilder {
           return true;
         }
       }
-      
+
       final int compilerSdkVersion = forkSdk == null? getCompilerSdkVersion(context) : forkSdk.getSecond();
-      
+
       final List<String> options = getCompilationOptions(compilerSdkVersion, context, chunk, profile, compilingTool);
       if (LOG.isDebugEnabled()) {
         LOG.debug("Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\"");
@@ -395,11 +395,17 @@ public class JavaBuilder extends ModuleLevelBuilder {
       }
 
       if (!_platformCp.isEmpty()) {
+        if (hasModules) {
+          String text = "The project has boot classpath dependencies (" + _platformCp + "). Please convert them into regular ones.";
+          context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, text));
+          return true;
+        }
+
         final int chunkSdkVersion = getChunkSdkVersion(chunk);
         if (chunkSdkVersion >= 9) {
           // if chunk's SDK is 9 or higher, there is no way to specify full platform classpath
           // because platform classes are stored in jimage binary files with unknown format.
-          // Because of this we are clearing platform classpath so that javac will resolve against its own bootclasspath
+          // Because of this we are clearing platform classpath so that javac will resolve against its own boot classpath
           // and prepending additional jars from the JDK configuration to compilation classpath
           final Collection<File> joined = new ArrayList<File>(_platformCp.size() + classpath.size());
           joined.addAll(_platformCp);
@@ -423,9 +429,10 @@ public class JavaBuilder extends ModuleLevelBuilder {
       }
 
       Collection<File> modulePath = Collections.emptyList();
-      if (targetLanguageLevel >= 9 && getJavaModuleIndex(context).hasJavaModules(modules)) {
+      if (hasModules) {
         // in Java 9, named modules are not allowed to read classes from the classpath
-        modulePath = classpath;
+        // moreover, the compiler requires all transitive dependencies to be on the module path
+        modulePath = ProjectPaths.getCompilationModulePath(chunk, false);
         classpath = Collections.emptyList();
       }
 
index bc0c1f2c84fb1398e4015d0e6ab5863aeed05c3a..43dc647d12b001f5b2d8208156e86e201a62e55f 100644 (file)
@@ -64,6 +64,7 @@ class ModuleClasspathTest(): JpsBuildTestCase() {
     val chunk = createChunk("main")
     assertClasspath(listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar"), getPathsList(ProjectPaths.getPlatformCompilationClasspath(chunk, true)))
     assertClasspath(listOf("main/lib/service.jar"), getPathsList(ProjectPaths.getCompilationClasspath(chunk, true)))
+    assertClasspath(listOf("main/lib/service.jar"), getPathsList(ProjectPaths.getCompilationModulePath(chunk, true)))
   }
 
   private fun assertClasspath(moduleName: String, includeTests: Boolean, expected: List<String>) {
@@ -92,4 +93,4 @@ class ModuleClasspathTest(): JpsBuildTestCase() {
       if (path.contains(".")) toCanonicalPath(path)!! else toSystemIndependentName(path)
     }
   }
-}
+}
\ No newline at end of file