diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java index 837205d8e277..7a9fac88d267 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java @@ -14,7 +14,6 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.fileTypes.InternalFileType; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -40,7 +39,10 @@ import com.intellij.util.concurrency.AppExecutorUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.*; import com.intellij.util.indexing.roots.*; -import com.intellij.util.indexing.roots.kind.ModuleRootOrigin; +import com.intellij.workspaceModel.ide.WorkspaceModel; +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; +import kotlin.sequences.Sequence; +import kotlin.sequences.SequencesKt; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -292,8 +294,8 @@ public final class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesU } private void doPushAll(@NotNull List> pushers) { - scanProject(myProject, moduleFileSet -> { - final Object[] moduleValues = getModuleImmediateValues(pushers, moduleFileSet.getOrigin()); + scanProject(myProject, module -> { + final Object[] moduleValues = getModuleImmediateValues(pushers, module); return fileOrDir -> { applyPushersToFile(fileOrDir, pushers, moduleValues); return ContentIteratorEx.Status.CONTINUE; @@ -302,31 +304,35 @@ public final class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesU } public static Object @NotNull [] getModuleImmediateValues(@NotNull List> pushers, - @NotNull ModuleRootOrigin origin) { + @NotNull Module module) { final Object[] moduleValues; moduleValues = new Object[pushers.size()]; for (int i = 0; i < moduleValues.length; i++) { - moduleValues[i] = pushers.get(i).getImmediateValue(origin.getModule()); + moduleValues[i] = pushers.get(i).getImmediateValue(module); } return moduleValues; } - public static void scanProject(@NotNull Project project, @NotNull Function iteratorProducer) { - Module[] modules = ReadAction.compute(() -> ModuleManager.getInstance(project).getModules()); + public static void scanProject(@NotNull Project project, @NotNull Function iteratorProducer) { + Sequence modulesSequence = ReadAction.compute(() -> + WorkspaceModel.Companion.getInstance(project).getEntityStorage(). + getCurrent().entities(ModuleEntity.class)); + List moduleEntities = SequencesKt.toList(modulesSequence); IndexableFilesDeduplicateFilter indexableFilesDeduplicateFilter = IndexableFilesDeduplicateFilter.create(); - List tasks = Arrays.stream(modules) - .flatMap(module -> { + List tasks = moduleEntities.stream() + .flatMap(moduleEntity -> { return ReadAction.compute(() -> { - if (module.isDisposed()) return Stream.empty(); + Module module = IndexableEntityProviderMethods.INSTANCE.findModuleForEntity(moduleEntity, project); + if (module == null) return Stream.empty(); ProgressManager.checkCanceled(); - return ContainerUtil.map(ModuleIndexableFilesIteratorImpl.getModuleIterators(module), it -> new Object() { - final IndexableFilesIterator files = it; - final ContentIteratorEx iterator = iteratorProducer.apply(it); - }) + return ContainerUtil.map(IndexableEntityProviderMethods.INSTANCE.createIterators(moduleEntity, project), it -> new Object() { + final IndexableFilesIterator files = it; + final ContentIteratorEx iterator = iteratorProducer.apply(module); + }) .stream() .map(pair -> (Runnable)() -> { - pair.files.iterateFiles(project, pair.iterator, indexableFilesDeduplicateFilter); - }); + pair.files.iterateFiles(project, pair.iterator, indexableFilesDeduplicateFilter); + }); }); }) .collect(Collectors.toList()); 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 50c7b57109ab..cb305e9d721f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/EntityIndexingServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/EntityIndexingServiceImpl.java @@ -7,21 +7,21 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.RootsChangeIndexingInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.SmartList; -import com.intellij.util.indexing.roots.IndexableEntityProvider; -import com.intellij.util.indexing.roots.IndexableEntityResolvingException; -import com.intellij.util.indexing.roots.IndexableFilesIterator; -import com.intellij.util.indexing.roots.ModuleIndexableFilesIteratorImpl; -import com.intellij.util.indexing.roots.kind.IndexableSetOrigin; +import com.intellij.util.indexing.roots.*; import com.intellij.workspaceModel.ide.WorkspaceModel; import com.intellij.workspaceModel.ide.impl.legacyBridge.project.ProjectRootsChangeListener; import com.intellij.workspaceModel.storage.EntityChange; import com.intellij.workspaceModel.storage.VersionedStorageChange; import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; class EntityIndexingServiceImpl implements EntityIndexingService { private static final Logger LOG = Logger.getInstance(EntityIndexingServiceImpl.class); @@ -44,17 +44,9 @@ class EntityIndexingServiceImpl implements EntityIndexingService { for (RootsChangeIndexingInfo change : changes) { if (change == RootsChangeIndexingInfo.NO_INDEXING_NEEDED) continue; if (change instanceof ProjectRootsChangeListener.WorkspaceEventIndexingInfo) { - try { - Collection iteratorsFromWorkspaceChange = - getIteratorsWorkspaceChange(project, ((ProjectRootsChangeListener.WorkspaceEventIndexingInfo)change).getEvent(), entityStorage); - iterators.addAll(iteratorsFromWorkspaceChange); - } - catch (IndexableEntityResolvingException e) { - LOG.warn(e); - DumbService.getInstance(project) - .queueTask(new UnindexedFilesUpdater(project, "Reindex on IndexableEntityResolvingException in EntityIndexingServiceImpl")); - return; - } + Collection iteratorsFromWorkspaceChange = + getIteratorsWorkspaceChange(project, ((ProjectRootsChangeListener.WorkspaceEventIndexingInfo)change).getEvent(), entityStorage); + iterators.addAll(iteratorsFromWorkspaceChange); } else { LOG.warn("Unexpected change " + change.getClass() + " " + change + ", full reindex requested"); @@ -65,7 +57,7 @@ class EntityIndexingServiceImpl implements EntityIndexingService { } if (!iterators.isEmpty()) { - iterators = mergeIterators(iterators); + iterators = IndexableEntityProviderMethods.INSTANCE.mergeIterators(iterators); StringBuilder sb = new StringBuilder("Accumulated iterators:"); for (IndexableFilesIterator iterator : iterators) { @@ -85,43 +77,35 @@ class EntityIndexingServiceImpl implements EntityIndexingService { @TestOnly @NotNull static List getIterators(@NotNull Project project, - @NotNull Collection events) - throws IndexableEntityResolvingException { + @NotNull Collection events) { WorkspaceEntityStorage entityStorage = WorkspaceModel.getInstance(project).getEntityStorage().getCurrent(); List result = new ArrayList<>(events.size()); for (VersionedStorageChange event : events) { result.addAll(getIteratorsWorkspaceChange(project, event, entityStorage)); } - return mergeIterators(result); + return IndexableEntityProviderMethods.INSTANCE.mergeIterators(result); } @NotNull private static List getIteratorsWorkspaceChange(@NotNull Project project, @NotNull VersionedStorageChange event, - WorkspaceEntityStorage entityStorage) - throws IndexableEntityResolvingException { + WorkspaceEntityStorage entityStorage) { List iterators = new SmartList<>(); Iterator> iterator = event.getAllChanges().iterator(); while (iterator.hasNext()) { EntityChange change = iterator.next(); if (change instanceof EntityChange.Added) { WorkspaceEntity entity = ((EntityChange.Added)change).getEntity(); - for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { - iterators.addAll(provider.getAddedEntityIterator(entity, entityStorage, project)); - } + collectIteratorsOnAdd(entity, entityStorage, project, iterators); } else if (change instanceof EntityChange.Replaced) { WorkspaceEntity newEntity = ((EntityChange.Replaced)change).getNewEntity(); WorkspaceEntity oldEntity = ((EntityChange.Replaced)change).getOldEntity(); - for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { - iterators.addAll(provider.getReplacedEntityIterator(oldEntity, newEntity, entityStorage, project)); - } + collectIteratorsOnReplace(oldEntity, newEntity, entityStorage, project, iterators); } else if (change instanceof EntityChange.Removed) { WorkspaceEntity entity = ((EntityChange.Removed)change).getEntity(); - for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { - iterators.addAll(provider.getRemovedEntityIterator(entity, entityStorage, project)); - } + collectIteratorsOnRemove(entity, entityStorage, project, iterators); } else { LOG.error("Unexpected change " + change.getClass() + " " + change); @@ -130,21 +114,53 @@ class EntityIndexingServiceImpl implements EntityIndexingService { return iterators; } - private static @NotNull List mergeIterators(List iterators) { - List result = new ArrayList<>(iterators.size()); - Collection rootIterators = new ArrayList<>(); - Set origins = new HashSet<>(); - for (IndexableFilesIterator iterator : iterators) { - if (iterator instanceof ModuleIndexableFilesIteratorImpl) { - rootIterators.add((ModuleIndexableFilesIteratorImpl)iterator); + private static void collectIteratorsOnAdd(@NotNull E entity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project, + @NotNull Collection iterators) { + Class entityClass = entity.getClass(); + for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { + if (entityClass == provider.getEntityClass()) { + //noinspection unchecked + iterators.addAll(((IndexableEntityProvider)provider).getAddedEntityIterator(entity, entityStorage, project)); } - else { - if (origins.add(iterator.getOrigin())) { - result.add(iterator); + } + } + + private static void collectIteratorsOnReplace(@NotNull E oldEntity, + @NotNull E newEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project, + @NotNull Collection iterators) { + Class entityClass = oldEntity.getClass(); + for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { + if (entityClass == provider.getEntityClass()) { + //noinspection unchecked + iterators.addAll(((IndexableEntityProvider)provider).getReplacedEntityIterator(oldEntity, newEntity, entityStorage, project)); + } + } + if (oldEntity instanceof ModuleEntity) { + ModuleEntity oldModule = (ModuleEntity)oldEntity; + ModuleEntity newModule = (ModuleEntity)newEntity; + for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { + if (provider instanceof IndexableEntityProvider.ModuleEntityDependent) { + iterators.addAll(((IndexableEntityProvider.ModuleEntityDependent)provider). + getReplacedModuleEntityIterator(oldModule, newModule, entityStorage, project)); } } } - result.addAll(ModuleIndexableFilesIteratorImpl.getMergedIterators(rootIterators)); - return result; + } + + private static void collectIteratorsOnRemove(@NotNull E entity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project, + @NotNull Collection iterators) { + Class entityClass = entity.getClass(); + for (IndexableEntityProvider provider : IndexableEntityProvider.EP_NAME.getExtensionList()) { + if (entityClass == provider.getEntityClass()) { + //noinspection unchecked + iterators.addAll(((IndexableEntityProvider)provider).getRemovedEntityIterator(entity, entityStorage, project)); + } + } } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java index ac2b4f513ca0..269cbcd727a0 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java @@ -403,7 +403,7 @@ public class UnindexedFilesUpdater extends DumbModeTask { Object[] moduleValues; if (origin instanceof ModuleRootOrigin && !((ModuleRootOrigin)origin).getModule().isDisposed()) { pushers = FilePropertyPusher.EP_NAME.getExtensionList(); - moduleValues = ReadAction.compute(() -> getModuleImmediateValues(pushers, (ModuleRootOrigin)origin)); + moduleValues = ReadAction.compute(() -> getModuleImmediateValues(pushers, ((ModuleRootOrigin)origin).getModule())); } else { pushers = null; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/ContentRootIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/ContentRootIndexableEntityProvider.java index b1f80009472c..2f75dec1b691 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/ContentRootIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/ContentRootIndexableEntityProvider.java @@ -7,7 +7,6 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.ContentRootEntity; import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; @@ -22,67 +21,76 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -class ContentRootIndexableEntityProvider implements IndexableEntityProvider { +class ContentRootIndexableEntityProvider implements IndexableEntityProvider.ModuleEntityDependent { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, - @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (entity instanceof ContentRootEntity) { - ContentRootEntity contentRootEntity = (ContentRootEntity)entity; - return IndexableEntityProviderMethods.INSTANCE.createIterators(contentRootEntity.getModule(), getVirtualFile(contentRootEntity), - project); + public @NotNull Class getEntityClass() { + return ContentRootEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull ContentRootEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { + if (moduleEntity.equals(entity.getModule())) { + return getExistingEntityIterator(entity, entityStorage, project); } return Collections.emptyList(); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, - @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (newEntity instanceof ModuleEntity) { - List newRoots = collectRoots(((ModuleEntity)newEntity).getContentRoots()); - List oldRoots = collectRoots(((ModuleEntity)oldEntity).getContentRoots()); - return IndexableEntityProviderMethods.INSTANCE.createIterators((ModuleEntity)newEntity, newRoots, oldRoots, project); - } - else if (newEntity instanceof ContentRootEntity) { - ContentRootEntity newContentRoot = (ContentRootEntity)newEntity; - ContentRootEntity oldContentRoot = (ContentRootEntity)oldEntity; + public @NotNull Collection getAddedEntityIterator(@NotNull ContentRootEntity entity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(entity.getModule(), getVirtualFile(entity), project); + } - if (!(newContentRoot.getExcludedPatterns().equals(oldContentRoot.getExcludedPatterns()))) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(newContentRoot.getModule(), getVirtualFile(newContentRoot), - project); - } - List newExcludedUrls = newContentRoot.getExcludedUrls(); - List oldExcludedUrls = oldContentRoot.getExcludedUrls(); - if (!oldExcludedUrls.equals(newExcludedUrls)) { - VirtualFileManager fileManager = VirtualFileManager.getInstance(); - List roots = new ArrayList<>(); - for (VirtualFileUrl oldUrl : oldExcludedUrls) { - boolean found = false; - String oldPath = oldUrl.getUrl(); - for (VirtualFileUrl newUrl : newExcludedUrls) { - if (VfsUtilCore.isEqualOrAncestor(newUrl.getUrl(), oldPath)) { - found = true; - break; - } + @Override + public @NotNull Collection getReplacedEntityIterator(@NotNull ContentRootEntity oldEntity, + @NotNull ContentRootEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + if (!(newEntity.getExcludedPatterns().equals(oldEntity.getExcludedPatterns()))) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity.getModule(), getVirtualFile(newEntity), + project); + } + List newExcludedUrls = newEntity.getExcludedUrls(); + List oldExcludedUrls = oldEntity.getExcludedUrls(); + if (!oldExcludedUrls.equals(newExcludedUrls)) { + VirtualFileManager fileManager = VirtualFileManager.getInstance(); + List roots = new ArrayList<>(); + for (VirtualFileUrl oldUrl : oldExcludedUrls) { + boolean found = false; + String oldPath = oldUrl.getUrl(); + for (VirtualFileUrl newUrl : newExcludedUrls) { + if (VfsUtilCore.isEqualOrAncestor(newUrl.getUrl(), oldPath)) { + found = true; + break; } - if (!found) { - VirtualFile file = fileManager.findFileByUrl(oldPath); - if (file != null) { - roots.add(file); - } + } + if (!found) { + VirtualFile file = fileManager.findFileByUrl(oldPath); + if (file != null) { + roots.add(file); } } - return IndexableEntityProviderMethods.INSTANCE.createIterators(newContentRoot.getModule(), roots, project); } + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity.getModule(), roots, project); } return Collections.emptyList(); } + @Override + public @NotNull Collection getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity, + @NotNull ModuleEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + List newRoots = collectRoots(newEntity.getContentRoots()); + List oldRoots = collectRoots(oldEntity.getContentRoots()); + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity, newRoots, oldRoots, project); + } + @NotNull private static List collectRoots(Sequence newContentRoots) { return SequencesKt.toList(SequencesKt.mapNotNull(newContentRoots, root -> getVirtualFile(root))); @@ -95,18 +103,14 @@ class ContentRootIndexableEntityProvider implements IndexableEntityProvider { } @Override - public @NotNull Collection getRemovedEntityIterator(@NotNull WorkspaceEntity entity, + public @NotNull Collection getRemovedEntityIterator(@NotNull ContentRootEntity entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (entity instanceof ContentRootEntity) { - ContentRootEntity contentRootEntity = (ContentRootEntity)entity; - if (!contentRootEntity.getExcludedPatterns().isEmpty() || !contentRootEntity.getExcludedUrls().isEmpty()) { - VirtualFile root = getVirtualFile(contentRootEntity); - if (root != null && ProjectFileIndex.getInstance(project).isInContent(root)) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(((ContentRootEntity)entity).getModule(), - Collections.singletonList(root), project); - } + @NotNull Project project) { + if (!entity.getExcludedPatterns().isEmpty() || !entity.getExcludedUrls().isEmpty()) { + VirtualFile root = getVirtualFile(entity); + if (root != null && ProjectFileIndex.getInstance(project).isInContent(root)) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(entity.getModule(), + Collections.singletonList(root), project); } } return Collections.emptyList(); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProvider.java index 7de60d71565c..ea232ae40692 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProvider.java @@ -5,6 +5,7 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -12,8 +13,31 @@ import java.util.Collection; import java.util.Collections; @ApiStatus.Experimental -public interface IndexableEntityProvider { - ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.indexableEntityProvider"); +public interface IndexableEntityProvider { + ExtensionPointName> EP_NAME = + new ExtensionPointName<>("com.intellij.indexableEntityProvider"); + + @NotNull + Class getEntityClass(); + + /** + * Provides iterators to index files when just project is indexed, no events given + */ + @NotNull + default Collection getExistingEntityIterator(@NotNull E entity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + return getAddedEntityIterator(entity, storage, project); + } + + /** + * Provides iterators to index files belonging to a module when just module content is indexed, no events given + */ + @NotNull + Collection getExistingEntityForModuleIterator(@NotNull E entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project); /** * Provides iterators to index files after {@code entity} was added @@ -21,9 +45,9 @@ public interface IndexableEntityProvider { * @param storage is initialized after the change happened. Be ready to situation when desired entity is missing */ @NotNull - Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, + Collection getAddedEntityIterator(@NotNull E entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) throws IndexableEntityResolvingException; + @NotNull Project project); /** * Provides iterators to index files after {@code oldEntity} was replaced with {@code newEntity} @@ -31,10 +55,10 @@ public interface IndexableEntityProvider { * @param storage is initialized after the change happened. Be ready to situation when desired entity is missing */ @NotNull - Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + Collection getReplacedEntityIterator(@NotNull E oldEntity, + @NotNull E newEntity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) throws IndexableEntityResolvingException; + @NotNull Project project); /** * Provides iterators to index files after {@code entity} was removed @@ -42,10 +66,26 @@ public interface IndexableEntityProvider { * @param storage is initialized after the change happened. Be ready to situation when desired entity is missing */ @NotNull - default Collection getRemovedEntityIterator(@NotNull WorkspaceEntity entity, + default Collection getRemovedEntityIterator(@NotNull E entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return Collections.emptyList(); } + + /** + * Should be used, when change related to desired WorkspaceEntity is visible as ModuleEntity change, + * for example, adding content root is visible as ModuleEntityChange, see {@link ContentRootIndexableEntityProvider}. + */ + interface ModuleEntityDependent extends IndexableEntityProvider { + /** + * Provides iterators to index files after {@code oldEntity} was replaced with {@code newEntity} + * + * @param storage is initialized after the change happened. Be ready to situation when desired entity is missing + */ + @NotNull + Collection getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity, + @NotNull ModuleEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project); + } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProviderMethods.kt b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProviderMethods.kt index 74d96d3ccfd5..f0a0eeba6eeb 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProviderMethods.kt +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityProviderMethods.kt @@ -8,7 +8,11 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.indexing.roots.ModuleIndexableFilesIteratorImpl.Companion.getMergedIterators +import com.intellij.util.indexing.roots.kind.IndexableSetOrigin +import com.intellij.workspaceModel.ide.WorkspaceModel import com.intellij.workspaceModel.ide.impl.legacyBridge.library.ProjectLibraryTableBridgeImpl.Companion.libraryMap +import com.intellij.workspaceModel.storage.WorkspaceEntity import com.intellij.workspaceModel.storage.WorkspaceEntityStorage import com.intellij.workspaceModel.storage.bridgeEntities.LibraryEntity import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity @@ -56,11 +60,23 @@ object IndexableEntityProviderMethods { } fun createIterators(entity: ModuleEntity, project: Project): Collection { - val module = findModuleForEntity(entity, project) - if (module == null) { - return emptyList() + val iterators = mutableListOf() + val entityStorage = WorkspaceModel.Companion.getInstance(project).entityStorage.current + for (provider in IndexableEntityProvider.EP_NAME.extensionList) { + addIteratorsFromProvider(provider, entity, entityStorage, project, iterators) + } + return mergeIterators(iterators) + } + + private fun addIteratorsFromProvider(provider: IndexableEntityProvider, + moduleEntity: ModuleEntity, + entityStorage: WorkspaceEntityStorage, + project: Project, + iterators: MutableList) { + val entityClass = provider.entityClass + for (entity in entityStorage.entities(entityClass)) { + iterators.addAll(provider.getExistingEntityForModuleIterator(entity, moduleEntity, entityStorage, project)) } - return ModuleIndexableFilesIteratorImpl.getModuleIterators(module) } fun createIterators(library: Library): Collection { @@ -70,4 +86,22 @@ object IndexableEntityProviderMethods { fun createIterators(sdk: Sdk): Collection { return listOf(SdkIndexableFilesIteratorImpl(sdk)) } + + fun mergeIterators(iterators: List): List { + val result: MutableList = java.util.ArrayList(iterators.size) + val rootIterators: MutableCollection = java.util.ArrayList() + val origins: MutableSet = HashSet() + for (iterator in iterators) { + if (iterator is ModuleIndexableFilesIteratorImpl) { + rootIterators.add(iterator) + } + else { + if (origins.add(iterator.origin)) { + result.add(iterator) + } + } + } + result.addAll(getMergedIterators(rootIterators)) + return result + } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityResolvingException.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityResolvingException.java deleted file mode 100644 index df52395e92e2..000000000000 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/IndexableEntityResolvingException.java +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.roots; - -/** - * To be used in {@link IndexableEntityProvider} to notify that proper partial rescan and reindex seems impossible, - * and it's better to make full rescan to avoid corruption of indices. - */ -public class IndexableEntityResolvingException extends Exception { - public IndexableEntityResolvingException(String message) { - super(message); - } -} diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaModuleSettingsIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaModuleSettingsIndexableEntityProvider.java index 9926ba917467..6dc0d3126070 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaModuleSettingsIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaModuleSettingsIndexableEntityProvider.java @@ -2,43 +2,54 @@ package com.intellij.util.indexing.roots; import com.intellij.openapi.project.Project; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.JavaModuleSettingsEntity; +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Collections; import java.util.Objects; -class JavaModuleSettingsIndexableEntityProvider implements IndexableEntityProvider { +class JavaModuleSettingsIndexableEntityProvider implements IndexableEntityProvider { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, + public @NotNull Class getEntityClass() { + return JavaModuleSettingsEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityIterator(@NotNull JavaModuleSettingsEntity entity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull JavaModuleSettingsEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getAddedEntityIterator(@NotNull JavaModuleSettingsEntity entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (entity instanceof JavaModuleSettingsEntity) { - JavaModuleSettingsEntity settingsEntity = (JavaModuleSettingsEntity)entity; - if (settingsEntity.getLanguageLevelId() != null) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(settingsEntity.getModule(), project); - } + @NotNull Project project) { + if (entity.getLanguageLevelId() != null) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(entity.getModule(), project); } return Collections.emptyList(); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + public @NotNull Collection getReplacedEntityIterator(@NotNull JavaModuleSettingsEntity oldEntity, + @NotNull JavaModuleSettingsEntity newEntity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (newEntity instanceof JavaModuleSettingsEntity) { - JavaModuleSettingsEntity newSettingsEntity = (JavaModuleSettingsEntity)newEntity; - JavaModuleSettingsEntity oldSettingsEntity = (JavaModuleSettingsEntity)oldEntity; - if (!Objects.equals(newSettingsEntity.getLanguageLevelId(), oldSettingsEntity.getLanguageLevelId())) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(newSettingsEntity.getModule(), project); - } + @NotNull Project project) { + if (!Objects.equals(newEntity.getLanguageLevelId(), oldEntity.getLanguageLevelId())) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity.getModule(), project); } return Collections.emptyList(); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaResourceRootIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaResourceRootIndexableEntityProvider.java index 61def4d52f60..7d81afcd8989 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaResourceRootIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaResourceRootIndexableEntityProvider.java @@ -4,7 +4,6 @@ package com.intellij.util.indexing.roots; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.JavaResourceRootEntity; import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; @@ -14,39 +13,51 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.Collections; import static com.intellij.util.indexing.roots.JavaSourceRootIndexableEntityProvider.collectIteratorsOnAddedEntityWithDataExtractor; import static com.intellij.util.indexing.roots.JavaSourceRootIndexableEntityProvider.collectIteratorsOnReplacedEntityWithDataExtractor; -class JavaResourceRootIndexableEntityProvider implements IndexableEntityProvider { +class JavaResourceRootIndexableEntityProvider implements IndexableEntityProvider { + @Override + public @NotNull Class getEntityClass() { + return JavaResourceRootEntity.class; + } @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull JavaResourceRootEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { + if (moduleEntity.equals(entity.getSourceRoot().getContentRoot().getModule())) { + return getExistingEntityIterator(entity, entityStorage, project); + } + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getAddedEntityIterator(@NotNull JavaResourceRootEntity entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return collectIteratorsOnAddedEntityWithDataExtractor(entity, JavaResourceRootIndexableEntityProvider::getDataToIndex, project); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + public @NotNull Collection getReplacedEntityIterator(@NotNull JavaResourceRootEntity oldEntity, + @NotNull JavaResourceRootEntity newEntity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return collectIteratorsOnReplacedEntityWithDataExtractor(oldEntity, newEntity, JavaResourceRootIndexableEntityProvider::getDataToIndex, project); } @Nullable - private static Pair getDataToIndex(WorkspaceEntity entity) { - if (entity instanceof JavaResourceRootEntity) { - SourceRootEntity sourceRootEntity = ((JavaResourceRootEntity)entity).getSourceRoot(); - VirtualFilePointer url = (VirtualFilePointer)sourceRootEntity.getUrl(); - if (url.isValid()) { - return new Pair<>(url.getFile(), sourceRootEntity.getContentRoot().getModule()); - } + private static Pair getDataToIndex(@NotNull JavaResourceRootEntity entity) { + SourceRootEntity sourceRootEntity = entity.getSourceRoot(); + VirtualFilePointer url = (VirtualFilePointer)sourceRootEntity.getUrl(); + if (url.isValid()) { + return new Pair<>(url.getFile(), sourceRootEntity.getContentRoot().getModule()); } return null; } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaSourceRootIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaSourceRootIndexableEntityProvider.java index 9a7369f4f4d8..b2ff14e99173 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaSourceRootIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/JavaSourceRootIndexableEntityProvider.java @@ -17,30 +17,44 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; -class JavaSourceRootIndexableEntityProvider implements IndexableEntityProvider { +class JavaSourceRootIndexableEntityProvider implements IndexableEntityProvider { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, + public @NotNull Class getEntityClass() { + return JavaSourceRootEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull JavaSourceRootEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { + if (entity.getSourceRoot().getContentRoot().getModule().equals(moduleEntity)) { + return getExistingEntityIterator(entity, entityStorage, project); + } + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getAddedEntityIterator(@NotNull JavaSourceRootEntity entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return collectIteratorsOnAddedEntityWithDataExtractor(entity, JavaSourceRootIndexableEntityProvider::getDataToIndex, project); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + public @NotNull Collection getReplacedEntityIterator(@NotNull JavaSourceRootEntity oldEntity, + @NotNull JavaSourceRootEntity newEntity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return collectIteratorsOnReplacedEntityWithDataExtractor(oldEntity, newEntity, JavaSourceRootIndexableEntityProvider::getDataToIndex, project); } @NotNull - static Collection collectIteratorsOnAddedEntityWithDataExtractor(@NotNull WorkspaceEntity entity, - @NotNull Function> extractor, - @NotNull Project project) { + static Collection collectIteratorsOnAddedEntityWithDataExtractor(@NotNull E entity, + @NotNull Function> extractor, + @NotNull Project project) { Pair data = extractor.fun(entity); if (data != null) { return IndexableEntityProviderMethods.INSTANCE.createIterators(data.getSecond(), data.getFirst(), project); @@ -49,10 +63,10 @@ class JavaSourceRootIndexableEntityProvider implements IndexableEntityProvider { } @NotNull - static Collection collectIteratorsOnReplacedEntityWithDataExtractor(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, - @NotNull Function> extractor, - @NotNull Project project) { + static Collection collectIteratorsOnReplacedEntityWithDataExtractor(@NotNull E oldEntity, + @NotNull E newEntity, + @NotNull Function> extractor, + @NotNull Project project) { Pair newData = extractor.fun(newEntity); if (newData != null) { Pair oldData = extractor.fun(oldEntity); @@ -64,13 +78,11 @@ class JavaSourceRootIndexableEntityProvider implements IndexableEntityProvider { } @Nullable - private static Pair getDataToIndex(WorkspaceEntity entity) { - if (entity instanceof JavaSourceRootEntity) { - SourceRootEntity sourceRootEntity = ((JavaSourceRootEntity)entity).getSourceRoot(); - VirtualFilePointer url = (VirtualFilePointer)sourceRootEntity.getUrl(); - if (url.isValid()) { - return new Pair<>(url.getFile(), sourceRootEntity.getContentRoot().getModule()); - } + private static Pair getDataToIndex(@NotNull JavaSourceRootEntity entity) { + SourceRootEntity sourceRootEntity = entity.getSourceRoot(); + VirtualFilePointer url = (VirtualFilePointer)sourceRootEntity.getUrl(); + if (url.isValid()) { + return new Pair<>(url.getFile(), sourceRootEntity.getContentRoot().getModule()); } return null; } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/LibraryIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/LibraryIndexableEntityProvider.java index cd2771e1fe04..88bbe8fd3603 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/LibraryIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/LibraryIndexableEntityProvider.java @@ -1,14 +1,13 @@ // Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.roots; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.libraries.Library; import com.intellij.workspaceModel.ide.WorkspaceModel; import com.intellij.workspaceModel.ide.impl.legacyBridge.project.ProjectRootsChangeListener; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.LibraryEntity; +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,35 +17,46 @@ import java.util.Collections; @ApiStatus.Internal @ApiStatus.Experimental -class LibraryIndexableEntityProvider implements IndexableEntityProvider { - private static final Logger LOG = Logger.getInstance(LibraryIndexableEntityProvider.class); +class LibraryIndexableEntityProvider implements IndexableEntityProvider { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, + public @NotNull Class getEntityClass() { + return LibraryEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull LibraryEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getAddedEntityIterator(@NotNull LibraryEntity entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return createIterators(entity, project); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + public @NotNull Collection getReplacedEntityIterator(@NotNull LibraryEntity oldEntity, + @NotNull LibraryEntity newEntity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { + @NotNull Project project) { return createIterators(newEntity, project); } @NotNull - static Collection createIterators(@Nullable WorkspaceEntity entity, + static Collection createIterators(@Nullable LibraryEntity entity, @NotNull Project project) { - if (entity instanceof LibraryEntity && + if (entity != null && ProjectRootsChangeListener.Companion.shouldFireRootsChanged$intellij_platform_lang_impl(entity, project)) { WorkspaceEntityStorage entityStorage = WorkspaceModel.getInstance(project).getEntityStorage().getCurrent(); - Library library = IndexableEntityProviderMethods.INSTANCE.findLibraryForEntity((LibraryEntity)entity, entityStorage); - LOG.assertTrue(library != null, "Failed to find library " + ((LibraryEntity)entity).getName()); - return IndexableEntityProviderMethods.INSTANCE.createIterators(library); + Library library = IndexableEntityProviderMethods.INSTANCE.findLibraryForEntity(entity, entityStorage); + if (library != null) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(library); + } } return Collections.emptyList(); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleCustomImlDataFilesIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleCustomImlDataFilesIndexableEntityProvider.java index 93242472af8b..dee5f3d4d34c 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleCustomImlDataFilesIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleCustomImlDataFilesIndexableEntityProvider.java @@ -2,7 +2,6 @@ package com.intellij.util.indexing.roots; import com.intellij.openapi.project.Project; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.ModuleCustomImlDataEntity; import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; @@ -12,31 +11,51 @@ import java.util.Collection; import java.util.Collections; import java.util.Objects; -public class ModuleCustomImlDataFilesIndexableEntityProvider implements IndexableEntityProvider { +public class ModuleCustomImlDataFilesIndexableEntityProvider + implements IndexableEntityProvider.ModuleEntityDependent { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, - @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (entity instanceof ModuleCustomImlDataEntity) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(((ModuleCustomImlDataEntity)entity).getModule(), project); - } + public @NotNull Class getEntityClass() { + return ModuleCustomImlDataEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull ModuleCustomImlDataEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { return Collections.emptyList(); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + public @NotNull Collection getExistingEntityIterator(@NotNull ModuleCustomImlDataEntity entity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (newEntity instanceof ModuleEntity) { - ModuleEntity oldModuleEntity = (ModuleEntity)oldEntity; - ModuleEntity newModuleEntity = (ModuleEntity)newEntity; - if (shouldBeReindexed(newModuleEntity, oldModuleEntity)) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(newModuleEntity, project); - } + @NotNull Project project) { + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getAddedEntityIterator(@NotNull ModuleCustomImlDataEntity entity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(entity.getModule(), project); + } + + @Override + public @NotNull Collection getReplacedEntityIterator(@NotNull ModuleCustomImlDataEntity oldEntity, + @NotNull ModuleCustomImlDataEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity, + @NotNull ModuleEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + if (shouldBeReindexed(newEntity, oldEntity)) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity, project); } return Collections.emptyList(); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleDependencyEntitiesIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleDependencyEntitiesIndexableEntityProvider.java index 36b0af0fd157..76bbc5214a30 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleDependencyEntitiesIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleDependencyEntitiesIndexableEntityProvider.java @@ -3,12 +3,12 @@ package com.intellij.util.indexing.roots; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.util.SmartList; import com.intellij.workspaceModel.ide.legacyBridge.ModifiableRootModelBridge; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.*; import com.intellij.workspaceModel.storage.bridgeEntities.LibraryTableId.GlobalLibraryTableId; @@ -19,65 +19,62 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -public class ModuleDependencyEntitiesIndexableEntityProvider implements IndexableEntityProvider { +public class ModuleDependencyEntitiesIndexableEntityProvider implements IndexableEntityProvider { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, - @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (entity instanceof ModuleEntity) { - List iterators = new SmartList<>(); - iterators.addAll(IndexableEntityProviderMethods.INSTANCE.createIterators((ModuleEntity)entity, project)); - for (ModuleDependencyItem dependency : ((ModuleEntity)entity).getDependencies()) { - iterators.addAll(createIteratorsForDependency(project, dependency, storage)); - } - return iterators; - } + public @NotNull Class getEntityClass() { + return ModuleEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull ModuleEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { return Collections.emptyList(); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, + public @NotNull Collection getAddedEntityIterator(@NotNull ModuleEntity entity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + List iterators = new SmartList<>(); + iterators.addAll(IndexableEntityProviderMethods.INSTANCE.createIterators(entity, project)); + for (ModuleDependencyItem dependency : entity.getDependencies()) { + iterators.addAll(createIteratorsForDependency(project, dependency, storage)); + } + return iterators; + } + + @Override + public @NotNull Collection getReplacedEntityIterator(@NotNull ModuleEntity oldEntity, + @NotNull ModuleEntity newEntity, @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (newEntity instanceof ModuleEntity) { - ModuleEntity oldModuleEntity = (ModuleEntity)oldEntity; - ModuleEntity newModuleEntity = (ModuleEntity)newEntity; - List iterators = new SmartList<>(); - List newDependencies = newModuleEntity.getDependencies(); - Collection oldDependencies = new HashSet<>(oldModuleEntity.getDependencies()); - for (ModuleDependencyItem dependency : newDependencies) { - if (!oldDependencies.contains(dependency)) { - iterators.addAll(createIteratorsForDependency(project, dependency, storage)); - } - } - if (!iterators.isEmpty()) { - return iterators; + @NotNull Project project) { + List iterators = new SmartList<>(); + List newDependencies = newEntity.getDependencies(); + Collection oldDependencies = new HashSet<>(oldEntity.getDependencies()); + for (ModuleDependencyItem dependency : newDependencies) { + if (!oldDependencies.contains(dependency)) { + iterators.addAll(createIteratorsForDependency(project, dependency, storage)); } } + if (!iterators.isEmpty()) { + return iterators; + } return Collections.emptyList(); } @NotNull private static Collection createIteratorsForDependency(@NotNull Project project, @NotNull ModuleDependencyItem dependency, - @NotNull WorkspaceEntityStorage storageAfter) - throws IndexableEntityResolvingException { + @NotNull WorkspaceEntityStorage storageAfter) { if (dependency instanceof ModuleDependencyItem.SdkDependency) { Sdk sdk = ModifiableRootModelBridge.findSdk(((ModuleDependencyItem.SdkDependency)dependency).getSdkName(), ((ModuleDependencyItem.SdkDependency)dependency).getSdkType()); if (sdk != null) { return IndexableEntityProviderMethods.INSTANCE.createIterators(sdk); } - else { - throw new IndexableEntityResolvingException("Failed to find sdk " + - ((ModuleDependencyItem.SdkDependency)dependency).getSdkName() + - " " + - ((ModuleDependencyItem.SdkDependency)dependency).getSdkType()); - } } else if (dependency instanceof ModuleDependencyItem.Exportable.LibraryDependency) { LibraryId libraryId = ((ModuleDependencyItem.Exportable.LibraryDependency)dependency).getLibrary(); @@ -87,10 +84,15 @@ public class ModuleDependencyEntitiesIndexableEntityProvider implements Indexabl } else { LibraryEntity libraryEntity = storageAfter.resolve(libraryId); - if (libraryEntity == null) { - throw new IndexableEntityResolvingException("Failed to find library " + libraryId); + if (libraryEntity != null) { + return LibraryIndexableEntityProvider.createIterators(libraryEntity, project); } - return LibraryIndexableEntityProvider.createIterators(libraryEntity, project); + } + } + else if (dependency instanceof ModuleDependencyItem.InheritedSdkDependency) { + Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk(); + if (sdk != null) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(sdk); } } return Collections.emptyList(); @@ -98,8 +100,7 @@ public class ModuleDependencyEntitiesIndexableEntityProvider implements Indexabl private static Collection findGlobalLibraryIterators(Project project, GlobalLibraryTableId tableId, - LibraryId libraryId) - throws IndexableEntityResolvingException { + LibraryId libraryId) { LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTableByLevel(tableId.getLevel(), project); if (table != null) { Library library = table.getLibraryByName(libraryId.getName()); @@ -107,6 +108,6 @@ public class ModuleDependencyEntitiesIndexableEntityProvider implements Indexabl return IndexableEntityProviderMethods.INSTANCE.createIterators(library); } } - throw new IndexableEntityResolvingException("Failed to find global library " + libraryId); + return Collections.emptyList(); } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleIndexableFilesIteratorImpl.kt b/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleIndexableFilesIteratorImpl.kt index 836267d5663d..6a001ddc657e 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleIndexableFilesIteratorImpl.kt +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/ModuleIndexableFilesIteratorImpl.kt @@ -1,14 +1,12 @@ // 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.util.indexing.roots -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleType import com.intellij.openapi.project.Project import com.intellij.openapi.project.rootManager import com.intellij.openapi.roots.ContentIterator import com.intellij.openapi.roots.ModuleRootManager -import com.intellij.openapi.roots.impl.ModuleFileIndexImpl import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileFilter @@ -18,31 +16,11 @@ import com.intellij.util.indexing.roots.kind.ModuleRootOrigin import com.intellij.util.indexing.roots.origin.ModuleRootOriginImpl import org.jetbrains.annotations.NonNls -open class ModuleIndexableFilesPolicy { - companion object { - fun getInstance() = ApplicationManager.getApplication().getService(ModuleIndexableFilesPolicy::class.java) - } - - open fun shouldIndexSeparateRoots() = true -} - internal class ModuleIndexableFilesIteratorImpl(private val module: Module, private val roots: List, private val printRootsInDebugName: Boolean) : ModuleIndexableFilesIterator { companion object { - @JvmStatic - fun getModuleIterators(module: Module): Collection { - val fileIndex = ModuleRootManager.getInstance(module).fileIndex as ModuleFileIndexImpl - val moduleRoots = fileIndex.moduleRootsToIterate.toList() - if (moduleRoots.isEmpty()) return emptyList() - - if (ModuleIndexableFilesPolicy.getInstance().shouldIndexSeparateRoots()) { - return moduleRoots.map { ModuleIndexableFilesIteratorImpl(module, listOf(it), moduleRoots.size > 1) } - } - return listOf(ModuleIndexableFilesIteratorImpl(module, moduleRoots, false)) - } - @JvmStatic fun getMergedIterators(rootIterators: Collection): Collection { if (rootIterators.isEmpty()) return emptyList() diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/SourceRootIndexableEntityProvider.java b/platform/lang-impl/src/com/intellij/util/indexing/roots/SourceRootIndexableEntityProvider.java index 734292289df8..0402c7137071 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/SourceRootIndexableEntityProvider.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/SourceRootIndexableEntityProvider.java @@ -4,7 +4,6 @@ package com.intellij.util.indexing.roots; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; -import com.intellij.workspaceModel.storage.WorkspaceEntity; import com.intellij.workspaceModel.storage.WorkspaceEntityStorage; import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity; import com.intellij.workspaceModel.storage.bridgeEntities.SourceRootEntity; @@ -17,45 +16,55 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -class SourceRootIndexableEntityProvider implements IndexableEntityProvider { +class SourceRootIndexableEntityProvider implements IndexableEntityProvider.ModuleEntityDependent { @Override - public @NotNull Collection getAddedEntityIterator(@NotNull WorkspaceEntity entity, - @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (entity instanceof SourceRootEntity) { - SourceRootEntity sourceRootEntity = (SourceRootEntity)entity; - return IndexableEntityProviderMethods.INSTANCE.createIterators(sourceRootEntity.getContentRoot().getModule(), - getVirtualFile(sourceRootEntity), - project); + public @NotNull Class getEntityClass() { + return SourceRootEntity.class; + } + + @Override + public @NotNull Collection getExistingEntityForModuleIterator(@NotNull SourceRootEntity entity, + @NotNull ModuleEntity moduleEntity, + @NotNull WorkspaceEntityStorage entityStorage, + @NotNull Project project) { + if (moduleEntity.equals(entity.getContentRoot().getModule())) { + return getExistingEntityIterator(entity, entityStorage, project); } return Collections.emptyList(); } @Override - public @NotNull Collection getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity, - @NotNull WorkspaceEntity newEntity, - @NotNull WorkspaceEntityStorage storage, - @NotNull Project project) - throws IndexableEntityResolvingException { - if (newEntity instanceof ModuleEntity) { - List newRoots = collectRoots(((ModuleEntity)newEntity).getSourceRoots()); - List oldRoots = collectRoots(((ModuleEntity)oldEntity).getSourceRoots()); - return IndexableEntityProviderMethods.INSTANCE.createIterators((ModuleEntity)newEntity, newRoots, oldRoots, project); - } - else if (newEntity instanceof SourceRootEntity) { - SourceRootEntity newSourceRoot = (SourceRootEntity)newEntity; - SourceRootEntity oldSourceRoot = (SourceRootEntity)oldEntity; + public @NotNull Collection getAddedEntityIterator(@NotNull SourceRootEntity entity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(entity.getContentRoot().getModule(), + getVirtualFile(entity), + project); + } - if (!(newSourceRoot.getUrl().equals(oldSourceRoot.getUrl())) || !newSourceRoot.getRootType().equals(oldSourceRoot.getRootType())) { - return IndexableEntityProviderMethods.INSTANCE.createIterators(newSourceRoot.getContentRoot().getModule(), - getVirtualFile(newSourceRoot), project); - } + @Override + public @NotNull Collection getReplacedEntityIterator(@NotNull SourceRootEntity oldEntity, + @NotNull SourceRootEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + if (!(newEntity.getUrl().equals(oldEntity.getUrl())) || !newEntity.getRootType().equals(oldEntity.getRootType())) { + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity.getContentRoot().getModule(), + getVirtualFile(newEntity), project); } return Collections.emptyList(); } + @Override + public @NotNull Collection getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity, + @NotNull ModuleEntity newEntity, + @NotNull WorkspaceEntityStorage storage, + @NotNull Project project) { + List newRoots = collectRoots(newEntity.getSourceRoots()); + List oldRoots = collectRoots(oldEntity.getSourceRoots()); + return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity, newRoots, oldRoots, project); + } + @NotNull private static List collectRoots(Sequence newContentRoots) { return SequencesKt.toList(SequencesKt.mapNotNull(newContentRoots, root -> getVirtualFile(root))); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/roots/standardContributors.kt b/platform/lang-impl/src/com/intellij/util/indexing/roots/standardContributors.kt index 580a6945a513..24088797ead3 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/roots/standardContributors.kt +++ b/platform/lang-impl/src/com/intellij/util/indexing/roots/standardContributors.kt @@ -3,46 +3,27 @@ package com.intellij.util.indexing.roots import com.intellij.ide.lightEdit.LightEdit import com.intellij.openapi.fileTypes.FileTypeManager -import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.* -import com.intellij.openapi.roots.libraries.Library +import com.intellij.openapi.roots.AdditionalLibraryRootsProvider +import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.indexing.AdditionalIndexableFileSet import com.intellij.util.indexing.IndexableSetContributor +import com.intellij.util.indexing.roots.IndexableEntityProviderMethods.mergeIterators +import com.intellij.workspaceModel.ide.WorkspaceModel +import com.intellij.workspaceModel.storage.WorkspaceEntity +import com.intellij.workspaceModel.storage.WorkspaceEntityStorage import org.jetbrains.annotations.Nls import java.util.function.Predicate internal class DefaultProjectIndexableFilesContributor : IndexableFilesContributor { override fun getIndexableFiles(project: Project): List { - val seenLibraries: MutableSet = HashSet() - val seenSdks: MutableSet = HashSet() - val modules = ModuleManager.getInstance(project).sortedModules - - val providers: MutableList = mutableListOf() - for (module in modules) { - providers.addAll(ModuleIndexableFilesIteratorImpl.getModuleIterators(module)) - - val orderEntries = ModuleRootManager.getInstance(module).orderEntries - for (orderEntry in orderEntries) { - when (orderEntry) { - is LibraryOrderEntry -> { - val library = orderEntry.library - if (library != null && seenLibraries.add(library)) { - providers.add(LibraryIndexableFilesIteratorImpl(library)) - } - } - is JdkOrderEntry -> { - val sdk = orderEntry.jdk - if (sdk != null && seenSdks.add(sdk)) { - providers.add(SdkIndexableFilesIteratorImpl(sdk)) - } - } - } - } + val iterators: MutableList = mutableListOf() + val entityStorage = WorkspaceModel.getInstance(project).entityStorage.current + for (provider in IndexableEntityProvider.EP_NAME.extensionList) { + addIteratorsFromProvider(provider, entityStorage, project, iterators) } - return providers + return mergeIterators(iterators) } override fun getOwnFilePredicate(project: Project): Predicate { @@ -58,6 +39,18 @@ internal class DefaultProjectIndexableFilesContributor : IndexableFilesContribut else false } } + + companion object { + private fun addIteratorsFromProvider(provider: IndexableEntityProvider, + entityStorage: WorkspaceEntityStorage, + project: Project, + iterators: MutableList) { + val entityClass = provider.entityClass + for (entity in entityStorage.entities(entityClass)) { + iterators.addAll(provider.getAddedEntityIterator(entity, entityStorage, project)) + } + } + } } internal class AdditionalFilesContributor : IndexableFilesContributor { diff --git a/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceTest.java b/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceTest.java index 5d3374d960cb..f341eda0e0be 100644 --- a/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceTest.java +++ b/platform/lang-impl/testSources/com/intellij/util/indexing/EntityIndexingServiceTest.java @@ -8,10 +8,7 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.DependencyScope; -import com.intellij.openapi.roots.ModifiableRootModel; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.ModuleRootManagerEx; +import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.OrderEntryUtil; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; @@ -84,14 +81,19 @@ public class EntityIndexingServiceTest extends HeavyPlatformTestCase { removeLibrary(library, LibraryTablesRegistrar.getInstance().getLibraryTable(getProject())); } - private static void removeLibrary(Library library, LibraryTable libraryTable) { + private void removeLibrary(Library library, LibraryTable libraryTable) { + ModifiableRootModel rootModel = ModuleRootManager.getInstance(getModule()).getModifiableModel(); + LibraryOrderEntry libraryOrderEntry = OrderEntryUtil.findLibraryOrderEntry(rootModel, library); + rootModel.removeOrderEntry(libraryOrderEntry); + rootModel.commit(); + LibraryTable.ModifiableModel libraryTableModifiableModel = libraryTable.getModifiableModel(); libraryTableModifiableModel.removeLibrary(library); libraryTableModifiableModel.commit(); } public void testIndexingGlobalLibrary() throws Exception { - doTest(this::createGlobalLibrary, EntityIndexingServiceTest::removeGlobalLibrary, + doTest(this::createGlobalLibrary, this::removeGlobalLibrary, IndexableEntityProviderMethods.INSTANCE::createIterators); } @@ -100,7 +102,7 @@ public class EntityIndexingServiceTest extends HeavyPlatformTestCase { return createLibrary(LibraryTablesRegistrar.getInstance().getLibraryTable()); } - private static void removeGlobalLibrary(Library library) { + private void removeGlobalLibrary(Library library) { removeLibrary(library, LibraryTablesRegistrar.getInstance().getLibraryTable()); } diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index c3dcb1f13812..2a3d2f4cb232 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -54,7 +54,6 @@ -