diff --git a/jps/src/org/jetbrains/jps/Module.groovy b/jps/src/org/jetbrains/jps/Module.groovy index 04efb43da8ea..4a593fb96ec4 100644 --- a/jps/src/org/jetbrains/jps/Module.groovy +++ b/jps/src/org/jetbrains/jps/Module.groovy @@ -11,6 +11,7 @@ class Module extends LazyInitializeableObject implements ClasspathItem {//}, Com Sdk sdk; private List dependencies = [] + List contentRoots = [] List sourceRoots = [] List testRoots = [] List excludes = [] @@ -54,6 +55,10 @@ class Module extends LazyInitializeableObject implements ClasspathItem {//}, Com dependencies << new ModuleDependency(new ModuleSourceEntry(module: this), PredefinedDependencyScopes.COMPILE, true) } + meta.content = {Object[] arg -> + arg.each { contentRoots << it} + } + meta.src = {Object[] arg -> arg.each { sourceRoots << it } } diff --git a/jps/src/org/jetbrains/jps/PathUtil.java b/jps/src/org/jetbrains/jps/PathUtil.java index c4da7b389c17..4c01b3701fb7 100644 --- a/jps/src/org/jetbrains/jps/PathUtil.java +++ b/jps/src/org/jetbrains/jps/PathUtil.java @@ -2,6 +2,7 @@ package org.jetbrains.jps; import java.io.File; import java.net.URI; +import java.util.Set; /** * @author nik @@ -17,4 +18,15 @@ public class PathUtil { } return new File(uri).getAbsolutePath(); } + + public static boolean isUnder(Set ancestors, File file) { + File current = file; + while (current != null) { + if (ancestors.contains(current)) { + return true; + } + current = current.getParentFile(); + } + return false; + } } diff --git a/jps/src/org/jetbrains/jps/ProjectBuilder.groovy b/jps/src/org/jetbrains/jps/ProjectBuilder.groovy index c1ce38c8a523..b7e5fa08461e 100644 --- a/jps/src/org/jetbrains/jps/ProjectBuilder.groovy +++ b/jps/src/org/jetbrains/jps/ProjectBuilder.groovy @@ -283,7 +283,7 @@ class ProjectBuilder { callback: callback, sourceFiles: sourceFiles, sourceRoots: chunkSources, - excludes: chunk.excludes, + excludes: computeExcludes(chunk.elements, chunkSources), classpath: chunkClasspath, sourceRootsFromModuleWithDependencies: sourceRootsWithDependencies, ) @@ -301,7 +301,7 @@ class ProjectBuilder { callback: callback, sourceFiles: sourceFiles, sourceRoots: sourceRoots, - excludes: it.excludes, + excludes: computeExcludes([it], sourceRoots), classpath: chunkClasspath, targetFolder: createOutputFolder(it.name, it, tests), sourceRootsFromModuleWithDependencies: sourceRootsWithDependencies @@ -362,6 +362,38 @@ class ProjectBuilder { } } + private List computeExcludes(Collection modules, List sourceRoots) { + Set otherModules = new HashSet(project.modules.values()) + otherModules.removeAll(modules) + + Set excludes = [] as Set + modules.each {Module module -> + excludes.addAll(module.excludes) + } + Set sourceRootFiles = sourceRoots.collect {new File(it)} as Set + otherModules.each {Module module -> + module.contentRoots.each { + if (PathUtil.isUnder(sourceRootFiles, new File(it))) { + excludes << it + } + } + } + + return excludes.asList() + } + + private Set getContentRootsUnder(Set root, Set modules) { + Set result = [] as Set + modules.each { + it.contentRoots.each {String contentRoot -> + if (PathUtil.isUnder(root, contentRoot)) { + result << contentRoot + } + } + } + return result + } + private String createOutputFolder(String name, Module module, boolean tests) { def dst = getProjectPaths().getModuleOutputDir(module, tests) if (dst == null) { diff --git a/jps/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy index 4d0a4778f40b..71dc85487c78 100644 --- a/jps/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy +++ b/jps/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy @@ -368,6 +368,10 @@ public class IdeaProjectLoader { def srcFolderExists = componentTag.content.sourceFolder[0] != null; + componentTag.content.each {Node contentTag -> + content moduleMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(contentTag.@url)) + } + componentTag.content.sourceFolder.each {Node folderTag -> String path = moduleMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(folderTag.@url)) String prefix = folderTag.@packagePrefix diff --git a/jps/testSrc/org/jetbrains/jps/OverlappingSourceRootsTest.groovy b/jps/testSrc/org/jetbrains/jps/OverlappingSourceRootsTest.groovy new file mode 100644 index 000000000000..767fcc291c15 --- /dev/null +++ b/jps/testSrc/org/jetbrains/jps/OverlappingSourceRootsTest.groovy @@ -0,0 +1,24 @@ +package org.jetbrains.jps + +/** + * @author nik + */ +public class OverlappingSourceRootsTest extends JpsBuildTestCase { + public void test() throws Exception { + doTest("testData/overlappingSourceRoots/overlappingSourceRoots.ipr", {}, { + dir("production") { + dir("inner") { + dir("y") { + file("a.properties") + file("Class2.class") + } + } + dir("overlappingSourceRoots") { + dir("x") { + file("MyClass.class") + } + } + } + }) + } +}