introduce FileBasedIndex.processFilesContainingAnyKey

GitOrigin-RevId: 9fcacda8b2e13f8976bbb5a60d4483e34b24e899
This commit is contained in:
Gregory.Shrago
2022-01-20 19:18:43 +03:00
committed by intellij-monorepo-bot
parent a96d2e233d
commit 1ad9a131f7
8 changed files with 146 additions and 19 deletions

View File

@@ -214,12 +214,10 @@ public final class FilenameIndex {
@NotNull GlobalSearchScope scope,
@Nullable IdFilter filter) {
Set<VirtualFile> files = CollectionFactory.createSmallMemoryFootprintSet();
for (String name : names) {
FileBasedIndex.getInstance().processValues(NAME, name, null, (file, value) -> {
files.add(file);
return true;
}, scope, filter);
}
FileBasedIndex.getInstance().processFilesContainingAnyKey(NAME, names, scope, filter, null, file -> {
files.add(file);
return true;
});
return files;
}
}

View File

@@ -124,6 +124,13 @@ public abstract class FileBasedIndex {
@Nullable Condition<? super V> valueChecker,
@NotNull Processor<? super VirtualFile> processor);
public abstract <K, V> boolean processFilesContainingAnyKey(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> dataKeys,
@NotNull GlobalSearchScope filter,
@Nullable IdFilter idFilter,
@Nullable Condition<? super V> valueChecker,
@NotNull Processor<? super VirtualFile> processor);
/**
* It is guaranteed to return data which is up-to-date within the given project.
* Keys obtained from the files which do not belong to the project specified may not be up-to-date or even exist.

View File

@@ -375,6 +375,18 @@ public abstract class FileBasedIndexEx extends FileBasedIndex {
return set != null && processVirtualFiles(set, filter, processor);
}
@Override
public <K, V> boolean processFilesContainingAnyKey(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> dataKeys,
@NotNull GlobalSearchScope filter,
@Nullable IdFilter idFilter,
@Nullable Condition<? super V> valueChecker,
@NotNull Processor<? super VirtualFile> processor) {
IdFilter idFilterAdjusted = idFilter != null ? idFilter : extractIdFilter(filter, filter.getProject());
IntSet set = collectFileIdsContainingAnyKey(indexId, dataKeys, filter, valueChecker, idFilterAdjusted);
return set != null && processVirtualFiles(set, filter, processor);
}
private boolean processFilesContainingAllKeysInPhysicalFiles(@NotNull Collection<? extends AllKeysQuery<?, ?>> queries,
@NotNull GlobalSearchScope filter,
Processor<? super VirtualFile> processor,
@@ -501,11 +513,11 @@ public abstract class FileBasedIndexEx extends FileBasedIndex {
}
@Nullable
private <K, V> IntSet collectFileIdsContainingAllKeys(@NotNull final ID<K, V> indexId,
@NotNull final Collection<? extends K> dataKeys,
@NotNull final GlobalSearchScope filter,
@Nullable final Condition<? super V> valueChecker,
@Nullable final IdFilter projectFilesFilter,
private <K, V> IntSet collectFileIdsContainingAllKeys(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> dataKeys,
@NotNull GlobalSearchScope filter,
@Nullable Condition<? super V> valueChecker,
@Nullable IdFilter projectFilesFilter,
@Nullable IntSet restrictedIds) {
IntPredicate accessibleFileFilter = getAccessibleFileIdFilter(filter.getProject());
IntPredicate idChecker = id -> (projectFilesFilter == null || projectFilesFilter.containsFileId(id)) &&
@@ -524,6 +536,28 @@ public abstract class FileBasedIndexEx extends FileBasedIndex {
return processExceptions(indexId, null, filter, convertor);
}
@Nullable
private <K, V> IntSet collectFileIdsContainingAnyKey(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> dataKeys,
@NotNull GlobalSearchScope filter,
@Nullable Condition<? super V> valueChecker,
@Nullable IdFilter projectFilesFilter) {
IntPredicate accessibleFileFilter = getAccessibleFileIdFilter(filter.getProject());
IntPredicate idChecker = id -> (projectFilesFilter == null || projectFilesFilter.containsFileId(id)) &&
accessibleFileFilter.test(id);
ThrowableConvertor<UpdatableIndex<K, V, FileContent>, IntSet, StorageException> convertor = index -> {
IndexDebugProperties.DEBUG_INDEX_ID.set(indexId);
try {
return InvertedIndexUtil.collectInputIdsContainingAnyKey(index, dataKeys, valueChecker, idChecker);
}
finally {
IndexDebugProperties.DEBUG_INDEX_ID.remove();
}
};
return processExceptions(indexId, null, filter, convertor);
}
private boolean processVirtualFiles(@NotNull IntCollection ids,
@NotNull GlobalSearchScope filter,
@NotNull Processor<? super VirtualFile> processor) {

View File

@@ -37,7 +37,10 @@ import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.psi.*;
import com.intellij.psi.PsiBinaryFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiDocumentTransactionListener;
import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
import com.intellij.psi.impl.source.PsiFileImpl;
@@ -1146,6 +1149,19 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
return super.processFilesContainingAllKeys(indexId, dataKeys, filter, valueChecker, processor);
}
@Override
public <K, V> boolean processFilesContainingAnyKey(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> dataKeys,
@NotNull GlobalSearchScope filter,
@Nullable IdFilter idFilter,
@Nullable Condition<? super V> valueChecker,
@NotNull Processor<? super VirtualFile> processor) {
IdFilter idFilterAdjusted = idFilter != null ? idFilter : extractIdFilter(filter, filter.getProject());
Boolean scanResult = FileBasedIndexScanUtil.processFilesContainingAnyKey(indexId, dataKeys, filter, idFilterAdjusted, valueChecker, processor);
if (scanResult != null) return scanResult;
return super.processFilesContainingAnyKey(indexId, dataKeys, filter, idFilterAdjusted, valueChecker, processor);
}
@Override
public boolean processFilesContainingAllKeys(@NotNull Collection<? extends AllKeysQuery<?, ?>> queries,
@NotNull GlobalSearchScope filter,

View File

@@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.BooleanSupplier;
@@ -114,21 +115,20 @@ public final class FileBasedIndexScanUtil {
if (indexId == FilenameIndex.NAME && Registry.is("indexing.filename.over.vfs")) {
ensureIdFilterUpToDate();
IntOpenHashSet ids = new IntOpenHashSet();
FSRecords.processFilesWithName((String)dataKey, id -> {
FSRecords.processFilesWithNames(Set.of((String)dataKey), id -> {
if (idFilter != null && !idFilter.containsFileId(id)) return true;
ids.add(id);
return true;
});
InThisThreadProcessor threadProcessor = new InThisThreadProcessor();
PersistentFS fs = PersistentFS.getInstance();
IntIterator iterator = ids.iterator();
while (iterator.hasNext()) {
VirtualFile file = fs.findFileById(iterator.nextInt());
if (file == null || !scope.contains(file)) continue;
if (!threadProcessor.process(() -> processor.process(file, null))) return false;
if (!processor.process(file, null)) return false;
if (ensureValueProcessedOnce) break;
}
return threadProcessor.processQueue();
return true;
}
else if (indexId == FileTypeIndex.NAME && Registry.is("indexing.filetype.over.vfs")) {
ensureIdFilterUpToDate();
@@ -245,4 +245,33 @@ public final class FileBasedIndexScanUtil {
}
return null;
}
public static <K, V> Boolean processFilesContainingAnyKey(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> keys,
@NotNull GlobalSearchScope scope,
@Nullable IdFilter idFilter,
@Nullable Condition<? super V> valueChecker,
@NotNull Processor<? super VirtualFile> processor) {
if (indexId == FilenameIndex.NAME && Registry.is("indexing.filename.over.vfs")) {
ensureIdFilterUpToDate();
IntOpenHashSet ids = new IntOpenHashSet();
//noinspection unchecked
FSRecords.processFilesWithNames((Set<String>)keys, id -> {
if (idFilter != null && !idFilter.containsFileId(id)) return true;
ids.add(id);
return true;
});
PersistentFS fs = PersistentFS.getInstance();
IntIterator iterator = ids.iterator();
while (iterator.hasNext()) {
VirtualFile file = fs.findFileById(iterator.nextInt());
if (file == null || !scope.contains(file)) continue;
//noinspection unchecked
if (valueChecker != null && !valueChecker.value((V)file.getName())) continue;
if (!processor.process(file)) return false;
}
return true;
}
return null;
}
}

View File

@@ -105,6 +105,16 @@ public final class EmptyFileBasedIndex extends FileBasedIndexEx {
return true;
}
@Override
public <K, V> boolean processFilesContainingAnyKey(@NotNull ID<K, V> indexId,
@NotNull Collection<? extends K> dataKeys,
@NotNull GlobalSearchScope filter,
@Nullable IdFilter idFilter,
@Nullable Condition<? super V> valueChecker,
@NotNull Processor<? super VirtualFile> processor) {
return true;
}
@Override
public @NotNull <K> Collection<K> getAllKeys(@NotNull ID<K, ?> indexId, @NotNull Project project) {
return Collections.emptyList();

View File

@@ -65,4 +65,31 @@ public final class InvertedIndexUtil {
return mainIntersection == null ? IntSets.EMPTY_SET : mainIntersection;
}
@NotNull
public static <K, V, I> IntSet collectInputIdsContainingAnyKey(@NotNull InvertedIndex<? super K, V, I> index,
@NotNull Collection<? extends K> dataKeys,
@Nullable Condition<? super V> valueChecker,
@Nullable IntPredicate idChecker) throws StorageException {
IntSet result = null;
for (K dataKey : dataKeys) {
IOCancellationCallbackHolder.checkCancelled();
ValueContainer<V> container = index.getData(dataKey);
for (ValueContainer.ValueIterator<V> valueIt = container.getValueIterator(); valueIt.hasNext(); ) {
V value = valueIt.next();
if (valueChecker != null && !valueChecker.value(value)) {
continue;
}
IOCancellationCallbackHolder.checkCancelled();
ValueContainer.IntIterator iterator = valueIt.getInputIdsIterator();
while (iterator.hasNext()) {
int id = iterator.next();
if (idChecker != null && !idChecker.test(id)) continue;
if (result == null) result = new IntOpenHashSet();
result.add(id);
}
}
}
return result == null ? IntSets.EMPTY_SET : result;
}
}

View File

@@ -30,6 +30,7 @@ import com.intellij.util.io.IOUtil;
import com.intellij.util.io.PersistentHashMapValueStorage;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import org.jetbrains.annotations.*;
import java.io.DataInputStream;
@@ -37,6 +38,7 @@ import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.function.IntPredicate;
@@ -555,12 +557,16 @@ public final class FSRecords {
return readAndHandleErrors(() -> ourConnection.getNames().processAllDataObjects(processor));
}
public static boolean processFilesWithName(@NotNull String name, @NotNull IntPredicate processor) {
int nameId = getNameId(name);
public static boolean processFilesWithNames(@NotNull Set<String> names, @NotNull IntPredicate processor) {
if (names.isEmpty()) return true;
IntOpenHashSet nameIds = new IntOpenHashSet();
for (String name : names) {
nameIds.add(getNameId(name));
}
return readAndHandleErrors(() -> {
PersistentFSRecordsStorage records = ourConnection.getRecords();
return records.processAll(r -> {
if (r.name == nameId &&
if (nameIds.contains(r.name) &&
!(BitUtil.isSet(r.flags, PersistentFSRecordAccessor.FREE_RECORD_FLAG) ||
ourRecordAccessor.getNewFreeRecords().contains(r.id))) {
if (!processor.test(r.id)) return false;