move fileScope and filesScope back from GlobalSearchScopes to GlobalSearchScope
[idea/community.git] / platform / lang-impl / src / com / intellij / psi / impl / file / impl / ResolveScopeManagerImpl.java
1 /*
2  * Copyright 2000-2011 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.psi.impl.file.impl;
17
18 import com.intellij.openapi.module.Module;
19 import com.intellij.openapi.progress.ProgressManager;
20 import com.intellij.openapi.project.Project;
21 import com.intellij.openapi.roots.*;
22 import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
23 import com.intellij.openapi.vfs.VirtualFile;
24 import com.intellij.psi.*;
25 import com.intellij.psi.impl.PsiManagerImpl;
26 import com.intellij.psi.impl.ResolveScopeManager;
27 import com.intellij.psi.impl.source.resolve.FileContextUtil;
28 import com.intellij.psi.search.GlobalSearchScope;
29 import com.intellij.psi.search.SearchScope;
30 import com.intellij.util.containers.ConcurrentFactoryMap;
31 import org.jetbrains.annotations.NotNull;
32
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Map;
36
37 public class ResolveScopeManagerImpl extends ResolveScopeManager {
38
39   private final Project myProject;
40   private final ProjectRootManager myProjectRootManager;
41   private final PsiManager myManager;
42
43   private final Map<VirtualFile, GlobalSearchScope> myDefaultResolveScopesCache = new ConcurrentFactoryMap<VirtualFile, GlobalSearchScope>() {
44     @Override
45     protected GlobalSearchScope create(VirtualFile key) {
46       GlobalSearchScope scope = null;
47       for(ResolveScopeProvider resolveScopeProvider: ResolveScopeProvider.EP_NAME.getExtensions()) {
48         scope = resolveScopeProvider.getResolveScope(key, myProject);
49         if (scope != null) break;
50       }
51       if (scope == null) scope = getInherentResolveScope(key);
52       for (ResolveScopeEnlarger enlarger : ResolveScopeEnlarger.EP_NAME.getExtensions()) {
53         final SearchScope extra = enlarger.getAdditionalResolveScope(key, myProject);
54         if (extra != null) {
55           scope = scope.union(extra);
56         }
57       }
58
59       return scope;
60     }
61   };
62
63   public ResolveScopeManagerImpl(Project project, ProjectRootManager projectRootManager, PsiManager psiManager) {
64     myProject = project;
65     myProjectRootManager = projectRootManager;
66     myManager = psiManager;
67
68     ((PsiManagerImpl) psiManager).registerRunnableToRunOnChange(new Runnable() {
69       @Override
70       public void run() {
71         myDefaultResolveScopesCache.clear();
72       }
73     });
74
75   }
76
77   private GlobalSearchScope getDefaultResolveScope(@NotNull PsiFile psiFile, @NotNull final VirtualFile vFile) {
78     return myDefaultResolveScopesCache.get(vFile);
79   }
80
81   private GlobalSearchScope getInherentResolveScope(VirtualFile vFile) {
82     ProjectFileIndex projectFileIndex = myProjectRootManager.getFileIndex();
83     Module module = projectFileIndex.getModuleForFile(vFile);
84     if (module != null) {
85       boolean includeTests = projectFileIndex.isInTestSourceContent(vFile) ||
86                              !projectFileIndex.isContentJavaSourceFile(vFile);
87       return GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, includeTests);
88     }
89     else {
90       // resolve references in libraries in context of all modules which contain it
91       List<Module> modulesLibraryUsedIn = new ArrayList<Module>();
92       List<OrderEntry> orderEntries = projectFileIndex.getOrderEntriesForFile(vFile);
93
94       for (OrderEntry entry : orderEntries) {
95         ProgressManager.checkCanceled();
96
97         if (entry instanceof JdkOrderEntry) {
98           return ((ProjectRootManagerEx)myProjectRootManager).getScopeForJdk((JdkOrderEntry)entry);
99         }
100
101         if (entry instanceof LibraryOrderEntry || entry instanceof ModuleOrderEntry) {
102           modulesLibraryUsedIn.add(entry.getOwnerModule());
103         }
104       }
105
106       return ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn);
107     }
108   }
109
110   @Override
111   @NotNull
112   public GlobalSearchScope getResolveScope(@NotNull PsiElement element) {
113     ProgressManager.checkCanceled();
114
115     VirtualFile vFile;
116     final PsiFile contextFile;
117     if (element instanceof PsiDirectory) {
118       vFile = ((PsiDirectory)element).getVirtualFile();
119       contextFile = null;
120     }
121     else {
122       final PsiFile containingFile = element.getContainingFile();
123       if (containingFile instanceof PsiCodeFragment) {
124         final GlobalSearchScope forcedScope = ((PsiCodeFragment)containingFile).getForcedResolveScope();
125         if (forcedScope != null) {
126           return forcedScope;
127         }
128         final PsiElement context = containingFile.getContext();
129         if (context == null) {
130           return GlobalSearchScope.allScope(myProject);
131         }
132         return getResolveScope(context);
133       }
134
135       contextFile = containingFile != null ? FileContextUtil.getContextFile(containingFile) : null;
136       if (contextFile == null) {
137         return GlobalSearchScope.allScope(myProject);
138       }
139       else if (contextFile instanceof FileResolveScopeProvider) {
140         return ((FileResolveScopeProvider) contextFile).getFileResolveScope();
141       }
142       vFile = contextFile.getOriginalFile().getVirtualFile();
143     }
144     if (vFile == null || contextFile == null) {
145       return GlobalSearchScope.allScope(myProject);
146     }
147
148     return getDefaultResolveScope(contextFile, vFile);
149   }
150
151
152   @Override
153   public GlobalSearchScope getDefaultResolveScope(final VirtualFile vFile) {
154     final PsiFile psiFile = myManager.findFile(vFile);
155     assert psiFile != null;
156     return getDefaultResolveScope(psiFile, vFile);
157   }
158
159
160   @Override
161   @NotNull
162   public GlobalSearchScope getUseScope(@NotNull PsiElement element) {
163     VirtualFile vFile;
164     final GlobalSearchScope allScope = GlobalSearchScope.allScope(myManager.getProject());
165     if (element instanceof PsiDirectory) {
166       vFile = ((PsiDirectory)element).getVirtualFile();
167     }
168     else {
169       final PsiFile containingFile = element.getContainingFile();
170       if (containingFile == null) return allScope;
171       final VirtualFile virtualFile = containingFile.getVirtualFile();
172       if (virtualFile == null) return allScope;
173       vFile = virtualFile.getParent();
174     }
175
176     if (vFile == null) return allScope;
177     ProjectFileIndex projectFileIndex = myProjectRootManager.getFileIndex();
178     Module module = projectFileIndex.getModuleForFile(vFile);
179     if (module != null) {
180       boolean isTest = projectFileIndex.isInTestSourceContent(vFile);
181       return isTest
182              ? GlobalSearchScope.moduleTestsWithDependentsScope(module)
183              : GlobalSearchScope.moduleWithDependentsScope(module);
184     }
185     else {
186       final PsiFile f = element.getContainingFile();
187       final VirtualFile vf = f == null ? null : f.getVirtualFile();
188
189       return f == null || vf == null || vf.isDirectory() || allScope.contains(vf)
190              ? allScope : GlobalSearchScope.fileScope(f).uniteWith(allScope);
191     }
192   }
193 }