diff --git a/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java b/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java index 8855a16ae9b0..6fda7f0efd7a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java +++ b/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java @@ -1,18 +1,22 @@ package org.jetbrains.jps; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.JpsDummyElement; import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.JpsSimpleElement; -import org.jetbrains.jps.model.java.JavaSourceRootProperties; -import org.jetbrains.jps.model.java.JavaSourceRootType; -import org.jetbrains.jps.model.java.JpsJavaClasspathKind; -import org.jetbrains.jps.model.java.JpsJavaExtensionService; -import org.jetbrains.jps.model.library.JpsLibrary; +import org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.library.JpsOrderRootType; -import org.jetbrains.jps.model.module.*; +import org.jetbrains.jps.model.library.sdk.JpsSdk; +import org.jetbrains.jps.model.module.JpsDependencyElement; +import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleSourceRoot; +import org.jetbrains.jps.model.module.JpsSdkDependency; import java.io.File; import java.util.*; @@ -21,93 +25,69 @@ import java.util.*; * @author Eugene Zhuravlev * Date: 9/30/11 */ -//todo[nik] use JpsDependenciesEnumerator instead public class ProjectPaths { private static final String DEFAULT_GENERATED_DIR_NAME = "generated"; @NotNull private final JpsProject myProject; //private final Map>> myCachedClasspath = new HashMap>>(); - public ProjectPaths(JpsProject project) { + public ProjectPaths(@NotNull JpsProject project) { myProject = project; } - public Collection getClasspathFiles(ModuleChunk chunk, JpsJavaClasspathKind kind) { - return getClasspathFiles(chunk, kind, !kind.isRuntime()); + public Collection getCompilationClasspathFiles(ModuleChunk chunk, boolean includeTests) { + return getCompilationClasspathFiles(chunk, includeTests, true, true); } - public List getClasspath(ModuleChunk chunk, JpsJavaClasspathKind kind) { - return getPathsList(getClasspathFiles(chunk, kind)); - } - - public Collection getClasspathFiles(ModuleChunk chunk, JpsJavaClasspathKind kind, final boolean excludeMainModuleOutput) { - return getClasspathFiles(chunk, kind, excludeMainModuleOutput, ClasspathPart.WHOLE); + public Collection getCompilationClasspathFiles(ModuleChunk chunk, + boolean includeTests, + final boolean excludeMainModuleOutput, + final boolean exportedOnly) { + return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(includeTests), excludeMainModuleOutput, ClasspathPart.WHOLE, exportedOnly); } public Collection getPlatformCompilationClasspath(ModuleChunk chunk, boolean excludeMainModuleOutput) { - return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.isTests()), excludeMainModuleOutput, ClasspathPart.BEFORE_JDK); + return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.isTests()), excludeMainModuleOutput, ClasspathPart.BEFORE_JDK, true); } public Collection getCompilationClasspath(ModuleChunk chunk, boolean excludeMainModuleOutput) { - return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.isTests()), excludeMainModuleOutput, ClasspathPart.AFTER_JDK); + return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.isTests()), excludeMainModuleOutput, ClasspathPart.AFTER_JDK, true); } - private Collection getClasspathFiles(ModuleChunk chunk, JpsJavaClasspathKind kind, final boolean excludeMainModuleOutput, ClasspathPart classpathPart) { + private Collection getClasspathFiles(ModuleChunk chunk, + JpsJavaClasspathKind kind, + final boolean excludeMainModuleOutput, + ClasspathPart classpathPart, final boolean exportedOnly) { final Set files = new LinkedHashSet(); for (JpsModule module : chunk.getModules()) { - final ClasspathItemFilter filter = classpathPart == ClasspathPart.WHOLE ? ACCEPT_ALL : - classpathPart == ClasspathPart.BEFORE_JDK ? new BeforeSdkItemFilter(module) : new NotFilter(new BeforeSdkItemFilter(module)); - collectClasspath(module, kind, files, new HashSet(), false, excludeMainModuleOutput, false, filter); + JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(module).includedIn(kind).recursively(); + if (exportedOnly) { + enumerator = enumerator.exportedOnly(); + } + if (classpathPart == ClasspathPart.BEFORE_JDK) { + enumerator = enumerator.satisfying(new BeforeSdkItemFilter(module)); + } + else if (classpathPart == ClasspathPart.AFTER_JDK) { + enumerator = enumerator.satisfying(Conditions.not(new BeforeSdkItemFilter(module))).withoutSdk(); + } + JpsJavaDependenciesRootsEnumerator rootsEnumerator = enumerator.classes(); + if (excludeMainModuleOutput) { + rootsEnumerator = rootsEnumerator.withoutSelfModuleOutput(); + } + files.addAll(rootsEnumerator.getRoots()); + } + + if (classpathPart == ClasspathPart.BEFORE_JDK) { + for (JpsModule module : chunk.getModules()) { + JpsSdk sdk = module.getSdk(JpsJavaSdkType.INSTANCE); + if (sdk != null) { + files.addAll(sdk.getParent().getFiles(JpsOrderRootType.COMPILED)); + } + } } return files; } - private void collectClasspath(JpsModule module, JpsJavaClasspathKind kind, Set classpath, Set processed, boolean exportedOnly, - boolean excludeMainModuleOutput, final boolean excludeSdk, ClasspathItemFilter filter) { - if (!processed.add(module)) { - return; - } - - for (JpsDependencyElement it : JpsJavaExtensionService.getInstance().getDependencies(module, kind, exportedOnly)) { - if (!filter.accept(module, it) || it instanceof JpsSdkDependency && excludeSdk) { - continue; - } - - if (it instanceof JpsModuleSourceDependency) { - if (!excludeMainModuleOutput && kind.isTestsIncluded()) { - final File out = getModuleOutputDir(module, true); - if (out != null) { - classpath.add(out); - } - } - if (!excludeMainModuleOutput || kind.isTestsIncluded()) { - final File out = getModuleOutputDir(module, false); - if (out != null) { - classpath.add(out); - } - } - } - else if (it instanceof JpsModuleDependency) { - final JpsModule dep = ((JpsModuleDependency)it).getModule(); - if (dep != null) { - collectClasspath(dep, kind, classpath, processed, !kind.isRuntime(), false, true, filter); - } - } - else if (it instanceof JpsLibraryDependency) { - addLibraryFiles(classpath, ((JpsLibraryDependency)it).getLibrary()); - } - else if (it instanceof JpsSdkDependency) { - addLibraryFiles(classpath, ((JpsSdkDependency)it).resolveSdk()); - } - } - } - - private static void addLibraryFiles(Set classpath, @Nullable JpsLibrary library) { - if (library != null) { - classpath.addAll(library.getFiles(JpsOrderRootType.COMPILED)); - } - } - private static void addFile(Set classpath, @Nullable String url) { if (url != null) { classpath.add(JpsPathUtil.urlToFile(url)); @@ -123,17 +103,19 @@ public class ProjectPaths { } /** + * * @param chunk - * @param includeTests * @return mapping "sourceRoot" -> "package prefix" Package prefix uses slashes instead of dots and ends with trailing slash */ - public static Map getSourceRootsWithDependents(ModuleChunk chunk, boolean includeTests) { + public static Map getSourceRootsWithDependents(ModuleChunk chunk) { + final boolean includeTests = chunk.isTests(); final Map result = new LinkedHashMap(); - collectPathsRecursively(chunk, JpsJavaClasspathKind.compile(includeTests), new PathsGetter() { - public void apply(JpsModule module, JpsJavaClasspathKind kind) { + processModulesRecursively(chunk, JpsJavaClasspathKind.compile(includeTests), new Consumer() { + @Override + public void consume(JpsModule module) { for (JpsModuleSourceRoot root : module.getSourceRoots()) { if (root.getRootType().equals(JavaSourceRootType.SOURCE) || - kind.isTestsIncluded() && root.getRootType().equals(JavaSourceRootType.TEST_SOURCE)) { + includeTests && root.getRootType().equals(JavaSourceRootType.TEST_SOURCE)) { JavaSourceRootProperties properties = (JavaSourceRootProperties)((JpsSimpleElement)root.getProperties()).getData(); String prefix = properties.getPackagePrefix(); if (!prefix.isEmpty()) { @@ -153,10 +135,12 @@ public class ProjectPaths { return result; } - public static Collection getOutputPathsWithDependents(final ModuleChunk chunk, final boolean forTests) { + public static Collection getOutputPathsWithDependents(final ModuleChunk chunk) { + final boolean forTests = chunk.isTests(); final Set sourcePaths = new LinkedHashSet(); - collectPathsRecursively(chunk, JpsJavaClasspathKind.compile(forTests), new PathsGetter() { - public void apply(JpsModule module, JpsJavaClasspathKind kind) { + processModulesRecursively(chunk, JpsJavaClasspathKind.compile(forTests), new Consumer() { + @Override + public void consume(JpsModule module) { addFile(sourcePaths, JpsJavaExtensionService.getInstance().getOutputUrl(module, forTests)); } }); @@ -164,40 +148,11 @@ public class ProjectPaths { } public static Set getModulesWithDependentsRecursively(final JpsModule module, final boolean includeTests) { - final Set result = new HashSet(); - collectPathsRecursively(module, JpsJavaClasspathKind.compile(includeTests), new HashSet(), new PathsGetter() { - public void apply(JpsModule module, JpsJavaClasspathKind kind) { - result.add(module); - } - }); - return result; + return JpsJavaExtensionService.dependencies(module).includedIn(JpsJavaClasspathKind.compile(includeTests)).recursively().getModules(); } - private interface PathsGetter { - void apply(JpsModule module, JpsJavaClasspathKind kind); - } - - private static void collectPathsRecursively(ModuleChunk chunk, JpsJavaClasspathKind kind, PathsGetter proc) { - final HashSet processed = new HashSet(); - for (JpsModule module : chunk.getModules()) { - collectPathsRecursively(module, kind, processed, proc); - } - } - - private static void collectPathsRecursively(JpsModule module, JpsJavaClasspathKind kind, Set processed, PathsGetter processor) { - if (processed.add(module)) { - for (JpsDependencyElement item : JpsJavaExtensionService.getInstance().getDependencies(module, kind, false)) { - if (item instanceof JpsModuleSourceDependency) { - processor.apply(module, kind); - } - else if (item instanceof JpsModuleDependency) { - final JpsModule dep = ((JpsModuleDependency)item).getModule(); - if (dep != null) { - collectPathsRecursively(dep, kind, processed, processor); - } - } - } - } + private static void processModulesRecursively(ModuleChunk chunk, JpsJavaClasspathKind kind, Consumer processor) { + JpsJavaExtensionService.getInstance().enumerateDependencies(chunk.getModules()).includedIn(kind).recursively().processModules(processor); } @Nullable @@ -236,33 +191,14 @@ public class ProjectPaths { } public List getProjectRuntimeClasspath(boolean includeTests) { - Set classpath = new LinkedHashSet(); final JpsJavaClasspathKind kind = JpsJavaClasspathKind.runtime(includeTests); - for (JpsModule module : myProject.getModules()) { - collectClasspath(module, kind, classpath, new HashSet(), false, false, false, WITHOUT_DEP_MODULES); - } + Set classpath = new LinkedHashSet(JpsJavaExtensionService.dependencies(myProject).includedIn(kind).withoutDepModules().classes().getRoots()); return getPathsList(classpath); } - private interface ClasspathItemFilter { - boolean accept(JpsModule module, JpsDependencyElement item); - } - private enum ClasspathPart {WHOLE, BEFORE_JDK, AFTER_JDK} - private static final ClasspathItemFilter ACCEPT_ALL = new ClasspathItemFilter() { - public boolean accept(JpsModule module, JpsDependencyElement item) { - return true; - } - }; - - private static final ClasspathItemFilter WITHOUT_DEP_MODULES = new ClasspathItemFilter() { - public boolean accept(JpsModule module, JpsDependencyElement item) { - return !(item instanceof JpsModuleDependency); - } - }; - - private static class BeforeSdkItemFilter implements ClasspathItemFilter { + private static class BeforeSdkItemFilter implements Condition { private JpsModule myModule; private boolean mySdkFound; @@ -270,24 +206,12 @@ public class ProjectPaths { myModule = module; } - public boolean accept(JpsModule module, JpsDependencyElement item) { - if (myModule.equals(module) && item instanceof JpsSdkDependency) { + @Override + public boolean value(JpsDependencyElement dependency) { + if (myModule.equals(dependency.getContainingModule()) && dependency instanceof JpsSdkDependency) { mySdkFound = true; - return true; } - return !mySdkFound && !(item instanceof JpsSdkDependency); - } - } - - private static class NotFilter implements ClasspathItemFilter { - private ClasspathItemFilter myFilter; - - private NotFilter(ClasspathItemFilter filter) { - myFilter = filter; - } - - public boolean accept(JpsModule module, JpsDependencyElement item) { - return !myFilter.accept(module, item); + return !mySdkFound && !(dependency instanceof JpsSdkDependency); } } 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 1045e9ae4cbb..547ff41c81ee 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 @@ -322,7 +322,7 @@ public class JavaBuilder extends ModuleLevelBuilder { context.checkCanceled(); if (!forms.isEmpty() || addNotNullAssertions) { - final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, chunk.isTests()); + final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk); final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, chunkSourcePath, outputSink); try { @@ -919,7 +919,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } final MyNestedFormLoader nestedFormsLoader = - new MyNestedFormLoader(chunkSourcePath, ProjectPaths.getOutputPathsWithDependents(chunk, chunk.isTests())); + new MyNestedFormLoader(chunkSourcePath, ProjectPaths.getOutputPathsWithDependents(chunk)); for (File formFile : formsToInstrument) { final LwRootContainer rootContainer; diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy index 1325652934e8..39eb66f69e37 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy @@ -3,7 +3,6 @@ import com.intellij.openapi.util.io.FileUtil import org.jetbrains.jps.ModuleChunk import org.jetbrains.jps.ProjectPaths import org.jetbrains.jps.builders.rebuild.JpsRebuildTestCase -import org.jetbrains.jps.model.java.JpsJavaClasspathKind /** * @author nik */ @@ -22,35 +21,22 @@ public class ModuleClasspathTest extends JpsRebuildTestCase { } public void testSimpleClasspath() { - assertClasspath('util', JpsJavaClasspathKind.PRODUCTION_COMPILE, ["util/lib/exported.jar", "/jdk15.jar"]) - assertClasspath('util', JpsJavaClasspathKind.PRODUCTION_RUNTIME, ["util/lib/exported.jar", "/jdk15.jar", "out/production/util"]) + assertClasspath('util', false, ["util/lib/exported.jar", "/jdk15.jar"]) } public void testScopes() { - assertClasspath("test-util", JpsJavaClasspathKind.PRODUCTION_COMPILE, + assertClasspath("test-util", false, ["/jdk.jar", "test-util/lib/provided.jar"]) - assertClasspath("test-util", JpsJavaClasspathKind.TEST_COMPILE, + assertClasspath("test-util", true, ["/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/test.jar", "out/production/test-util"]) - assertClasspath("test-util", JpsJavaClasspathKind.PRODUCTION_RUNTIME, - ["/jdk.jar", "test-util/lib/runtime.jar", "out/production/test-util"]) - assertClasspath("test-util", JpsJavaClasspathKind.TEST_RUNTIME, - ["/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/runtime.jar", - "test-util/lib/test.jar", "out/test/test-util", "out/production/test-util"]) } public void testDepModules() { - assertClasspath("main", JpsJavaClasspathKind.PRODUCTION_COMPILE, + assertClasspath("main", false, ["util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"]) - assertClasspath("main", JpsJavaClasspathKind.TEST_COMPILE, + assertClasspath("main", true, ["out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar", "out/test/test-util", "out/production/test-util", "main/lib/service.jar"]) - - assertClasspath("main", JpsJavaClasspathKind.PRODUCTION_RUNTIME, - ["out/production/main", "util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"]) - assertClasspath("main", JpsJavaClasspathKind.TEST_RUNTIME, - ["out/test/main", "out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar", - "test-util/lib/provided.jar", "test-util/lib/runtime.jar", "test-util/lib/test.jar", "out/test/test-util", - "out/production/test-util","main/lib/service.jar"]) } public void testCompilationClasspath() { @@ -72,9 +58,9 @@ public class ModuleClasspathTest extends JpsRebuildTestCase { return new ProjectPaths(myJpsProject) } - private def assertClasspath(String moduleName, JpsJavaClasspathKind classpathKind, List expected) { + private def assertClasspath(String moduleName, boolean includeTests, List expected) { ModuleChunk chunk = createChunk(moduleName) - final List classpath = new ProjectPaths(myJpsProject).getClasspath(chunk, classpathKind) + final List classpath = ProjectPaths.getPathsList(new ProjectPaths(myJpsProject).getCompilationClasspathFiles(chunk, includeTests)) assertClasspath(expected, toSystemIndependentPaths(classpath)) } diff --git a/jps/model-api/jps-model-api.iml b/jps/model-api/jps-model-api.iml index 4d3f06e41375..7e88b0067116 100644 --- a/jps/model-api/jps-model-api.iml +++ b/jps/model-api/jps-model-api.iml @@ -8,6 +8,7 @@ + diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java index 0795089ff882..5f983abed999 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java @@ -1,6 +1,8 @@ package org.jetbrains.jps.model.java; +import com.intellij.openapi.util.Condition; import org.jetbrains.jps.model.module.JpsDependenciesEnumerator; +import org.jetbrains.jps.model.module.JpsDependencyElement; /** * @author nik @@ -19,6 +21,9 @@ public interface JpsJavaDependenciesEnumerator extends JpsDependenciesEnumerator @Override JpsJavaDependenciesEnumerator recursively(); + @Override + JpsJavaDependenciesEnumerator satisfying(Condition condition); + JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind); JpsJavaDependenciesRootsEnumerator classes(); diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java index aa7d98280b9b..ea2115530f49 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java +++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java @@ -1,5 +1,7 @@ package org.jetbrains.jps.model.module; +import com.intellij.openapi.util.Condition; +import com.intellij.util.Consumer; import org.jetbrains.jps.model.library.JpsLibrary; import java.util.Set; @@ -13,6 +15,10 @@ public interface JpsDependenciesEnumerator { JpsDependenciesEnumerator withoutSdk(); JpsDependenciesEnumerator withoutModuleSourceEntries(); JpsDependenciesEnumerator recursively(); + JpsDependenciesEnumerator satisfying(Condition condition); + Set getModules(); Set getLibraries(); + + void processModules(Consumer consumer); } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java index aea986f0491b..ed783c46fa46 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java @@ -1,5 +1,6 @@ package org.jetbrains.jps.model.module.impl; +import com.intellij.openapi.util.Condition; import com.intellij.util.CollectConsumer; import com.intellij.util.Consumer; import com.intellij.util.Processor; @@ -21,6 +22,7 @@ public abstract class JpsDependenciesEnumeratorBase myRootModules; + private Condition myCondition; protected JpsDependenciesEnumeratorBase(Collection rootModules) { myRootModules = rootModules; @@ -50,6 +52,12 @@ public abstract class JpsDependenciesEnumeratorBase condition) { + myCondition = condition; + return self(); + } + @Override public Self recursively() { myRecursively = true; @@ -65,6 +73,7 @@ public abstract class JpsDependenciesEnumeratorBase consumer) { processDependencies(new Processor() { @Override @@ -97,13 +106,17 @@ public abstract class JpsDependenciesEnumeratorBase(cp);