Switch DefaultProjectIndexableFilesContributor and all 'index whole module` cases to IndexableEntityProviders

GitOrigin-RevId: 08419313e0e7505adf389b19414fd9855e91bbd9
This commit is contained in:
Elena Shaverdova
2021-08-27 11:14:43 +00:00
committed by intellij-monorepo-bot
parent aae7b709c7
commit a0d0ab565e
19 changed files with 515 additions and 372 deletions
@@ -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<? extends FilePropertyPusher<?>> 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<? extends FilePropertyPusher<?>> 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<? super ModuleIndexableFilesIterator, ? extends ContentIteratorEx> iteratorProducer) {
Module[] modules = ReadAction.compute(() -> ModuleManager.getInstance(project).getModules());
public static void scanProject(@NotNull Project project, @NotNull Function<Module, ? extends ContentIteratorEx> iteratorProducer) {
Sequence<ModuleEntity> modulesSequence = ReadAction.compute(() ->
WorkspaceModel.Companion.getInstance(project).getEntityStorage().
getCurrent().entities(ModuleEntity.class));
List<ModuleEntity> moduleEntities = SequencesKt.toList(modulesSequence);
IndexableFilesDeduplicateFilter indexableFilesDeduplicateFilter = IndexableFilesDeduplicateFilter.create();
List<Runnable> tasks = Arrays.stream(modules)
.flatMap(module -> {
List<Runnable> 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());
@@ -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<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> 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<IndexableFilesIterator> getIterators(@NotNull Project project,
@NotNull Collection<? extends VersionedStorageChange> events)
throws IndexableEntityResolvingException {
@NotNull Collection<? extends VersionedStorageChange> events) {
WorkspaceEntityStorage entityStorage = WorkspaceModel.getInstance(project).getEntityStorage().getCurrent();
List<IndexableFilesIterator> 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<IndexableFilesIterator> getIteratorsWorkspaceChange(@NotNull Project project,
@NotNull VersionedStorageChange event,
WorkspaceEntityStorage entityStorage)
throws IndexableEntityResolvingException {
WorkspaceEntityStorage entityStorage) {
List<IndexableFilesIterator> iterators = new SmartList<>();
Iterator<EntityChange<?>> iterator = event.getAllChanges().iterator();
while (iterator.hasNext()) {
EntityChange<? extends WorkspaceEntity> change = iterator.next();
if (change instanceof EntityChange.Added) {
WorkspaceEntity entity = ((EntityChange.Added<? extends WorkspaceEntity>)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<? extends WorkspaceEntity>)change).getNewEntity();
WorkspaceEntity oldEntity = ((EntityChange.Replaced<? extends WorkspaceEntity>)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<? extends WorkspaceEntity>)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<IndexableFilesIterator> mergeIterators(List<? extends IndexableFilesIterator> iterators) {
List<IndexableFilesIterator> result = new ArrayList<>(iterators.size());
Collection<ModuleIndexableFilesIteratorImpl> rootIterators = new ArrayList<>();
Set<IndexableSetOrigin> origins = new HashSet<>();
for (IndexableFilesIterator iterator : iterators) {
if (iterator instanceof ModuleIndexableFilesIteratorImpl) {
rootIterators.add((ModuleIndexableFilesIteratorImpl)iterator);
private static <E extends WorkspaceEntity> void collectIteratorsOnAdd(@NotNull E entity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project,
@NotNull Collection<IndexableFilesIterator> iterators) {
Class<? extends WorkspaceEntity> entityClass = entity.getClass();
for (IndexableEntityProvider<?> provider : IndexableEntityProvider.EP_NAME.getExtensionList()) {
if (entityClass == provider.getEntityClass()) {
//noinspection unchecked
iterators.addAll(((IndexableEntityProvider<E>)provider).getAddedEntityIterator(entity, entityStorage, project));
}
else {
if (origins.add(iterator.getOrigin())) {
result.add(iterator);
}
}
private static <E extends WorkspaceEntity> void collectIteratorsOnReplace(@NotNull E oldEntity,
@NotNull E newEntity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project,
@NotNull Collection<IndexableFilesIterator> iterators) {
Class<? extends WorkspaceEntity> entityClass = oldEntity.getClass();
for (IndexableEntityProvider<?> provider : IndexableEntityProvider.EP_NAME.getExtensionList()) {
if (entityClass == provider.getEntityClass()) {
//noinspection unchecked
iterators.addAll(((IndexableEntityProvider<E>)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 <E extends WorkspaceEntity> void collectIteratorsOnRemove(@NotNull E entity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project,
@NotNull Collection<IndexableFilesIterator> iterators) {
Class<? extends WorkspaceEntity> entityClass = entity.getClass();
for (IndexableEntityProvider<?> provider : IndexableEntityProvider.EP_NAME.getExtensionList()) {
if (entityClass == provider.getEntityClass()) {
//noinspection unchecked
iterators.addAll(((IndexableEntityProvider<E>)provider).getRemovedEntityIterator(entity, entityStorage, project));
}
}
}
}
@@ -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;
@@ -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<ContentRootEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<ContentRootEntity> getEntityClass() {
return ContentRootEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project)
throws IndexableEntityResolvingException {
if (newEntity instanceof ModuleEntity) {
List<VirtualFile> newRoots = collectRoots(((ModuleEntity)newEntity).getContentRoots());
List<VirtualFile> 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<? extends IndexableFilesIterator> 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<VirtualFileUrl> newExcludedUrls = newContentRoot.getExcludedUrls();
List<VirtualFileUrl> oldExcludedUrls = oldContentRoot.getExcludedUrls();
if (!oldExcludedUrls.equals(newExcludedUrls)) {
VirtualFileManager fileManager = VirtualFileManager.getInstance();
List<VirtualFile> 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<? extends IndexableFilesIterator> 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<VirtualFileUrl> newExcludedUrls = newEntity.getExcludedUrls();
List<VirtualFileUrl> oldExcludedUrls = oldEntity.getExcludedUrls();
if (!oldExcludedUrls.equals(newExcludedUrls)) {
VirtualFileManager fileManager = VirtualFileManager.getInstance();
List<VirtualFile> 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<? extends IndexableFilesIterator> getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity,
@NotNull ModuleEntity newEntity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project) {
List<VirtualFile> newRoots = collectRoots(newEntity.getContentRoots());
List<VirtualFile> oldRoots = collectRoots(oldEntity.getContentRoots());
return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity, newRoots, oldRoots, project);
}
@NotNull
private static List<VirtualFile> collectRoots(Sequence<ContentRootEntity> newContentRoots) {
return SequencesKt.toList(SequencesKt.mapNotNull(newContentRoots, root -> getVirtualFile(root)));
@@ -95,18 +103,14 @@ class ContentRootIndexableEntityProvider implements IndexableEntityProvider {
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getRemovedEntityIterator(@NotNull WorkspaceEntity entity,
public @NotNull Collection<? extends IndexableFilesIterator> 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();
@@ -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<IndexableEntityProvider> EP_NAME = new ExtensionPointName<>("com.intellij.indexableEntityProvider");
public interface IndexableEntityProvider<E extends WorkspaceEntity> {
ExtensionPointName<IndexableEntityProvider<? extends WorkspaceEntity>> EP_NAME =
new ExtensionPointName<>("com.intellij.indexableEntityProvider");
@NotNull
Class<E> getEntityClass();
/**
* Provides iterators to index files when just project is indexed, no events given
*/
@NotNull
default Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull WorkspaceEntity entity,
Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getRemovedEntityIterator(@NotNull WorkspaceEntity entity,
default Collection<? extends IndexableFilesIterator> 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<E extends WorkspaceEntity> extends IndexableEntityProvider<E> {
/**
* 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<? extends IndexableFilesIterator> getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity,
@NotNull ModuleEntity newEntity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project);
}
}
@@ -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<IndexableFilesIterator> {
val module = findModuleForEntity(entity, project)
if (module == null) {
return emptyList()
val iterators = mutableListOf<IndexableFilesIterator>()
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 <E : WorkspaceEntity> addIteratorsFromProvider(provider: IndexableEntityProvider<E>,
moduleEntity: ModuleEntity,
entityStorage: WorkspaceEntityStorage,
project: Project,
iterators: MutableList<IndexableFilesIterator>) {
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<IndexableFilesIterator> {
@@ -70,4 +86,22 @@ object IndexableEntityProviderMethods {
fun createIterators(sdk: Sdk): Collection<IndexableFilesIterator> {
return listOf(SdkIndexableFilesIteratorImpl(sdk))
}
fun mergeIterators(iterators: List<IndexableFilesIterator>): List<IndexableFilesIterator> {
val result: MutableList<IndexableFilesIterator> = java.util.ArrayList(iterators.size)
val rootIterators: MutableCollection<ModuleIndexableFilesIteratorImpl> = java.util.ArrayList()
val origins: MutableSet<IndexableSetOrigin> = 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
}
}
@@ -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);
}
}
@@ -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<JavaModuleSettingsEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull WorkspaceEntity entity,
public @NotNull Class<JavaModuleSettingsEntity> getEntityClass() {
return JavaModuleSettingsEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getExistingEntityIterator(@NotNull JavaModuleSettingsEntity entity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project) {
return Collections.emptyList();
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getExistingEntityForModuleIterator(@NotNull JavaModuleSettingsEntity entity,
@NotNull ModuleEntity moduleEntity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project) {
return Collections.emptyList();
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
public @NotNull Collection<? extends IndexableFilesIterator> 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();
}
@@ -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<JavaResourceRootEntity> {
@Override
public @NotNull Class<JavaResourceRootEntity> getEntityClass() {
return JavaResourceRootEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull WorkspaceEntity entity,
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
public @NotNull Collection<? extends IndexableFilesIterator> 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<VirtualFile, ModuleEntity> 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<VirtualFile, ModuleEntity> 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;
}
@@ -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<JavaSourceRootEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull WorkspaceEntity entity,
public @NotNull Class<JavaSourceRootEntity> getEntityClass() {
return JavaSourceRootEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
public @NotNull Collection<? extends IndexableFilesIterator> 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<IndexableFilesIterator> collectIteratorsOnAddedEntityWithDataExtractor(@NotNull WorkspaceEntity entity,
@NotNull Function<? super WorkspaceEntity, Pair<VirtualFile, ModuleEntity>> extractor,
@NotNull Project project) {
static <E extends WorkspaceEntity> Collection<IndexableFilesIterator> collectIteratorsOnAddedEntityWithDataExtractor(@NotNull E entity,
@NotNull Function<? super E, Pair<VirtualFile, ModuleEntity>> extractor,
@NotNull Project project) {
Pair<VirtualFile, ModuleEntity> 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<IndexableFilesIterator> collectIteratorsOnReplacedEntityWithDataExtractor(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
@NotNull Function<? super WorkspaceEntity, Pair<VirtualFile, ModuleEntity>> extractor,
@NotNull Project project) {
static <E extends WorkspaceEntity> Collection<IndexableFilesIterator> collectIteratorsOnReplacedEntityWithDataExtractor(@NotNull E oldEntity,
@NotNull E newEntity,
@NotNull Function<? super E, Pair<VirtualFile, ModuleEntity>> extractor,
@NotNull Project project) {
Pair<VirtualFile, ModuleEntity> newData = extractor.fun(newEntity);
if (newData != null) {
Pair<VirtualFile, ModuleEntity> oldData = extractor.fun(oldEntity);
@@ -64,13 +78,11 @@ class JavaSourceRootIndexableEntityProvider implements IndexableEntityProvider {
}
@Nullable
private static Pair<VirtualFile, ModuleEntity> 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<VirtualFile, ModuleEntity> 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;
}
@@ -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<LibraryEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull WorkspaceEntity entity,
public @NotNull Class<LibraryEntity> getEntityClass() {
return LibraryEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getExistingEntityForModuleIterator(@NotNull LibraryEntity entity,
@NotNull ModuleEntity moduleEntity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project) {
return Collections.emptyList();
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull LibraryEntity entity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project)
throws IndexableEntityResolvingException {
@NotNull Project project) {
return createIterators(entity, project);
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> createIterators(@Nullable WorkspaceEntity entity,
static Collection<? extends IndexableFilesIterator> 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();
}
@@ -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<ModuleCustomImlDataEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<ModuleCustomImlDataEntity> getEntityClass() {
return ModuleCustomImlDataEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getExistingEntityForModuleIterator(@NotNull ModuleCustomImlDataEntity entity,
@NotNull ModuleEntity moduleEntity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project) {
return Collections.emptyList();
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull ModuleCustomImlDataEntity entity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project) {
return IndexableEntityProviderMethods.INSTANCE.createIterators(entity.getModule(), project);
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull ModuleCustomImlDataEntity oldEntity,
@NotNull ModuleCustomImlDataEntity newEntity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project) {
return Collections.emptyList();
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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();
}
@@ -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<ModuleEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull WorkspaceEntity entity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project)
throws IndexableEntityResolvingException {
if (entity instanceof ModuleEntity) {
List<IndexableFilesIterator> 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<ModuleEntity> getEntityClass() {
return ModuleEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getExistingEntityForModuleIterator(@NotNull ModuleEntity entity,
@NotNull ModuleEntity moduleEntity,
@NotNull WorkspaceEntityStorage entityStorage,
@NotNull Project project) {
return Collections.emptyList();
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
public @NotNull Collection<? extends IndexableFilesIterator> getAddedEntityIterator(@NotNull ModuleEntity entity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project) {
List<IndexableFilesIterator> 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<? extends IndexableFilesIterator> 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<IndexableFilesIterator> iterators = new SmartList<>();
List<ModuleDependencyItem> newDependencies = newModuleEntity.getDependencies();
Collection<ModuleDependencyItem> 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<IndexableFilesIterator> iterators = new SmartList<>();
List<ModuleDependencyItem> newDependencies = newEntity.getDependencies();
Collection<ModuleDependencyItem> 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<? extends IndexableFilesIterator> 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<IndexableFilesIterator> 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();
}
}
@@ -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<VirtualFile>,
private val printRootsInDebugName: Boolean) : ModuleIndexableFilesIterator {
companion object {
@JvmStatic
fun getModuleIterators(module: Module): Collection<ModuleIndexableFilesIteratorImpl> {
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<ModuleIndexableFilesIteratorImpl>): Collection<IndexableFilesIterator> {
if (rootIterators.isEmpty()) return emptyList()
@@ -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<SourceRootEntity> {
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<SourceRootEntity> getEntityClass() {
return SourceRootEntity.class;
}
@Override
public @NotNull Collection<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedEntityIterator(@NotNull WorkspaceEntity oldEntity,
@NotNull WorkspaceEntity newEntity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project)
throws IndexableEntityResolvingException {
if (newEntity instanceof ModuleEntity) {
List<VirtualFile> newRoots = collectRoots(((ModuleEntity)newEntity).getSourceRoots());
List<VirtualFile> 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<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> 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<? extends IndexableFilesIterator> getReplacedModuleEntityIterator(@NotNull ModuleEntity oldEntity,
@NotNull ModuleEntity newEntity,
@NotNull WorkspaceEntityStorage storage,
@NotNull Project project) {
List<VirtualFile> newRoots = collectRoots(newEntity.getSourceRoots());
List<VirtualFile> oldRoots = collectRoots(oldEntity.getSourceRoots());
return IndexableEntityProviderMethods.INSTANCE.createIterators(newEntity, newRoots, oldRoots, project);
}
@NotNull
private static List<VirtualFile> collectRoots(Sequence<SourceRootEntity> newContentRoots) {
return SequencesKt.toList(SequencesKt.mapNotNull(newContentRoots, root -> getVirtualFile(root)));
@@ -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<IndexableFilesIterator> {
val seenLibraries: MutableSet<Library> = HashSet()
val seenSdks: MutableSet<Sdk> = HashSet()
val modules = ModuleManager.getInstance(project).sortedModules
val providers: MutableList<IndexableFilesIterator> = 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<IndexableFilesIterator> = 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<VirtualFile> {
@@ -58,6 +39,18 @@ internal class DefaultProjectIndexableFilesContributor : IndexableFilesContribut
else false
}
}
companion object {
private fun <E : WorkspaceEntity> addIteratorsFromProvider(provider: IndexableEntityProvider<E>,
entityStorage: WorkspaceEntityStorage,
project: Project,
iterators: MutableList<IndexableFilesIterator>) {
val entityClass = provider.entityClass
for (entity in entityStorage.entities(entityClass)) {
iterators.addAll(provider.getAddedEntityIterator(entity, entityStorage, project))
}
}
}
}
internal class AdditionalFilesContributor : IndexableFilesContributor {
@@ -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());
}
@@ -54,7 +54,6 @@
<vfs.asyncListener implementation="com.intellij.util.indexing.events.ChangedFilesCollector"/>
<applicationInitializedListener implementation="com.intellij.util.indexing.FileBasedIndexLoader"/>
<applicationService serviceImplementation="com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper" preload="notLightEdit"/>
<applicationService serviceImplementation="com.intellij.util.indexing.roots.ModuleIndexableFilesPolicy"/>
<!-- required for any persistence state component (pathMacroSubstitutor.expandPaths), so, preload -->
<applicationService serviceInterface="com.intellij.openapi.application.PathMacros"
@@ -95,6 +95,9 @@ class IndexableFilesRegularTest : IndexableFilesBaseTest() {
lateinit var sourcesDir: DirectorySpec
lateinit var excludedSourcesDir: DirectorySpec
lateinit var firstLibraryClassesDir: DirectorySpec
lateinit var firstLibraryFile: FileSpec
buildDirectoryContent(commonRoot) {
dir("library") {
classesDir = dir("classes") {
@@ -109,6 +112,9 @@ class IndexableFilesRegularTest : IndexableFilesBaseTest() {
}
sourceFile = file("SourceFile.java", "class SourceFile {}")
}
firstLibraryClassesDir = dir("firstLibraryClasses") {
firstLibraryFile = file("FirstLibraryFile.java", "class FirstLibraryFile {}")
}
}
}
val module = projectModelRule.createModule()
@@ -118,11 +124,15 @@ class IndexableFilesRegularTest : IndexableFilesBaseTest() {
model.addRoot(sourcesDir.file, OrderRootType.SOURCES)
model.addExcludedRoot(excludedClassesDir.file.url)
model.addExcludedRoot(excludedSourcesDir.file.url)
if ("libraryOne" == libraryName) {
model.addRoot(firstLibraryClassesDir.file, OrderRootType.CLASSES)
}
}
}
// ClassFile.java and SourceFile.java are iterated by only one of the "file iterators"
// So they must be skipped when iterating for the second time.
assertIndexableFiles(expectedNumberOfSkippedFiles = 2, expectedFiles = arrayOf(classFile.file, sourceFile.file))
assertIndexableFiles(expectedNumberOfSkippedFiles = 2,
expectedFiles = arrayOf(classFile.file, sourceFile.file, firstLibraryFile.file))
}
@Test