Skip to content

CodeGeneration ver 0.7.2 to ver 0.8.0 #487

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
droideveloper opened this issue Apr 28, 2025 · 9 comments · Fixed by #489
Closed

CodeGeneration ver 0.7.2 to ver 0.8.0 #487

droideveloper opened this issue Apr 28, 2025 · 9 comments · Fixed by #489
Labels
bug Something isn't working

Comments

@droideveloper
Copy link

droideveloper commented Apr 28, 2025

Image
Image
code generation produce invalid dependency access in newer version you could see in the screen shots.

@evant evant added the bug Something isn't working label Apr 28, 2025
@evant
Copy link
Owner

evant commented Apr 28, 2025

Thanks for the report, if you can share a component graph that reproduces the issue that'd help a lot

@droideveloper
Copy link
Author

droideveloper commented Apr 29, 2025

sure here is graph classes

@FeatureScope
@Component
abstract class CityComponent(
    @Component val databaseComponent: DatabaseComponent,
    @Component val dataStoreComponent: DataStoreComponent,
)
@DataStoreScope
@Component
abstract class DataStoreComponent(
    @Component val parent: AppComponent,
    @get:DataStoreScope @get:Provides val dataStoreName: DataStoreName = DataStoreName.DefaultDataStore,
)

fun AppComponent.createDataStoreComponent(
    dataStoreName: DataStoreName = DataStoreName.DefaultDataStore
)
@DatabaseScope
@Component
abstract class DatabaseComponent(
    @Component val parent: AppComponent,
    @get:DatabaseScope @get:Provides val databaseName: DatabaseName = DatabaseName.DefaultDatabase,
)

fun AppComponent.createDatabaseComponent(
    databaseName: DatabaseName = DatabaseName.DefaultDatabase
)

CityComponent has functions in commonMain for @KmpComponentCreate

code screenshots I did share code generated for CityComponent, hope it helps, thanks.
ps: each component has Module interfaces that provide some binding but I believe they are not relevant, if they are I could share them too.

@droideveloper
Copy link
Author

From what I could see in new code generation is that tries to bind provided component dependencies from itself as it seems it looks for them with this@InjectCityComponent which looks like the main issue, hope it helps.

@asapha
Copy link
Contributor

asapha commented May 1, 2025

If you still need a graph, here's a simple one:

@Inject
class Repository(val http: Http)

@Inject
class RealHttp : Http

interface Http

@Component
abstract class AppComponent {
    @Provides
    fun provideRealHttp(): RealHttp = RealHttp()

    val RealHttp.bind: Http
        @Provides get() = this
}

@Component
abstract class ActivityComponent(
    @Component val appComponent: AppComponent,
) {
    abstract val repo: Repository
}

results in

e: […]InjectActivityComponent.kt:11:38 Unresolved reference 'provideRealHttp'.

public fun KClass<ActivityComponent>.create(appComponent: AppComponent): ActivityComponent = InjectActivityComponent(appComponent)

public class InjectActivityComponent(
  appComponent: AppComponent,
) : ActivityComponent(appComponent) {
  override val repo: Repository
    get() = Repository(
      http = with(appComponent) {
        this@InjectActivityComponent.provideRealHttp().bind
      }
    )
}

evant added a commit that referenced this issue May 2, 2025
@evant
Copy link
Owner

evant commented May 2, 2025

ok, have a branch with a failing test that reproduces the codegen issue.
I'll dig into it when I get a chance, but anyone feel free to take a look
d240906

@evant
Copy link
Owner

evant commented May 2, 2025

Looks like it has to do with the combination of receivers and parent bindings. In the meantime switching from a receiver to a function arg should work around it.
ex:

@Provides fun bindHttp(real: RealHttp): Http = real

instead of

val RealHttp.bind: Http
    @Provides get() = this

@evant
Copy link
Owner

evant commented May 3, 2025

I've merged in a fix, can you test by pointing to the snapshot version and see if it resolves this issue?

repositories {
    maven {
        uri("https://oss.sonatype.org/content/repositories/snapshots/")
    }
}

dependencies {
    ksp("me.tatarka.inject:kotlin-inject-compiler-ksp:0.8.1-SNAPSHOT")
}

@asapha
Copy link
Contributor

asapha commented May 3, 2025

@evant It works on my end, thanks!

@asapha
Copy link
Contributor

asapha commented May 4, 2025

Seems like we can trigger a variation of the bug when using @AssistedFactory

Repro

@Inject
class Repository(val http: Http, @Assisted val url: String) {
  @AssistedFactory
  fun interface Factory {
    operator fun invoke(url: String): Repository
  }
}

@Inject class RealHttp : Http

interface Http

@Component
abstract class AppComponent {
  abstract val repoFactory: Repository.Factory

  @Provides fun provideRealHttp(): RealHttp = RealHttp()

  val RealHttp.bind: Http
    @Provides get() = this
}

Generated code

public fun KClass<AppComponent>.create(): AppComponent = InjectAppComponent()

public class InjectAppComponent : AppComponent() {
  override val repoFactory: Repository.Factory
    get() = object : Repository.Factory {
      override fun invoke(url: String): Repository = Repository(
        http = this@InjectAppComponent.this@InjectAppComponent.provideRealHttp().bind,
        url = url
      )
    }
}

asapha added a commit to asapha/kotlin-inject that referenced this issue May 11, 2025
We'd get
foo = [email protected]@InjectAssistedFactoryComponent.provideFoo().bind

instead of
foo = [email protected]().bind

See evant#487 (comment)
asapha added a commit to asapha/kotlin-inject that referenced this issue May 11, 2025
We'd get
foo = [email protected]@InjectAssistedFactoryComponent.provideFoo().bind

instead of
foo = [email protected]().bind

See evant#487 (comment)
evant pushed a commit that referenced this issue May 11, 2025
We'd get
foo = [email protected]@InjectAssistedFactoryComponent.provideFoo().bind

instead of
foo = [email protected]().bind

See #487 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants