diff --git a/platform/indexing-impl/src/com/intellij/util/indexing/AdditionalIndexableFileSet.java b/platform/indexing-impl/src/com/intellij/util/indexing/AdditionalIndexableFileSet.java index 0eb21e10dcd3..68f184724415 100644 --- a/platform/indexing-impl/src/com/intellij/util/indexing/AdditionalIndexableFileSet.java +++ b/platform/indexing-impl/src/com/intellij/util/indexing/AdditionalIndexableFileSet.java @@ -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 myExtensions; private final CachedValue 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 files = new THashSet<>(); Set 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 projectRoots = IndexableSetContributor.getProjectRootsToIndex(contributor, myProject); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java index f7edd62aff11..3692767f32d0 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java @@ -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 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 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 @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); + } + } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/roots/impl/indexing/IndexableFilesRegularTest.kt b/platform/platform-tests/testSrc/com/intellij/openapi/roots/impl/indexing/IndexableFilesRegularTest.kt index 976d4c477857..3f9edb2e214c 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/roots/impl/indexing/IndexableFilesRegularTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/openapi/roots/impl/indexing/IndexableFilesRegularTest.kt @@ -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) + } } \ No newline at end of file