diff --git a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java index d82f710adc7d..6b0c06f3b6a1 100644 --- a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java @@ -145,6 +145,42 @@ public class ModuleScopesTest extends ModuleTestCase { assertTrue(deps.contains(file)); } + public void testModuleContentWithDependenciesScopeRootOrdering() throws IOException { + Module m = createModule("m.iml", StdModuleTypes.JAVA); + Module a = createModule("a.iml", StdModuleTypes.JAVA); + Module b = createModule("b.iml", StdModuleTypes.JAVA); + Module c = createModule("c.iml", StdModuleTypes.JAVA); + + ModuleRootModificationUtil.addDependency(b, m, DependencyScope.COMPILE, true); + ModuleRootModificationUtil.addDependency(a, b, DependencyScope.COMPILE, true); + ModuleRootModificationUtil.addDependency(a, m, DependencyScope.COMPILE, true); + ModuleRootModificationUtil.addDependency(c, a, DependencyScope.COMPILE, true); + + VirtualFile mRoot = myFixture.findOrCreateDir("m"); + PsiTestUtil.addSourceContentToRoots(m, mRoot); + VirtualFile aRoot = myFixture.findOrCreateDir("a"); + PsiTestUtil.addSourceContentToRoots(a, aRoot); + VirtualFile bRoot = myFixture.findOrCreateDir("b"); + PsiTestUtil.addSourceContentToRoots(b, bRoot); + VirtualFile cRoot = myFixture.findOrCreateDir("c"); + PsiTestUtil.addSourceContentToRoots(c, cRoot); + VirtualFile file = cRoot.createChildData(this, "x.txt"); + + GlobalSearchScope deps = c.getModuleContentWithDependenciesScope(); + assertTrue(deps.contains(file)); + + assertTrue(deps.compare(mRoot, aRoot) < 0); + assertTrue(deps.compare(mRoot, bRoot) < 0); + assertTrue(deps.compare(mRoot, cRoot) < 0); + assertTrue(deps.compare(bRoot, aRoot) < 0); + assertTrue(deps.compare(bRoot, cRoot) < 0); + assertTrue(deps.compare(aRoot, cRoot) < 0); + assertTrue(deps.compare(cRoot, mRoot) > 0); + assertTrue(deps.compare(cRoot, aRoot) > 0); + assertTrue(deps.compare(cRoot, bRoot) > 0); + assertEquals(0, deps.compare(cRoot, cRoot)); + } + public void testTestOnlyLibraryDependency() throws IOException { Module m = createModule("a.iml", StdModuleTypes.JAVA); addLibrary(m, DependencyScope.TEST); diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java index bfc6114a0f16..53ffff527843 100644 --- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java +++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java @@ -24,7 +24,6 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.NotNullFunction; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; -import gnu.trove.THashSet; import gnu.trove.TObjectIntHashMap; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; @@ -50,7 +49,7 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope { private final ProjectFileIndex myProjectFileIndex; - private final Set myModules; + private volatile Set myModules; private final TObjectIntHashMap myRoots = new TObjectIntHashMap(); public ModuleWithDependenciesScope(@NotNull Module module, @ScopeConstant int options) { @@ -60,39 +59,11 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope { myProjectFileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex(); - OrderEnumerator en = ModuleRootManager.getInstance(module).orderEntries(); - en.recursively(); - - if (hasOption(COMPILE)) { - en.exportedOnly().compileOnly(); - } - if (hasOption(RUNTIME)) { - en.runtimeOnly(); - } - if (!hasOption(LIBRARIES)) en.withoutLibraries().withoutSdk(); - if (!hasOption(MODULES)) en.withoutDepModules(); - if (!hasOption(TESTS)) en.productionOnly(); - - final LinkedHashSet modules = ContainerUtil.newLinkedHashSet(); - - en.forEach(new Processor() { - @Override - public boolean process(OrderEntry each) { - if (each instanceof ModuleOrderEntry) { - ContainerUtil.addIfNotNull(modules, ((ModuleOrderEntry)each).getModule()); - } - else if (each instanceof ModuleSourceOrderEntry) { - ContainerUtil.addIfNotNull(modules, each.getOwnerModule()); - } - return true; - } - }); - - myModules = new THashSet(modules); - final LinkedHashSet roots = ContainerUtil.newLinkedHashSet(); if (hasOption(CONTENT)) { + Set modules = calcModules(); + myModules = ContainerUtil.newTroveSet(modules); for (Module m : modules) { for (ContentEntry entry : ModuleRootManager.getInstance(m).getContentEntries()) { ContainerUtil.addIfNotNull(entry.getFile(), roots); @@ -100,6 +71,7 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope { } } else { + OrderEnumerator en = getOrderEnumeratorForOptions(); Collections.addAll(roots, en.roots(new NotNullFunction() { @NotNull @Override @@ -116,6 +88,43 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope { } } + private OrderEnumerator getOrderEnumeratorForOptions() { + OrderEnumerator en = ModuleRootManager.getInstance(myModule).orderEntries(); + en.recursively(); + + if (hasOption(COMPILE)) { + en.exportedOnly().compileOnly(); + } + if (hasOption(RUNTIME)) { + en.runtimeOnly(); + } + if (!hasOption(LIBRARIES)) en.withoutLibraries().withoutSdk(); + if (!hasOption(MODULES)) en.withoutDepModules(); + if (!hasOption(TESTS)) en.productionOnly(); + return en; + } + + @NotNull + private Set calcModules() { + // In the case that hasOption(CONTENT), the order of the modules set matters for + // ordering the content roots, so use a LinkedHashSet + final Set modules = ContainerUtil.newLinkedHashSet(); + OrderEnumerator en = getOrderEnumeratorForOptions(); + en.forEach(new Processor() { + @Override + public boolean process(OrderEntry each) { + if (each instanceof ModuleOrderEntry) { + ContainerUtil.addIfNotNull(modules, ((ModuleOrderEntry)each).getModule()); + } + else if (each instanceof ModuleSourceOrderEntry) { + ContainerUtil.addIfNotNull(modules, each.getOwnerModule()); + } + return true; + } + }); + return modules; + } + @NotNull public Module getModule() { return myModule; @@ -134,7 +143,11 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope { @Override public boolean isSearchInModuleContent(@NotNull Module aModule) { - return myModules.contains(aModule); + Set allModules = myModules; + if (allModules == null) { + myModules = allModules = ContainerUtil.newTroveSet(calcModules()); + } + return allModules.contains(aModule); } @Override