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 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 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 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"),