diff --git a/.idea/libraries/qdox_java_parser.xml b/.idea/libraries/qdox_java_parser.xml
new file mode 100644
index 000000000000..8ac24b1c0c9c
--- /dev/null
+++ b/.idea/libraries/qdox_java_parser.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/groovy/org/jetbrains/intellij/build/CommunityStandaloneJpsBuilder.groovy b/build/groovy/org/jetbrains/intellij/build/CommunityStandaloneJpsBuilder.groovy
index 1d55d2a0d620..3e9e879504d7 100644
--- a/build/groovy/org/jetbrains/intellij/build/CommunityStandaloneJpsBuilder.groovy
+++ b/build/groovy/org/jetbrains/intellij/build/CommunityStandaloneJpsBuilder.groovy
@@ -75,7 +75,7 @@ class CommunityStandaloneJpsBuilder {
[
"JDOM", "jna", "OroMatcher", "Trove4j", "ASM", "NanoXML", "protobuf", "cli-parser", "Log4J", "jgoodies-forms", "Eclipse",
"netty-codec-http", "lz4-java", "commons-codec", "commons-logging", "http-client", "Slf4j", "Guava", "plexus-utils",
- "jetbrains-annotations-java5", "maven-model"
+ "jetbrains-annotations-java5", "maven-model", "qdox-java-parser"
].each {
projectLibrary(it)
}
diff --git a/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_1.jar b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_1.jar
new file mode 100644
index 000000000000..ddcf8dad7693
Binary files /dev/null and b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_1.jar differ
diff --git a/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_2.jar b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_2.jar
new file mode 100644
index 000000000000..2f562e8afe79
Binary files /dev/null and b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_2.jar differ
diff --git a/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_3.jar b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_3.jar
new file mode 100644
index 000000000000..39f8ae7461f9
Binary files /dev/null and b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_3.jar differ
diff --git a/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_util.jar b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_util.jar
new file mode 100644
index 000000000000..6739ac56d756
Binary files /dev/null and b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/lib/module_lib_util.jar differ
diff --git a/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/moduleA/src/module-info.java b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/moduleA/src/module-info.java
new file mode 100644
index 000000000000..fc4b4e8a9bc1
--- /dev/null
+++ b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/moduleA/src/module-info.java
@@ -0,0 +1,5 @@
+module A {
+ requires module_lib1;
+ requires mod.lib2;
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/moduleA/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/moduleA/src/ppp/Main.java
new file mode 100644
index 000000000000..d277e70cf6b6
--- /dev/null
+++ b/java/java-tests/testData/compileServer/incremental/java9-features/splitModulePath/moduleA/src/ppp/Main.java
@@ -0,0 +1,7 @@
+package ppp;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello");
+ }
+}
diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java
index 08016b463848..4754f521b2d4 100644
--- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java
+++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java
@@ -97,23 +97,6 @@ public class JavacMain {
return false;
}
- if (!classpath.isEmpty()) {
- try {
- fileManager.setLocation(StandardLocation.CLASS_PATH, classpath);
- if (!usingJavac &&
- isAnnotationProcessingEnabled(_options) &&
- !_options.contains("-processorpath") &&
- (javacBefore9 || !_options.contains("--processor-module-path"))) {
- // for non-javac file manager ensure annotation processor path defaults to classpath
- fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath);
- }
- }
- catch (IOException e) {
- fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
- return false;
- }
- }
-
if (!platformClasspath.isEmpty()) {
try {
fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
@@ -156,6 +139,24 @@ public class JavacMain {
}
}
+ if (!classpath.isEmpty()) {
+ // because module path has priority if present, initialize classpath after the module path
+ try {
+ fileManager.setLocation(StandardLocation.CLASS_PATH, classpath);
+ if (!usingJavac &&
+ isAnnotationProcessingEnabled(_options) &&
+ !_options.contains("-processorpath") &&
+ (javacBefore9 || (!_options.contains("--processor-module-path") && getLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH") == null))) {
+ // for non-javac file manager ensure annotation processor path defaults to classpath
+ fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath);
+ }
+ }
+ catch (IOException e) {
+ fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ return false;
+ }
+ }
+
if (javacBefore9 || !sourcePath.isEmpty() || modulePath.isEmpty()) {
try {
// ensure the source path is set;
diff --git a/jps/jps-builders/intellij.platform.jps.build.iml b/jps/jps-builders/intellij.platform.jps.build.iml
index a34a7be27f17..9eddd4415efa 100644
--- a/jps/jps-builders/intellij.platform.jps.build.iml
+++ b/jps/jps-builders/intellij.platform.jps.build.iml
@@ -34,5 +34,6 @@
+
\ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
index 9c43e439548e..8b8ace99605c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
@@ -11,6 +11,7 @@ import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.jgoodies.forms.layout.CellConstraints;
+import com.thoughtworks.qdox.JavaProjectBuilder;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.EventLoopGroup;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
@@ -72,6 +73,7 @@ public class ClasspathBootstrap {
cp.add(getResourcePath(CellConstraints.class)); // jGoodies-forms
cp.addAll(getInstrumentationUtilRoots());
cp.add(getResourcePath(IXMLBuilder.class)); // nano-xml
+ cp.add(getResourcePath(JavaProjectBuilder.class)); // qdox lightweight java parser
cp.addAll(ContainerUtil.map(ArtifactRepositoryManager.getClassesFromDependencies(), ClasspathBootstrap::getResourcePath));
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
index 57af1b045fad..26b5d7fb7705 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
@@ -59,8 +59,7 @@ import org.jetbrains.jps.model.serialization.PathMacroUtil;
import org.jetbrains.jps.service.JpsServiceManager;
import org.jetbrains.jps.service.SharedThreadPool;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
+import javax.tools.*;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
@@ -82,6 +81,8 @@ public class JavaBuilder extends ModuleLevelBuilder {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.JavaBuilder");
private static final String JAVA_EXTENSION = "java";
+ private static final String USE_MODULE_PATH_ONLY_OPTION = "compiler.force.module.path";
+
public static final String BUILDER_NAME = "java";
public static final Key IS_ENABLED = Key.create("_java_compiler_enabled_");
public static final FileFilter JAVA_SOURCES_FILTER = FileFilters.withExtension(JAVA_EXTENSION);
@@ -90,6 +91,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
private static final Key PREFER_TARGET_JDK_COMPILER = GlobalContextKey.create("_prefer_target_jdk_javac_");
private static final Key COMPILING_TOOL = Key.create("_java_compiling_tool_");
private static final Key>> COMPILER_USAGE_STATISTICS = Key.create("_java_compiler_usage_stats_");
+ private static final Key MODULE_PATH_SPLITTER = GlobalContextKey.create("_module_path_splitter_");
private static final List COMPILABLE_EXTENSIONS = Collections.singletonList(JAVA_EXTENSION);
private static final Set FILTERED_OPTIONS = ContainerUtil.newHashSet(
@@ -145,6 +147,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
if (LOG.isDebugEnabled()) {
LOG.debug("Java compiler ID: " + compilerId);
}
+ MODULE_PATH_SPLITTER.set(context, new ModulePathSplitter());
JavaCompilingTool compilingTool = JavaBuilderUtil.findCompilingTool(compilerId);
COMPILING_TOOL.set(context, compilingTool);
COMPILER_USAGE_STATISTICS.set(context, new ConcurrentHashMap<>());
@@ -230,12 +233,17 @@ public class JavaBuilder extends ModuleLevelBuilder {
return true;
});
+ File moduleInfoFile = null;
int javaModulesCount = 0;
if ((!filesToCompile.isEmpty() || dirtyFilesHolder.hasRemovedFiles()) &&
getTargetPlatformLanguageVersion(chunk.representativeTarget().getModule()) >= 9) {
for (ModuleBuildTarget target : chunk.getTargets()) {
- if (JavaBuilderUtil.findModuleInfoFile(context, target) != null) {
+ final File moduleInfo = JavaBuilderUtil.findModuleInfoFile(context, target);
+ if (moduleInfo != null) {
javaModulesCount++;
+ if (moduleInfoFile == null) {
+ moduleInfoFile = moduleInfo;
+ }
}
}
}
@@ -254,7 +262,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
return ExitCode.ABORT;
}
- return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer, compilingTool, javaModulesCount > 0);
+ return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer, compilingTool, moduleInfoFile);
}
catch (BuildDataCorruptedException | PersistentEnumeratorBase.CorruptedException | ProjectBuildException e) {
throw e;
@@ -276,7 +284,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
Collection extends File> files,
OutputConsumer outputConsumer,
JavaCompilingTool compilingTool,
- boolean hasModules) throws Exception {
+ File moduleInfoFile) throws Exception {
ExitCode exitCode = ExitCode.NOTHING_DONE;
final boolean hasSourcesToCompile = !files.isEmpty();
@@ -329,7 +337,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
}
}
try {
- compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink, compilingTool, hasModules);
+ compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink, compilingTool, moduleInfoFile);
}
finally {
filesWithErrors = diagnosticSink.getFilesWithErrors();
@@ -373,17 +381,19 @@ public class JavaBuilder extends ModuleLevelBuilder {
DiagnosticOutputConsumer diagnosticSink,
OutputFileConsumer outputSink,
JavaCompilingTool compilingTool,
- boolean hasModules) {
+ File moduleInfoFile) {
final Semaphore counter = new Semaphore();
COUNTER_KEY.set(context, counter);
final Set modules = chunk.getModules();
ProcessorConfigProfile profile = null;
+ final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getCompilerConfiguration(
+ context.getProjectDescriptor().getProject()
+ );
+ assert compilerConfig != null;
+
if (modules.size() == 1) {
- final JpsJavaCompilerConfiguration compilerConfig =
- JpsJavaExtensionService.getInstance().getCompilerConfiguration(context.getProjectDescriptor().getProject());
- assert compilerConfig != null;
profile = compilerConfig.getAnnotationProcessingProfile(modules.iterator().next());
}
else {
@@ -436,12 +446,24 @@ public class JavaBuilder extends ModuleLevelBuilder {
Collection modulePath = Collections.emptyList();
Collection extends File> upgradeModulePath = Collections.emptyList();
- if (hasModules) {
- // in Java 9, named modules are not allowed to read classes from the classpath
- // moreover, the compiler requires all transitive dependencies to be on the module path
- modulePath = ProjectPaths.getCompilationModulePath(chunk, false);
- classPath = Collections.emptyList();
- // modules located above the JDK make a module upgrade path
+ if (moduleInfoFile != null) { // has modules
+ final boolean useModulePathOnly = Boolean.parseBoolean(System.getProperty(USE_MODULE_PATH_ONLY_OPTION))/*compilerConfig.useModulePathOnly()*/;
+ if (useModulePathOnly) {
+ // in Java 9, named modules are not allowed to read classes from the classpath
+ // moreover, the compiler requires all transitive dependencies to be on the module path
+ modulePath = ProjectPaths.getCompilationModulePath(chunk, false);
+ classPath = Collections.emptyList();
+ }
+ else {
+ // placing only explicitly referenced modules into the module path and the rest of deps to classpath
+ final ModulePathSplitter splitter = MODULE_PATH_SPLITTER.get(context);
+ final Pair, Collection> pair = splitter.splitPath(
+ moduleInfoFile, outs.keySet(), ProjectPaths.getCompilationModulePath(chunk, false)
+ );
+ modulePath = pair.first;
+ classPath = pair.second;
+ }
+ // modules above the JDK in the order entry list make a module upgrade path
upgradeModulePath = platformCp;
platformCp = Collections.emptyList();
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ModulePathSplitter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ModulePathSplitter.java
new file mode 100644
index 000000000000..d39d4a3b3d87
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ModulePathSplitter.java
@@ -0,0 +1,147 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+import com.thoughtworks.qdox.JavaProjectBuilder;
+import com.thoughtworks.qdox.library.OrderedClassLibraryBuilder;
+import com.thoughtworks.qdox.model.JavaModule;
+import com.thoughtworks.qdox.model.JavaModuleDescriptor;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.javac.JpsJavacFileManager;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 26-Sep-19
+ */
+public class ModulePathSplitter {
+
+ private final Map myCache = Collections.synchronizedMap(new THashMap<>(FileUtil.FILE_HASHING_STRATEGY));
+ private static final Method myModuleFinderCreateMethod;
+ private static final Method myFindAll;
+ private static final Method myGetDescriptor;
+ private static final Method myDescriptorName;
+ private static final Method myRequiresName;
+ private static final Method myDescriptorRequires;
+
+ static {
+ Method of = null;
+ Method findAll = null;
+ Method getDescriptor = null;
+ Method descriptorName = null;
+ Method requiresName = null;
+ Method descriptorRequires = null;
+ try {
+ final Class> finderClass = Class.forName("java.lang.module.ModuleFinder");
+ final Class> descriptorClass = Class.forName("java.lang.module.ModuleDescriptor");
+ final Class> referenceClass = Class.forName("java.lang.module.ModuleReference");
+ final Class> requireClass = Class.forName("java.lang.module.ModuleDescriptor$Requires");
+ of = finderClass.getDeclaredMethod("of", Path[].class);
+ findAll = finderClass.getDeclaredMethod("findAll");
+ getDescriptor = referenceClass.getDeclaredMethod("descriptor");
+ descriptorName = descriptorClass.getDeclaredMethod("name");
+ descriptorRequires = descriptorClass.getDeclaredMethod("requires");
+ requiresName = requireClass.getDeclaredMethod("name");
+ }
+ catch (Throwable ignored) {
+ }
+ myModuleFinderCreateMethod = of;
+ myFindAll = findAll;
+ myGetDescriptor = getDescriptor;
+ myDescriptorName = descriptorName;
+ myRequiresName = requiresName;
+ myDescriptorRequires = descriptorRequires;
+ }
+
+ public ModulePathSplitter() {
+ }
+
+ public Pair, Collection> splitPath(File chunkModuleInfo, Set chunkOutputs, Collection path) {
+ if (myModuleFinderCreateMethod == null) {
+ // the module API is not available
+ return Pair.create(path, Collections.emptyList());
+ }
+ final List modulePath = new ArrayList<>();
+ final List classpath = new ArrayList<>();
+
+ final Set allRequired = collectRequired(chunkModuleInfo, JpsJavacFileManager.filter(path, file -> !chunkOutputs.contains(file)));
+ for (File file : path) {
+ (chunkOutputs.contains(file) || allRequired.contains(getModuleInfo(file).name) ? modulePath : classpath).add(file);
+ }
+ return Pair.create(Collections.unmodifiableList(modulePath), Collections.unmodifiableList(classpath));
+ }
+
+ private Set collectRequired(File chunkModuleInfo, Iterable extends File> path) {
+ final Set result = new HashSet<>();
+ // first, add all requires from chunk module-info
+ final JavaModuleDescriptor chunkDescr = new JavaProjectBuilder(new OrderedClassLibraryBuilder()).addSourceFolder(chunkModuleInfo.getParentFile()).getDescriptor();
+ for (JavaModuleDescriptor.JavaRequires require : chunkDescr.getRequires()) {
+ final JavaModule rm = require.getModule();
+ if (rm != null) {
+ result.add(rm.getName());
+ }
+ }
+ for (File file : path) {
+ result.addAll(getModuleInfo(file).requires);
+ }
+ return result;
+ }
+
+ @NotNull
+ private ModuleInfo getModuleInfo(File f) {
+ ModuleInfo info = myCache.get(f);
+ if (info != null) {
+ return info;
+ }
+ info = ModuleInfo.EMPTY;
+
+ try {
+ Object mf = myModuleFinderCreateMethod.invoke(null, (Object)new Path[]{f.toPath()}); // ModuleFinder.of(f.toPath());
+ for (Object moduleRef : (Set)myFindAll.invoke(mf)) { // mf.findAll()
+ final Object descriptor = myGetDescriptor.invoke(moduleRef); // moduleRef.descriptor()
+ final String moduleName = (String)myDescriptorName.invoke(descriptor); // descriptor.name();
+ final Set requires = (Set)myDescriptorRequires.invoke(descriptor); //descriptor.requires();
+ if (requires.isEmpty()) {
+ info = new ModuleInfo(moduleName);
+ }
+ else {
+ final Set req = new HashSet<>();
+ for (Object require : requires) {
+ req.add((String)myRequiresName.invoke(require)/*require.name()*/);
+ }
+ info = new ModuleInfo(moduleName, req);
+ }
+ break;
+ }
+ }
+ catch (Throwable ignored) {
+ }
+ myCache.put(f, info);
+ return info;
+ }
+
+ private static final class ModuleInfo {
+ static final ModuleInfo EMPTY = new ModuleInfo(null, Collections.emptyList());
+
+ @Nullable
+ final String name;
+ @NotNull
+ final Collection requires;
+
+ ModuleInfo(String name) {
+ this(name, Collections.emptyList());
+ }
+
+ ModuleInfo(@Nullable String name, @NotNull Collection requires) {
+ this.name = name;
+ this.requires = Collections.unmodifiableCollection(requires);
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
index f94a6e601239..c32329d484a9 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
@@ -219,8 +219,12 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase {
}
protected JpsLibrary addLibrary(final String jarPath) {
- JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
- library.addRoot(new File(getAbsolutePath(jarPath)), JpsOrderRootType.COMPILED);
+ return addLibrary("l", new File(getAbsolutePath(jarPath)));
+ }
+
+ protected JpsLibrary addLibrary(final String libraryName, final File jarFile) {
+ JpsLibrary library = myProject.addLibrary(libraryName, JpsJavaLibraryType.INSTANCE);
+ library.addRoot(jarFile, JpsOrderRootType.COMPILED);
return library;
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/Java9Test.java b/jps/jps-builders/testSrc/org/jetbrains/ether/Java9Test.java
index f46613dd9a82..51616e7ec70d 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/ether/Java9Test.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/Java9Test.java
@@ -1,9 +1,24 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.ether;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.builders.BuildResult;
import org.jetbrains.jps.builders.CompileScopeTestBuilder;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.incremental.java.ModulePathSplitter;
+import org.jetbrains.jps.model.JpsModuleRootModificationUtil;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
/**
* @author Eugene Zhuravlev
@@ -101,4 +116,38 @@ public class Java9Test extends IncrementalTestCase {
modify(1);
doBuild(CompileScopeTestBuilder.make().allModules()).assertFailed();
}
+
+ public void testSplitModulePath() {
+ setupInitialProject();
+ final Map modules = setupModules();
+
+ assertEquals(1, modules.size());
+
+ final JpsModule module = modules.values().iterator().next();
+ final ModuleBuildTarget target = new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION);
+
+ final File outputDir = target.getOutputDir();
+ final File libDir = new File(getAbsolutePath("lib"));
+ for (File jarFile : libDir.listFiles((dir, name) -> name.endsWith(".jar"))) {
+ JpsLibrary lib = addLibrary(jarFile.getName(), jarFile);
+ JpsModuleRootModificationUtil.addDependency(module, lib, JpsJavaDependencyScope.COMPILE, false);
+ }
+
+ final File moduleInfoPath = new File(getAbsolutePath("moduleA/src/module-info.java"));
+
+ final ModulePathSplitter splitter = new ModulePathSplitter();
+ final Collection dependencies = ProjectPaths.getCompilationModulePath(new ModuleChunk(Collections.singleton(target)), false);
+ final Pair, Collection> split = splitter.splitPath(moduleInfoPath, Collections.singleton(outputDir), dependencies);
+ final Collection modulePath = split.first;
+ final Collection classpath = split.second;
+
+ assertEquals(4, modulePath.size());
+ assertTrue(modulePath.contains(outputDir));
+ assertTrue(modulePath.contains(new File(libDir, "module_lib_1.jar")));
+ assertTrue(modulePath.contains(new File(libDir, "module_lib_2.jar")));
+ assertTrue(modulePath.contains(new File(libDir, "module_lib_util.jar")));
+
+ assertEquals(1, classpath.size());
+ assertTrue(classpath.contains(new File(libDir, "module_lib_3.jar")));
+ }
}
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy
index 32d8d8f76e66..3a54c37469f1 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy
@@ -593,6 +593,9 @@ class CommunityLibraryLicenses {
new LibraryLicense(name: "XZ for Java", libraryName: "xz", version: "1.5", license: "Public Domain",
url: "http://tukaani.org/xz/java.html"),
+ new LibraryLicense(name: "qdox-java-parser", libraryName: "qdox-java-parser", version: "2.0", license: "Apache 2.0",
+ url: "https://github.com/paul-hammant/qdox", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0"),
+
jetbrainsLibrary("completion-ranking-java"),
jetbrainsLibrary("completion-ranking-kotlin"),