mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-252666 fix module indexable iterators not created
if CONTENT root was under CONTENT_NON_INDEXABLE from the same module. GitOrigin-RevId: 9bd6b465ae3d6442480f670abc8213eebf9fe965
This commit is contained in:
committed by
intellij-monorepo-bot
parent
32960aeff5
commit
cad67986c3
+71
-1
@@ -6,6 +6,7 @@ import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.SdkType
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.jps.entities.ModuleEntity
|
||||
@@ -18,8 +19,10 @@ import com.intellij.util.indexing.dependenciesCache.DependenciesIndexedStatusSer
|
||||
import com.intellij.util.indexing.roots.kind.LibraryOrigin
|
||||
import com.intellij.util.indexing.roots.origin.IndexingRootHolder
|
||||
import com.intellij.util.indexing.roots.origin.IndexingSourceRootHolder
|
||||
import com.intellij.util.indexing.roots.origin.LibraryOriginImpl
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndex
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileKind
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSet
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetWithCustomData
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.ModuleRelatedRootData
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexEx
|
||||
@@ -131,4 +134,71 @@ class IndexingIteratorsProviderImpl(
|
||||
}
|
||||
return iterators
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun processModuleRoot(
|
||||
fileSet: WorkspaceFileSetWithCustomData<*>,
|
||||
project: Project,
|
||||
includeNestedRoots: Boolean = false,
|
||||
): IndexableFilesIterator? {
|
||||
val customData = fileSet.data
|
||||
val root = fileSet.root
|
||||
customData as ModuleRelatedRootData
|
||||
|
||||
return if (!includeNestedRoots && isNestedRootOfModuleIndexableContent(root, customData.module, WorkspaceFileIndexEx.getInstance(project))) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
ModuleFilesIteratorImpl(customData.module, root, fileSet.recursive, true)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun processLibraryEntity(entity: LibraryEntity, fileSet: WorkspaceFileSet): Pair<LibraryOrigin, IndexableFilesIterator> {
|
||||
return processLibrary(entity.name, fileSet)
|
||||
}
|
||||
|
||||
internal fun processLibrary(libraryName: String, fileSet: WorkspaceFileSet): Pair<LibraryOrigin, IndexableFilesIterator> {
|
||||
val sourceRoot = fileSet.kind == WorkspaceFileKind.EXTERNAL_SOURCE
|
||||
val origin = if (sourceRoot) {
|
||||
LibraryOriginImpl(emptyList(), listOf(fileSet.root))
|
||||
}
|
||||
else {
|
||||
LibraryOriginImpl(listOf(fileSet.root), emptyList())
|
||||
}
|
||||
val iterator = GenericDependencyIterator.forLibraryEntity(origin, libraryName, fileSet.root, sourceRoot)
|
||||
return origin to iterator
|
||||
}
|
||||
|
||||
private fun isNestedRootOfModuleIndexableContent(
|
||||
root: VirtualFile,
|
||||
module: Module,
|
||||
workspaceFileIndex: WorkspaceFileIndexEx,
|
||||
): Boolean {
|
||||
val parent = root.getParent()
|
||||
if (parent == null) {
|
||||
return false
|
||||
}
|
||||
val fileInfo = workspaceFileIndex.getFileInfo(
|
||||
parent,
|
||||
honorExclusion = false,
|
||||
includeContentSets = true,
|
||||
includeContentNonIndexableSets = false,
|
||||
includeExternalSets = false,
|
||||
includeExternalSourceSets = false,
|
||||
includeExternalNonIndexableSets = false,
|
||||
includeCustomKindSets = false
|
||||
)
|
||||
return fileInfo.findFileSet { fileSet -> hasRecursiveRootFromModuleContent(fileSet, module) } != null
|
||||
}
|
||||
|
||||
private fun hasRecursiveRootFromModuleContent(
|
||||
fileSet: WorkspaceFileSetWithCustomData<*>,
|
||||
module: Module,
|
||||
): Boolean {
|
||||
return fileSet.recursive && isInContent(fileSet, module)
|
||||
}
|
||||
|
||||
private fun isInContent(fileSet: WorkspaceFileSetWithCustomData<*>, module: Module): Boolean {
|
||||
val data = fileSet.data
|
||||
return data is ModuleRelatedRootData && module == data.module
|
||||
}
|
||||
|
||||
-57
@@ -7,33 +7,26 @@ import com.intellij.openapi.extensions.forEachExtensionSafeInline
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.progress.Cancellation
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Condition
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.OSAgnosticPathUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.backend.workspace.virtualFile
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.storage.EntityPointer
|
||||
import com.intellij.platform.workspace.storage.EntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import com.intellij.util.indexing.roots.kind.LibraryOrigin
|
||||
import com.intellij.util.indexing.roots.origin.IndexingUrlRootHolder
|
||||
import com.intellij.util.indexing.roots.origin.IndexingUrlSourceRootHolder
|
||||
import com.intellij.util.indexing.roots.origin.LibraryOriginImpl
|
||||
import com.intellij.util.indexing.roots.origin.MutableIndexingUrlRootHolder
|
||||
import com.intellij.util.indexing.roots.origin.MutableIndexingUrlSourceRootHolder
|
||||
import com.intellij.workspaceModel.core.fileIndex.EntityStorageKind
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndexContributor
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileKind
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSet
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetData
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetExclusionCondition
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetRegistrar
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetWithCustomData
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.ModuleRelatedRootData
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexEx
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl
|
||||
import java.util.NavigableMap
|
||||
import java.util.TreeMap
|
||||
@@ -252,56 +245,6 @@ private class RootData<E : WorkspaceEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun processModuleRoot(fileSet: WorkspaceFileSetWithCustomData<*>, project: Project, includeNestedRoots: Boolean = false): IndexableFilesIterator? {
|
||||
val customData = fileSet.data
|
||||
val root = fileSet.root
|
||||
customData as ModuleRelatedRootData
|
||||
|
||||
return if (!includeNestedRoots && isNestedRootOfModuleContent(root, customData.module, WorkspaceFileIndexEx.getInstance(project))) {
|
||||
null
|
||||
} else {
|
||||
ModuleFilesIteratorImpl(customData.module, root, fileSet.recursive, true)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun processLibraryEntity(entity: LibraryEntity, fileSet: WorkspaceFileSet): Pair<LibraryOrigin, IndexableFilesIterator> {
|
||||
val sourceRoot = fileSet.kind == WorkspaceFileKind.EXTERNAL_SOURCE
|
||||
val origin = if (sourceRoot) {
|
||||
LibraryOriginImpl(emptyList(), listOf(fileSet.root))
|
||||
}
|
||||
else {
|
||||
LibraryOriginImpl(listOf(fileSet.root), emptyList())
|
||||
}
|
||||
val iterator = GenericDependencyIterator.forLibraryEntity(origin, entity.name, fileSet.root, sourceRoot)
|
||||
return origin to iterator
|
||||
}
|
||||
|
||||
private fun isNestedRootOfModuleContent(root: VirtualFile, module: Module, workspaceFileIndex: WorkspaceFileIndexEx): Boolean {
|
||||
val parent = root.getParent()
|
||||
if (parent == null) {
|
||||
return false
|
||||
}
|
||||
val fileInfo = workspaceFileIndex.getFileInfo(
|
||||
parent,
|
||||
honorExclusion = false,
|
||||
includeContentSets = true,
|
||||
includeContentNonIndexableSets = true,
|
||||
includeExternalSets = false,
|
||||
includeExternalSourceSets = false,
|
||||
includeExternalNonIndexableSets = false,
|
||||
includeCustomKindSets = false
|
||||
)
|
||||
return fileInfo.findFileSet { fileSet -> hasRecursiveRootFromModuleContent(fileSet, module) } != null
|
||||
}
|
||||
|
||||
private fun hasRecursiveRootFromModuleContent(fileSet: WorkspaceFileSetWithCustomData<*>, module: Module): Boolean {
|
||||
return fileSet.recursive && isInContent(fileSet, module)
|
||||
}
|
||||
|
||||
private fun isInContent(fileSet: WorkspaceFileSetWithCustomData<*>, module: Module): Boolean {
|
||||
val data = fileSet.data
|
||||
return data is ModuleRelatedRootData && module == data.module
|
||||
}
|
||||
|
||||
private class MyWorkspaceFileSetRegistrar<E : WorkspaceEntity>(contributor: WorkspaceFileIndexContributor<E>,
|
||||
ignoreModuleRoots: Boolean) : WorkspaceFileSetRegistrar {
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by a license that can be found in the LICENSE file.
|
||||
package com.intellij.util.indexing.roots
|
||||
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ContentIterator
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileFilter
|
||||
import com.intellij.platform.backend.workspace.toVirtualFileUrl
|
||||
import com.intellij.platform.backend.workspace.workspaceModel
|
||||
import com.intellij.platform.workspace.storage.EntityStorage
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
import com.intellij.testFramework.rules.ProjectModelExtension
|
||||
import com.intellij.testFramework.workspaceModel.update
|
||||
import com.intellij.util.containers.TreeNodeProcessingResult
|
||||
import com.intellij.util.indexing.testEntities.IndexingTestEntity
|
||||
import com.intellij.util.indexing.testEntities.NonIndexableTestEntity
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndexContributor
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileKind
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetRegistrar
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.ModuleRelatedRootData
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexEx
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl
|
||||
import com.intellij.workspaceModel.ide.NonPersistentEntitySource
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.RegisterExtension
|
||||
|
||||
@TestApplication
|
||||
internal class IndexingIteratorsProviderImplTest {
|
||||
@RegisterExtension
|
||||
private val projectModel = ProjectModelExtension()
|
||||
|
||||
private val project: Project get() = projectModel.project
|
||||
private val workspaceModel get() = project.workspaceModel
|
||||
private val disposable get() = projectModel.disposableRule.disposable
|
||||
|
||||
|
||||
@Test
|
||||
fun `iterates indexable content below non-indexable content`() = timeoutRunBlocking {
|
||||
val project = projectModel.project
|
||||
val module = projectModel.createModule()
|
||||
val nonIndexableRoot = projectModel.baseProjectDir.newVirtualDirectory("non-indexable")
|
||||
val nonIndexableFile = projectModel.baseProjectDir.newVirtualFile("non-indexable/non-indexable.txt")
|
||||
val indexableRoot = projectModel.baseProjectDir.newVirtualDirectory("non-indexable/indexable")
|
||||
val indexableFile = projectModel.baseProjectDir.newVirtualFile("non-indexable/indexable/indexable.txt")
|
||||
|
||||
WorkspaceFileIndexImpl.EP_NAME.point.registerExtension(ModuleNonIndexableFileSetContributor(module), disposable)
|
||||
WorkspaceFileIndexImpl.EP_NAME.point.registerExtension(ModuleContentFileSetContributor(module), disposable)
|
||||
|
||||
workspaceModel.update {
|
||||
it.addEntity(NonIndexableTestEntity(nonIndexableRoot.toVirtualFileUrl(), NonPersistentEntitySource))
|
||||
it.addEntity(IndexingTestEntity(listOf(indexableRoot.toVirtualFileUrl()), emptyList(), NonPersistentEntitySource))
|
||||
}
|
||||
|
||||
val indexableFiles = readAction {
|
||||
val files = mutableSetOf<VirtualFile>()
|
||||
val processed = WorkspaceFileIndexEx.getInstance(project).processIndexableContentUnderDirectory(
|
||||
nonIndexableRoot,
|
||||
{ file -> files.add(file); TreeNodeProcessingResult.CONTINUE },
|
||||
VirtualFileFilter.ALL,
|
||||
) { true }
|
||||
assertTrue(processed)
|
||||
assertTrue(nonIndexableFile !in files)
|
||||
assertTrue(indexableRoot in files)
|
||||
assertTrue(indexableFile in files)
|
||||
files
|
||||
}
|
||||
|
||||
val iteratedFiles = readAction {
|
||||
val iterators = IndexingIteratorsProviderImpl(project).getIndexingIterators()
|
||||
val files = mutableSetOf<VirtualFile>()
|
||||
for (iterator in iterators) {
|
||||
assertTrue(iterator.iterateFiles(project, ContentIterator { file -> files.add(file); true }, VirtualFileFilter.ALL))
|
||||
}
|
||||
files
|
||||
}
|
||||
|
||||
assertTrue(iteratedFiles.containsAll(indexableFiles), "Missing indexable files: ${indexableFiles - iteratedFiles}")
|
||||
}
|
||||
|
||||
private fun VirtualFile.toVirtualFileUrl(): VirtualFileUrl = toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager())
|
||||
|
||||
private class ModuleNonIndexableFileSetContributor(private val module: Module) :
|
||||
WorkspaceFileIndexContributor<NonIndexableTestEntity> {
|
||||
override val entityClass: Class<NonIndexableTestEntity> = NonIndexableTestEntity::class.java
|
||||
|
||||
override fun registerFileSets(
|
||||
entity: NonIndexableTestEntity,
|
||||
registrar: WorkspaceFileSetRegistrar,
|
||||
storage: EntityStorage,
|
||||
) {
|
||||
registrar.registerFileSet(entity.root, WorkspaceFileKind.CONTENT_NON_INDEXABLE, entity, ModuleRootData(module))
|
||||
}
|
||||
}
|
||||
|
||||
private class ModuleContentFileSetContributor(private val module: Module) :
|
||||
WorkspaceFileIndexContributor<IndexingTestEntity> {
|
||||
override val entityClass: Class<IndexingTestEntity> = IndexingTestEntity::class.java
|
||||
|
||||
override fun registerFileSets(
|
||||
entity: IndexingTestEntity,
|
||||
registrar: WorkspaceFileSetRegistrar,
|
||||
storage: EntityStorage,
|
||||
) {
|
||||
for (root in entity.roots) {
|
||||
registrar.registerFileSet(root, WorkspaceFileKind.CONTENT, entity, ModuleRootData(module))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class ModuleRootData(override val module: Module) : ModuleRelatedRootData
|
||||
}
|
||||
Reference in New Issue
Block a user