evant / kotlin-inject

Dependency injection lib for kotlin
Apache License 2.0
1.14k stars 51 forks source link

Combination of Lazy, circular dependencies, and Scopes results in invalid generated code #313

Closed dvolodin closed 3 weeks ago

dvolodin commented 8 months ago

A scoped component that provides a scoped class (Foo) with a Lazy and real dependency on another class (Bar), which in turn has a Lazy dependency on the first class, results in invalid generated code.

import me.tatarka.inject.annotations.Component
import me.tatarka.inject.annotations.Inject
import me.tatarka.inject.annotations.Scope

@Scope
annotation class CustomScope

@CustomScope
@Component
abstract class BaseComponent {
    abstract val foo: Foo
    abstract val bar: Bar
}

@CustomScope
@Inject
class Foo(
    val lazy: Lazy<Bar>,
    val real: Bar,
)

@Inject
class Bar(
    val foo: Lazy<Foo>
)

The resulting generated override for Foo is invalid:

import kotlin.reflect.KClass
import me.tatarka.inject.`internal`.LazyMap
import me.tatarka.inject.`internal`.ScopedComponent

public fun KClass<BaseComponent>.create(): BaseComponent = InjectBaseComponent()

public class InjectBaseComponent() : BaseComponent(), ScopedComponent {
  override val _scoped: LazyMap = LazyMap()

  override val foo: Foo
    get() = run<Foo> {
      lateinit var foo: Foo
      foo.also {
        foo = it
      }
    }

  override val bar: Bar
    get() = Bar(
      foo = lazy {
        foo
      }
    )
}