file based index: do not completely rebuild indexes on file-type change, use indexed file type to invalidate indexes per file

GitOrigin-RevId: 73a2b9e2bc130c2af6c8d617d9fc62c9d68f07ad
This commit is contained in:
Dmitro Batko
2019-12-31 13:06:25 +00:00
committed by intellij-monorepo-bot
parent d153a0e89a
commit 5f197fe078
8 changed files with 212 additions and 239 deletions
@@ -47,21 +47,7 @@ public final class FileTypeIndexImpl
@Override
public int getVersion() {
int version = 2;
if (!InvertedIndex.ARE_COMPOSITE_INDEXERS_ENABLED) {
FileType[] types = FileTypeRegistry.getInstance().getRegisteredFileTypes();
for (FileType type : types) {
version += type.getName().hashCode();
}
version *= 31;
for (FileTypeRegistry.FileTypeDetector detector : FileTypeRegistry.FileTypeDetector.EP_NAME.getExtensionList()) {
version += detector.getVersion();
}
}
return version;
return 2;
}
@NotNull
@@ -17,7 +17,6 @@ import java.io.DataOutput;
import java.io.IOException;
class FileTypeKeyDescriptor implements KeyDescriptor<FileType> {
private static final FileType OUT_DATED_FILE_TYPE = new OutDatedFileType();
static final FileTypeKeyDescriptor INSTANCE = new FileTypeKeyDescriptor();
@Override
@@ -29,6 +28,9 @@ class FileTypeKeyDescriptor implements KeyDescriptor<FileType> {
public boolean isEqual(FileType val1, FileType val2) {
if (val1 instanceof SubstitutedFileType) val1 = ((SubstitutedFileType)val1).getFileType();
if (val2 instanceof SubstitutedFileType) val2 = ((SubstitutedFileType)val2).getFileType();
if (val1 instanceof OutDatedFileType || val2 instanceof OutDatedFileType) {
return Comparing.equal(val1.getName(), val2.getName());
}
return Comparing.equal(val1, val2);
}
@@ -41,14 +43,19 @@ class FileTypeKeyDescriptor implements KeyDescriptor<FileType> {
public FileType read(@NotNull DataInput in) throws IOException {
String read = EnumeratorStringDescriptor.INSTANCE.read(in);
FileType fileType = FileTypeRegistry.getInstance().findFileTypeByName(read);
return fileType == null ? OUT_DATED_FILE_TYPE : fileType;
return fileType == null ? new OutDatedFileType(read) : fileType;
}
private static class OutDatedFileType implements FileType {
@NotNull
private final String myName;
private OutDatedFileType(@NotNull String name) {myName = name;}
@NotNull
@Override
public String getName() {
throw new UnsupportedOperationException();
return myName;
}
@NotNull
@@ -23,17 +23,14 @@ class FileTypeMapReduceIndex extends VfsAwareMapReduceIndex<FileType, Void, File
@Override
public boolean isIndexedStateForFile(int fileId, @NotNull IndexedFile file) {
boolean isIndexed = super.isIndexedStateForFile(fileId, file);
if (!InvertedIndex.ARE_COMPOSITE_INDEXERS_ENABLED) return isIndexed;
if (isIndexed) {
try {
Map<FileType, Void> inputData = ((MapInputDataDiffBuilder<FileType, Void>) getKeysDiffBuilder(fileId)). getMap();
FileType indexedFileType = ContainerUtil.getFirstItem(inputData.keySet());
// can be null if file type name is outdated
return FileTypeKeyDescriptor.INSTANCE.isEqual(indexedFileType, file.getFileType());
} catch (IOException e) {
LOG.error(e);
}
if (!isIndexed) return false;
try {
Map<FileType, Void> inputData = ((MapInputDataDiffBuilder<FileType, Void>) getKeysDiffBuilder(fileId)). getMap();
FileType indexedFileType = ContainerUtil.getFirstItem(inputData.keySet());
return FileTypeKeyDescriptor.INSTANCE.isEqual(indexedFileType, file.getFileType());
} catch (IOException e) {
LOG.error(e);
return false;
}
return isIndexed;
}
}
@@ -2,88 +2,22 @@
package com.intellij.util.indexing;
import com.intellij.openapi.fileTypes.*;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.*;
class FileBasedIndexFileTypeListener implements FileTypeListener {
@Nullable private Map<FileType, Set<String>> myTypeToExtensionMap;
@Override
public void beforeFileTypesChanged(@NotNull final FileTypeEvent event) {
FileBasedIndexImpl.cleanupProcessedFlag();
myTypeToExtensionMap = new THashMap<>();
FileTypeManager fileTypeManager = FileTypeManager.getInstance();
for (FileType type : fileTypeManager.getRegisteredFileTypes()) {
myTypeToExtensionMap.put(type, getExtensions(type, fileTypeManager));
}
}
@Override
public void fileTypesChanged(@NotNull final FileTypeEvent event) {
final Map<FileType, Set<String>> oldTypeToExtensionsMap = myTypeToExtensionMap;
myTypeToExtensionMap = null;
// file type added
FileBasedIndexImpl fileBasedIndex = (FileBasedIndexImpl)FileBasedIndex.getInstance();
if (event.getAddedFileType() != null) {
fileBasedIndex.rebuildAllIndices("The following file type was added: " + event.getAddedFileType());
return;
}
if (oldTypeToExtensionsMap == null) {
return;
}
final Map<FileType, Set<String>> newTypeToExtensionsMap = new THashMap<>();
FileTypeManager fileTypeManager = FileTypeManager.getInstance();
for (FileType type : fileTypeManager.getRegisteredFileTypes()) {
newTypeToExtensionsMap.put(type, getExtensions(type, fileTypeManager));
}
// file type changes and removals
if (!newTypeToExtensionsMap.keySet().containsAll(oldTypeToExtensionsMap.keySet())) {
Set<FileType> removedFileTypes = new HashSet<>(oldTypeToExtensionsMap.keySet());
removedFileTypes.removeAll(newTypeToExtensionsMap.keySet());
fileBasedIndex
.rebuildAllIndices("The following file types were removed/are no longer associated: " + removedFileTypes);
return;
}
for (Map.Entry<FileType, Set<String>> entry : oldTypeToExtensionsMap.entrySet()) {
FileType fileType = entry.getKey();
Set<String> oldMatchers = entry.getValue();
Set<String> newMatchers = newTypeToExtensionsMap.get(fileType);
if (!newMatchers.equals(oldMatchers)) {
Set<String> removed = complement(oldMatchers, newMatchers);
Set<String> added = complement(newMatchers, oldMatchers);
fileBasedIndex.rebuildAllIndices(fileType.getName()
+ " is no longer associated with matchers "
+ String.join(",", removed)
+ ", added matchers "
+ String.join(",", added));
return;
Set<ID<?, ?>> indexesToRebuild = new THashSet<>();
for (FileBasedIndexExtension<?, ?> extension : FileBasedIndexExtension.EXTENSION_POINT_NAME.getExtensionList()) {
if (IndexingStamp.versionDiffers(extension.getName(), extension.getVersion())) {
indexesToRebuild.add(extension.getName());
}
}
}
@NotNull
private static Set<String> getExtensions(@NotNull FileType type, @NotNull FileTypeManager fileTypeManager) {
return fileTypeManager
.getAssociations(type)
.stream()
.map(FileNameMatcher::getPresentableString)
.collect(Collectors.toCollection(THashSet::new));
}
private static Set<String> complement(Set<String> set, Set<String> toRemove) {
THashSet<String> result = new THashSet<>(set);
result.removeAll(toRemove);
return result;
FileBasedIndexImpl fileBasedIndex = (FileBasedIndexImpl)FileBasedIndex.getInstance();
fileBasedIndex.scheduleFullIndexesRescan(indexesToRebuild);
}
}
@@ -29,15 +29,12 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.*;
import com.intellij.openapi.roots.CollectingContentIterator;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdaterImpl;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.AsyncFileListener;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.openapi.vfs.newvfs.AsyncEventSupport;
@@ -57,7 +54,6 @@ import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.SerializationManagerEx;
import com.intellij.util.*;
@@ -213,19 +209,13 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
initComponent();
}
void rebuildAllIndices(@NotNull String reason) {
doClearIndices(id -> {
if (!InvertedIndex.ARE_COMPOSITE_INDEXERS_ENABLED) return true;
if (id.equals(FileTypeIndex.NAME)) return false;
if (getState().getIndex(id).getExtension().getIndexer() instanceof CompositeDataIndexer) {
return false;
}
return true;
});
scheduleIndexRebuild("File type change" + ", " + reason);
void scheduleFullIndexesRescan(@NotNull Collection<ID<?, ?>> indexesToRebuild) {
cleanupProcessedFlag();
doClearIndices(id -> indexesToRebuild.contains(id));
String rebuiltIndexesLog = indexesToRebuild.isEmpty()
? ""
: "; indexes \" + indexesToRebuild + \" will be rebuild completely due to version change\" ";
scheduleIndexRebuild("File type change" + rebuiltIndexesLog);
}
@VisibleForTesting
@@ -1247,7 +1237,7 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
}
@NotNull
private List<ID<?, ?>> getAffectedIndexCandidates(@NotNull VirtualFile file) {
List<ID<?, ?>> getAffectedIndexCandidates(@NotNull VirtualFile file) {
if (file.isDirectory()) {
return isProjectOrWorkspaceFile(file, null) ? Collections.emptyList() : myRegisteredIndexes.getIndicesForDirectories();
}
@@ -1271,7 +1261,7 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
fc.putUserData(IndexingDataKeys.PROJECT, project);
}
private boolean updateSingleIndex(@NotNull ID<?, ?> indexId, @Nullable VirtualFile file, int inputId, @Nullable FileContent currentFC) {
boolean updateSingleIndex(@NotNull ID<?, ?> indexId, @Nullable VirtualFile file, int inputId, @Nullable FileContent currentFC) {
if (!myRegisteredIndexes.isExtensionsDataLoaded()) reportUnexpectedAsyncInitState();
if (!RebuildStatus.isOk(indexId) && !myIsUnitTestMode) {
return false; // the index is scheduled for rebuild, no need to update
@@ -1380,7 +1370,7 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
}
}
private boolean needsFileContentLoading(@NotNull ID<?, ?> indexId) {
boolean needsFileContentLoading(@NotNull ID<?, ?> indexId) {
return !myRegisteredIndexes.isNotRequiringContentIndex(indexId);
}
@@ -1458,7 +1448,7 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
if (!contentChange) {
FileContent fileContent = null;
for (ID<?, ?> indexId : fileIsDirectory ? myRegisteredIndexes.getIndicesForDirectories() : myRegisteredIndexes.getNotRequiringContentIndices()) {
for (ID<?, ?> indexId : getContentLessIndexes(fileIsDirectory)) {
if (getInputFilter(indexId).acceptInput(file)) {
if (fileContent == null) {
fileContent = new FileContentImpl(file);
@@ -1507,7 +1497,12 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
}
}
private static FileTypeManagerImpl getFileTypeManager() {
@NotNull
Collection<ID<?, ?>> getContentLessIndexes(boolean isDirectory) {
return isDirectory ? myRegisteredIndexes.getIndicesForDirectories() : myRegisteredIndexes.getNotRequiringContentIndices();
}
static FileTypeManagerImpl getFileTypeManager() {
return (FileTypeManagerImpl)FileTypeManager.getInstance();
}
@@ -1756,110 +1751,7 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
return file instanceof VirtualFileWithId ?((VirtualFileWithId)file).getId() : IndexingStamp.INVALID_FILE_ID;
}
private class UnindexedFilesFinder implements CollectingContentIterator {
private final List<VirtualFile> myFiles = new ArrayList<>();
private final Project myProject;
private final boolean myDoTraceForFilesToBeIndexed = LOG.isTraceEnabled();
UnindexedFilesFinder(@NotNull Project project) {
myProject = project;
}
@NotNull
@Override
public List<VirtualFile> getFiles() {
List<VirtualFile> files;
synchronized (myFiles) {
files = myFiles;
}
// When processing roots concurrently myFiles looses the local order of local vs archive files
// If we process the roots in 2 threads we can just separate local vs archive
// IMPORTANT: also remove duplicated file that can appear due to roots intersection
BitSet usedFileIds = new BitSet(files.size());
List<VirtualFile> localFileSystemFiles = new ArrayList<>(files.size() / 2);
List<VirtualFile> archiveFiles = new ArrayList<>(files.size() / 2);
for(VirtualFile file:files) {
int fileId = ((VirtualFileWithId)file).getId();
if (usedFileIds.get(fileId)) continue;
usedFileIds.set(fileId);
if (file.getFileSystem() instanceof LocalFileSystem) localFileSystemFiles.add(file);
else archiveFiles.add(file);
}
localFileSystemFiles.addAll(archiveFiles);
return localFileSystemFiles;
}
@Override
public boolean processFile(@NotNull final VirtualFile file) {
return ReadAction.compute(() -> {
if (!file.isValid()) {
return true;
}
if (file instanceof VirtualFileSystemEntry && ((VirtualFileSystemEntry)file).isFileIndexed()) {
return true;
}
if (!(file instanceof VirtualFileWithId)) {
return true;
}
getFileTypeManager().freezeFileTypeTemporarilyIn(file, () -> {
IndexedFile fileContent = new IndexedFileImpl(file, myProject);
boolean isUptoDate = true;
boolean isDirectory = file.isDirectory();
if (!isDirectory && !isTooLarge(file)) {
final List<ID<?, ?>> affectedIndexCandidates = getAffectedIndexCandidates(file);
//noinspection ForLoopReplaceableByForEach
for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
try {
if (needsFileContentLoading(indexId) && shouldIndexFile(fileContent, indexId)) {
if (myDoTraceForFilesToBeIndexed) {
LOG.trace("Scheduling indexing of " + file + " by request of index " + indexId);
}
synchronized (myFiles) {
myFiles.add(file);
}
isUptoDate = false;
break;
}
}
catch (RuntimeException e) {
final Throwable cause = e.getCause();
if (cause instanceof IOException || cause instanceof StorageException) {
LOG.info(e);
requestRebuild(indexId);
}
else {
throw e;
}
}
}
}
int inputId = Math.abs(getIdMaskingNonIdBasedFile(file));
for (ID<?, ?> indexId : isDirectory ? myRegisteredIndexes.getIndicesForDirectories() : myRegisteredIndexes.getNotRequiringContentIndices()) {
if (shouldIndexFile(fileContent, indexId)) {
updateSingleIndex(indexId, file, inputId, new IndexedFileWrapper(fileContent));
}
}
IndexingStamp.flushCache(inputId);
if (isUptoDate && file instanceof VirtualFileSystemEntry) {
((VirtualFileSystemEntry)file).setFileIndexed(true);
}
});
ProgressManager.checkCanceled();
return true;
});
}
}
private boolean shouldIndexFile(@NotNull IndexedFile file, @NotNull ID<?, ?> indexId) {
boolean shouldIndexFile(@NotNull IndexedFile file, @NotNull ID<?, ?> indexId) {
VirtualFile virtualFile = file.getFile();
return getInputFilter(indexId).acceptInput(virtualFile) &&
(isMock(virtualFile) || !getIndex(indexId).isIndexedStateForFile(((NewVirtualFile) virtualFile).getId(), file));
@@ -1869,7 +1761,7 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
return !(file instanceof NewVirtualFile);
}
private boolean isTooLarge(@NotNull VirtualFile file) {
boolean isTooLarge(@NotNull VirtualFile file) {
if (SingleRootFileViewProvider.isTooLargeForIntelligence(file)) {
return !myRegisteredIndexes.skipLimitCheck(file) || SingleRootFileViewProvider.isTooLargeForContentLoading(file);
}
@@ -1883,11 +1775,6 @@ public final class FileBasedIndexImpl extends FileBasedIndexEx {
return false;
}
@NotNull
CollectingContentIterator createContentIterator(@NotNull Project project) {
return new UnindexedFilesFinder(project);
}
@Override
public void registerIndexableSet(@NotNull IndexableFileSet set, @Nullable Project project) {
myIndexableSets.add(set);
@@ -0,0 +1,160 @@
// 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.
package com.intellij.util.indexing;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CollectingContentIterator;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Map;
class UnindexedFilesFinder implements CollectingContentIterator {
private static final Logger LOG = Logger.getInstance(UnindexedFilesFinder.class);
private final List<VirtualFile> myFiles = new ArrayList<>();
private final Project myProject;
private final boolean myDoTraceForFilesToBeIndexed = FileBasedIndexImpl.LOG.isTraceEnabled();
private final FileBasedIndexImpl myFileBasedIndex;
UnindexedFilesFinder(@NotNull Project project) {
myProject = project;
myFileBasedIndex = ((FileBasedIndexImpl)FileBasedIndex.getInstance());
}
@NotNull
@Override
public List<VirtualFile> getFiles() {
List<VirtualFile> files;
synchronized (myFiles) {
files = myFiles;
}
// When processing roots concurrently myFiles looses the local order of local vs archive files
// If we process the roots in 2 threads we can just separate local vs archive
// IMPORTANT: also remove duplicated file that can appear due to roots intersection
BitSet usedFileIds = new BitSet(files.size());
List<VirtualFile> localFileSystemFiles = new ArrayList<>(files.size() / 2);
List<VirtualFile> archiveFiles = new ArrayList<>(files.size() / 2);
for(VirtualFile file:files) {
int fileId = ((VirtualFileWithId)file).getId();
if (usedFileIds.get(fileId)) continue;
usedFileIds.set(fileId);
if (file.getFileSystem() instanceof LocalFileSystem) localFileSystemFiles.add(file);
else archiveFiles.add(file);
}
localFileSystemFiles.addAll(archiveFiles);
return localFileSystemFiles;
}
@Override
public boolean processFile(@NotNull final VirtualFile file) {
return ReadAction.compute(() -> {
if (!file.isValid()) {
return true;
}
if (file instanceof VirtualFileSystemEntry && ((VirtualFileSystemEntry)file).isFileIndexed()) {
return true;
}
if (!(file instanceof VirtualFileWithId)) {
return true;
}
FileBasedIndexImpl.getFileTypeManager().freezeFileTypeTemporarilyIn(file, () -> {
IndexedFile fileContent = new IndexedFileImpl(file, myProject);
boolean isUptoDate = true;
boolean isDirectory = file.isDirectory();
int inputId = Math.abs(FileBasedIndexImpl.getIdMaskingNonIdBasedFile(file));
if (!isDirectory && !myFileBasedIndex.isTooLarge(file)) {
if (!isIndexedFileTypeUpToDate(fileContent, inputId)) {
for (ID<?, ?> state : IndexingStamp.getNontrivialFileIndexedStates(inputId)) {
myFileBasedIndex.getIndex(state).resetIndexedStateForFile(inputId);
}
synchronized (myFiles) {
myFiles.add(file);
}
isUptoDate = false;
}
if (isUptoDate) {
final List<ID<?, ?>> affectedIndexCandidates = myFileBasedIndex.getAffectedIndexCandidates(file);
//noinspection ForLoopReplaceableByForEach
for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
try {
if (myFileBasedIndex.needsFileContentLoading(indexId) && myFileBasedIndex.shouldIndexFile(fileContent, indexId)) {
if (myDoTraceForFilesToBeIndexed) {
LOG.trace("Scheduling indexing of " + file + " by request of index " + indexId);
}
synchronized (myFiles) {
myFiles.add(file);
}
isUptoDate = false;
break;
}
}
catch (RuntimeException e) {
final Throwable cause = e.getCause();
if (cause instanceof IOException || cause instanceof StorageException) {
LOG.info(e);
myFileBasedIndex.requestRebuild(indexId);
}
else {
throw e;
}
}
}
}
}
for (ID<?, ?> indexId : myFileBasedIndex.getContentLessIndexes(isDirectory)) {
if (myFileBasedIndex.shouldIndexFile(fileContent, indexId)) {
myFileBasedIndex.updateSingleIndex(indexId, file, inputId, new IndexedFileWrapper(fileContent));
}
}
IndexingStamp.flushCache(inputId);
if (isUptoDate && file instanceof VirtualFileSystemEntry) {
((VirtualFileSystemEntry)file).setFileIndexed(true);
}
});
ProgressManager.checkCanceled();
return true;
});
}
private boolean isIndexedFileTypeUpToDate(@NotNull IndexedFile file, int inputId) {
long stamp = IndexingStamp.getIndexStamp(inputId, FileTypeIndex.NAME);
long fileTypeIndexVersion = IndexingStamp.getIndexCreationStamp(FileTypeIndex.NAME);
if (stamp != fileTypeIndexVersion) return false;
FileType actualFileType = file.getFileType();
try {
Map<FileType, Void> indexedFileType = myFileBasedIndex.getIndex(FileTypeIndex.NAME).getIndexedFileData(inputId);
return actualFileType.equals(ContainerUtil.getFirstItem(indexedFileType.keySet()));
}
catch (StorageException e) {
myFileBasedIndex.requestRebuild(FileTypeIndex.NAME, e);
LOG.error(e);
return false;
}
}
}
@@ -58,7 +58,7 @@ public final class UnindexedFilesUpdater extends DumbModeTask {
myIndex.clearIndicesIfNecessary();
CollectingContentIterator finder = myIndex.createContentIterator(myProject);
CollectingContentIterator finder = new UnindexedFilesFinder(myProject);
snapshot = PerformanceWatcher.takeSnapshot();
myIndex.iterateIndexableFilesConcurrently(finder, myProject, indicator);
@@ -21,19 +21,21 @@ public class FileTypeIndexTest extends BasePlatformTestCase {
public void testAddFileType() {
FileTypeIndexImpl index = FileBasedIndexExtension.EXTENSION_POINT_NAME.findExtension(FileTypeIndexImpl.class);
myFixture.configureByText("foo.test", "abc");
VirtualFile file = myFixture.configureByText("foo.test", "abc").getVirtualFile();
FileTypeIndex.getFiles(PlainTextFileType.INSTANCE, GlobalSearchScope.allScope(getProject()));
FileType foo = registerFakeFileType();
int version = index.getVersion();
FileType foo = registerFakeFileType();
try {
assertSame(!InvertedIndex.ARE_COMPOSITE_INDEXERS_ENABLED,version == index.getVersion());
assertEquals(version, index.getVersion());
Collection<VirtualFile> files = FileTypeIndex.getFiles(foo, GlobalSearchScope.allScope(getProject()));
assertEquals(1, files.size());
assertOneElement(files);
assertEquals(foo, FileTypeIndex.getIndexedFileType(file, getProject()));
}
finally {
FileTypeManagerEx.getInstanceEx().unregisterFileType(foo);
}
assertEquals(PlainTextFileType.INSTANCE, FileTypeIndex.getIndexedFileType(file, getProject()));
assertEmpty(FileTypeIndex.getFiles(foo, GlobalSearchScope.allScope(getProject())));
}