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() } } }