InsertKoinIO / koin-annotations

Koin Annotations - About Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform insert-koin.io
https://insert-koin.io
Apache License 2.0
123 stars 30 forks source link

KOIN_CONFIG_CHECK fails with Missing Definition type on library module when it shouldn't #121

Open danielesegato opened 3 months ago

danielesegato commented 3 months ago

Describe the bug It is OK for library modules to have some Missing Definition, this shouldn't be checked by KOIN_CONFIG_CHECK, or at least it shouldn't be the default behavior.

To Reproduce

  1. Create a project a Library module (Android)
  2. setup koin annotation with ksp compiler
  3. In the Library module add this code
    
    package com.example

import org.koin.core.annotation.ComponentScan import org.koin.core.annotation.Factory import org.koin.core.annotation.Module

data class Config(val dummy: String)

@Factory class ExternallyConfigurableComponent( val config: Config ) { fun useConfig() { println(config.dummy) } }

@Module @ComponentScan("com.example") class MyModule

4. enable `KOIN_CONFIG_CHECK`

**Expected behavior**
this should compile.

**Actual behavior**
This fails with 

Task :lib:kspDebugKotlinAndroid FAILED w: [ksp] [Experimental] Koin Configuration Check w: [ksp] [Experimental] Koin Configuration Check e: [ksp] --> Missing Definition type 'com.example.Config' for 'com.example.ExternallyConfigurableComponent'. Fix your configuration to define type 'Config'. e: Error occurred in KSP, check log for detail

Koin project used and used version:

koin = "3.5.3"
koin-annotation = "1.3.1"

koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" }
koin-annotation = { module = "io.insert-koin:koin-annotations", version.ref = "koin-annotation" }
koin-annotation-compiler = { module = "io.insert-koin:koin-ksp-compiler", version.ref = "koin-annotation" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }

Additional informations If I have an Android Application depending on this it should be possible to define another module injecting Config. And this works perfectly fine if I disable the check.

You can try yourself by creating an android application depending on the library and injecting in the Application onCreate:

startKoin {
  androidContext(this@App)
  modules(
    module {
      factory { Config("foo") }
    },
    MyModule().module,
  )
}

and than injecting ExternallyConfigurableComponent and calling useConfig

it will print foo if you disable the check, and it will not compile if you enable the check.

Dagger / Hilt also works this way: you can inject from outside a module as long as it is not an application module.

Jadarma commented 2 months ago

Duplicate of #95. Since you provide the external dependency in the Koin DSL, which is runtime, the compiler check cannot verify it at build time, hence the error.

danielesegato commented 1 month ago

I made the example with a "config" class but how am I going to access the application android context, for instance, from a module with kotlin-annotation if the only way to inject that is from the application?

I know I can expose a method to create the module of my library that inject the context, however in a modularized app it is way more convenient if that's provided by the app and modules that needs it can access it in the android side of the code.

arnaudgiuliani commented 2 weeks ago

you can use context Android parameter as injected in your class. Koin annotations won't need to declare anything.