evant / kotlin-inject

Dependency injection lib for kotlin
Apache License 2.0
1.29k stars 60 forks source link

check for duplicate bindings between child and parent components #445

Closed hectorups closed 1 month ago

hectorups commented 1 month ago

Fixes issue #444

hectorups commented 1 month ago

@evant one of the integration test is failing after the changes to compile:

@Component abstract class ParentComponent {
    abstract val parentNamedFoo: NamedFoo

    @Provides
    protected fun foo() = NamedFoo("parent")

    val Foo.binds: IFoo
        @Provides get() = this
}

@Component abstract class SimpleChildComponent1(@Component val parent: ParentComponent) {
    abstract val namedFoo: NamedFoo

    val BarImpl.binds: IBar
        @Provides get() = this

    abstract val foo: IFoo
}

In this example the binding NamedFoo is provided by both the parent and child components, creating a situation we're trying to avoid. Currently, a type inside SimpleChildComponent1 that requires NamedFoo will receive the one from the parent. In my opinion, this is arbitrary and likely unwanted, especially in large projects with complex dependency graphs. We should enforce having only one type binding per dependency graph. If multiple bindings of the same type are necessary, qualifiers, type-aliases, or multibindings can be used.

evant commented 1 month ago

I don't see see how the type is provided multiple times in that example? Both should be getting an instance from @Provides protected fun foo() right?

hectorups commented 1 month ago

I don't see see how the type is provided multiple times in that example? Both should be getting an instance from @Provides protected fun foo() right?

👍 my mental model of Dagger, where Components don't use @Provides, caused my confusion.