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