| /* |
| * 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.module.ModuleManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.*; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.psi.search.ProjectScope; |
| import com.intellij.psi.util.CachedValueProvider; |
| import com.intellij.psi.util.CachedValuesManager; |
| import com.intellij.util.containers.MultiMap; |
| import com.intellij.util.containers.Queue; |
| import gnu.trove.THashSet; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.Set; |
| |
| /** |
| * @author max |
| */ |
| class ModuleWithDependentsScope extends GlobalSearchScope { |
| private final Module myModule; |
| |
| private final ProjectFileIndex myProjectFileIndex; |
| private final Set<Module> myModules; |
| private final GlobalSearchScope myProjectScope; |
| |
| ModuleWithDependentsScope(@NotNull Module module) { |
| super(module.getProject()); |
| myModule = module; |
| |
| myProjectFileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex(); |
| myProjectScope = ProjectScope.getProjectScope(module.getProject()); |
| |
| myModules = buildDependents(myModule); |
| } |
| |
| private static Set<Module> buildDependents(Module module) { |
| Set<Module> result = new THashSet<Module>(); |
| result.add(module); |
| |
| Set<Module> processedExporting = new THashSet<Module>(); |
| |
| ModuleIndex index = getModuleIndex(module.getProject()); |
| |
| Queue<Module> walkingQueue = new Queue<Module>(10); |
| walkingQueue.addLast(module); |
| |
| while (!walkingQueue.isEmpty()) { |
| Module current = walkingQueue.pullFirst(); |
| processedExporting.add(current); |
| result.addAll(index.plainUsages.get(current)); |
| for (Module dependent : index.exportingUsages.get(current)) { |
| result.add(dependent); |
| if (processedExporting.add(dependent)) { |
| walkingQueue.addLast(dependent); |
| } |
| } |
| } |
| return result; |
| } |
| |
| private static class ModuleIndex { |
| final MultiMap<Module, Module> plainUsages = MultiMap.create(); |
| final MultiMap<Module, Module> exportingUsages = MultiMap.create(); |
| } |
| |
| private static ModuleIndex getModuleIndex(final Project project) { |
| return CachedValuesManager.getManager(project).getCachedValue(project, new CachedValueProvider<ModuleIndex>() { |
| @Nullable |
| @Override |
| public Result<ModuleIndex> compute() { |
| ModuleIndex index = new ModuleIndex(); |
| for (Module module : ModuleManager.getInstance(project).getModules()) { |
| for (OrderEntry orderEntry : ModuleRootManager.getInstance(module).getOrderEntries()) { |
| if (orderEntry instanceof ModuleOrderEntry) { |
| Module referenced = ((ModuleOrderEntry)orderEntry).getModule(); |
| if (referenced != null) { |
| MultiMap<Module, Module> map = ((ModuleOrderEntry)orderEntry).isExported() ? index.exportingUsages : index.plainUsages; |
| map.putValue(referenced, module); |
| } |
| } |
| } |
| } |
| return Result.create(index, ProjectRootManager.getInstance(project)); |
| } |
| }); |
| } |
| |
| @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 || !myModules.contains(moduleOfFile)) return false; |
| if (myOnlyTests && !myProjectFileIndex.isInTestSourceContent(file)) return false; |
| return myProjectScope.contains(file); |
| } |
| |
| @Override |
| public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { |
| return 0; |
| } |
| |
| @Override |
| public boolean isSearchInModuleContent(@NotNull Module aModule) { |
| return myModules.contains(aModule); |
| } |
| |
| @Override |
| public boolean isSearchInLibraries() { |
| return false; |
| } |
| |
| @NonNls |
| public String toString() { |
| return "Module with dependents:" + myModule.getName(); |
| } |
| |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (!(o instanceof ModuleWithDependentsScope)) return false; |
| |
| final ModuleWithDependentsScope moduleWithDependentsScope = (ModuleWithDependentsScope)o; |
| |
| return myModule.equals(moduleWithDependentsScope.myModule); |
| } |
| |
| public int hashCode() { |
| return myModule.hashCode(); |
| } |
| } |