Skip to content

Commit

Permalink
Mainly reformat Set binding
Browse files Browse the repository at this point in the history
  • Loading branch information
romainbsl committed Nov 10, 2022
1 parent 7e01985 commit 996440a
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 46 deletions.
9 changes: 7 additions & 2 deletions kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt
@@ -1,7 +1,8 @@
@file:Suppress("FunctionName")

package org.kodein.di

import org.kodein.di.bindings.*
import org.kodein.di.internal.DIBuilderImpl
import org.kodein.di.internal.DIImpl
import org.kodein.type.TypeToken
import org.kodein.type.generic
Expand Down Expand Up @@ -292,7 +293,11 @@ public interface DI : DIAware {
* @param tag The tag to bind.
* @param overrides Whether this bind **must** or **must not** override an existing binding.
*/
public fun <T : Any> BindSet(tag: Any? = null, overrides: Boolean? = null, binding: DIBinding<*, *, T>)
public fun <T : Any> BindSet(
tag: Any? = null,
overrides: Boolean? = null,
binding: DIBinding<*, *, T>,
)

/**
* Starts the binding of a given type with a given tag.
Expand Down
37 changes: 32 additions & 5 deletions kodein-di/src/commonMain/kotlin/org/kodein/di/SetBindings.kt
Expand Up @@ -2,7 +2,11 @@

package org.kodein.di

import org.kodein.di.bindings.*
import org.kodein.di.bindings.ArgSetBinding
import org.kodein.di.bindings.DIBinding
import org.kodein.di.bindings.InSet
import org.kodein.di.bindings.SetBinding
import org.kodein.di.bindings.TypeBinderInSet
import org.kodein.type.TypeToken
import org.kodein.type.erasedComp
import org.kodein.type.generic
Expand All @@ -16,7 +20,11 @@ import org.kodein.type.generic
* @return A set binding ready to be bound.
*/
@Suppress("RemoveExplicitTypeArguments")
public inline fun <reified T: Any> DI.Builder.bindSet(tag: Any? = null, overrides: Boolean? = null): Unit = Bind(tag = tag, overrides = overrides, binding = SetBinding(TypeToken.Any, generic<T>(), erasedComp(Set::class, generic<T>()) as TypeToken<Set<T>>))
public inline fun <reified T : Any> DI.Builder.bindSet(tag: Any? = null, overrides: Boolean? = null): Unit = Bind(
tag = tag,
overrides = overrides,
binding = SetBinding(TypeToken.Any, generic<T>(), erasedComp(Set::class, generic<T>()) as TypeToken<Set<T>>)
)

/**
* Creates a set: multiple bindings can be added in this set.
Expand All @@ -28,7 +36,19 @@ public inline fun <reified T: Any> DI.Builder.bindSet(tag: Any? = null, override
* @return A set binding ready to be bound.
*/
@Suppress("RemoveExplicitTypeArguments")
public inline fun <reified A : Any, reified T: Any> DI.Builder.bindArgSet(tag: Any? = null, overrides: Boolean? = null): Unit = Bind(tag = tag, overrides = overrides, binding = ArgSetBinding(TypeToken.Any, generic<A>(), generic<T>(), erasedComp(Set::class, generic<T>()) as TypeToken<Set<T>>))
public inline fun <reified A : Any, reified T : Any> DI.Builder.bindArgSet(
tag: Any? = null,
overrides: Boolean? = null
): Unit = Bind(
tag = tag,
overrides = overrides,
binding = ArgSetBinding(
TypeToken.Any,
generic<A>(),
generic<T>(),
erasedComp(Set::class, generic<T>()) as TypeToken<Set<T>>
)
)

/**
* Defines that the binding will be saved in a set binding.
Expand All @@ -37,7 +57,8 @@ public inline fun <reified A : Any, reified T: Any> DI.Builder.bindArgSet(tag: A
*
* @param T The type of the binding.
*/
public inline fun <reified T: Any> DI.Builder.TypeBinder<T>.inSet(): TypeBinderInSet<T, Set<T>> = InSet(erasedComp(Set::class, generic<T>()) as TypeToken<Set<T>>)
public inline fun <reified T : Any> DI.Builder.TypeBinder<T>.inSet(): TypeBinderInSet<T, Set<T>> =
InSet(erasedComp(Set::class, generic<T>()) as TypeToken<Set<T>>)

/**
* Defines that the binding will be saved in a set binding.
Expand All @@ -46,4 +67,10 @@ public inline fun <reified T: Any> DI.Builder.TypeBinder<T>.inSet(): TypeBinderI
*
* @param T The type of the binding.
*/
public inline fun <reified T: Any> DI.Builder.inSet(tag: Any? = null, overrides: Boolean? = null, creator: () -> DIBinding<*, *, T>): Unit = BindSet(tag = tag, overrides = overrides, creator())
public inline fun <reified T : Any> DI.Builder.inSet(
tag: Any? = null,
overrides: Boolean? = null,
creator: () -> DIBinding<*, *, T>
): Unit {
BindSet(tag = tag, overrides = overrides, creator())
}
31 changes: 23 additions & 8 deletions kodein-di/src/commonMain/kotlin/org/kodein/di/bindings/set.kt
Expand Up @@ -11,7 +11,7 @@ import org.kodein.type.TypeToken
* @param A The argument type of all bindings in the set.
* @param T The provided type of all bindings in the set.
*/
public abstract class BaseMultiBinding<C : Any, A, T: Any> : DIBinding<C, A, Set<T>> {
public abstract class BaseMultiBinding<C : Any, A, T : Any> : DIBinding<C, A, Set<T>> {
internal abstract val set: MutableSet<DIBinding<C, A, T>>

override fun factoryName(): String = "bindingSet"
Expand All @@ -30,7 +30,12 @@ private class SetBindingDI<out C : Any>(private val _base: BindingDI<C>) : Bindi
* @param A The argument type of all bindings in the set.
* @param T The provided type of all bindings in the set.
*/
public class ArgSetBinding<C : Any, A, T: Any>(override val contextType: TypeToken<in C>, override val argType: TypeToken<in A>, private val _elementType: TypeToken<out T>, override val createdType: TypeToken<out Set<T>>) : BaseMultiBinding<C, A, T>() {
public class ArgSetBinding<C : Any, A, T : Any>(
override val contextType: TypeToken<in C>,
override val argType: TypeToken<in A>,
private val _elementType: TypeToken<out T>,
override val createdType: TypeToken<out Set<T>>
) : BaseMultiBinding<C, A, T>() {

override val set = LinkedHashSet<DIBinding<C, A, T>>()

Expand All @@ -41,7 +46,7 @@ public class ArgSetBinding<C : Any, A, T: Any>(override val contextType: TypeTok
val subKey = DI.Key(key.contextType, key.argType, _elementType, key.tag)
set.map { it.getFactory(subKey, SetBindingDI(di)) }
}.also { lateInitFactories = it }
factories.asSequence().map { it.invoke(arg) } .toSet()
factories.asSequence().map { it.invoke(arg) }.toSet()
}
}

Expand All @@ -58,7 +63,11 @@ public class ArgSetBinding<C : Any, A, T: Any>(override val contextType: TypeTok
* @param C The context type of all bindings in the set.
* @param T The provided type of all bindings in the set.
*/
public class SetBinding<C : Any, T: Any>(override val contextType: TypeToken<in C>, private val _elementType: TypeToken<out T>, override val createdType: TypeToken<out Set<T>>) : NoArgDIBinding<C, Set<T>>, BaseMultiBinding<C, Unit, T>() {
public class SetBinding<C : Any, T : Any>(
override val contextType: TypeToken<in C>,
private val _elementType: TypeToken<out T>,
override val createdType: TypeToken<out Set<T>>
) : NoArgDIBinding<C, Set<T>>, BaseMultiBinding<C, Unit, T>() {

@Suppress("UNCHECKED_CAST")
override val set = LinkedHashSet<DIBinding<C, Unit, T>>()
Expand Down Expand Up @@ -87,7 +96,10 @@ public class SetBinding<C : Any, T: Any>(override val contextType: TypeToken<in
*
* @param T The type of the binding in the set.
*/
public class TypeBinderInSet<in T : Any, S: Any> internal constructor(private val _binder: DI.Builder.TypeBinder<T>, private val _colTypeToken: TypeToken<S>) {
public class TypeBinderInSet<in T : Any, S : Any> internal constructor(
private val _binder: DI.Builder.TypeBinder<T>,
private val _colTypeToken: TypeToken<S>
) {

/**
* Second part of the `bind<Type>().inSet() with binding` syntax.
Expand All @@ -99,9 +111,11 @@ public class TypeBinderInSet<in T : Any, S: Any> internal constructor(private va
public infix fun <C : Any> with(binding: DIBinding<in C, *, out T>) {
_binder as DIBuilderImpl.TypeBinder
val setKey = DI.Key(binding.contextType, binding.argType, _colTypeToken, _binder.tag)
val setBinding = _binder.containerBuilder.bindingsMap[setKey]?.first() ?: throw IllegalStateException("No set binding to $setKey")
val setBinding = _binder.containerBuilder.bindingsMap[setKey]?.first()
?: throw IllegalStateException("No set binding to $setKey")

setBinding.binding as? BaseMultiBinding<C, *, T> ?: throw IllegalStateException("$setKey is associated to a ${setBinding.binding.factoryName()} while it should be associated with bindingSet")
setBinding.binding as? BaseMultiBinding<C, *, T>
?: throw IllegalStateException("$setKey is associated to a ${setBinding.binding.factoryName()} while it should be associated with bindingSet")

(setBinding.binding.set as MutableSet<DIBinding<*, *, *>>).add(binding)
}
Expand All @@ -116,4 +130,5 @@ public class TypeBinderInSet<in T : Any, S: Any> internal constructor(private va
* @param setTypeToken The type of the bound set.
*/
@Suppress("FunctionName")
public fun <T: Any> DI.Builder.TypeBinder<T>.InSet(setTypeToken: TypeToken<Set<T>>): TypeBinderInSet<T, Set<T>> = TypeBinderInSet(this, setTypeToken)
public fun <T : Any> DI.Builder.TypeBinder<T>.InSet(setTypeToken: TypeToken<Set<T>>): TypeBinderInSet<T, Set<T>> =
TypeBinderInSet(this, setTypeToken)
@@ -1,15 +1,26 @@
@file:Suppress("FunctionName")

package org.kodein.di.internal

import org.kodein.di.*
import org.kodein.di.bindings.*
import org.kodein.di.Copy
import org.kodein.di.DI
import org.kodein.di.DirectDI
import org.kodein.di.bindings.BaseMultiBinding
import org.kodein.di.bindings.ContextTranslator
import org.kodein.di.bindings.DIBinding
import org.kodein.di.bindings.ExternalSource
import org.kodein.di.bindings.InstanceBinding
import org.kodein.di.bindings.NoScope
import org.kodein.di.bindings.Provider
import org.kodein.di.bindings.Scope
import org.kodein.type.TypeToken
import org.kodein.type.erasedComp

internal open class DIBuilderImpl internal constructor(
private val moduleName: String?,
private val prefix: String,
internal val importedModules: MutableSet<String>,
override val containerBuilder: DIContainerBuilderImpl
private val moduleName: String?,
private val prefix: String,
internal val importedModules: MutableSet<String>,
override val containerBuilder: DIContainerBuilderImpl
) : DI.Builder {

override val contextType = TypeToken.Any
Expand All @@ -18,10 +29,19 @@ internal open class DIBuilderImpl internal constructor(

override val explicitContext: Boolean get() = false

inner class TypeBinder<T : Any> internal constructor(val type: TypeToken<out T>, val tag: Any?, val overrides: Boolean?) : DI.Builder.TypeBinder<T> {
inner class TypeBinder<T : Any> internal constructor(
val type: TypeToken<out T>,
val tag: Any?,
val overrides: Boolean?
) : DI.Builder.TypeBinder<T> {
internal val containerBuilder get() = this@DIBuilderImpl.containerBuilder

override infix fun <C : Any, A> with(binding: DIBinding<in C, in A, out T>) = containerBuilder.bind(DI.Key(binding.contextType, binding.argType, type, tag), binding, moduleName, overrides)
override infix fun <C : Any, A> with(binding: DIBinding<in C, in A, out T>) = containerBuilder.bind(
DI.Key(binding.contextType, binding.argType, type, tag),
binding,
moduleName,
overrides
)
}

/**
Expand All @@ -41,18 +61,28 @@ internal open class DIBuilderImpl internal constructor(
}
}

inner class DirectBinder internal constructor(private val _tag: Any?, private val _overrides: Boolean?) : DI.Builder.DirectBinder
inner class DirectBinder internal constructor(private val _tag: Any?, private val _overrides: Boolean?) :
DI.Builder.DirectBinder

inner class ConstantBinder internal constructor(private val _tag: Any, private val _overrides: Boolean?) : DI.Builder.ConstantBinder {
@Suppress("FunctionName")
override fun <T: Any> With(valueType: TypeToken<out T>, value: T) = Bind(tag = _tag, overrides = _overrides, binding = InstanceBinding(valueType, value))
inner class ConstantBinder internal constructor(private val _tag: Any, private val _overrides: Boolean?) :
DI.Builder.ConstantBinder {
override fun <T : Any> With(valueType: TypeToken<out T>, value: T) =
Bind(tag = _tag, overrides = _overrides, binding = InstanceBinding(valueType, value))
}

@Suppress("FunctionName")
override fun <T : Any> Bind(type: TypeToken<out T>, tag: Any?, overrides: Boolean?) = TypeBinder(type, tag, overrides)
override fun <T : Any> Bind(
type: TypeToken<out T>,
tag: Any?,
overrides: Boolean?
) = TypeBinder(type, tag, overrides)

@Suppress("FunctionName")
override fun <T : Any> Bind(tag: Any?, overrides: Boolean?, binding: DIBinding<*, *, T>) {
override fun <T : Any> Bind(
tag: Any?,
overrides: Boolean?,
binding: DIBinding<*, *, T>
) {
containerBuilder.bind(
key = DI.Key(binding.contextType, binding.argType, binding.createdType, tag = tag),
binding = binding,
Expand All @@ -61,17 +91,23 @@ internal open class DIBuilderImpl internal constructor(
)
}

@Suppress("UNCHECKED_CAST")
override fun <T : Any> BindSet(tag: Any?, overrides: Boolean?, binding: DIBinding<*, *, T>) {
@Suppress("unchecked_cast")
override fun <T : Any> BindSet(
tag: Any?,
overrides: Boolean?,
binding: DIBinding<*, *, T>,
) {
val setType = erasedComp(Set::class, binding.createdType) as TypeToken<Set<T>>
val setKey = DI.Key(binding.contextType, binding.argType, setType, tag)
val setBinding = containerBuilder.bindingsMap[setKey]?.first() ?: throw IllegalStateException("No set binding to $setKey")
val setBinding =
containerBuilder.bindingsMap[setKey]?.first() ?: throw IllegalStateException("No set binding to $setKey")

setBinding.binding as? BaseMultiBinding<*, *, T> ?: throw IllegalStateException("$setKey is associated to a ${setBinding.binding.factoryName()} while it should be associated with bindingSet")
(setBinding.binding.set as MutableSet<DIBinding<*, *, *>>).add(binding)
val multipleBinding =
setBinding.binding as? BaseMultiBinding<*, *, T>
?: throw IllegalStateException("$setKey is associated to a ${setBinding.binding.factoryName()} while it should be associated with bindingSet")
(multipleBinding.set as MutableSet<DIBinding<*, *, *>>).add(binding)
}

@Suppress("FunctionName")
override fun Bind(tag: Any?, overrides: Boolean?): DirectBinder = DirectBinder(tag, overrides)

override fun constant(tag: Any, overrides: Boolean?) = ConstantBinder(tag, overrides)
Expand All @@ -88,14 +124,19 @@ internal open class DIBuilderImpl internal constructor(
throw IllegalStateException("Module \"$moduleName\" has already been imported!")
}
importedModules += moduleName
DIBuilderImpl(moduleName, prefix + module.prefix, importedModules, containerBuilder.subBuilder(allowOverride, module.allowSilentOverride)).apply(module.init)
DIBuilderImpl(
moduleName,
prefix + module.prefix,
importedModules,
containerBuilder.subBuilder(allowOverride, module.allowSilentOverride)
).apply(module.init)
}

override fun importAll(modules: Iterable<DI.Module>, allowOverride: Boolean) =
modules.forEach { import(it, allowOverride) }
modules.forEach { import(it, allowOverride) }

override fun importAll(vararg modules: DI.Module, allowOverride: Boolean) =
modules.forEach { import(it, allowOverride) }
modules.forEach { import(it, allowOverride) }

override fun importOnce(module: DI.Module, allowOverride: Boolean) {
if (module.name.isEmpty())
Expand All @@ -106,11 +147,17 @@ internal open class DIBuilderImpl internal constructor(

override fun onReady(cb: DirectDI.() -> Unit) = containerBuilder.onReady(cb)

override fun RegisterContextTranslator(translator: ContextTranslator<*, *>) = containerBuilder.registerContextTranslator(translator)
override fun RegisterContextTranslator(translator: ContextTranslator<*, *>) =
containerBuilder.registerContextTranslator(translator)

}

internal open class DIMainBuilderImpl(allowSilentOverride: Boolean) : DIBuilderImpl(null, "", HashSet(), DIContainerBuilderImpl(true, allowSilentOverride, HashMap(), ArrayList(), ArrayList())), DI.MainBuilder {
internal open class DIMainBuilderImpl(allowSilentOverride: Boolean) : DIBuilderImpl(
null,
"",
HashSet(),
DIContainerBuilderImpl(true, allowSilentOverride, HashMap(), ArrayList(), ArrayList())
), DI.MainBuilder {

override val externalSources: MutableList<ExternalSource> = ArrayList()

Expand All @@ -123,9 +170,9 @@ internal open class DIMainBuilderImpl(allowSilentOverride: Boolean) : DIBuilderI
containerBuilder.extend(di.container, allowOverride, keys)
externalSources += di.container.tree.externalSources
importedModules.addAll(
containerBuilder.bindingsMap
.flatMap { it.value.map { it.fromModule } }
.filterNotNull()
containerBuilder.bindingsMap
.flatMap { it.value.map { it.fromModule } }
.filterNotNull()
)
}

Expand All @@ -135,9 +182,9 @@ internal open class DIMainBuilderImpl(allowSilentOverride: Boolean) : DIBuilderI
containerBuilder.extend(directDI.container, allowOverride, keys)
externalSources += directDI.container.tree.externalSources
importedModules.addAll(
containerBuilder.bindingsMap
.flatMap { it.value.map { it.fromModule } }
.filterNotNull()
containerBuilder.bindingsMap
.flatMap { it.value.map { it.fromModule } }
.filterNotNull()
)
}
}

0 comments on commit 996440a

Please sign in to comment.