diff --git a/platform/lang-impl/src/com/intellij/psi/impl/cache/CacheManager.java b/platform/lang-impl/src/com/intellij/psi/impl/cache/CacheManager.java index cc945d7ea04a..5773600672f6 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/cache/CacheManager.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/cache/CacheManager.java @@ -23,7 +23,6 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.IndexPattern; import com.intellij.psi.search.IndexPatternProvider; -import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; @@ -41,12 +40,6 @@ public interface CacheManager { boolean processFilesWithWord(@NotNull Processor processor,@NotNull String word, short occurenceMask, @NotNull GlobalSearchScope scope, final boolean caseSensitively); - // IMPORTANT!!! - // Do not call indices directly or indirectly from 'process' method, deadlocks are possible (IDEADEV-42137). - public boolean collectVirtualFilesWithWord(@NotNull final CommonProcessors.CollectProcessor fileProcessor, - @NotNull final String word, final short occurrenceMask, - @NotNull final GlobalSearchScope scope, final boolean caseSensitively); - /** * @return all VirtualFile's that contain todo-items under project roots */ diff --git a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java index 8b23fb509d01..689b68b7725d 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java @@ -80,8 +80,7 @@ public class IndexCacheManagerImpl implements CacheManager{ // Since implementation of virtualFileProcessor.process() may call indices directly or indirectly, // we cannot call it inside FileBasedIndex.processValues() method except in collecting form // If we do, deadlocks are possible (IDEADEV-42137). Process the files without not holding indices' read lock. - @Override - public boolean collectVirtualFilesWithWord(@NotNull final CommonProcessors.CollectProcessor fileProcessor, + private boolean collectVirtualFilesWithWord(@NotNull final Processor fileProcessor, @NotNull final String word, final short occurrenceMask, @NotNull final GlobalSearchScope scope, final boolean caseSensitively) { if (myProject.isDefault()) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 15d6995c4c41..5cbfb27eefe6 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -48,7 +48,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.indexing.FileBasedIndex; import com.intellij.util.text.StringSearcher; -import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -369,22 +368,16 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { final ArrayList entries = getWordEntries(text, caseSensitively); if (entries.isEmpty()) return true; - final Collection fileSet = ApplicationManager.getApplication().runReadAction(new Computable>() { + final CommonProcessors.CollectProcessor collectProcessor = new CommonProcessors.CollectProcessor(); + processFilesContainingAllKeys(scope, new Condition() { @Override - public Collection compute() { - final CommonProcessors.CollectProcessor collectProcessor = new CommonProcessors.CollectProcessor(); - FileBasedIndex.getInstance().processFilesContainingAllKeys(IdIndex.NAME, entries, scope, new Condition() { - @Override - public boolean value(Integer integer) { - return (integer.intValue() & searchContext) != 0; - } - }, collectProcessor); - return collectProcessor.getResults(); + public boolean value(Integer integer) { + return (integer.intValue() & searchContext) != 0; } - }); + }, collectProcessor, getWordEntries(text, caseSensitively)); final FileIndexFacade index = FileIndexFacade.getInstance(myManager.getProject()); - return ContainerUtil.process(fileSet, new ReadActionProcessor() { + return ContainerUtil.process(collectProcessor.getResults(), new ReadActionProcessor() { @Override public boolean processInReadAction(VirtualFile virtualFile) { return !IndexCacheManagerImpl.shouldBeFound(scope, virtualFile, index) || processor.process(virtualFile); @@ -690,16 +683,9 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { continue; } - final Collection fileSet = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Collection compute() { - final CommonProcessors.CollectProcessor processor = new CommonProcessors.CollectProcessor(); - FileBasedIndex.getInstance().processFilesContainingAllKeys(IdIndex.NAME, key, commonScope, null, processor); - return processor.getResults(); - } - }); - - for (final VirtualFile file : fileSet) { + final CommonProcessors.CollectProcessor processor = new CommonProcessors.CollectProcessor(); + processFilesContainingAllKeys(commonScope, null, processor, key); + for (final VirtualFile file : processor.getResults()) { if (progress != null) { progress.checkCanceled(); } @@ -834,22 +820,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { @Nullable final PsiFile fileToIgnoreOccurencesIn, @Nullable ProgressIndicator progress) { - final ArrayList keys = getWordEntries(name, true); - if (keys.isEmpty()) return SearchCostResult.ZERO_OCCURRENCES; - - final TIntHashSet set = ApplicationManager.getApplication().runReadAction(new NullableComputable() { - @Override - public TIntHashSet compute() { - return FileBasedIndex.getInstance().collectFileIdsContainingAllKeys(IdIndex.NAME, keys, scope, null); - } - }); - - if (set == null || set.size() > 1000 && !ApplicationManager.getApplication().isUnitTestMode()) { - return SearchCostResult.TOO_MANY_OCCURRENCES; - } - final AtomicInteger count = new AtomicInteger(); - final FileIndexFacade index = FileIndexFacade.getInstance(myManager.getProject()); final Processor processor = new Processor() { private final VirtualFile fileToIgnoreOccurencesInVirtualFile = @@ -863,12 +834,8 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return value < 10; } }; - final boolean cheap = ApplicationManager.getApplication().runReadAction(new NullableComputable() { - @Override - public Boolean compute() { - return FileBasedIndex.processVirtualFiles(set, scope, processor); - } - }); + final ArrayList keys = getWordEntries(name, true); + final boolean cheap = keys.isEmpty() || processFilesContainingAllKeys(scope, null, processor, keys); if (!cheap) { return SearchCostResult.TOO_MANY_OCCURRENCES; @@ -877,6 +844,17 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return count.get() == 0 ? SearchCostResult.ZERO_OCCURRENCES : SearchCostResult.FEW_OCCURRENCES; } + private static boolean processFilesContainingAllKeys(final GlobalSearchScope scope, + @Nullable final Condition checker, + final Processor processor, final Collection keys) { + return ApplicationManager.getApplication().runReadAction(new NullableComputable() { + @Override + public Boolean compute() { + return FileBasedIndex.getInstance().processFilesContainingAllKeys(IdIndex.NAME, keys, scope, checker, processor); + } + }); + } + private static ArrayList getWordEntries(String name, boolean caseSensitively) { List words = StringUtil.getWordsIn(name); final ArrayList keys = new ArrayList(); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index ced92a753e96..75491603c11a 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -940,19 +940,20 @@ public class FileBasedIndex implements ApplicationComponent { return result == null || result.booleanValue(); } - public void processFilesContainingAllKeys(final ID indexId, + public boolean processFilesContainingAllKeys(final ID indexId, final Collection dataKeys, final GlobalSearchScope filter, @Nullable Condition valueChecker, final Processor processor) { final TIntHashSet set = collectFileIdsContainingAllKeys(indexId, dataKeys, filter, valueChecker); - if (set != null) { - processVirtualFiles(set, filter, processor); + if (set == null) { + return false; } + return processVirtualFiles(set, filter, processor); } @Nullable - public TIntHashSet collectFileIdsContainingAllKeys(final ID indexId, + private TIntHashSet collectFileIdsContainingAllKeys(final ID indexId, final Collection dataKeys, final GlobalSearchScope filter, @Nullable final Condition valueChecker) { @@ -995,7 +996,7 @@ public class FileBasedIndex implements ApplicationComponent { return processExceptions(indexId, null, filter, convertor); } - public static boolean processVirtualFiles(TIntHashSet ids, final GlobalSearchScope filter, final Processor processor) { + private static boolean processVirtualFiles(TIntHashSet ids, final GlobalSearchScope filter, final Processor processor) { final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); return ids.forEach(new TIntProcedure() { @Override