From 95c1ab65f41993a85f5d6c9ade894bfdf45163ae Mon Sep 17 00:00:00 2001 From: Elena Shaverdova Date: Wed, 8 Mar 2023 20:50:32 +0100 Subject: [PATCH] Switch collecting builders to IndexingRootsDescriptions GitOrigin-RevId: 7b3946290e106973350a9a595efbd2f30566b342 --- .../indexing/EntityIndexingServiceImpl.java | 79 +++--- .../roots/IndexingRootsCollectionUtil.java | 89 ------ .../roots/IndexingRootsDescriptions.kt | 262 ++++++++++++++++++ ...tyIndexingServiceOnCustomEntitiesTest.java | 25 +- 4 files changed, 313 insertions(+), 142 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsDescriptions.kt diff --git a/platform/lang-impl/src/com/intellij/util/indexing/EntityIndexingServiceImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/EntityIndexingServiceImpl.java index 5ad49b59368d..09fbe8dca7dd 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/EntityIndexingServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/EntityIndexingServiceImpl.java @@ -8,7 +8,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.RootsChangeRescanningInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.dependenciesCache.DependenciesIndexedStatusService; @@ -16,7 +15,7 @@ import com.intellij.util.indexing.dependenciesCache.DependenciesIndexedStatusSer import com.intellij.util.indexing.roots.IndexableEntityProvider; import com.intellij.util.indexing.roots.IndexableEntityProvider.IndexableIteratorBuilder; import com.intellij.util.indexing.roots.IndexableFilesIterator; -import com.intellij.util.indexing.roots.IndexingRootsCollectionUtil; +import com.intellij.util.indexing.roots.IndexingRootsDescriptionsBuilder; import com.intellij.util.indexing.roots.LibraryIndexableEntityProvider; import com.intellij.util.indexing.roots.builders.IndexableIteratorBuilders; import com.intellij.workspaceModel.core.fileIndex.DependencyDescription; @@ -41,7 +40,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; class EntityIndexingServiceImpl implements EntityIndexingServiceEx { @@ -178,13 +180,15 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { @NotNull private static List getBuildersOnWorkspaceChange(@NotNull Project project, - @NotNull Collection> event, + @NotNull Collection> events, @NotNull EntityStorage entityStorage) { List builders = new SmartList<>(); - for (EntityChange change : event) { + IndexingRootsDescriptionsBuilder descriptionsBuilder = new IndexingRootsDescriptionsBuilder(); + for (EntityChange change : events) { collectIteratorBuildersOnChange(Change.fromEntityChange(change), change.getOldEntity(), change.getNewEntity(), project, builders, - entityStorage); + descriptionsBuilder, entityStorage); } + builders.addAll(descriptionsBuilder.createBuilders(project)); return builders; } @@ -193,27 +197,26 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { @Nullable E newEntity, @NotNull Project project, @NotNull Collection builders, + @NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder, @NotNull EntityStorage entityStorage) { LOG.assertTrue(newEntity != null || change == Change.Removed, "New entity " + newEntity + ", change " + change); LOG.assertTrue(oldEntity != null || change == Change.Added, "Old entity " + oldEntity + ", change " + change); //noinspection unchecked Class entityClass = (Class)Objects.requireNonNull(newEntity == null ? oldEntity : newEntity).getEntityInterface(); - IndexingRootsCollectionUtil.RootsCollector collector = new IndexingRootsCollectionUtil.RootsCollector(null); if (IndexableFilesIndex.isEnabled()) { List newBuilders = new ArrayList<>(); - collectWFICIteratorsOnChange(change, oldEntity, newEntity, project, newBuilders, collector, entityClass, false, entityStorage); + collectWFICIteratorsOnChange(change, oldEntity, newEntity, project, newBuilders, descriptionsBuilder, entityClass, false, + entityStorage); builders.addAll(newBuilders); } else { List oldBuilders = new ArrayList<>(); - collectIEPIteratorsOnChange(change, oldEntity, newEntity, project, oldBuilders, collector, entityClass, false, entityStorage); + collectIEPIteratorsOnChange(change, oldEntity, newEntity, project, oldBuilders, descriptionsBuilder, entityClass, false, + entityStorage); builders.addAll(oldBuilders); } - - Collection reincludedRoots = collector.removeReincludedRoots(); - builders.addAll(ReincludedRootsUtil.createBuildersForReincludedFiles(project, reincludedRoots)); } private static void collectIEPIteratorsOnChange(@NotNull Change change, @@ -221,7 +224,7 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { @Nullable E newEntity, @NotNull Project project, @NotNull Collection builders, - @NotNull IndexingRootsCollectionUtil.RootsCollector collector, + @NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder, @NotNull Class entityClass, boolean enforcedOnly, @NotNull EntityStorage entityStorage) { @@ -253,7 +256,8 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { } if (!enforcedOnly) { - collectWFICIteratorsOnChange(change, oldEntity, newEntity, project, builders, collector, entityClass, true, entityStorage + collectWFICIteratorsOnChange(change, oldEntity, newEntity, project, builders, descriptionsBuilder, entityClass, true, + entityStorage ); } } @@ -263,7 +267,7 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { @Nullable E newEntity, @NotNull Project project, @NotNull Collection builders, - @NotNull IndexingRootsCollectionUtil.RootsCollector collector, + @NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder, @NotNull Class entityClass, boolean customOnly, @NotNull EntityStorage entityStorage) { @@ -273,26 +277,30 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { List> contributors = ((WorkspaceFileIndexImpl)WorkspaceFileIndex.getInstance(project)).getContributors(); for (WorkspaceFileIndexContributor uncheckedContributor : contributors) { + if (uncheckedContributor.getStorageKind() != EntityStorageKind.MAIN) { + continue; + } if (customOnly && uncheckedContributor instanceof PlatformInternalWorkspaceFileIndexContributor) { continue; } if (entityClass == uncheckedContributor.getEntityClass()) { //noinspection unchecked WorkspaceFileIndexContributor contributor = (WorkspaceFileIndexContributor)uncheckedContributor; - if (change != Change.Removed) { - builders.addAll(createBuildersForIncludedRoots(contributor, newEntity, entityStorage, collector)); - } - if (change != Change.Added) { - collector.registerExcludedRoots(oldEntity, contributor, entityStorage); + switch (change) { + case Added -> descriptionsBuilder.registerAddedEntity(newEntity, contributor, entityStorage); + case Replaced -> descriptionsBuilder.registerChangedEntity(oldEntity, newEntity, contributor, entityStorage); + case Removed -> descriptionsBuilder.registerRemovedEntity(oldEntity, contributor, entityStorage); } } if (change == Change.Replaced) { - handleDependencies(oldEntity, newEntity, builders, collector, entityClass, uncheckedContributor, entityStorage); + handleDependencies(oldEntity, newEntity, descriptionsBuilder, entityClass, uncheckedContributor, + entityStorage); } } if (!customOnly) { - collectIEPIteratorsOnChange(change, oldEntity, newEntity, project, builders, collector, entityClass, true, entityStorage); + collectIEPIteratorsOnChange(change, oldEntity, newEntity, project, builders, descriptionsBuilder, entityClass, true, + entityStorage); } if (!customOnly && change != Change.Removed && isLibraryIgnoredByLibraryRootFileIndexContributor(newEntity)) { @@ -306,17 +314,6 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { } } - @NotNull - private static Collection createBuildersForIncludedRoots(@NotNull WorkspaceFileIndexContributor contributor, - @NotNull E entity, - @NotNull EntityStorage entityStorage, - @NotNull IndexingRootsCollectionUtil.RootsCollector collector) { - if (contributor.getStorageKind() != EntityStorageKind.MAIN) return Collections.emptyList(); - IndexingRootsCollectionUtil.IndexingRootsDescriptions roots = new IndexingRootsCollectionUtil.IndexingRootsDescriptions(); - collector.registerAndCollectAllRoots(roots, contributor, SequencesKt.sequenceOf(entity), entityStorage); - return IndexingRootsCollectionUtil.createBuildersFromRootsDescriptions(roots); - } - private static boolean isLibraryIgnoredByLibraryRootFileIndexContributor(@NotNull E newEntity) { return newEntity instanceof LibraryEntity && ((LibraryEntity)newEntity).getSymbolicId().getTableId() instanceof LibraryTableId.GlobalLibraryTableId; @@ -324,21 +321,20 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { private static void handleDependencies(@NotNull E oldEntity, @NotNull E newEntity, - @NotNull Collection builders, - @NotNull IndexingRootsCollectionUtil.RootsCollector collector, + @NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder, @NotNull Class entityClass, @NotNull WorkspaceFileIndexContributor contributor, @NotNull EntityStorage entityStorage) { for (DependencyDescription dependency : contributor.getDependenciesOnOtherEntities()) { - handleChildEntities(entityClass, oldEntity, newEntity, builders, collector, contributor, dependency, entityStorage); + handleChildEntities(entityClass, oldEntity, newEntity, descriptionsBuilder, contributor, dependency, + entityStorage); } } private static void handleChildEntities(@NotNull Class entityClass, @NotNull E oldEntity, @NotNull E newEntity, - @NotNull Collection builders, - @NotNull IndexingRootsCollectionUtil.RootsCollector collector, + @NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder, @NotNull WorkspaceFileIndexContributor contributor, @NotNull DependencyDescription dependency, @NotNull EntityStorage entityStorage) { @@ -352,7 +348,7 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { newElements.removeAll(oldElements); for (C element : newElements) { - builders.addAll(createBuildersForIncludedRoots(contributor, element, entityStorage, collector)); + descriptionsBuilder.registerAddedEntity(element, contributor, entityStorage); } } @@ -360,9 +356,12 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx { @NotNull List entities, @NotNull EntityStorage entityStorage) { List builders = new SmartList<>(); + + IndexingRootsDescriptionsBuilder descriptionsBuilder = new IndexingRootsDescriptionsBuilder(); for (WorkspaceEntity entity : entities) { - collectIteratorBuildersOnChange(Change.Added, null, entity, project, builders, entityStorage); + collectIteratorBuildersOnChange(Change.Added, null, entity, project, builders, descriptionsBuilder, entityStorage); } + builders.addAll(descriptionsBuilder.createBuilders(project)); return builders; } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsCollectionUtil.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsCollectionUtil.java index a1e69db837dd..681bf7c04529 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsCollectionUtil.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsCollectionUtil.java @@ -12,7 +12,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ObjectUtils; import com.intellij.util.SmartList; import com.intellij.util.containers.MultiMap; -import com.intellij.util.indexing.roots.IndexableEntityProvider.IndexableIteratorBuilder; import com.intellij.util.indexing.roots.kind.IndexableSetOrigin; import com.intellij.workspaceModel.core.fileIndex.*; import com.intellij.workspaceModel.core.fileIndex.impl.LibraryRootFileIndexContributor; @@ -20,7 +19,6 @@ import com.intellij.workspaceModel.core.fileIndex.impl.ModuleContentOrSourceRoot import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl; import com.intellij.workspaceModel.ide.VirtualFileUrls; import com.intellij.workspaceModel.ide.impl.legacyBridge.library.LibraryEntityUtils; -import com.intellij.workspaceModel.ide.legacyBridge.ModuleBridge; import com.intellij.workspaceModel.storage.EntityReference; import com.intellij.workspaceModel.storage.EntityStorage; import com.intellij.workspaceModel.storage.WorkspaceEntity; @@ -36,7 +34,6 @@ import java.util.*; import java.util.function.Consumer; import static com.intellij.util.indexing.roots.LibraryIndexableFilesIteratorImpl.createIterator; -import static com.intellij.util.indexing.roots.builders.IndexableIteratorBuilders.INSTANCE; public class IndexingRootsCollectionUtil { @@ -136,28 +133,6 @@ public class IndexingRootsCollectionUtil { } } - @NotNull - public static Collection createBuildersFromRootsDescriptions(@NotNull IndexingRootsDescriptions descriptions) { - ArrayList builders = new ArrayList<>(); - for (ModuleRootsDescription moduleRootsDescription : descriptions.moduleRoots()) { - builders.addAll(INSTANCE.forModuleRootsFileBased(((ModuleBridge)moduleRootsDescription.module()).getModuleEntityId(), - moduleRootsDescription.roots())); - } - for (LibraryRootsDescription libraryRoot : descriptions.libraryRoots()) { - builders.addAll(INSTANCE.forLibraryEntity(libraryRoot.library().getSymbolicId(), false, - libraryRoot.classRoots(), libraryRoot.sourceRoots())); - } - - for (EntityContentRootsDescription description : descriptions.contentEntityRoots()) { - builders.addAll(INSTANCE.forModuleUnawareContentEntity(description.entityReference(), description.roots())); - } - - for (EntityRootsDescription description : descriptions.externalEntityRoots()) { - builders.addAll(INSTANCE.forExternalEntity(description.entityReference(), description.roots(), description.sourceRoots())); - } - return builders; - } - public static List optimizeRoots(@NotNull Collection roots) { int size = roots.size(); if (size == 0) { @@ -202,7 +177,6 @@ public class IndexingRootsCollectionUtil { private final MultiMap myLibrarySourceRoots = MultiMap.createSet(); private final MultiMap myExternalRoots = MultiMap.createSet(); private final MultiMap myExternalSourceRoots = MultiMap.createSet(); - private final List myReincludedRoots = new ArrayList<>(); @Nullable private WorkspaceFileIndexContributor myCurrentContributor; @@ -238,23 +212,6 @@ public class IndexingRootsCollectionUtil { clearNonModuleAwareMaps(); } - public void registerAndCollectAllRoots(@NotNull IndexingRootsDescriptions roots, - @NotNull WorkspaceFileIndexContributor contributor, - @NotNull Sequence entities, - @NotNull EntityStorage entityStorage) { - if (shouldIgnore(contributor)) return; - myContents.clear(); - clearNonModuleAwareMaps(); - myCurrentContributor = contributor; - for (E entity : SequencesKt.asIterable(entities)) { - contributor.registerFileSets(entity, myRegistrar, entityStorage); - } - myCurrentContributor = null; - collectModuleAwareRoots(roots); - doCollectNonModuleAwareRoots(roots); - clearNonModuleAwareMaps(); - } - private void doCollectNonModuleAwareRoots(@NotNull IndexingRootsDescriptions roots) { for (Map.Entry> entry : myContentRoots.entrySet()) { roots.contentEntityRoots.add(new EntityContentRootsDescription(entry.getKey().createReference(), entry.getValue())); @@ -301,39 +258,13 @@ public class IndexingRootsCollectionUtil { myContents.clear(); } - public void registerExcludedRoots(@NotNull E entity, - @NotNull WorkspaceFileIndexContributor contributor, - @NotNull EntityStorage storage) { - myRegistrar.setRootsToCollect(MyWorkspaceFileSetRegistrar.RootType.Excluded); - try { - contributor.registerFileSets(entity, myRegistrar, storage); - } - finally { - myRegistrar.setRootsToCollect(MyWorkspaceFileSetRegistrar.RootType.Included); - } - } - - public Collection removeReincludedRoots() { - List result = new ArrayList<>(myReincludedRoots); - myReincludedRoots.clear(); - return result; - } - private class MyWorkspaceFileSetRegistrar implements WorkspaceFileSetRegistrar { - enum RootType {Included, Excluded} - - private RootType rootsToCollect = RootType.Included; - - private void setRootsToCollect(@NotNull RootType rootType) { - rootsToCollect = rootType; - } @Override public void registerFileSet(@NotNull VirtualFileUrl root, @NotNull WorkspaceFileKind kind, @NotNull WorkspaceEntity entity, @Nullable WorkspaceFileSetData customData) { - if (rootsToCollect != RootType.Included) return; VirtualFile file = VirtualFileUrls.getVirtualFile(root); if (file != null) { doRegisterFileSet(file, kind, entity, customData); @@ -345,7 +276,6 @@ public class IndexingRootsCollectionUtil { @NotNull WorkspaceFileKind kind, @NotNull WorkspaceEntity entity, @Nullable WorkspaceFileSetData customData) { - if (rootsToCollect != RootType.Included) return; doRegisterFileSet(root, kind, entity, customData); } @@ -379,53 +309,34 @@ public class IndexingRootsCollectionUtil { @Override public void registerExcludedRoot(@NotNull VirtualFileUrl excludedRoot, @NotNull WorkspaceEntity entity) { - if (rootsToCollect != RootType.Excluded) return; - addReincludedRoot(excludedRoot); - } - - private void addReincludedRoot(VirtualFileUrl root) { - VirtualFile file = VirtualFileUrls.getVirtualFile(root); - if (file != null) { - myReincludedRoots.add(file); - } } @Override public void registerExcludedRoot(@NotNull VirtualFileUrl excludedRoot, @NotNull WorkspaceFileKind excludedFrom, @NotNull WorkspaceEntity entity) { - if (rootsToCollect != RootType.Excluded) return; - addReincludedRoot(excludedRoot); } @Override public void registerExcludedRoot(@NotNull VirtualFile excludedRoot, @NotNull WorkspaceFileKind excludedFrom, @NotNull WorkspaceEntity entity) { - if (rootsToCollect != RootType.Excluded) return; - myReincludedRoots.add(excludedRoot); } @Override public void registerExclusionPatterns(@NotNull VirtualFileUrl root, @NotNull List patterns, @NotNull WorkspaceEntity entity) { - if (rootsToCollect != RootType.Excluded) return; - addReincludedRoot(root); } @Override public void registerExclusionCondition(@NotNull VirtualFile root, @NotNull Function1 condition, @NotNull WorkspaceEntity entity) { - if (rootsToCollect != RootType.Excluded) return; - myReincludedRoots.add(root); } @Override public void registerExclusionCondition(@NotNull VirtualFileUrl root, @NotNull Function1 condition, @NotNull WorkspaceEntity entity) { - if (rootsToCollect != RootType.Excluded) return; - addReincludedRoot(root); } } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsDescriptions.kt b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsDescriptions.kt new file mode 100644 index 000000000000..5368ed39f4b8 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexingRootsDescriptions.kt @@ -0,0 +1,262 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.util.indexing.roots + +import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.containers.MultiMap +import com.intellij.util.indexing.ReincludedRootsUtil +import com.intellij.util.indexing.roots.IndexableEntityProvider.IndexableIteratorBuilder +import com.intellij.util.indexing.roots.builders.IndexableIteratorBuilders.forExternalEntity +import com.intellij.util.indexing.roots.builders.IndexableIteratorBuilders.forLibraryEntity +import com.intellij.util.indexing.roots.builders.IndexableIteratorBuilders.forModuleRootsFileBased +import com.intellij.util.indexing.roots.builders.IndexableIteratorBuilders.forModuleUnawareContentEntity +import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndexContributor +import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileKind +import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetData +import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetRegistrar +import com.intellij.workspaceModel.core.fileIndex.impl.LibraryRootFileIndexContributor +import com.intellij.workspaceModel.core.fileIndex.impl.ModuleContentOrSourceRootData +import com.intellij.workspaceModel.ide.legacyBridge.ModuleBridge +import com.intellij.workspaceModel.ide.virtualFile +import com.intellij.workspaceModel.storage.EntityReference +import com.intellij.workspaceModel.storage.EntityStorage +import com.intellij.workspaceModel.storage.WorkspaceEntity +import com.intellij.workspaceModel.storage.bridgeEntities.LibraryEntity +import com.intellij.workspaceModel.storage.url.VirtualFileUrl + +internal sealed interface IndexingRootsDescription { + fun createBuilders(): Collection +} + +internal data class LibraryRootsDescription(val library: LibraryEntity, + val classRoots: List, + val sourceRoots: List) : IndexingRootsDescription { + override fun createBuilders(): Collection { + return forLibraryEntity(library.symbolicId, false, classRoots, sourceRoots) + } +} + +internal data class EntityContentRootsDescription(val entityReference: EntityReference<*>, + val roots: Collection) : IndexingRootsDescription { + override fun createBuilders(): Collection { + return forModuleUnawareContentEntity(entityReference, roots) + } +} + +internal data class EntityExternalRootsDescription(val entityReference: EntityReference<*>, + val roots: Collection, + val sourceRoots: Collection) : IndexingRootsDescription { + override fun createBuilders(): Collection { + return forExternalEntity(entityReference, roots, sourceRoots) + } +} + +private fun toList(value: Collection): List { + if (value is List) return value + return if (value.isEmpty()) emptyList() else ArrayList(value) +} + +internal class IndexingRootsDescriptionsBuilder { + private val moduleRoots: MultiMap = MultiMap.create() + private val descriptions: MutableCollection = mutableListOf() + private val reincludedRoots: MutableCollection = HashSet() + + fun registerAddedEntity(entity: E, contributor: WorkspaceFileIndexContributor, storage: EntityStorage) { + val rootData = rootData(contributor, entity, storage) + rootData.cleanExcludedRoots() + loadRegistrarData(rootData) + } + + private fun rootData(contributor: WorkspaceFileIndexContributor, + entity: E, + storage: EntityStorage): RootData { + val registrar = MyWorkspaceFileSetRegistrar(contributor) + contributor.registerFileSets(entity, registrar, storage) + return registrar.rootData + } + + fun registerRemovedEntity(entity: E, contributor: WorkspaceFileIndexContributor, storage: EntityStorage) { + val rootData = rootData(contributor, entity, storage) + rootData.cleanIncludedRoots() + loadRegistrarData(rootData) + } + + fun registerChangedEntity(oldEntity: E, + newEntity: E, + contributor: WorkspaceFileIndexContributor, + storage: EntityStorage) { + val oldRootData = rootData(contributor, oldEntity, storage) + val newRootData = rootData(contributor, newEntity, storage) + + val data = RootData() + data.moduleContents.putAllValues(diff(oldRootData.moduleContents, newRootData.moduleContents)) + data.contentRoots.putAllValues(diff(oldRootData.contentRoots, newRootData.contentRoots)) + data.libraryRoots.putAllValues(diff(oldRootData.libraryRoots, newRootData.libraryRoots)) + data.librarySourceRoots.putAllValues(diff(oldRootData.librarySourceRoots, newRootData.librarySourceRoots)) + data.externalRoots.putAllValues(diff(oldRootData.externalRoots, newRootData.externalRoots)) + data.externalSourceRoots.putAllValues(diff(oldRootData.externalSourceRoots, newRootData.externalSourceRoots)) + data.excludedRoots.addAll(oldRootData.excludedRoots) + data.excludedRoots.removeAll(newRootData.excludedRoots) + loadRegistrarData(data) + } + + + private fun diff(old: MultiMap, new: MultiMap): MultiMap { + val result: MultiMap = MultiMap() + result.putAllValues(new) + for ((key, values) in old.entrySet()) { + for (value in values) { + result.remove(key, value) + } + } + return result + } + + private fun loadRegistrarData(rootData: RootData) { + moduleRoots.putAllValues(rootData.moduleContents) + + for (entry in rootData.contentRoots.entrySet()) { + descriptions.add(EntityContentRootsDescription(entry.key, entry.value)) + } + + for ((libraryEntity, roots) in rootData.libraryRoots.entrySet()) { + val sourceRoots = (rootData.librarySourceRoots.remove(libraryEntity)) ?: emptyList() + descriptions.add(LibraryRootsDescription(libraryEntity, toList(roots), toList(sourceRoots))) + } + for ((key, value) in rootData.librarySourceRoots.entrySet()) { + descriptions.add(LibraryRootsDescription(key, emptyList(), toList(value))) + } + + for ((rootEntity, roots) in rootData.externalRoots.entrySet()) { + var sourceRoots = rootData.externalSourceRoots.remove(rootEntity) + sourceRoots = sourceRoots ?: emptyList() + descriptions.add(EntityExternalRootsDescription(rootEntity, roots, sourceRoots)) + } + for ((rootEntity, roots) in rootData.externalSourceRoots.entrySet()) { + descriptions.add(EntityExternalRootsDescription(rootEntity, emptyList(), roots)) + } + + reincludedRoots.addAll(rootData.excludedRoots) + } + + fun createBuilders(project: Project): Collection { + val builders = mutableListOf() + for (entry in moduleRoots.entrySet()) { + builders.addAll(forModuleRootsFileBased((entry.key as ModuleBridge).moduleEntityId, entry.value)) + } + + for (description in descriptions) { + builders.addAll(description.createBuilders()) + } + + builders.addAll(ReincludedRootsUtil.createBuildersForReincludedFiles(project, reincludedRoots)) + return builders + } +} + +private class RootData { + val moduleContents = MultiMap.create() + val contentRoots = MultiMap.createSet, VirtualFile>() + val libraryRoots = MultiMap.createSet() + val librarySourceRoots = MultiMap.createSet() + val externalRoots = MultiMap.createSet, VirtualFile>() + val externalSourceRoots = MultiMap.createSet, VirtualFile>() + val excludedRoots = mutableListOf() + + fun registerFileSet(contributor: WorkspaceFileIndexContributor<*>, + root: VirtualFile, + kind: WorkspaceFileKind, + entity: WorkspaceEntity, + customData: WorkspaceFileSetData?) { + if (customData is ModuleContentOrSourceRootData) { + moduleContents.putValue(customData.module, root) + } + else if (kind.isContent) { + contentRoots.putValue(entity.createReference(), root) + } + else if (kind === WorkspaceFileKind.EXTERNAL) { + if (contributor is LibraryRootFileIndexContributor) { + libraryRoots.putValue(entity as LibraryEntity, root) + } + else { + externalRoots.putValue(entity.createReference(), root) + } + } + else { + if (contributor is LibraryRootFileIndexContributor) { + librarySourceRoots.putValue(entity as LibraryEntity, root) + } + else { + externalSourceRoots.putValue(entity.createReference(), root) + } + } + } + + fun registerFileSet(contributor: WorkspaceFileIndexContributor<*>, + root: VirtualFileUrl, + kind: WorkspaceFileKind, + entity: WorkspaceEntity, + customData: WorkspaceFileSetData?) { + root.virtualFile?.let { registerFileSet(contributor, it, kind, entity, customData) } + } + + fun registerExcludedRoot(root: VirtualFile) { + excludedRoots.add(root) + } + + fun registerExcludedRoot(root: VirtualFileUrl) { + root.virtualFile?.let { excludedRoots.add(it) } + } + + fun cleanIncludedRoots() { + moduleContents.clear() + contentRoots.clear() + libraryRoots.clear() + librarySourceRoots.clear() + externalRoots.clear() + externalSourceRoots.clear() + } + + fun cleanExcludedRoots() { + excludedRoots.clear() + } +} + +private class MyWorkspaceFileSetRegistrar(val contributor: WorkspaceFileIndexContributor<*>) : WorkspaceFileSetRegistrar { + val rootData: RootData = RootData() + + override fun registerFileSet(root: VirtualFileUrl, kind: WorkspaceFileKind, entity: WorkspaceEntity, customData: WorkspaceFileSetData?) { + rootData.registerFileSet(contributor, root, kind, entity, customData) + } + + override fun registerFileSet(root: VirtualFile, kind: WorkspaceFileKind, entity: WorkspaceEntity, customData: WorkspaceFileSetData?) { + rootData.registerFileSet(contributor, root, kind, entity, customData) + } + + override fun registerExcludedRoot(excludedRoot: VirtualFileUrl, entity: WorkspaceEntity) { + rootData.registerExcludedRoot(excludedRoot) + } + + override fun registerExcludedRoot(excludedRoot: VirtualFile, excludedFrom: WorkspaceFileKind, entity: WorkspaceEntity) { + rootData.registerExcludedRoot(excludedRoot) + } + + override fun registerExcludedRoot(excludedRoot: VirtualFileUrl, excludedFrom: WorkspaceFileKind, entity: WorkspaceEntity) { + rootData.registerExcludedRoot(excludedRoot) + } + + override fun registerExclusionPatterns(root: VirtualFileUrl, patterns: List, entity: WorkspaceEntity) { + rootData.registerExcludedRoot(root) + } + + override fun registerExclusionCondition(root: VirtualFileUrl, condition: (VirtualFile) -> Boolean, entity: WorkspaceEntity) { + rootData.registerExcludedRoot(root) + } + + override fun registerExclusionCondition(root: VirtualFile, condition: (VirtualFile) -> Boolean, entity: WorkspaceEntity) { + rootData.registerExcludedRoot(root) + } +} + + diff --git a/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceOnCustomEntitiesTest.java b/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceOnCustomEntitiesTest.java index 622b2451f010..52828a10af38 100644 --- a/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceOnCustomEntitiesTest.java +++ b/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceOnCustomEntitiesTest.java @@ -126,17 +126,17 @@ public class EntityIndexingServiceOnCustomEntitiesTest extends EntityIndexingSer }); } - /* public void testRemovingExcludedRootFromCustomWorkspaceEntity() throws Exception { - registerWorkspaceFileIndexContributor((entity, registrar) -> { - for (VirtualFileUrl root : entity.getRoots()) { - registrar.registerFileSet(root, WorkspaceFileKind.EXTERNAL, entity, null); - } - for (VirtualFileUrl root : entity.getExcludedRoots()) { - registrar.registerExcludedRoot(root, entity); - } - }); - File root = createTempDir("customRoot"); - VirtualFile virtualRoot = Objects.requireNonNull(LocalFileSystem.getInstance().refreshAndFindFileByNioFile(root.toPath())); + public void testRemovingExcludedRootFromCustomWorkspaceEntity() throws Exception { + registerWorkspaceFileIndexContributor((entity, registrar) -> { + for (VirtualFileUrl root : entity.getRoots()) { + registrar.registerFileSet(root, WorkspaceFileKind.EXTERNAL, entity, null); + } + for (VirtualFileUrl root : entity.getExcludedRoots()) { + registrar.registerExcludedRoot(root, entity); + } + }); + File root = createTempDir("customRoot"); + VirtualFile virtualRoot = Objects.requireNonNull(LocalFileSystem.getInstance().refreshAndFindFileByNioFile(root.toPath())); VirtualFile excluded = WriteAction.compute(() -> virtualRoot.createChildDirectory(this, "excluded")); VirtualFileUrlManager fileUrlManager = VirtualFileUrlManagerUtil.getInstance(VirtualFileUrlManager.Companion, myProject); VirtualFileUrl url = fileUrlManager.fromUrl(virtualRoot.getUrl()); @@ -154,12 +154,11 @@ public class EntityIndexingServiceOnCustomEntitiesTest extends EntityIndexingSer }); return createdEntity; }, (entity) -> { - //todo[lene] fix to avoid reindexing included root return IndexableEntityProviderMethods.INSTANCE.createExternalEntityIterators(entity.createReference(), Collections.singletonList(excluded), Collections.emptyList()); }); - }*/ + } public void testRemovingCustomWorkspaceEntityWithExcludedRoot() throws Exception { registerWorkspaceFileIndexContributor((entity, registrar) -> {