Switch collecting builders to IndexingRootsDescriptions

GitOrigin-RevId: 7b3946290e106973350a9a595efbd2f30566b342
This commit is contained in:
Elena Shaverdova
2023-03-08 21:24:51 +00:00
committed by intellij-monorepo-bot
parent 96bb0a6a03
commit 95c1ab65f4
4 changed files with 313 additions and 142 deletions
@@ -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<IndexableIteratorBuilder> getBuildersOnWorkspaceChange(@NotNull Project project,
@NotNull Collection<? extends EntityChange<?>> event,
@NotNull Collection<? extends EntityChange<?>> events,
@NotNull EntityStorage entityStorage) {
List<IndexableIteratorBuilder> builders = new SmartList<>();
for (EntityChange<? extends WorkspaceEntity> change : event) {
IndexingRootsDescriptionsBuilder descriptionsBuilder = new IndexingRootsDescriptionsBuilder();
for (EntityChange<? extends WorkspaceEntity> 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<? super IndexableIteratorBuilder> 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<? super E> entityClass = (Class<? super E>)Objects.requireNonNull(newEntity == null ? oldEntity : newEntity).getEntityInterface();
IndexingRootsCollectionUtil.RootsCollector collector = new IndexingRootsCollectionUtil.RootsCollector(null);
if (IndexableFilesIndex.isEnabled()) {
List<IndexableIteratorBuilder> 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<IndexableIteratorBuilder> 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<VirtualFile> reincludedRoots = collector.removeReincludedRoots();
builders.addAll(ReincludedRootsUtil.createBuildersForReincludedFiles(project, reincludedRoots));
}
private static <E extends WorkspaceEntity> void collectIEPIteratorsOnChange(@NotNull Change change,
@@ -221,7 +224,7 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx {
@Nullable E newEntity,
@NotNull Project project,
@NotNull Collection<? super IndexableIteratorBuilder> builders,
@NotNull IndexingRootsCollectionUtil.RootsCollector collector,
@NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder,
@NotNull Class<? super E> 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<? super IndexableIteratorBuilder> builders,
@NotNull IndexingRootsCollectionUtil.RootsCollector collector,
@NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder,
@NotNull Class<? super E> entityClass,
boolean customOnly,
@NotNull EntityStorage entityStorage) {
@@ -273,26 +277,30 @@ class EntityIndexingServiceImpl implements EntityIndexingServiceEx {
List<WorkspaceFileIndexContributor<?>> 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<E> contributor = (WorkspaceFileIndexContributor<E>)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 <E extends WorkspaceEntity> Collection<IndexableIteratorBuilder> createBuildersForIncludedRoots(@NotNull WorkspaceFileIndexContributor<E> 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 <E extends WorkspaceEntity> 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 <E extends WorkspaceEntity, C extends WorkspaceEntity> void handleDependencies(@NotNull E oldEntity,
@NotNull E newEntity,
@NotNull Collection<? super IndexableIteratorBuilder> builders,
@NotNull IndexingRootsCollectionUtil.RootsCollector collector,
@NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder,
@NotNull Class<? super E> entityClass,
@NotNull WorkspaceFileIndexContributor<C> contributor,
@NotNull EntityStorage entityStorage) {
for (DependencyDescription<C> dependency : contributor.getDependenciesOnOtherEntities()) {
handleChildEntities(entityClass, oldEntity, newEntity, builders, collector, contributor, dependency, entityStorage);
handleChildEntities(entityClass, oldEntity, newEntity, descriptionsBuilder, contributor, dependency,
entityStorage);
}
}
private static <E extends WorkspaceEntity, C extends WorkspaceEntity> void handleChildEntities(@NotNull Class<? super E> entityClass,
@NotNull E oldEntity,
@NotNull E newEntity,
@NotNull Collection<? super IndexableIteratorBuilder> builders,
@NotNull IndexingRootsCollectionUtil.RootsCollector collector,
@NotNull IndexingRootsDescriptionsBuilder descriptionsBuilder,
@NotNull WorkspaceFileIndexContributor<C> contributor,
@NotNull DependencyDescription<C> 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<? extends WorkspaceEntity> entities,
@NotNull EntityStorage entityStorage) {
List<IndexableIteratorBuilder> 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;
}
@@ -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<IndexableIteratorBuilder> createBuildersFromRootsDescriptions(@NotNull IndexingRootsDescriptions descriptions) {
ArrayList<IndexableIteratorBuilder> 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<VirtualFile> optimizeRoots(@NotNull Collection<VirtualFile> roots) {
int size = roots.size();
if (size == 0) {
@@ -202,7 +177,6 @@ public class IndexingRootsCollectionUtil {
private final MultiMap<LibraryEntity, VirtualFile> myLibrarySourceRoots = MultiMap.createSet();
private final MultiMap<WorkspaceEntity, VirtualFile> myExternalRoots = MultiMap.createSet();
private final MultiMap<WorkspaceEntity, VirtualFile> myExternalSourceRoots = MultiMap.createSet();
private final List<VirtualFile> myReincludedRoots = new ArrayList<>();
@Nullable
private WorkspaceFileIndexContributor<?> myCurrentContributor;
@@ -238,23 +212,6 @@ public class IndexingRootsCollectionUtil {
clearNonModuleAwareMaps();
}
public <E extends WorkspaceEntity> void registerAndCollectAllRoots(@NotNull IndexingRootsDescriptions roots,
@NotNull WorkspaceFileIndexContributor<E> contributor,
@NotNull Sequence<E> 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<WorkspaceEntity, Collection<VirtualFile>> entry : myContentRoots.entrySet()) {
roots.contentEntityRoots.add(new EntityContentRootsDescription(entry.getKey().createReference(), entry.getValue()));
@@ -301,39 +258,13 @@ public class IndexingRootsCollectionUtil {
myContents.clear();
}
public <E extends WorkspaceEntity> void registerExcludedRoots(@NotNull E entity,
@NotNull WorkspaceFileIndexContributor<E> contributor,
@NotNull EntityStorage storage) {
myRegistrar.setRootsToCollect(MyWorkspaceFileSetRegistrar.RootType.Excluded);
try {
contributor.registerFileSets(entity, myRegistrar, storage);
}
finally {
myRegistrar.setRootsToCollect(MyWorkspaceFileSetRegistrar.RootType.Included);
}
}
public Collection<VirtualFile> removeReincludedRoots() {
List<VirtualFile> 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<String> patterns, @NotNull WorkspaceEntity entity) {
if (rootsToCollect != RootType.Excluded) return;
addReincludedRoot(root);
}
@Override
public void registerExclusionCondition(@NotNull VirtualFile root,
@NotNull Function1<? super VirtualFile, Boolean> condition,
@NotNull WorkspaceEntity entity) {
if (rootsToCollect != RootType.Excluded) return;
myReincludedRoots.add(root);
}
@Override
public void registerExclusionCondition(@NotNull VirtualFileUrl root,
@NotNull Function1<? super VirtualFile, Boolean> condition,
@NotNull WorkspaceEntity entity) {
if (rootsToCollect != RootType.Excluded) return;
addReincludedRoot(root);
}
}
}
@@ -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<IndexableIteratorBuilder>
}
internal data class LibraryRootsDescription(val library: LibraryEntity,
val classRoots: List<VirtualFile>,
val sourceRoots: List<VirtualFile>) : IndexingRootsDescription {
override fun createBuilders(): Collection<IndexableIteratorBuilder> {
return forLibraryEntity(library.symbolicId, false, classRoots, sourceRoots)
}
}
internal data class EntityContentRootsDescription(val entityReference: EntityReference<*>,
val roots: Collection<VirtualFile>) : IndexingRootsDescription {
override fun createBuilders(): Collection<IndexableIteratorBuilder> {
return forModuleUnawareContentEntity(entityReference, roots)
}
}
internal data class EntityExternalRootsDescription(val entityReference: EntityReference<*>,
val roots: Collection<VirtualFile>,
val sourceRoots: Collection<VirtualFile>) : IndexingRootsDescription {
override fun createBuilders(): Collection<IndexableIteratorBuilder> {
return forExternalEntity(entityReference, roots, sourceRoots)
}
}
private fun <T> toList(value: Collection<T>): List<T> {
if (value is List<T>) return value
return if (value.isEmpty()) emptyList() else ArrayList(value)
}
internal class IndexingRootsDescriptionsBuilder {
private val moduleRoots: MultiMap<Module, VirtualFile> = MultiMap.create()
private val descriptions: MutableCollection<IndexingRootsDescription> = mutableListOf()
private val reincludedRoots: MutableCollection<VirtualFile> = HashSet()
fun <E : WorkspaceEntity> registerAddedEntity(entity: E, contributor: WorkspaceFileIndexContributor<E>, storage: EntityStorage) {
val rootData = rootData(contributor, entity, storage)
rootData.cleanExcludedRoots()
loadRegistrarData(rootData)
}
private fun <E : WorkspaceEntity> rootData(contributor: WorkspaceFileIndexContributor<E>,
entity: E,
storage: EntityStorage): RootData {
val registrar = MyWorkspaceFileSetRegistrar(contributor)
contributor.registerFileSets(entity, registrar, storage)
return registrar.rootData
}
fun <E : WorkspaceEntity> registerRemovedEntity(entity: E, contributor: WorkspaceFileIndexContributor<E>, storage: EntityStorage) {
val rootData = rootData(contributor, entity, storage)
rootData.cleanIncludedRoots()
loadRegistrarData(rootData)
}
fun <E : WorkspaceEntity> registerChangedEntity(oldEntity: E,
newEntity: E,
contributor: WorkspaceFileIndexContributor<E>,
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 <K : Any, V> diff(old: MultiMap<K, V>, new: MultiMap<K, V>): MultiMap<K, V> {
val result: MultiMap<K, V> = 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<IndexableIteratorBuilder> {
val builders = mutableListOf<IndexableIteratorBuilder>()
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<Module, VirtualFile>()
val contentRoots = MultiMap.createSet<EntityReference<*>, VirtualFile>()
val libraryRoots = MultiMap.createSet<LibraryEntity, VirtualFile>()
val librarySourceRoots = MultiMap.createSet<LibraryEntity, VirtualFile>()
val externalRoots = MultiMap.createSet<EntityReference<*>, VirtualFile>()
val externalSourceRoots = MultiMap.createSet<EntityReference<*>, VirtualFile>()
val excludedRoots = mutableListOf<VirtualFile>()
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<WorkspaceEntity>(), root)
}
else if (kind === WorkspaceFileKind.EXTERNAL) {
if (contributor is LibraryRootFileIndexContributor) {
libraryRoots.putValue(entity as LibraryEntity, root)
}
else {
externalRoots.putValue(entity.createReference<WorkspaceEntity>(), root)
}
}
else {
if (contributor is LibraryRootFileIndexContributor) {
librarySourceRoots.putValue(entity as LibraryEntity, root)
}
else {
externalSourceRoots.putValue(entity.createReference<WorkspaceEntity>(), 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<String>, 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)
}
}
@@ -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) -> {