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