c8bc08cfb3a8ff6b6741390ff64ff8a76686b836
[idea/community.git] / platform / projectModel-impl / src / com / intellij / openapi / roots / impl / FileIndexBase.java
1 /*
2  * Copyright 2000-2017 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.openapi.roots.impl;
17
18 import com.intellij.injected.editor.VirtualFileWindow;
19 import com.intellij.notebook.editor.BackedVirtualFile;
20 import com.intellij.openapi.application.ReadAction;
21 import com.intellij.openapi.fileTypes.FileTypeRegistry;
22 import com.intellij.openapi.module.Module;
23 import com.intellij.openapi.roots.ContentIterator;
24 import com.intellij.openapi.roots.FileIndex;
25 import com.intellij.openapi.roots.ModuleRootManager;
26 import com.intellij.openapi.util.Comparing;
27 import com.intellij.openapi.vfs.VfsUtilCore;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.openapi.vfs.VirtualFileFilter;
30 import com.intellij.openapi.vfs.VirtualFileVisitor;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33 import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
34
35 /**
36  * @author nik
37  */
38 abstract class FileIndexBase implements FileIndex {
39   private final FileTypeRegistry myFileTypeRegistry;
40   final DirectoryIndex myDirectoryIndex;
41
42   FileIndexBase(@NotNull DirectoryIndex directoryIndex, @NotNull FileTypeRegistry fileTypeManager) {
43     myDirectoryIndex = directoryIndex;
44     myFileTypeRegistry = fileTypeManager;
45   }
46
47   protected abstract boolean isScopeDisposed();
48
49   @Override
50   public boolean iterateContent(@NotNull ContentIterator processor) {
51     return iterateContent(processor, null);
52   }
53
54   @Override
55   public boolean iterateContentUnderDirectory(@NotNull final VirtualFile dir,
56                                               @NotNull final ContentIterator processor,
57                                               @Nullable VirtualFileFilter customFilter) {
58     final VirtualFileVisitor.Result result = VfsUtilCore.visitChildrenRecursively(dir, new VirtualFileVisitor<Void>() {
59       @NotNull
60       @Override
61       public Result visitFileEx(@NotNull VirtualFile file) {
62         DirectoryInfo info = ReadAction.compute(() -> getInfoForFileOrDirectory(file));
63         if (file.isDirectory()) {
64           if (info.isExcluded(file)) {
65             if (!info.processContentBeneathExcluded(file, content -> iterateContentUnderDirectory(content, processor, customFilter))) {
66               return skipTo(dir);
67             }
68             return SKIP_CHILDREN;
69           }
70           if (info.isIgnored()) {
71             // it's certain nothing can be found under ignored directory
72             return SKIP_CHILDREN;
73           }
74         }
75         boolean accepted = ReadAction.compute(() -> !isScopeDisposed() && isInContent(file, info))
76                            && (customFilter == null || customFilter.accept(file));
77         return !accepted || processor.processFile(file) ? CONTINUE : skipTo(dir);
78       }
79     });
80     return !Comparing.equal(result.skipToParent, dir);
81   }
82
83   @Override
84   public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator processor) {
85     return iterateContentUnderDirectory(dir, processor, null);
86   }
87
88   boolean isTestSourcesRoot(@NotNull DirectoryInfo info) {
89     JpsModuleSourceRootType<?> rootType = myDirectoryIndex.getSourceRootType(info);
90     return rootType != null && rootType.isForTests();
91   }
92
93   @NotNull
94   public DirectoryInfo getInfoForFileOrDirectory(@NotNull VirtualFile file) {
95     if (file instanceof VirtualFileWindow) {
96       file = ((VirtualFileWindow)file).getDelegate();
97     }
98     file = BackedVirtualFile.getOriginFileIfBacked(file);
99     return myDirectoryIndex.getInfoForFile(file);
100   }
101
102   @Override
103   public boolean isContentSourceFile(@NotNull VirtualFile file) {
104     return !file.isDirectory() &&
105            !myFileTypeRegistry.isFileIgnored(file) &&
106            isInSourceContent(file);
107   }
108
109   @NotNull
110   static VirtualFile[][] getModuleContentAndSourceRoots(@NotNull Module module) {
111     return new VirtualFile[][]{ModuleRootManager.getInstance(module).getContentRoots(),
112       ModuleRootManager.getInstance(module).getSourceRoots()};
113   }
114
115   protected boolean isInContent(@NotNull VirtualFile file, @NotNull DirectoryInfo info) {
116     return ProjectFileIndexImpl.isFileInContent(file, info);
117   }
118 }