diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt index d7be8b91e7d..dd3184ddc6a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.util.PersistentSetMultimap import org.jetbrains.kotlin.name.Name class PersistentImplicitReceiverStack private constructor( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt index d4dd9312a77..fd89cf77da7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirVariable -import org.jetbrains.kotlin.fir.resolve.PersistentMultimap +import org.jetbrains.kotlin.fir.util.PersistentMultimap import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope import org.jetbrains.kotlin.fir.scopes.FirScope diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/ChainedIterator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/ChainedIterator.kt new file mode 100644 index 00000000000..dcebc1873db --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/ChainedIterator.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2021 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.fir.util + +class ChainedIterator(delegates: Collection>) : Iterator { + private var metaIterator = delegates.iterator() + private var currentIterator: Iterator? = null + + private fun promote() { + if (currentIterator?.hasNext() == true) return + while (metaIterator.hasNext()) { + currentIterator = metaIterator.next() + if (currentIterator!!.hasNext()) return + } + } + + override fun hasNext(): Boolean { + promote() + return currentIterator?.hasNext() == true + } + + override fun next(): T { + promote() + return currentIterator?.next() ?: throw NoSuchElementException() + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/Multimap.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/Multimap.kt new file mode 100644 index 00000000000..ce90a9568bc --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/Multimap.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2021 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.fir.util + +interface Multimap> { + operator fun get(key: K): C + operator fun contains(key: K): Boolean + val keys: Set + val values: Collection +} + +interface MutableMultimap> : Multimap { + fun put(key: K, value: V) + fun putAll(key: K, values: Collection) { + values.forEach { put(key, it) } + } + + fun remove(key: K, value: V) + fun removeKey(key: K) + + fun clear() +} + +abstract class BaseMultimap, MC : MutableCollection> : MutableMultimap { + private val map: MutableMap = mutableMapOf() + protected abstract fun createContainer(): MC + protected abstract fun createEmptyContainer(): C + + override fun get(key: K): C { + @Suppress("UNCHECKED_CAST") + return map[key] as C? ?: createEmptyContainer() + } + + override operator fun contains(key: K): Boolean { + return key in map + } + + override val keys: Set + get() = map.keys + + override val values: Collection + get() = object : AbstractCollection() { + override val size: Int + get() = map.values.sumBy { it.size } + + override fun iterator(): Iterator { + return ChainedIterator(map.values.map { it.iterator() }) + } + } + + override fun put(key: K, value: V) { + val container = map.getOrPut(key) { createContainer() } + container.add(value) + } + + override fun remove(key: K, value: V) { + val collection = map[key] ?: return + collection.remove(value) + if (collection.isEmpty()) { + map.remove(key) + } + } + + override fun removeKey(key: K) { + map.remove(key) + } + + override fun clear() { + map.clear() + } +} + +class SetMultimap : BaseMultimap, MutableSet>() { + override fun createContainer(): MutableSet { + return mutableSetOf() + } + + override fun createEmptyContainer(): Set { + return emptySet() + } +} + +class ListMultimap : BaseMultimap, MutableList>() { + override fun createContainer(): MutableList { + return mutableListOf() + } + + override fun createEmptyContainer(): List { + return emptyList() + } +} + +fun setMultimapOf(): SetMultimap = SetMultimap() +fun listMultimapOf(): ListMultimap = ListMultimap() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentMultimap.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/PersistentMultimap.kt similarity index 98% rename from compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentMultimap.kt rename to compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/PersistentMultimap.kt index 2d2961c3314..a38ac6bea2e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentMultimap.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/util/PersistentMultimap.kt @@ -3,7 +3,7 @@ * 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.fir.resolve +package org.jetbrains.kotlin.fir.util import kotlinx.collections.immutable.*