org.jetbrains.kotlin.fir.utils.ArrayMapOwner.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2020 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.utils
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
@RequiresOptIn
annotation class Protected
@OptIn(Protected::class)
abstract class AbstractArrayMapOwner {
// TODO: make [arrayMap] protected and remove annotation after KT-19306 fix
@get:Protected
abstract val arrayMap: ArrayMap
protected abstract val typeRegistry: TypeRegistry
abstract class AbstractArrayMapAccessor(
protected val key: KClass,
protected val id: Int
) {
protected fun extractValue(thisRef: AbstractArrayMapOwner): T? {
@Suppress("UNCHECKED_CAST")
return thisRef.arrayMap[id] as T?
}
}
protected abstract fun registerComponent(tClass: KClass, value: V)
}
class ArrayMapAccessor(
key: KClass,
id: Int
) : AbstractArrayMapOwner.AbstractArrayMapAccessor(key, id), ReadOnlyProperty, V> {
override fun getValue(thisRef: AbstractArrayMapOwner, property: KProperty<*>): T {
return extractValue(thisRef) ?: error("No '$key'($id) in array owner: $thisRef")
}
}
class NullableArrayMapAccessor(
key: KClass,
id: Int
) : AbstractArrayMapOwner.AbstractArrayMapAccessor(key, id), ReadOnlyProperty, V?> {
override fun getValue(thisRef: AbstractArrayMapOwner, property: KProperty<*>): T? {
return extractValue(thisRef)
}
}
abstract class TypeRegistry {
private val idPerType = ConcurrentHashMap, Int>()
private val idCounter = AtomicInteger(0)
fun generateAccessor(kClass: KClass): ArrayMapAccessor {
return ArrayMapAccessor(kClass, getId(kClass))
}
fun generateNullableAccessor(kClass: KClass): NullableArrayMapAccessor {
return NullableArrayMapAccessor(kClass, getId(kClass))
}
fun getId(kClass: KClass): Int {
return idPerType.computeIfAbsent(kClass) { idCounter.getAndIncrement() }
}
protected val indices: Collection
get() = idPerType.values
}