diff --git a/plugins/kotlin/compiler-reference-index/resources/intellij.kotlin.compilerReferenceIndex.xml b/plugins/kotlin/compiler-reference-index/resources/intellij.kotlin.compilerReferenceIndex.xml
index 24d614aa0106..3fd1aebaf0fa 100644
--- a/plugins/kotlin/compiler-reference-index/resources/intellij.kotlin.compilerReferenceIndex.xml
+++ b/plugins/kotlin/compiler-reference-index/resources/intellij.kotlin.compilerReferenceIndex.xml
@@ -22,6 +22,19 @@
implementation="org.jetbrains.kotlin.idea.search.refIndex.KotlinDirectInheritorProvider"/>
+
+
+
+
+
+
+
+
()
-
- fun open(project: Project, projectPath: String): KotlinCompilerReferenceIndexStorage? {
- if (project.isDisposed) return null
- val buildDataPaths = project.buildDataPaths
- val kotlinDataContainerPath = buildDataPaths.kotlinDataContainer ?: kotlin.run {
- LOG.warn("${SettingConstants.KOTLIN_DATA_CONTAINER_ID} is not found")
- return null
- }
-
- val lookupStorageReader = LookupStorageReader.create(kotlinDataContainerPath, projectPath) ?: kotlin.run {
- LOG.warn("LookupStorage not found or corrupted")
- return null
- }
-
- val storage = KotlinCompilerReferenceIndexStorage(kotlinDataContainerPath, lookupStorageReader)
- if (!storage.initialize(buildDataPaths)) return null
- return storage
- }
-
- fun close(storage: KotlinCompilerReferenceIndexStorage?) {
- storage?.close().let {
- LOG.info("KCRI storage is closed" + if (it == null) " (didn't exist)" else "")
- }
- }
-
- fun hasIndex(project: Project): Boolean = LookupStorageReader.hasStorage(project)
-
- @TestOnly
- fun initializeForTests(
- buildDataPaths: BuildDataPaths,
- destination: ClassOneToManyStorage,
- ) = initializeSubtypeStorage(buildDataPaths, destination)
-
- internal val Project.buildDataPaths: BuildDataPaths
- get() = BuildDataPathsImpl(BuildManager.getInstance().getProjectSystemDir(this))
-
- internal val BuildDataPaths.kotlinDataContainer: Path?
- get() = targetsDataRoot
- .resolve(SettingConstants.KOTLIN_DATA_CONTAINER_ID)
- .takeIf { it.exists() && it.isDirectory() }
- ?.listDirectoryEntries("${SettingConstants.KOTLIN_DATA_CONTAINER_ID}*")
- ?.firstOrNull()
-
- private fun initializeSubtypeStorage(buildDataPaths: BuildDataPaths, destination: ClassOneToManyStorage): Boolean {
- var wasCorrupted = false
- val destinationMap = MultiMap.createConcurrentSet()
-
- val futures = mutableListOf>()
- val timeOfFilling = measureTimeMillis {
- visitSubtypeStorages(buildDataPaths) { storagePath ->
- futures += STORAGE_INDEXING_EXECUTOR.submit {
- try {
- initializeStorage(destinationMap, storagePath)
- } catch (e: CorruptedException) {
- wasCorrupted = true
- LOG.warn("KCRI storage was corrupted", e)
- }
- }
- }
-
- try {
- for (future in futures) {
- future.get()
- }
- } catch (e: InterruptedException) {
- LOG.warn("KCRI initialization was interrupted")
- throw e
- }
- }
-
- if (wasCorrupted) return false
-
- val timeOfFlush = measureTimeMillis {
- for ((key, values) in destinationMap.entrySet()) {
- destination.put(key, values)
- }
- }
-
- LOG.info("KCRI storage is opened: took ${timeOfFilling + timeOfFlush} ms for ${futures.size} storages (filling map: $timeOfFilling ms, flush to storage: $timeOfFlush ms)")
- return true
- }
-
- private fun visitSubtypeStorages(buildDataPaths: BuildDataPaths, processor: (Path) -> Unit) {
- for (buildTargetType in JavaModuleBuildTargetType.ALL_TYPES) {
- val buildTargetPath = buildDataPaths.getTargetTypeDataRootDir(buildTargetType)
- if (buildTargetPath.notExists() || !buildTargetPath.isDirectory()) continue
- buildTargetPath.forEachDirectoryEntry { targetDataRoot ->
- val workingPath = targetDataRoot.takeIf { it.isDirectory() }
- ?.resolve(KOTLIN_CACHE_DIRECTORY_NAME)
- ?.resolve(SUBTYPES_STORAGE_NAME)
- ?.takeUnless { it.notExists() }
- ?: return@forEachDirectoryEntry
-
- processor(workingPath)
- }
- }
- }
- }
-
- private val subtypesStorage = ClassOneToManyStorage(kotlinDataContainerPath.resolve(SUBTYPES_STORAGE_NAME))
+/**
+ * Interface responsible for managing the storage of the Kotlin Compiler Reference Index (KCRI).
+ * Implementations can choose how the data is retrieved from the CRI data.
+ * Typically there should be one implementation for each build system that wants to offer CRI capabilities.
+ */
+@ApiStatus.Experimental
+interface KotlinCompilerReferenceIndexStorage {
+ /**
+ * Returns the list of [VirtualFile]s that make use of the given [fqName].
+ */
+ fun getUsages(fqName: FqName): List
/**
- * @return true if initialization was successful
+ * Returns subtypes of the class/interface identified by [fqName] stored within this storage.
+ * When [deep] is true, the returned [Sequence] represents the transitive closure over the subtype relation.
*/
- private fun initialize(buildDataPaths: BuildDataPaths): Boolean = initializeSubtypeStorage(buildDataPaths, subtypesStorage)
+ fun getSubtypesOf(fqName: FqName, deep: Boolean): Sequence
- private fun close() {
- lookupStorageReader.close()
- subtypesStorage.closeAndClean()
- }
+ /**
+ * Closes the storage and releases any held resources.
+ */
+ fun close()
- fun getUsages(fqName: FqName): List = lookupStorageReader[fqName].mapNotNull { VfsUtil.findFile(it, false) }
+ companion object {
+ /**
+ * Opens a storage for the given [project] by finding the first [KotlinCompilerReferenceIndexStorageProvider]
+ * that is applicable for the [project].
+ * Returns null if no provider is applicable or if storage creation fails (e.g. index missing or corrupted).
+ */
+ internal fun open(project: Project, projectPath: String): KotlinCompilerReferenceIndexStorage? {
+ val provider = KotlinCompilerReferenceIndexStorageProvider.getApplicableProvider(project) ?: return null
+ return provider.createStorage(project, projectPath)
+ }
- fun getSubtypesOf(fqName: FqName, deep: Boolean): Sequence = subtypesStorage[fqName, deep]
-}
-
-private fun initializeStorage(destinationMap: MultiMap, subtypesSourcePath: Path) {
- createKotlinDataReader(subtypesSourcePath).use { source ->
- source.processKeys { key ->
- source[key]?.let { values ->
- destinationMap.putValues(key, values)
- }
-
- true
+ /**
+ * Returns true if the first applicable [KotlinCompilerReferenceIndexStorageProvider] reports that an index exists for [project].
+ */
+ internal fun hasIndex(project: Project): Boolean {
+ return KotlinCompilerReferenceIndexStorageProvider.getApplicableProvider(project)?.hasIndex(project) == true
}
}
-}
-
-private fun createKotlinDataReader(storagePath: Path): PersistentHashMap> = openReadOnlyPersistentHashMap(
- storagePath,
- EnumeratorStringDescriptor.INSTANCE,
- CollectionExternalizer(EnumeratorStringDescriptor.INSTANCE, ::SmartList),
-)
+}
\ No newline at end of file
diff --git a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerReferenceIndexStorageProvider.kt b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerReferenceIndexStorageProvider.kt
new file mode 100644
index 000000000000..989aa1791985
--- /dev/null
+++ b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerReferenceIndexStorageProvider.kt
@@ -0,0 +1,54 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.search.refIndex
+
+import com.intellij.openapi.extensions.ExtensionPointName
+import com.intellij.openapi.project.Project
+import org.jetbrains.annotations.ApiStatus
+
+/**
+ * Provider for [KotlinCompilerReferenceIndexStorage] implementations.
+ * The provider is responsible for checking whether it is applicable for a given project and, if it is the case,
+ * for creating a [KotlinCompilerReferenceIndexStorage] instance.
+ *
+ * Typically, there should be one implementation per build system that wants to offer Kotlin CRI capabilities.
+ *
+ * Implementations can register themselves via the `org.jetbrains.kotlin.kotlinCompilerReferenceIndexStorageProvider` EP.
+ */
+@ApiStatus.Experimental
+interface KotlinCompilerReferenceIndexStorageProvider {
+ /**
+ * Returns true if this provider can operate in the given [project] environment.
+ *
+ * The method should be fast and side‑effect free. It is called on the UI thread during provider selection.
+ */
+ fun isApplicable(project: Project): Boolean
+
+ /**
+ * Returns true iff the underlying index required by this provider exists for the given [project].
+ * Implementations should avoid heavy I/O here; a cheap existence/corruption check is sufficient.
+ */
+ fun hasIndex(project: Project): Boolean
+
+ /**
+ * Creates a new storage instance or returns null if storage cannot be created (e.g., index absent/corrupted).
+ *
+ * The [projectPath] is a base directory used by implementations that rely on relative paths persisted in the
+ * index. Implementations should perform any required light‑weight initialization here and delay heavy work if
+ * possible. The returned storage must be closed by the caller.
+ */
+ fun createStorage(project: Project, projectPath: String): KotlinCompilerReferenceIndexStorage?
+
+
+ companion object {
+ val EP_NAME: ExtensionPointName =
+ ExtensionPointName.create("org.jetbrains.kotlin.kotlinCompilerReferenceIndexStorageProvider")
+
+ /**
+ * Returns the first provider whose [isApplicable] returns true according to the EP registration order.
+ *
+ * To change precedence, adjust the `order` attribute in `intellij.kotlin.compilerReferenceIndex.xml`.
+ */
+ fun getApplicableProvider(project: Project): KotlinCompilerReferenceIndexStorageProvider? =
+ EP_NAME.extensionList.firstOrNull { it.isApplicable(project) }
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/ClassOneToManyStorage.kt b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsClassOneToManyStorage.kt
similarity index 73%
rename from plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/ClassOneToManyStorage.kt
rename to plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsClassOneToManyStorage.kt
index 3a8dcf4992a7..60a291fef87f 100644
--- a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/ClassOneToManyStorage.kt
+++ b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsClassOneToManyStorage.kt
@@ -1,8 +1,7 @@
-// Copyright 2000-2022 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 org.jetbrains.kotlin.idea.search.refIndex
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.search.refIndex.jps
import com.intellij.openapi.diagnostic.logger
-import com.intellij.openapi.util.IntellijInternalApi
import com.intellij.util.containers.generateRecursiveSequence
import com.intellij.util.io.EnumeratorStringDescriptor
import com.intellij.util.io.PersistentMapBuilder
@@ -14,8 +13,7 @@ import kotlin.io.path.deleteIfExists
import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.name
-@IntellijInternalApi
-class ClassOneToManyStorage(storagePath: Path) {
+internal class JpsClassOneToManyStorage(storagePath: Path) {
init {
val storageName = storagePath.name
storagePath.parent.listDirectoryEntries("$storageName*").ifNotEmpty {
@@ -25,9 +23,9 @@ class ClassOneToManyStorage(storagePath: Path) {
}
private val storage = PersistentMapBuilder.newBuilder(
- storagePath,
- EnumeratorStringDescriptor.INSTANCE,
- externalizer,
+ storagePath,
+ EnumeratorStringDescriptor.INSTANCE,
+ externalizer,
).build()
fun closeAndClean(): Unit = storage.closeAndClean()
@@ -42,12 +40,12 @@ class ClassOneToManyStorage(storagePath: Path) {
if (!deep) return values
return generateRecursiveSequence(values) {
- storage[it]?.asSequence() ?: emptySequence()
+ storage[it]?.asSequence() ?: emptySequence()
}
}
companion object {
private val externalizer = StringCollectionExternalizer>(::ArrayList)
- private val LOG = logger()
+ private val LOG = logger()
}
}
\ No newline at end of file
diff --git a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsKotlinCompilerReferenceIndexStorage.kt b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsKotlinCompilerReferenceIndexStorage.kt
new file mode 100644
index 000000000000..bf5a619bdd05
--- /dev/null
+++ b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsKotlinCompilerReferenceIndexStorage.kt
@@ -0,0 +1,143 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.search.refIndex.jps
+
+import com.intellij.openapi.diagnostic.logger
+import com.intellij.openapi.vfs.VfsUtil
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.util.SmartList
+import com.intellij.util.concurrency.AppExecutorUtil
+import com.intellij.util.containers.MultiMap
+import com.intellij.util.indexing.UnindexedFilesUpdater
+import com.intellij.util.io.CorruptedException
+import com.intellij.util.io.EnumeratorStringDescriptor
+import com.intellij.util.io.PersistentHashMap
+import org.jetbrains.annotations.TestOnly
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType
+import org.jetbrains.jps.builders.storage.BuildDataPaths
+import org.jetbrains.kotlin.idea.search.refIndex.KotlinCompilerReferenceIndexStorage
+import org.jetbrains.kotlin.incremental.KOTLIN_CACHE_DIRECTORY_NAME
+import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
+import org.jetbrains.kotlin.incremental.storage.CollectionExternalizer
+import org.jetbrains.kotlin.name.FqName
+import java.nio.file.Path
+import java.util.concurrent.Future
+import kotlin.collections.component1
+import kotlin.collections.component2
+import kotlin.io.path.forEachDirectoryEntry
+import kotlin.io.path.isDirectory
+import kotlin.io.path.notExists
+import kotlin.system.measureTimeMillis
+
+internal class JpsKotlinCompilerReferenceIndexStorageImpl(
+ private val lookupStorageReader: JpsLookupStorageReader,
+ private val subtypesStorage: JpsClassOneToManyStorage,
+) : KotlinCompilerReferenceIndexStorage {
+ companion object {
+ /**
+ * [org.jetbrains.kotlin.incremental.AbstractIncrementalCache.SUBTYPES]
+ */
+ internal val SUBTYPES_STORAGE_NAME = "subtypes.${BasicMapsOwner.CACHE_EXTENSION}"
+
+ private val STORAGE_INDEXING_EXECUTOR = AppExecutorUtil.createBoundedApplicationPoolExecutor(
+ "Kotlin compiler references indexing", UnindexedFilesUpdater.getMaxNumberOfIndexingThreads()
+ )
+
+ private val LOG = logger()
+ }
+
+ override fun getUsages(fqName: FqName): List =
+ lookupStorageReader[fqName].mapNotNull { VfsUtil.findFile(it, false) }
+
+ override fun getSubtypesOf(fqName: FqName, deep: Boolean): Sequence =
+ subtypesStorage[fqName, deep]
+
+ override fun close() {
+ lookupStorageReader.close()
+ subtypesStorage.closeAndClean()
+ }
+
+ private fun visitSubtypeStorages(buildDataPaths: BuildDataPaths, processor: (Path) -> Unit) {
+ for (buildTargetType in JavaModuleBuildTargetType.ALL_TYPES) {
+ val buildTargetPath = buildDataPaths.getTargetTypeDataRootDir(buildTargetType)
+ if (buildTargetPath.notExists() || !buildTargetPath.isDirectory()) continue
+ buildTargetPath.forEachDirectoryEntry { targetDataRoot ->
+ val workingPath = targetDataRoot.takeIf { it.isDirectory() }
+ ?.resolve(KOTLIN_CACHE_DIRECTORY_NAME)
+ ?.resolve(SUBTYPES_STORAGE_NAME)
+ ?.takeUnless { it.notExists() }
+ ?: return@forEachDirectoryEntry
+
+ processor(workingPath)
+ }
+ }
+ }
+
+ private fun initializeSubtypeStorage(buildDataPaths: BuildDataPaths, destination: JpsClassOneToManyStorage): Boolean {
+ var wasCorrupted = false
+ val destinationMap = MultiMap.createConcurrentSet()
+
+ val futures = mutableListOf>()
+ val timeOfFilling = measureTimeMillis {
+ visitSubtypeStorages(buildDataPaths) { storagePath ->
+ futures += STORAGE_INDEXING_EXECUTOR.submit {
+ try {
+ initializeStorage(destinationMap, storagePath)
+ } catch (e: CorruptedException) {
+ wasCorrupted = true
+ LOG.warn("KCRI storage was corrupted", e)
+ }
+ }
+ }
+
+ try {
+ for (future in futures) {
+ future.get()
+ }
+ } catch (e: InterruptedException) {
+ LOG.warn("KCRI initialization was interrupted")
+ throw e
+ }
+ }
+
+ if (wasCorrupted) return false
+
+ val timeOfFlush = measureTimeMillis {
+ for ((key, values) in destinationMap.entrySet()) {
+ destination.put(key, values)
+ }
+ }
+
+ LOG.info("KCRI storage is opened: took ${timeOfFilling + timeOfFlush} ms for ${futures.size} storages (filling map: $timeOfFilling ms, flush to storage: $timeOfFlush ms)")
+ return true
+ }
+
+ @TestOnly
+ fun initializeForTests(
+ buildDataPaths: BuildDataPaths,
+ destination: JpsClassOneToManyStorage,
+ ) = initializeSubtypeStorage(buildDataPaths, destination)
+
+ /**
+ * @return true if initialization was successful
+ */
+ internal fun initialize(buildDataPaths: BuildDataPaths): Boolean =
+ initializeSubtypeStorage(buildDataPaths, subtypesStorage)
+}
+
+private fun initializeStorage(destinationMap: MultiMap, subtypesSourcePath: Path) {
+ createKotlinDataReader(subtypesSourcePath).use { source ->
+ source.processKeys { key ->
+ source[key]?.let { values ->
+ destinationMap.putValues(key, values)
+ }
+
+ true
+ }
+ }
+}
+
+private fun createKotlinDataReader(storagePath: Path): PersistentHashMap> = openReadOnlyPersistentHashMap(
+ storagePath,
+ EnumeratorStringDescriptor.INSTANCE,
+ CollectionExternalizer(EnumeratorStringDescriptor.INSTANCE, ::SmartList),
+)
diff --git a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsKotlinCompilerReferenceIndexStorageProvider.kt b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsKotlinCompilerReferenceIndexStorageProvider.kt
new file mode 100644
index 000000000000..72ce24481fbb
--- /dev/null
+++ b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsKotlinCompilerReferenceIndexStorageProvider.kt
@@ -0,0 +1,61 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.search.refIndex.jps
+
+import com.intellij.compiler.server.BuildManager
+import com.intellij.openapi.diagnostic.logger
+import com.intellij.openapi.project.Project
+import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
+import org.jetbrains.jps.builders.storage.BuildDataPaths
+import org.jetbrains.kotlin.config.SettingConstants
+import org.jetbrains.kotlin.idea.search.refIndex.KotlinCompilerReferenceIndexStorage
+import org.jetbrains.kotlin.idea.search.refIndex.KotlinCompilerReferenceIndexStorageProvider
+import java.nio.file.Path
+import kotlin.io.path.exists
+import kotlin.io.path.isDirectory
+import kotlin.io.path.listDirectoryEntries
+
+internal class JpsKotlinCompilerReferenceIndexStorageProvider : KotlinCompilerReferenceIndexStorageProvider {
+ companion object {
+ private val LOG = logger()
+ }
+
+ override fun isApplicable(project: Project): Boolean {
+ val buildDataPaths = project.buildDataPaths
+ return buildDataPaths.kotlinDataContainer != null
+ }
+
+ override fun hasIndex(project: Project): Boolean {
+ return JpsLookupStorageReader.hasStorage(project)
+ }
+
+ override fun createStorage(project: Project, projectPath: String): KotlinCompilerReferenceIndexStorage? {
+ if (project.isDisposed) return null
+ val buildDataPaths = project.buildDataPaths
+ val kotlinDataContainerPath = buildDataPaths.kotlinDataContainer ?: run {
+ LOG.warn("${SettingConstants.KOTLIN_DATA_CONTAINER_ID} is not found")
+ return null
+ }
+
+ val lookupStorageReader = JpsLookupStorageReader.create(kotlinDataContainerPath, projectPath) ?: run {
+ LOG.warn("LookupStorage not found or corrupted")
+ return null
+ }
+ val classOneToManyStorage = JpsClassOneToManyStorage(
+ kotlinDataContainerPath.resolve(JpsKotlinCompilerReferenceIndexStorageImpl.SUBTYPES_STORAGE_NAME))
+
+
+ val storage = JpsKotlinCompilerReferenceIndexStorageImpl(lookupStorageReader, classOneToManyStorage)
+ if (!storage.initialize(buildDataPaths)) return null
+ return storage
+ }
+}
+
+internal val Project.buildDataPaths: BuildDataPaths
+ get() = BuildDataPathsImpl(BuildManager.getInstance().getProjectSystemDir(this))
+
+internal val BuildDataPaths.kotlinDataContainer: Path?
+ get() = targetsDataRoot
+ .resolve(SettingConstants.KOTLIN_DATA_CONTAINER_ID)
+ .takeIf { it.exists() && it.isDirectory() }
+ ?.listDirectoryEntries("${SettingConstants.KOTLIN_DATA_CONTAINER_ID}*")
+ ?.firstOrNull()
\ No newline at end of file
diff --git a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/LookupStorageReader.kt b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsLookupStorageReader.kt
similarity index 68%
rename from plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/LookupStorageReader.kt
rename to plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsLookupStorageReader.kt
index 1a84af44f3e9..76d917c9dece 100644
--- a/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/LookupStorageReader.kt
+++ b/plugins/kotlin/compiler-reference-index/src/org/jetbrains/kotlin/idea/search/refIndex/jps/JpsLookupStorageReader.kt
@@ -1,17 +1,27 @@
-// Copyright 2000-2022 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 org.jetbrains.kotlin.idea.search.refIndex
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.search.refIndex.jps
import com.intellij.openapi.project.Project
-import com.intellij.util.io.*
-import org.jetbrains.kotlin.idea.search.refIndex.KotlinCompilerReferenceIndexStorage.Companion.buildDataPaths
-import org.jetbrains.kotlin.idea.search.refIndex.KotlinCompilerReferenceIndexStorage.Companion.kotlinDataContainer
-import org.jetbrains.kotlin.incremental.storage.*
+import com.intellij.util.io.DataExternalizer
+import com.intellij.util.io.EnumeratorStringDescriptor
+import com.intellij.util.io.ExternalIntegerKeyDescriptor
+import com.intellij.util.io.KeyDescriptor
+import com.intellij.util.io.PersistentHashMap
+import com.intellij.util.io.PersistentMapBuilder
+import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
+import org.jetbrains.kotlin.incremental.storage.IntCollectionExternalizer
+import org.jetbrains.kotlin.incremental.storage.LookupSymbolKey
+import org.jetbrains.kotlin.incremental.storage.LookupSymbolKeyDescriptor
+import org.jetbrains.kotlin.incremental.storage.RelativeFileToPathConverter
import org.jetbrains.kotlin.name.FqName
import java.io.File
import java.nio.file.Path
+import kotlin.collections.mapNotNull
+import kotlin.collections.orEmpty
import kotlin.io.path.exists
-class LookupStorageReader private constructor(
+
+internal class JpsLookupStorageReader private constructor(
private val lookupStorage: PersistentHashMap>,
private val idToFileStorage: PersistentHashMap,
projectPath: String,
@@ -33,7 +43,7 @@ class LookupStorageReader private constructor(
}
companion object {
- fun create(kotlinDataContainerPath: Path, projectPath: String): LookupStorageReader? {
+ fun create(kotlinDataContainerPath: Path, projectPath: String): JpsLookupStorageReader? {
val lookupStoragePath = kotlinDataContainerPath.resolve(LOOKUP_STORAGE_NAME).takeIf { it.exists() } ?: return null
val idToFileStoragePath = kotlinDataContainerPath.resolve(ID_TO_FILE_STORAGE_NAME).takeIf { it.exists() } ?: return null
val lookupStorage = openReadOnlyPersistentHashMap(
@@ -48,7 +58,7 @@ class LookupStorageReader private constructor(
EnumeratorStringDescriptor.INSTANCE,
)
- return LookupStorageReader(lookupStorage, idToFileStorage, projectPath)
+ return JpsLookupStorageReader(lookupStorage, idToFileStorage, projectPath)
}
fun hasStorage(project: Project): Boolean = project.buildDataPaths