diff --git a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/util/SublistMerger.kt b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/util/SublistMerger.kt
new file mode 100644
index 00000000000..f36d32e3c9f
--- /dev/null
+++ b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/util/SublistMerger.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.analysis.providers.impl.util
+
+import org.jetbrains.kotlin.utils.addIfNotNull
+import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
+
+/**
+ * With each call to [merge], [SublistMerger] can merge all elements of a specific (reified) type into a single element using a supplied
+ * constructor and then add it to [destination]. Unmerged elements are added to [destination] using [finish].
+ *
+ * The purpose of [SublistMerger] is to merge multiple different types of elements from a single origin list without the need for
+ * intermediate list management and [partitionIsInstance] boilerplate.
+ */
+public class SublistMerger(
+ initialElements: List,
+ public val destination: MutableList,
+) {
+ public var remainingElements: List = initialElements
+
+ public inline fun merge(create: (List) -> A?) {
+ val (specificElements, remainingElements) = this.remainingElements.partitionIsInstance<_, R>()
+ destination.addIfNotNull(create(specificElements))
+ this.remainingElements = remainingElements
+ }
+
+ public fun finish() {
+ destination.addAll(remainingElements)
+ remainingElements = emptyList()
+ }
+}
+
+public fun List.mergeInto(destination: MutableList, f: SublistMerger.() -> Unit) {
+ SublistMerger(this, destination).apply {
+ f()
+ finish()
+ }
+}
+
+public fun List.mergeWith(f: SublistMerger.() -> Unit): List =
+ mutableListOf().also { destination -> mergeInto(destination, f) }
+
+public inline fun List.mergeOnly(crossinline create: (List) -> A?): List =
+ mergeWith { merge(create) }
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt
index 20285ab621f..b9b54e7ca53 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt
@@ -46,10 +46,9 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.scripting.compiler.plugin.FirScriptingSamWithReceiverExtensionRegistrar
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
-import org.jetbrains.kotlin.utils.addIfNotNull
-import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
+import org.jetbrains.kotlin.analysis.providers.impl.util.mergeInto
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
internal abstract class LLFirAbstractSessionFactory(protected val project: Project) {
@@ -503,29 +502,10 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
session: LLFirSession,
destination: MutableList,
) {
- SymbolProviderMerger(this, destination).apply {
+ mergeInto(destination) {
merge { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) }
merge { LLFirCombinedJavaSymbolProvider.merge(session, project, it) }
merge { LLFirCombinedSyntheticFunctionSymbolProvider.merge(session, it) }
- finish()
- }
- }
-
- private class SymbolProviderMerger(
- symbolProviders: List,
- private val destination: MutableList
- ) {
- private var remainingSymbolProviders = symbolProviders
-
- inline fun merge(create: (List) -> FirSymbolProvider?) {
- val (specificSymbolProviders, remainingSymbolProviders) = remainingSymbolProviders.partitionIsInstance<_, A>()
- destination.addIfNotNull(create(specificSymbolProviders))
- this.remainingSymbolProviders = remainingSymbolProviders
- }
-
- fun finish() {
- destination.addAll(remainingSymbolProviders)
- remainingSymbolProviders = emptyList()
}
}
}