af837efb9a71944384a034a01d9a68c914363534
[idea/community.git] / platform / projectModel-impl / src / com / intellij / openapi / roots / impl / ProjectFileIndexImpl.java
1 /*
2  * Copyright 2000-2012 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
17 package com.intellij.openapi.roots.impl;
18
19 import com.intellij.injected.editor.VirtualFileWindow;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.fileTypes.FileTypeRegistry;
22 import com.intellij.openapi.module.Module;
23 import com.intellij.openapi.module.ModuleManager;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.roots.ContentIterator;
26 import com.intellij.openapi.roots.ModuleRootManager;
27 import com.intellij.openapi.roots.OrderEntry;
28 import com.intellij.openapi.roots.ProjectFileIndex;
29 import com.intellij.openapi.vfs.VfsUtilCore;
30 import com.intellij.openapi.vfs.VirtualFile;
31 import com.intellij.openapi.vfs.VirtualFileFilter;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
34
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38
39 public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIndex {
40   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.ProjectFileIndexImpl");
41   private final Project myProject;
42   private final ContentFilter myContentFilter;
43
44   public ProjectFileIndexImpl(@NotNull Project project, @NotNull DirectoryIndex directoryIndex, @NotNull FileTypeRegistry fileTypeManager) {
45     super(directoryIndex, fileTypeManager, project);
46     myProject = project;
47     myContentFilter = new ContentFilter();
48   }
49
50   @Override
51   public boolean iterateContent(@NotNull ContentIterator iterator) {
52     Module[] modules = ModuleManager.getInstance(myProject).getModules();
53     for (Module module : modules) {
54       if (module.isDisposed()) continue;
55       VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
56       for (VirtualFile contentRoot : contentRoots) {
57         DirectoryInfo info = getInfoForFileOrDirectory(contentRoot);
58         if (info == null) continue; // is excluded or ignored
59         if (!module.equals(info.getModule())) continue; // maybe 2 modules have the same content root?
60
61         VirtualFile parent = contentRoot.getParent();
62         if (parent != null) {
63           DirectoryInfo parentInfo = getInfoForFileOrDirectory(parent);
64           if (parentInfo != null && parentInfo.getModule() != null) continue; // inner content - skip it
65         }
66
67         boolean finished = VfsUtilCore.iterateChildrenRecursively(contentRoot, myContentFilter, iterator);
68         if (!finished) return false;
69       }
70     }
71
72     return true;
73   }
74
75   @Override
76   public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator iterator) {
77     return VfsUtilCore.iterateChildrenRecursively(dir, myContentFilter, iterator);
78   }
79
80   @Override
81   public boolean isIgnored(@NotNull VirtualFile file) {
82     if (myFileTypeRegistry.isFileIgnored(file)) return true;
83     if (myExclusionManager != null && myExclusionManager.isExcluded(file)) return true;
84     VirtualFile dir = file.isDirectory() ? file : file.getParent();
85     if (dir == null) return false;
86
87     DirectoryInfo info = getInfoForFileOrDirectory(dir);
88     if (info != null) return false;
89     if (myDirectoryIndex.isProjectExcludeRoot(dir)) return true;
90
91     VirtualFile parent = dir.getParent();
92     while (true) {
93       if (parent == null) return false;
94       DirectoryInfo parentInfo = getInfoForFileOrDirectory(parent);
95       if (parentInfo != null) return true;
96       if (myDirectoryIndex.isProjectExcludeRoot(parent)) return true;
97       parent = parent.getParent();
98     }
99   }
100
101   @Override
102   public Module getModuleForFile(@NotNull VirtualFile file) {
103     if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
104     VirtualFile dir = file.isDirectory() ? file : file.getParent();
105     if (dir == null) return null;
106     DirectoryInfo info = getInfoForFileOrDirectory(dir);
107     if (info == null) return null;
108     return info.getModule();
109   }
110
111   @Override
112   @NotNull
113   public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile file) {
114     DirectoryInfo info = getInfoForFileOrDirectory(file);
115     if (info == null) return Collections.emptyList();
116     return Arrays.asList(info.getOrderEntries());
117   }
118
119   @Override
120   public VirtualFile getClassRootForFile(@NotNull VirtualFile file) {
121     final DirectoryInfo info = getInfoForFileOrDirectory(file);
122     if (info == null) return null;
123     return info.getLibraryClassRoot();
124   }
125
126   @Override
127   public VirtualFile getSourceRootForFile(@NotNull VirtualFile file) {
128     final DirectoryInfo info = getInfoForFileOrDirectory(file);
129     if (info == null) return null;
130     return info.getSourceRoot();
131   }
132
133   @Override
134   public VirtualFile getContentRootForFile(@NotNull VirtualFile file) {
135     final DirectoryInfo info = getInfoForFileOrDirectory(file);
136     if (info == null) return null;
137     return info.getContentRoot();
138   }
139
140   @Override
141   public String getPackageNameByDirectory(@NotNull VirtualFile dir) {
142     LOG.assertTrue(dir.isDirectory());
143     return myDirectoryIndex.getPackageName(dir);
144   }
145
146   @Override
147   public boolean isLibraryClassFile(@NotNull VirtualFile file) {
148     if (file.isDirectory()) return false;
149     if (myFileTypeRegistry.isFileIgnored(file)) return false;
150     DirectoryInfo parentInfo = getInfoForFileOrDirectory(file);
151     return parentInfo != null && parentInfo.hasLibraryClassRoot();
152   }
153
154   @Override
155   public boolean isInSource(@NotNull VirtualFile fileOrDir) {
156     DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
157     if (info != null) {
158       return info.isInModuleSource() || info.isInLibrarySource();
159     }
160     else {
161       VirtualFile parent = fileOrDir.getParent();
162       return parent != null && isInSource(parent);
163     }
164   }
165
166   @Override
167   public boolean isInLibraryClasses(@NotNull VirtualFile fileOrDir) {
168     DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
169     if (info != null) {     
170       return info.hasLibraryClassRoot();
171     }
172     else {
173       VirtualFile parent = fileOrDir.getParent();
174       return parent != null && isInLibraryClasses(parent);
175     }
176   }
177
178   @Override
179   public boolean isInLibrarySource(@NotNull VirtualFile fileOrDir) {
180     DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
181     if (info != null) {
182       return info.isInLibrarySource();
183     }
184     else {
185       VirtualFile parent = fileOrDir.getParent();
186       return parent != null && isInLibrarySource(parent);
187     }
188   }
189
190   @Override
191   public boolean isInContent(@NotNull VirtualFile fileOrDir) {
192     DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
193     return info != null && info.getModule() != null;
194   }
195
196   @Override
197   public boolean isInSourceContent(@NotNull VirtualFile fileOrDir) {
198     DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
199     return info != null && info.isInModuleSource();
200   }
201
202   @Override
203   public boolean isInTestSourceContent(@NotNull VirtualFile fileOrDir) {
204     DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
205     return info != null && info.isInModuleSource() && JavaModuleSourceRootTypes.isTestSourceOrResource(myDirectoryIndex.getSourceRootType(info));
206   }
207
208   private class ContentFilter implements VirtualFileFilter {
209     @Override
210     public boolean accept(@NotNull VirtualFile file) {
211       if (file.isDirectory()) {
212         DirectoryInfo info = getInfoForFileOrDirectory(file);
213         return info != null && info.getModule() != null;
214       }
215       else {
216         return (myExclusionManager == null || !myExclusionManager.isExcluded(file))
217                && !myFileTypeRegistry.isFileIgnored(file);
218       }
219     }
220   }
221 }