fix "IDEA-221944 Deadlock on opening second project" and support preloading for proje...
[idea/community.git] / platform / projectModel-impl / src / com / intellij / openapi / roots / impl / FileIndexBase.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.openapi.roots.impl;
3
4 import com.intellij.injected.editor.VirtualFileWindow;
5 import com.intellij.notebook.editor.BackedVirtualFile;
6 import com.intellij.openapi.application.ReadAction;
7 import com.intellij.openapi.fileTypes.FileTypeRegistry;
8 import com.intellij.openapi.module.Module;
9 import com.intellij.openapi.roots.ContentIterator;
10 import com.intellij.openapi.roots.FileIndex;
11 import com.intellij.openapi.roots.ModuleRootManager;
12 import com.intellij.openapi.util.Comparing;
13 import com.intellij.openapi.vfs.VfsUtilCore;
14 import com.intellij.openapi.vfs.VirtualFile;
15 import com.intellij.openapi.vfs.VirtualFileFilter;
16 import com.intellij.openapi.vfs.VirtualFileVisitor;
17 import org.jetbrains.annotations.NotNull;
18 import org.jetbrains.annotations.Nullable;
19 import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
20
21 /**
22  * @author nik
23  */
24 abstract class FileIndexBase implements FileIndex {
25   private final FileTypeRegistry myFileTypeRegistry;
26   final DirectoryIndex myDirectoryIndex;
27
28   FileIndexBase(@NotNull DirectoryIndex directoryIndex) {
29     myDirectoryIndex = directoryIndex;
30     myFileTypeRegistry = FileTypeRegistry.getInstance();
31   }
32
33   protected abstract boolean isScopeDisposed();
34
35   @Override
36   public boolean iterateContent(@NotNull ContentIterator processor) {
37     return iterateContent(processor, null);
38   }
39
40   @Override
41   public boolean iterateContentUnderDirectory(@NotNull final VirtualFile dir,
42                                               @NotNull final ContentIterator processor,
43                                               @Nullable VirtualFileFilter customFilter) {
44     final VirtualFileVisitor.Result result = VfsUtilCore.visitChildrenRecursively(dir, new VirtualFileVisitor<Void>() {
45       @NotNull
46       @Override
47       public Result visitFileEx(@NotNull VirtualFile file) {
48         DirectoryInfo info = ReadAction.compute(() -> getInfoForFileOrDirectory(file));
49         if (file.isDirectory()) {
50           if (info.isExcluded(file)) {
51             if (!info.processContentBeneathExcluded(file, content -> iterateContentUnderDirectory(content, processor, customFilter))) {
52               return skipTo(dir);
53             }
54             return SKIP_CHILDREN;
55           }
56           if (info.isIgnored()) {
57             // it's certain nothing can be found under ignored directory
58             return SKIP_CHILDREN;
59           }
60         }
61         boolean accepted = ReadAction.compute(() -> !isScopeDisposed() && isInContent(file, info))
62                            && (customFilter == null || customFilter.accept(file));
63         return !accepted || processor.processFile(file) ? CONTINUE : skipTo(dir);
64       }
65     });
66     return !Comparing.equal(result.skipToParent, dir);
67   }
68
69   @Override
70   public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator processor) {
71     return iterateContentUnderDirectory(dir, processor, null);
72   }
73
74   boolean isTestSourcesRoot(@NotNull DirectoryInfo info) {
75     JpsModuleSourceRootType<?> rootType = myDirectoryIndex.getSourceRootType(info);
76     return rootType != null && rootType.isForTests();
77   }
78
79   @NotNull
80   public DirectoryInfo getInfoForFileOrDirectory(@NotNull VirtualFile file) {
81     if (file instanceof VirtualFileWindow) {
82       file = ((VirtualFileWindow)file).getDelegate();
83     }
84     file = BackedVirtualFile.getOriginFileIfBacked(file);
85     return myDirectoryIndex.getInfoForFile(file);
86   }
87
88   @Override
89   public boolean isContentSourceFile(@NotNull VirtualFile file) {
90     return !file.isDirectory() &&
91            !myFileTypeRegistry.isFileIgnored(file) &&
92            isInSourceContent(file);
93   }
94
95   @NotNull
96   static VirtualFile[][] getModuleContentAndSourceRoots(@NotNull Module module) {
97     return new VirtualFile[][]{ModuleRootManager.getInstance(module).getContentRoots(),
98       ModuleRootManager.getInstance(module).getSourceRoots()};
99   }
100
101   protected boolean isInContent(@NotNull VirtualFile file, @NotNull DirectoryInfo info) {
102     return ProjectFileIndexImpl.isFileInContent(file, info);
103   }
104 }