index: files from project additional indexable set should be re-indexed on their change

GitOrigin-RevId: 908d819f2d7bfe0fcec7d9d7e984259b516fe2aa
This commit is contained in:
Dmitry Batkovich
2020-06-19 13:04:58 +03:00
committed by intellij-monorepo-bot
parent c457e61953
commit d1c1d33e8a
3 changed files with 70 additions and 19 deletions
@@ -17,29 +17,33 @@ import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.function.Supplier;
/**
* @author peter
*/
public class AdditionalIndexableFileSet implements IndexableFileSet {
@Nullable
private final Project myProject;
private final boolean myOnlyProjectPart;
private final Supplier<IndexableSetContributor[]> myExtensions;
private final CachedValue<AdditionalIndexableRoots> myAdditionalIndexableRoots;
public AdditionalIndexableFileSet(@Nullable Project project, IndexableSetContributor @NotNull ... extensions) {
myProject = project;
myOnlyProjectPart = false;
myExtensions = () -> extensions;
myAdditionalIndexableRoots = new CachedValueImpl<>(() -> new CachedValueProvider.Result<>(collectFilesAndDirectories(),
VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS));
}
public AdditionalIndexableFileSet(@Nullable Project project) {
public AdditionalIndexableFileSet(@Nullable Project project, boolean onlyProjectPart) {
myProject = project;
myExtensions = () -> IndexableSetContributor.EP_NAME.getExtensions();
myAdditionalIndexableRoots = new CachedValueImpl<>(() -> new CachedValueProvider.Result<>(collectFilesAndDirectories(),
VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS,
IndexableSetContributorModificationTracker.getInstance()));
myOnlyProjectPart = onlyProjectPart;
}
public AdditionalIndexableFileSet(@Nullable Project project) {
this(project, false);
}
public AdditionalIndexableFileSet() {
@@ -51,8 +55,10 @@ public class AdditionalIndexableFileSet implements IndexableFileSet {
Set<VirtualFile> files = new THashSet<>();
Set<VirtualFile> directories = new THashSet<>();
for (IndexableSetContributor contributor : myExtensions.get()) {
for (VirtualFile root : IndexableSetContributor.getRootsToIndex(contributor)) {
(root.isDirectory() ? directories : files).add(root);
if (myProject == null || !myOnlyProjectPart) {
for (VirtualFile root : IndexableSetContributor.getRootsToIndex(contributor)) {
(root.isDirectory() ? directories : files).add(root);
}
}
if (myProject != null) {
Set<VirtualFile> projectRoots = IndexableSetContributor.getProjectRootsToIndex(contributor, myProject);
@@ -40,8 +40,6 @@ public final class FileBasedIndexProjectHandler implements IndexableFileSet {
private final Project myProject;
private final @NotNull ProjectFileIndex myProjectFileIndex;
private boolean isRemoved;
private FileBasedIndexProjectHandler(@NotNull Project project) {
myProject = project;
myProjectFileIndex = ProjectFileIndex.getInstance(myProject);
@@ -76,23 +74,31 @@ public final class FileBasedIndexProjectHandler implements IndexableFileSet {
DumbService.getInstance(project).queueTask(new UnindexedFilesUpdater(project, IndexInfrastructure.isIndexesInitializationSuspended()));
}
FileBasedIndexProjectHandler handler = project.getService(FileBasedIndexProjectHandler.class);
fileBasedIndex.registerIndexableSet(handler, project);
for (Class<? extends IndexableFileSet> indexableSetClass : getProjectIndexableSetClasses()) {
IndexableFileSet set = project.getService(indexableSetClass);
fileBasedIndex.registerIndexableSet(set, project);
}
// done mostly for tests. In real life this is no-op, because the set was removed on project closing
Disposer.register(project, () -> removeProjectIndexableSet(project));
}
private static void removeProjectIndexableSet(@NotNull Project project) {
FileBasedIndexProjectHandler handler = project.getServiceIfCreated(FileBasedIndexProjectHandler.class);
if (handler != null && !handler.isRemoved) {
handler.isRemoved = true;
ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
ReadAction.run(() -> {
for (Class<? extends IndexableFileSet> indexableSetClass : getProjectIndexableSetClasses()) {
IndexableFileSet set = project.getServiceIfCreated(indexableSetClass);
if (set != null) {
FileBasedIndex.getInstance().removeIndexableSet(set);
}
}
});
}, IndexingBundle.message("removing.indexable.set.project.handler"), false, project);
}
ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
ReadAction.run(() -> {
FileBasedIndex.getInstance().removeIndexableSet(handler);
});
}, IndexingBundle.message("removing.indexable.set.project.handler"), false, project);
}
@SuppressWarnings("unchecked")
private static Class<? extends IndexableFileSet> @NotNull [] getProjectIndexableSetClasses() {
return new Class[]{FileBasedIndexProjectHandler.class, ProjectAdditionalIndexableFileSet.class};
}
}
@@ -199,4 +205,13 @@ public final class FileBasedIndexProjectHandler implements IndexableFileSet {
}
});
}
// TODO automated project indexable file set management
@ApiStatus.Internal
@Service
public static final class ProjectAdditionalIndexableFileSet extends AdditionalIndexableFileSet {
public ProjectAdditionalIndexableFileSet(@NotNull Project project) {
super(project, true);
}
}
}
@@ -1,15 +1,22 @@
// Copyright 2000-2020 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.openapi.roots.impl.indexing
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.AdditionalLibraryRootsProvider
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.SyntheticLibrary
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.impl.cache.CacheManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.UsageSearchContext
import com.intellij.testFramework.RunsInEdt
import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.indexing.IndexableSetContributor
import org.junit.Test
import kotlin.test.assertEquals
@RunsInEdt
class IndexableFilesRegularTest : IndexableFilesBaseTest() {
@@ -137,6 +144,17 @@ class IndexableFilesRegularTest : IndexableFilesBaseTest() {
}
maskIndexableSetContributors(contributor)
assertIndexableFiles(additionalProjectRootJava.file, additionalRootJava.file)
assertIdIndexContainsWord(additionalRootJava.file, "AdditionalRoot")
assertIdIndexContainsWord(additionalProjectRootJava.file, "AdditionalProjectRoot")
// make some change
runWriteAction {
VfsUtil.saveText(additionalRootJava.file, "class Foo {}")
VfsUtil.saveText(additionalProjectRootJava.file, "class Foo {}")
}
assertIdIndexContainsWord(additionalRootJava.file, "Foo")
assertIdIndexContainsWord(additionalProjectRootJava.file, "Foo")
}
@Test
@@ -200,4 +218,16 @@ class IndexableFilesRegularTest : IndexableFilesBaseTest() {
maskAdditionalLibraryRootsProviders(additionalLibraryRootsProvider)
assertIndexableFiles(sourceFile.file, binaryFile.file, reIncludedSource.file, reIncludedBinary.file)
}
private fun assertIdIndexContainsWord(file: VirtualFile, word: String) {
val fileScope = GlobalSearchScope.fileScope(project, file)
val cacheManager = CacheManager.getInstance(project)
val filesFromIndex = cacheManager.getVirtualFilesWithWord(word,
UsageSearchContext.ANY,
fileScope,
true)
val fileFromIndex = UsefulTestCase.assertOneElement(filesFromIndex)
assertEquals(file, fileFromIndex)
}
}