K2: Add ability identify DI components by string key instead of KClass

It allows having several the same typed-component in the container
This commit is contained in:
Denis.Zharkov
2023-01-04 11:14:15 +01:00
committed by Space Team
parent 58c1b5dd1f
commit dab50daf56
4 changed files with 37 additions and 18 deletions
@@ -24,6 +24,10 @@ abstract class FirSession @PrivateSessionConstructor constructor(
return generateAccessor(T::class) return generateAccessor(T::class)
} }
inline fun <reified T : FirSessionComponent> sessionComponentAccessor(id: String): ArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
return generateAccessor(id)
}
inline fun <reified T : FirSessionComponent> nullableSessionComponentAccessor(): NullableArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> { inline fun <reified T : FirSessionComponent> nullableSessionComponentAccessor(): NullableArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
return generateNullableAccessor(T::class) return generateNullableAccessor(T::class)
} }
@@ -38,6 +42,11 @@ abstract class FirSession @PrivateSessionConstructor constructor(
registerComponent(tClass, value) registerComponent(tClass, value)
} }
@SessionConfiguration
fun register(keyQualifiedName: String, value: FirSessionComponent) {
registerComponent(keyQualifiedName, value)
}
override fun toString(): String { override fun toString(): String {
val moduleData = nullableModuleData ?: return "Libraries session" val moduleData = nullableModuleData ?: return "Libraries session"
return "Source session for module ${moduleData.name}" return "Source session for module ${moduleData.name}"
@@ -19,7 +19,6 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
protected abstract val typeRegistry: TypeRegistry<K, V> protected abstract val typeRegistry: TypeRegistry<K, V>
abstract class AbstractArrayMapAccessor<K : Any, V : Any, T : V>( abstract class AbstractArrayMapAccessor<K : Any, V : Any, T : V>(
protected val key: KClass<out K>,
protected val id: Int protected val id: Int
) { ) {
protected fun extractValue(thisRef: AbstractArrayMapOwner<K, V>): T? { protected fun extractValue(thisRef: AbstractArrayMapOwner<K, V>): T? {
@@ -28,7 +27,11 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
} }
} }
protected abstract fun registerComponent(tClass: KClass<out K>, value: V) protected abstract fun registerComponent(keyQualifiedName: String, value: V)
protected fun registerComponent(tClass: KClass<out K>, value: V) {
registerComponent(tClass.qualifiedName!!, value)
}
final override fun iterator(): Iterator<V> = arrayMap.iterator() final override fun iterator(): Iterator<V> = arrayMap.iterator()
@@ -40,21 +43,20 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
} }
class ArrayMapAccessor<K : Any, V : Any, T : V>( class ArrayMapAccessor<K : Any, V : Any, T : V>(
key: KClass<out K>, private val keyQualifiedName: String,
id: Int, id: Int,
val default: T? = null val default: T? = null
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> { ) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> {
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T { override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T {
return extractValue(thisRef) return extractValue(thisRef)
?: default ?: default
?: error("No '$key'($id) in array owner: $thisRef") ?: error("No '$keyQualifiedName'($id) in array owner: $thisRef")
} }
} }
class NullableArrayMapAccessor<K : Any, V : Any, T : V>( class NullableArrayMapAccessor<K : Any, V : Any, T : V>(
key: KClass<out K>,
id: Int id: Int
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V?> { ) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V?> {
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T? { override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T? {
return extractValue(thisRef) return extractValue(thisRef)
} }
@@ -65,19 +67,27 @@ abstract class TypeRegistry<K : Any, V : Any> {
private val idCounter = AtomicInteger(0) private val idCounter = AtomicInteger(0)
fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>, default: T? = null): ArrayMapAccessor<K, V, T> { fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>, default: T? = null): ArrayMapAccessor<K, V, T> {
return ArrayMapAccessor(kClass, getId(kClass), default) return ArrayMapAccessor(kClass.qualifiedName!!, getId(kClass), default)
}
fun <T : V> generateAccessor(keyQualifiedName: String, default: T? = null): ArrayMapAccessor<K, V, T> {
return ArrayMapAccessor(keyQualifiedName, getId(keyQualifiedName), default)
} }
fun <T : V, KK : K> generateNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, T> { fun <T : V, KK : K> generateNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, T> {
return NullableArrayMapAccessor(kClass, getId(kClass)) return NullableArrayMapAccessor(getId(kClass))
} }
fun <KK : K> generateAnyNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, *> { fun <KK : K> generateAnyNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, *> {
return NullableArrayMapAccessor(kClass, getId(kClass)) return NullableArrayMapAccessor(getId(kClass))
} }
fun <T : K> getId(kClass: KClass<T>): Int { fun <T : K> getId(kClass: KClass<T>): Int {
return idPerType.customComputeIfAbsent(kClass.qualifiedName!!) { idCounter.getAndIncrement() } return getId(kClass.qualifiedName!!)
}
fun getId(keyQualifiedName: String): Int {
return idPerType.customComputeIfAbsent(keyQualifiedName) { idCounter.getAndIncrement() }
} }
/* /*
@@ -25,8 +25,8 @@ abstract class AttributeArrayOwner<K : Any, T : Any> protected constructor(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
constructor() : this(EmptyArrayMap as ArrayMap<T>) constructor() : this(EmptyArrayMap as ArrayMap<T>)
final override fun registerComponent(tClass: KClass<out K>, value: T) { final override fun registerComponent(keyQualifiedName: String, value: T) {
val id = typeRegistry.getId(tClass) val id = typeRegistry.getId(keyQualifiedName)
when (arrayMap.size) { when (arrayMap.size) {
0 -> { 0 -> {
arrayMap = OneElementArrayMap(value, id) arrayMap = OneElementArrayMap(value, id)
@@ -15,12 +15,12 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
final override val arrayMap: ArrayMap<V> = final override val arrayMap: ArrayMap<V> =
ArrayMapImpl() ArrayMapImpl()
final override fun registerComponent(tClass: KClass<out K>, value: V) { final override fun registerComponent(keyQualifiedName: String, value: V) {
val id = typeRegistry.getId(tClass) val id = typeRegistry.getId(keyQualifiedName)
try { try {
arrayMap[id] = value arrayMap[id] = value
} catch (e: Exception) { } catch (e: Exception) {
throw RuntimeException(createDiagnosticMessage(id, tClass), e) throw RuntimeException(createDiagnosticMessage(id, keyQualifiedName), e)
} }
} }
@@ -29,10 +29,10 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
return arrayMap[id] ?: error("No '$key'($id) component in array: $this") return arrayMap[id] ?: error("No '$key'($id) component in array: $this")
} }
private fun createDiagnosticMessage(id: Int, tClass: KClass<*>): String = buildString { private fun createDiagnosticMessage(id: Int, keyQualifiedName: String): String = buildString {
appendLine("Error occurred during registration of component in array") appendLine("Error occurred during registration of component in array")
appendLine("Currently registered") appendLine("Currently registered")
appendLine(" $id: $tClass") appendLine(" $id: $keyQualifiedName")
appendLine("Registrar:") appendLine("Registrar:")
for ((kClass, x) in typeRegistry.allValuesThreadUnsafeForRendering()) { for ((kClass, x) in typeRegistry.allValuesThreadUnsafeForRendering()) {
appendLine(" $x: $kClass") appendLine(" $x: $kClass")