Skip to content

Koin KSP assigns definitions from other KSP processors to defaultModule #324

@vldi01

Description

@vldi01

Describe the bug
When a class containing Koin annotations (like @Single and @Named) is generated by a separate, custom KSP processor, the Koin KSP processor (koin-ksp-compiler) incorrectly assigns its definitions to the defaultModule.

This behavior does not occur if the exact same class is written manually in the source code.

The issue appears to be related to KSP processing rounds. When Koin's processor runs on the output of another processor (in a subsequent round), it seems to lose the context of the original module and falls back to the defaultModule.

This bug manifests even when defaultModule generation is disabled, resulting in fragmented and incorrect generated files:

  1. The intended module file (e.g., AppModule.kt) is generated but is empty.
  2. An empty KoinMeta.kt is generated.
  3. A partial DefaultModule.kt is generated, containing the definition that should have been in AppModule.kt.
  4. A second KoinMeta file is generated, mapping the class to the defaultModule.

To Reproduce
Steps to reproduce the behavior:

  1. Create a multi-module project.
  2. In a module (e.g., module-b), include koin-annotations and koin-ksp-compiler.
  3. Create a custom KSP processor that generates a new class file based on some other annotation (e.g., @Screen).
  4. Ensure this new, generated class file contains Koin annotations (e.g., @Single).
  5. Build the project.
  6. Observe the KSP-generated files (in build/generated/ksp/...). The definition from the generated class will be in a DefaultModule.kt file, not the module file for module-b.

I have a minimal reproduction repository available here:
https://github.com/vldi01/ModernKMPArchitecture

Expected behavior
The Koin KSP processor should treat a class generated by another KSP processor the same way it treats a manually written class.

The definitions from the generated class (e.g., BScreenInjector) should be correctly added to its own module's generated file (e.g., BModule.kt), not the defaultModule. Only two files should be generated for the module (the module definition and its KoinMeta file), just as with manually-written annotated classes.

Koin project used and used version (please complete the following information):

  • koin-bom: 4.1.1
  • koin-annotations: 2.3.0
  • kotlin: 2.2.21
  • kotlin-ksp: 2.3.0

Additional context
The core problem is the interoperability between KSP processors.

Working Example (Manual Class)

If I write this class manually in module-a, Koin works perfectly:

// In module 'a'
@Single
@Named(type = DestinationA::class)
class AScreenInjector : ScreenInjector {
    override fun getNavEntry(key: Destination): NavEntry<Destination>? {
        if (key !is DestinationA) return null

        return NavEntry(key) {
            AScreen(key, koinViewModel { parametersOf(key) })
        }
    }
}

Result: Koin generates AModule.kt (with the AScreenInjector singleton) and KoinMeta.kt.

Failing Example (Generated Class)

My custom processor generates this class in module-b:

// This class is generated by my custom KSP processor in module 'b'
@Single
@Named(type = DestinationB::class)
public class BScreenInjector : ScreenInjector {
  override fun getNavEntry(key: Destination): NavEntry<Destination>? {
    if (key !is DestinationB) return null

    return NavEntry(key) {
      BScreen()
    }
  }
}

Result: Koin generates four files:

  1. BModule.kt (empty)
  2. KoinMeta.kt (empty)
  3. DefaultModule.kt (containing the BScreenInjector singleton definition)
  4. KoinMeta_DefaultModule.kt (mapping BScreenInjector to the default module)

This strongly suggests the Koin processor isn't correctly identifying the source module for KSP-generated files from a previous round.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions