| /* |
| * Copyright 2000-2013 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.execution.testframework; |
| |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.util.containers.HashMap; |
| import com.intellij.util.graph.Graph; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| /** |
| * @author dyoma |
| */ |
| public abstract class SourceScope { |
| public abstract GlobalSearchScope getGlobalSearchScope(); |
| public abstract Project getProject(); |
| public abstract GlobalSearchScope getLibrariesScope(); |
| |
| public static Map<Module, Collection<Module>> buildAllDependencies(final Project project) { |
| Graph<Module> graph = ModuleManager.getInstance(project).moduleGraph(); |
| Map<Module, Collection<Module>> result = new HashMap<Module, Collection<Module>>(); |
| for (final Module module : graph.getNodes()) { |
| buildDependenciesForModule(module, graph, result); |
| } |
| return result; |
| } |
| |
| private static void buildDependenciesForModule(final Module module, final Graph<Module> graph, Map<Module, Collection<Module>> map) { |
| final Set<Module> deps = new com.intellij.util.containers.HashSet<Module>(); |
| map.put(module, deps); |
| |
| new Object() { |
| void traverse(Module m) { |
| for (Iterator<Module> iterator = graph.getIn(m); iterator.hasNext();) { |
| final Module dep = iterator.next(); |
| if (!deps.contains(dep)) { |
| deps.add(dep); |
| traverse(dep); |
| } |
| } |
| } |
| }.traverse(module); |
| } |
| |
| private abstract static class ModuleSourceScope extends SourceScope { |
| private final Project myProject; |
| |
| protected ModuleSourceScope(final Project project) { |
| myProject = project; |
| } |
| |
| public Project getProject() { |
| return myProject; |
| } |
| |
| } |
| |
| public static SourceScope wholeProject(final Project project) { |
| return new SourceScope() { |
| public GlobalSearchScope getGlobalSearchScope() { |
| return GlobalSearchScope.allScope(project); |
| } |
| |
| public Project getProject() { |
| return project; |
| } |
| |
| public Module[] getModulesToCompile() { |
| return ModuleManager.getInstance(project).getModules(); |
| } |
| |
| public GlobalSearchScope getLibrariesScope() { |
| return getGlobalSearchScope(); |
| } |
| }; |
| } |
| |
| public static SourceScope modulesWithDependencies(final Module[] modules) { |
| if (modules == null || modules.length == 0) return null; |
| return new ModuleSourceScope(modules[0].getProject()) { |
| public GlobalSearchScope getGlobalSearchScope() { |
| return evaluateScopesAndUnite(modules, new ScopeForModuleEvaluator() { |
| public GlobalSearchScope evaluate(final Module module) { |
| return GlobalSearchScope.moduleWithDependenciesScope(module); |
| } |
| }); |
| } |
| |
| public GlobalSearchScope getLibrariesScope() { |
| return evaluateScopesAndUnite(modules, new ScopeForModuleEvaluator() { |
| public GlobalSearchScope evaluate(final Module module) { |
| return new ModuleWithDependenciesAndLibsDependencies(module); |
| } |
| }); |
| } |
| |
| public Module[] getModulesToCompile() { |
| return modules; |
| } |
| }; |
| } |
| |
| private interface ScopeForModuleEvaluator { |
| GlobalSearchScope evaluate(Module module); |
| } |
| private static GlobalSearchScope evaluateScopesAndUnite(final Module[] modules, final ScopeForModuleEvaluator evaluator) { |
| GlobalSearchScope scope = evaluator.evaluate(modules[0]); |
| for (int i = 1; i < modules.length; i++) { |
| final Module module = modules[i]; |
| final GlobalSearchScope otherscope = evaluator.evaluate(module); |
| scope = scope.uniteWith(otherscope); |
| } |
| return scope; |
| } |
| |
| public static SourceScope modules(final Module[] modules) { |
| if (modules == null || modules.length == 0) return null; |
| return new ModuleSourceScope(modules[0].getProject()) { |
| public GlobalSearchScope getGlobalSearchScope() { |
| return evaluateScopesAndUnite(modules, new ScopeForModuleEvaluator() { |
| public GlobalSearchScope evaluate(final Module module) { |
| return GlobalSearchScope.moduleScope(module); |
| } |
| }); |
| } |
| |
| public GlobalSearchScope getLibrariesScope() { |
| return evaluateScopesAndUnite(modules, new ScopeForModuleEvaluator() { |
| public GlobalSearchScope evaluate(final Module module) { |
| return GlobalSearchScope.moduleWithLibrariesScope(module); |
| } |
| }); |
| } |
| |
| public Module[] getModulesToCompile() { |
| return modules; |
| } |
| }; |
| } |
| |
| public abstract Module[] getModulesToCompile(); |
| |
| private static class ModuleWithDependenciesAndLibsDependencies extends GlobalSearchScope { |
| private final GlobalSearchScope myMainScope; |
| private final List<GlobalSearchScope> myScopes = new ArrayList<GlobalSearchScope>(); |
| |
| public ModuleWithDependenciesAndLibsDependencies(final Module module) { |
| super(module.getProject()); |
| myMainScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module); |
| final Map<Module, Collection<Module>> map = buildAllDependencies(module.getProject()); |
| if (map == null) return; |
| final Collection<Module> modules = map.get(module); |
| for (final Module dependency : modules) { |
| myScopes.add(GlobalSearchScope.moduleWithLibrariesScope(dependency)); |
| } |
| } |
| |
| public boolean contains(@NotNull final VirtualFile file) { |
| return findScopeFor(file) != null; |
| } |
| |
| public int compare(@NotNull final VirtualFile file1, @NotNull final VirtualFile file2) { |
| final GlobalSearchScope scope = findScopeFor(file1); |
| assert scope != null; |
| if (scope.contains(file2)) return scope.compare(file1, file2); |
| return 0; |
| } |
| |
| public boolean isSearchInModuleContent(@NotNull final Module aModule) { |
| return myMainScope.isSearchInModuleContent(aModule); |
| } |
| |
| public boolean isSearchInLibraries() { |
| return true; |
| } |
| |
| @Nullable |
| private GlobalSearchScope findScopeFor(final VirtualFile file) { |
| if (myMainScope.contains(file)) return myMainScope; |
| //noinspection ForLoopReplaceableByForEach |
| for (int i = 0, size = myScopes.size(); i < size; i++) { |
| GlobalSearchScope scope = myScopes.get(i); |
| if (scope.contains(file)) return scope; |
| } |
| return null; |
| } |
| } |
| } |