diff --git a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java index 180a8ee3c66a..514348e5913b 100644 --- a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java @@ -1,12 +1,29 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.roots; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.StdModuleTypes; +import com.intellij.openapi.module.impl.ModuleEx; import com.intellij.openapi.module.impl.scopes.LibraryScope; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.testFramework.ModuleTestCase; import com.intellij.testFramework.PsiTestUtil; import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; @@ -207,4 +224,28 @@ public class ModuleScopesTest extends ModuleTestCase { addLibrary(myModule, DependencyScope.COMPILE); assertTrue(myModule.getModuleWithDependenciesAndLibrariesScope(false).contains(file)); } + + public void testScopeEquality() { + Module module = createModule("a.iml", StdModuleTypes.JAVA); + addDependentModule(module, DependencyScope.COMPILE); + addLibrary(module, DependencyScope.COMPILE); + + GlobalSearchScope deps = module.getModuleWithDependentsScope(); + GlobalSearchScope depsTests = module.getModuleTestsWithDependentsScope(); + + assertFalse(deps.equals(depsTests)); + assertFalse(depsTests.equals(deps)); + + ((ModuleEx)module).clearScopesCache(); + + GlobalSearchScope deps2 = module.getModuleWithDependentsScope(); + GlobalSearchScope depsTests2 = module.getModuleTestsWithDependentsScope(); + + assertFalse(deps2.equals(depsTests2)); + assertFalse(depsTests2.equals(deps2)); + assertNotSame(deps, deps2); + assertNotSame(depsTests, depsTests2); + assertEquals(deps, deps2); + assertEquals(depsTests, depsTests2); + } } diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleScopeProviderImpl.java similarity index 78% rename from platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java rename to platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleScopeProviderImpl.java index 052c73022d53..2e7c581f0976 100644 --- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java +++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleScopeProviderImpl.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.module.impl; +package com.intellij.openapi.module.impl.scopes; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope; -import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope; +import com.intellij.openapi.module.impl.ModuleScopeProvider; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.ConcurrentIntObjectMap; import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap; import org.jetbrains.annotations.NotNull; @@ -27,16 +27,15 @@ import org.jetbrains.annotations.NotNull; */ public class ModuleScopeProviderImpl implements ModuleScopeProvider { private final Module myModule; - private final StripedLockIntObjectConcurrentHashMap myScopeCache = new StripedLockIntObjectConcurrentHashMap(); - private GlobalSearchScope myModuleWithDependentsScope; - private GlobalSearchScope myModuleTestsWithDependentsScope; + private final ConcurrentIntObjectMap myScopeCache = new StripedLockIntObjectConcurrentHashMap(); + private ModuleWithDependentsTestScope myModuleTestsWithDependentsScope; public ModuleScopeProviderImpl(@NotNull Module module) { myModule = module; } @NotNull - public GlobalSearchScope getCachedScope(@ModuleWithDependenciesScope.ScopeConstant int options) { + private GlobalSearchScope getCachedScope(@ModuleWithDependenciesScope.ScopeConstant int options) { GlobalSearchScope scope = myScopeCache.get(options); if (scope == null) { scope = new ModuleWithDependenciesScope(myModule, options); @@ -45,7 +44,6 @@ public class ModuleScopeProviderImpl implements ModuleScopeProvider { return scope; } - @Override @NotNull public GlobalSearchScope getModuleScope() { @@ -93,19 +91,15 @@ public class ModuleScopeProviderImpl implements ModuleScopeProvider { @Override @NotNull public GlobalSearchScope getModuleWithDependentsScope() { - GlobalSearchScope scope = myModuleWithDependentsScope; - if (scope == null) { - myModuleWithDependentsScope = scope = new ModuleWithDependentsScope(myModule, false); - } - return scope; + return getModuleTestsWithDependentsScope().getBaseScope(); } @Override @NotNull - public GlobalSearchScope getModuleTestsWithDependentsScope() { - GlobalSearchScope scope = myModuleTestsWithDependentsScope; + public ModuleWithDependentsTestScope getModuleTestsWithDependentsScope() { + ModuleWithDependentsTestScope scope = myModuleTestsWithDependentsScope; if (scope == null) { - myModuleTestsWithDependentsScope = scope = new ModuleWithDependentsScope(myModule, true); + myModuleTestsWithDependentsScope = scope = new ModuleWithDependentsTestScope(myModule); } return scope; } @@ -120,8 +114,6 @@ public class ModuleScopeProviderImpl implements ModuleScopeProvider { @Override public void clearCache() { myScopeCache.clear(); - myModuleWithDependentsScope = null; myModuleTestsWithDependentsScope = null; } - } diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java index 7228eb7e5215..5f64932abb35 100644 --- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java +++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java @@ -31,24 +31,22 @@ import java.util.Set; /** * @author max */ -public class ModuleWithDependentsScope extends GlobalSearchScope { +class ModuleWithDependentsScope extends GlobalSearchScope { private final Module myModule; - private final boolean myOnlyTests; private final ProjectFileIndex myProjectFileIndex; private final Set myModules; private final GlobalSearchScope myProjectScope; - ModuleWithDependentsScope(Module module, boolean onlyTests) { + ModuleWithDependentsScope(@NotNull Module module) { super(module.getProject()); myModule = module; - myOnlyTests = onlyTests; - myProjectFileIndex = ProjectRootManager.getInstance(myModule.getProject()).getFileIndex(); - myProjectScope = ProjectScope.getProjectScope(myModule.getProject()); + myProjectFileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex(); + myProjectScope = ProjectScope.getProjectScope(module.getProject()); myModules = new THashSet(); - myModules.add(myModule); + myModules.add(module); fillModules(); } @@ -76,12 +74,14 @@ public class ModuleWithDependentsScope extends GlobalSearchScope { } } - @Override public boolean contains(@NotNull VirtualFile file) { + return contains(file, false); + } + + boolean contains(@NotNull VirtualFile file, boolean myOnlyTests) { Module moduleOfFile = myProjectFileIndex.getModuleForFile(file); - if (moduleOfFile == null) return false; - if (!myModules.contains(moduleOfFile)) return false; + if (moduleOfFile == null || !myModules.contains(moduleOfFile)) return false; if (myOnlyTests && !myProjectFileIndex.isInTestSourceContent(file)) return false; return myProjectScope.contains(file); } @@ -112,10 +112,7 @@ public class ModuleWithDependentsScope extends GlobalSearchScope { final ModuleWithDependentsScope moduleWithDependentsScope = (ModuleWithDependentsScope)o; - if (myOnlyTests != moduleWithDependentsScope.myOnlyTests) return false; - if (!myModule.equals(moduleWithDependentsScope.myModule)) return false; - - return true; + return myModule.equals(moduleWithDependentsScope.myModule); } public int hashCode() { diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsTestScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsTestScope.java new file mode 100644 index 000000000000..f9ec689a40ab --- /dev/null +++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsTestScope.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.module.impl.scopes; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.DelegatingGlobalSearchScope; +import org.jetbrains.annotations.NotNull; + +// Tests only (module plus dependencies) scope +// Delegates to ModuleWithDependentsScope with extra flag testOnly to reduce memory for holding modules and CPU for traversing dependencies. +class ModuleWithDependentsTestScope extends DelegatingGlobalSearchScope { + ModuleWithDependentsTestScope(@NotNull Module module) { + // the additional equality argument allows to distinguish ModuleWithDependentsTestScope from ModuleWithDependentsScope + super(new ModuleWithDependentsScope(module), true); + } + + @Override + public boolean contains(@NotNull VirtualFile file) { + return getBaseScope().contains(file, true); + } + + @NotNull + ModuleWithDependentsScope getBaseScope() { + return (ModuleWithDependentsScope)myBaseScope; + } +} diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java index e855b92a53e0..f451245b93d0 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java @@ -32,6 +32,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleComponent; +import com.intellij.openapi.module.impl.scopes.ModuleScopeProviderImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.impl.storage.ClasspathStorage; import com.intellij.openapi.util.Comparing;