From e49a769357022aed34bab1615c7db5eb1735f5f4 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 21 May 2015 14:43:21 +0200 Subject: [PATCH] project/module file index: be prepared to iteration outside read action, e.g. from pushers (EA-68060, EA-68579) --- .../roots/impl/ModuleFileIndexImpl.java | 50 ++++++++---- .../roots/impl/ProjectFileIndexImpl.java | 77 +++++++++++++------ 2 files changed, 87 insertions(+), 40 deletions(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java index eb8a9ddf5587..2a3b3e5c5c27 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java @@ -16,13 +16,16 @@ package com.intellij.openapi.roots.impl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileFilter; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; @@ -45,14 +48,25 @@ public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileInde @Override public boolean iterateContent(@NotNull ContentIterator iterator) { - VirtualFile[] contentRoots = ModuleRootManager.getInstance(myModule).getContentRoots(); - for (VirtualFile contentRoot : contentRoots) { - VirtualFile parent = contentRoot.getParent(); - if (parent != null) { - DirectoryInfo parentInfo = myDirectoryIndex.getInfoForFile(parent); - if (parentInfo.isInProject() && myModule.equals(parentInfo.getModule())) continue; // inner content - skip it - } + final List contentRoots = ApplicationManager.getApplication().runReadAction(new Computable>() { + @Override + public List compute() { + if (myModule.isDisposed()) return Collections.emptyList(); + + List result = ContainerUtil.newArrayList(); + for (VirtualFile contentRoot : ModuleRootManager.getInstance(myModule).getContentRoots()) { + VirtualFile parent = contentRoot.getParent(); + if (parent != null) { + DirectoryInfo parentInfo = myDirectoryIndex.getInfoForFile(parent); + if (parentInfo.isInProject() && myModule.equals(parentInfo.getModule())) continue; // inner content - skip it + } + result.add(contentRoot); + } + return result; + } + }); + for (VirtualFile contentRoot : contentRoots) { boolean finished = VfsUtilCore.iterateChildrenRecursively(contentRoot, myContentFilter, iterator); if (!finished) return false; } @@ -194,14 +208,20 @@ public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileInde private class ContentFilter implements VirtualFileFilter { @Override - public boolean accept(@NotNull VirtualFile file) { - if (file.isDirectory()) { - DirectoryInfo info = myDirectoryIndex.getInfoForFile(file); - return info.isInProject() && myModule.equals(info.getModule()); - } - else { - return !myFileTypeRegistry.isFileIgnored(file); - } + public boolean accept(@NotNull final VirtualFile file) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + if (myModule.isDisposed()) return false; + if (file.isDirectory()) { + DirectoryInfo info = myDirectoryIndex.getInfoForFile(file); + return info.isInProject() && myModule.equals(info.getModule()); + } + else { + return !myFileTypeRegistry.isFileIgnored(file); + } + } + }); } } } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java index aec6e11a6d15..df33d358b370 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java @@ -17,6 +17,7 @@ package com.intellij.openapi.roots.impl; import com.intellij.injected.editor.VirtualFileWindow; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.module.Module; @@ -26,15 +27,18 @@ import com.intellij.openapi.roots.ContentIterator; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileFilter; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -51,21 +55,14 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn @Override public boolean iterateContent(@NotNull ContentIterator iterator) { - Module[] modules = ModuleManager.getInstance(myProject).getModules(); - for (Module module : modules) { - if (module.isDisposed()) continue; - VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); - for (VirtualFile contentRoot : contentRoots) { - DirectoryInfo info = getInfoForFileOrDirectory(contentRoot); - if (!info.isInProject()) continue; // is excluded or ignored - if (!module.equals(info.getModule())) continue; // maybe 2 modules have the same content root? - - VirtualFile parent = contentRoot.getParent(); - if (parent != null) { - DirectoryInfo parentInfo = getInfoForFileOrDirectory(parent); - if (parentInfo.isInProject() && parentInfo.getModule() != null) continue; // inner content - skip it - } - + Module[] modules = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Module[] compute() { + return ModuleManager.getInstance(myProject).getModules(); + } + }); + for (final Module module : modules) { + for (VirtualFile contentRoot : getRootsToIterate(module)) { boolean finished = VfsUtilCore.iterateChildrenRecursively(contentRoot, myContentFilter, iterator); if (!finished) return false; } @@ -74,6 +71,31 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn return true; } + private List getRootsToIterate(final Module module) { + return ApplicationManager.getApplication().runReadAction(new Computable>() { + @Override + public List compute() { + if (module.isDisposed()) return Collections.emptyList(); + + List result = ContainerUtil.newArrayList(); + for (VirtualFile contentRoot : ModuleRootManager.getInstance(module).getContentRoots()) { + DirectoryInfo info = getInfoForFileOrDirectory(contentRoot); + if (!info.isInProject()) continue; // is excluded or ignored + if (!module.equals(info.getModule())) continue; // maybe 2 modules have the same content root? + + VirtualFile parent = contentRoot.getParent(); + if (parent != null) { + DirectoryInfo parentInfo = getInfoForFileOrDirectory(parent); + if (parentInfo.isInProject() && parentInfo.getModule() != null) continue; + } + result.add(contentRoot); + } + + return result; + } + }); + } + @Override public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator iterator) { return VfsUtilCore.iterateChildrenRecursively(dir, myContentFilter, iterator); @@ -200,16 +222,21 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn private class ContentFilter implements VirtualFileFilter { @Override - public boolean accept(@NotNull VirtualFile file) { - DirectoryInfo info = getInfoForFileOrDirectory(file); - if (!info.isInProject() || info.getModule() == null) return false; - - if (file.isDirectory()) { - return true; - } - else { - return !myFileTypeRegistry.isFileIgnored(file); - } + public boolean accept(@NotNull final VirtualFile file) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + DirectoryInfo info = getInfoForFileOrDirectory(file); + if (!info.isInProject() || info.getModule() == null) return false; + + if (file.isDirectory()) { + return true; + } + else { + return !myFileTypeRegistry.isFileIgnored(file); + } + } + }); } } }