Skip to content

Releases: InsertKoinIO/koin-compiler-plugin

1.0.0-RC2

22 Apr 09:50

Choose a tag to compare

1.0.0-RC2 Pre-release
Pre-release

Koin Compiler Plugin 1.0.0-RC2

Stability pass on top of RC1: fixes user-reported crashes on iOS/Native, multi-module dex-merge collisions, and a module load-order behaviour change that makes app-level overrides actually win.

Requires: Kotlin 2.3.x+ (K2) | Koin 4.2.1+


What's New Since 1.0.0-RC1

Cross-module visibility

  • @Module + @ComponentScan without @Configuration now emits cross-module scan hints — previously scan-covered definitions were invisible to downstream compileSafety unless the module was also @Configuration. See PR #25.
  • @Single(binds = [...]) on @Module provider functions preserves binding metadata across module boundaries — consumers can now resolve interfaces bound via provider functions in a dependency JAR. See PR #23 / #22.

Fixes

  • Module load order (koin#2402) — auto-discovered @Configuration modules now load first and explicit @KoinApplication(modules = [...]) load last, so app-level overrides win over dependency defaults under Koin's last-wins semantics.
  • Duplicate call-site hint classes in multi-module Android builds (#20) — hint filenames are now prefixed with the compilation module identifier; no more org.koin.plugin.hints.XxxCallsiteKt collisions at dex merge.
  • Generic DSL types on iOS/Native (#18) — Kotlin/Native klib signature mangler no longer crashes on generic DSL types (single<Navigator<Key>>()). Hint emission erases type arguments to match runtime Koin's erasure behaviour.
  • Arrow Raise.bind() / ktor resourceScope { bind() } crash (#17) — collectBindType now matches Koin's bind by FqName, no longer intercepting unrelated library bind functions.
  • single<T> { create(::Impl) } with interface type parameter — the outer <T> is now registered as the provided type (previously Impl), so koin.get<Interface>() compile-safety passes as expected.
  • Missing DSL-artifact error (RC2.3) — @KoinViewModel / @KoinWorker without their runtime artifact (koin-core-viewmodel / koin-android-workmanager) now fails the build with a clear message pointing at the missing dependency, instead of silently producing a broken definition.
  • Unit-returning top-level @Singleton functions (RC2.2) — klib signature-clash fix; two qualified side-effect initializers no longer collide on iOS/JS/Wasm.
  • Custom qualifier annotations (RC2.1) — plain custom @Qualifier annotations now produce TypeQualifier, matching runtime named<T>() / typeQualifier<T>() semantics.

Documentation

Extended docs on module load order, generic DSL types (with the named<T>() qualifier pattern used by koin-compose-navigation3), and troubleshooting the new missing-artifact compile error.


Behaviour change to note when upgrading

Module load order: if your app declares @KoinApplication(modules = [AppModule::class]) and AppModule defines a binding that is also defined in a @Configuration-discovered dependency module, the app's binding now wins (previously, the dep overrode the app). This is the documented last-wins semantic applied correctly — but if you were relying on the previous behaviour, reorder via an explicit modules = [Dep::class, AppModule::class] list to control load order precisely.


Contributors

Code contributions this release:

Ongoing contributors (carried over from RC1):

  • Arnaud Giuliani — project lead
  • @JellyBrick — caching optimisations (PR #5), Gradle release signing fix
  • Kevin Chiu — Gradle plugin package fix
  • Youssef Shoaib — runtime annotations provider, build improvements

Issue reporters — the reproductions were excellent, thank you:

And Francois Dabonot (Kotzilla Slack), whose migration feedback drove the missing-artifact compile error introduced in RC2.3.


Full changelog

1.0.0-RC1

10 Apr 14:27

Choose a tag to compare

1.0.0-RC1 Pre-release
Pre-release

Koin Compiler Plugin 1.0.0-RC1

A native Kotlin Compiler Plugin for Koin dependency injection. Inline compile-time transformations — no generated Kotlin files to manage.

Replaces Koin Annotations (KSP) with a K2 compiler plugin that transforms DSL calls and processes annotations directly in the FIR/IR pipeline. Full Kotlin Multiplatform support.

Requires: Kotlin 2.3.x+ (K2) | Koin 4.2.1+


Features

DSL Transformations

Write idiomatic Koin DSL — the plugin resolves constructors at compile time.

DSL Call Description
single<T>(), factory<T>(), viewModel<T>(), worker<T>(), scoped<T>() Definition with automatic constructor resolution
create(::T) Constructor reference in scopes
startKoin<T>(), koinApplication<T>(), module<T>() Application and module loading
modules(vararg KClass) Multi-module loading

Annotations

Full annotation-driven DI as an alternative (or complement) to DSL.

Definitions — on classes, @Module functions, or top-level functions:
@Singleton, @Factory, @Scoped, @KoinViewModel, @KoinWorker

Modules:
@Module, @ComponentScan, @Configuration (with label-based grouping)

Parameters:
@Named, @Qualifier (string and type), @InjectedParam, @Property, @PropertyValue, @ScopeId, @Provided

Compile-Time Safety

Detect missing or mismatched dependencies at build time — not at runtime.

Level Scope
A1 Per-module: local definitions + explicit includes
A2 Configuration group: @Configuration siblings share definitions
A3 Full graph: all modules assembled via startKoin<T>()
A4 Call-site: get<T>(), inject<T>(), koinViewModel<T>()
B DSL modules: single<T>(), factory<T>() in hand-written modules
C Cross-module: definitions from dependency JARs via hint functions
D Properties: @Property/@PropertyValue key matching

Automatically skipped: nullable params, @InjectedParam, @Provided, @ScopeId, Scope params, default values, List<T>, Android framework types (Context, Application, SavedStateHandle, etc.)

Cross-Module Discovery

Definitions, qualifiers, scopes, and bindings propagate across Gradle modules via lightweight hint functions. No runtime reflection, no classpath scanning.

Kotlin Multiplatform

Full KMP support — JVM, JS, Wasm, Native. Dramatically simplified setup compared to the KSP-based approach (no per-target wiring).


What's New in 1.0.0-RC1

Since 0.6.2:

  • Fixed missing binding detection during compile-time safety validation

Since 0.4.x:

  • @ScopeId — inject dependencies from named or typed scopes
  • Scope parameter injection — pass the Koin scope receiver directly
  • @PropertyValue/@Property validation with warnings for missing defaults
  • @Provided annotation — mark types as externally available, skip safety validation
  • module<T>() and modules(vararg KClass) DSL interception
  • binds=[] respected to suppress auto-binding (#12)
  • Actualized IR return types for Wasm/JS targets (#11)
  • Performance: cached referenceFunctions, batched hint file generation

Getting Started

// build.gradle.kts
plugins {
    id("io.insert-koin.compiler.plugin") version "1.0.0-RC1"
}

koinCompiler {
    compileSafety = true        // Compile-time dependency validation (default)
    skipDefaultValues = true    // Use Kotlin defaults instead of DI resolution (default)
    unsafeDslChecks = true      // Validate create() lambda safety (default)
    userLogs = true             // Component detection logs
    debugLogs = false           // Verbose internal logs
}

Migrating from Koin Annotations (KSP)

  1. Replace ksp("io.insert-koin:koin-ksp-compiler:...") with the Gradle plugin above
  2. Remove ksp { } configuration blocks
  3. Delete generated *Module.kt files — the plugin transforms inline
  4. See the full Migration Guide for details

Contributors

  • Arnaud Giuliani — project lead
  • JellyBrick — caching optimizations (PR #5), Gradle release signing fix
  • Kevin Chiu — Gradle plugin package fix
  • Youssef Shoaib — runtime annotations provider, build improvements

0.6.2

03 Apr 17:16

Choose a tag to compare

Koin Compiler Plugin 0.6.2

Compatibility: Kotlin 2.3.20 · Koin 4.2.1-RC1

Bug Fixes

  • Fix #11 — WASM/JS type actualization — Actualize IR return types for generic Koin calls (Scope.get<T>(), getOrNull<T>(), inject<T>(), getAll<T>(), ParametersHolder.get<T>()). Prevents unbound IrTypeParameterSymbolImpl crashes on WASM/JS/Native targets. (3d9d2d8)

  • Fix #12 — Delegation pattern auto-binding — Respect binds = [] to suppress auto-binding. Classes using the delegation pattern (class Decorated(val delegate: MyService) : MyService) with @Singleton(binds = []) no longer cause recursive resolution stack overflows. (78f477c)

Performance

  • Cache referenceFunctions() lookups — Avoid repeated expensive compiler API calls across modules. Same CallableId queried N times → 1 real lookup + (N-1) O(1) cache hits.
  • Cache @Configuration module discoverydiscoverConfigurationModulesFromHints() results cached by label set. 10 modules with same labels → 1 discovery instead of 10.
  • Cache modulesByFqName map — Built once, reused across all module validations.
  • Batch hint IrFile creation — One IrFile per module instead of per definition, reducing synthetic file count from O(definitions) to O(modules).

Caching optimizations inspired by @JellyBrick (PR #5) 🙏

Compile Safety

  • Phase 3.6 guard — Cross-module call-site hint validation now only runs when a full graph has been assembled (via @KoinApplication). Prevents false positives in library modules without full graph visibility.

Build

  • Gradle signing fix — Only apply signing plugin when IS_RELEASE is set (PR #4).

0.6.1

30 Mar 16:56

Choose a tag to compare

0.6.1 Pre-release
Pre-release

Koin Compiler Plugin 0.6.1

Release date: 2026-03-30

New Features

module<T>() and modules(vararg KClass) APIs

Load @Module classes without referencing generated code directly. The compiler plugin intercepts these calls and transforms them at compile time. (#14)

startKoin {
    module<NetworkModule>()
    modules(DataModule::class, CacheModule::class)
}

Requires Koin 4.2.1-beta-1+

@ScopeId Parameter Support

Resolve dependencies from named Koin scopes. Generates getScope("id").get<T>(). Compile safety skips @ScopeId parameters. (#2)

@Factory
class ProfileService(@ScopeId(name = "user_session") val session: UserSession)
// Generates: ProfileService(scope.getScope("user_session").get())

@Provided on Parameters

Previously only worked on classes. Now also works on individual constructor parameters to skip compile safety for that specific parameter. (#7)

@Singleton
class MyService(@Provided val ctx: PlatformContext)

Scope Parameter Injection

Parameters of type org.koin.core.scope.Scope are automatically injected with the scope receiver. No annotation needed.

@Scoped
class ScopedService(val scope: Scope)
// Generates: ScopedService(scope)

@Property/@PropertyValue Validation

Warns at compile time when @Property("key") has no matching @PropertyValue("key") default.

@PropertyValue("api.timeout")
val defaultTimeout = 30

@Factory
class ApiClient(@Property("api.timeout") val timeout: Int)  // OK

@Factory
class Other(@Property("missing.key") val value: String)     // WARNING

DSL Compile Safety Improvements

  • Module reachability validation — Tracks which DSL modules are loaded via modules() and includes(). Reports compile errors for definitions in unreachable modules.
  • bind() operator support — Explicit bind(Interface::class) is now tracked for DSL definitions. Auto-binding of supertypes removed for DSL path (matches Koin runtime behavior).
  • create(::function) hints — Provider-only definitions from create(::function) now generate cross-module hints with providerOnly flag.
  • Qualifier propagation in DSL hints@Named, @Qualifier, and type qualifiers are now encoded in DSL cross-module hints.
  • Call-site detectionby inject() and by viewModel() property delegates in class bodies are now detected for A4 validation.

Bug Fixes

  • Fix qualifier propagation in function definition calls
  • Fix @Monitor tracing: warn if Kotzilla SDK library is missing
  • Fix DSL bind() not being tracked — removing bind now correctly triggers compile error
  • Fix create(::function) not producing cross-module DSL hints
  • Fix FIR module data null for external library types (e.g., DataStore, CoroutineDispatcher)
  • Fix cross-module qualifier encoding with dots in names

Breaking Changes

  • DSL auto-binding removed — DSL definitions (single<T>(), factory<T>()) no longer auto-bind to supertypes. Use explicit bind(Interface::class) to register secondary types. This matches Koin runtime behavior.

Compatibility

Dependency Version
Koin 4.2.1-beta-1+ (for module<T>() API), 4.2.0-RC2+ (for other features)
Kotlin 2.3.x+ (K2 compiler required)

Resolved Issues

  • #2@ScopeId unrecognized
  • #7@Provided still flagging missing dependencies
  • #14 — Generated .module() extension not recognized by IntelliJ (mitigated with module<T>() API)

0.4.0

12 Mar 17:08

Choose a tag to compare

0.4.0 Pre-release
Pre-release

Native Kotlin Compiler Plugin for Koin — K2 Required (Kotlin 2.3.x+) | Koin 4.2.0-RC2+

Highlights

Compile-Time Dependency Safety is the headline feature of 0.4.0. The plugin now validates your entire dependency graph at compile time, catching missing bindings before they become runtime crashes.

New Features

Compile-Time Safety Checks (compileSafety = true, on by default)

Multi-layered validation that progressively widens visibility:

  • A1 — Per-Module: validates definitions within a single @module plus its explicit includes
  • A2 — Configuration Groups: modules sharing a @configuration label are validated together
  • A3 — Full Graph (startKoin): validates the complete assembled graph when using @KoinApplication
  • A4 — Call-Site Validation: checks get(), inject(), and koinViewModel() call sites against the known graph
  • B — DSL Definitions: single(), factory(), etc. participate in the safety graph alongside annotation-based definitions
  • C — Cross-Gradle-Module: definitions from dependency JARs are discovered via hint functions
  • C2 — Full Hint Metadata: cross-module function hints now carry qualifier, scope, and binding information

Catches missing non-nullable dependencies, unresolved Lazy, qualifier mismatches, and cross-scope errors at compile time. Nullable params, @InjectedParam, @Property, List, and defaulted
parameters are safely skipped.

@provided Annotation

Mark types as externally available at runtime (e.g., platform types not declared as Koin definitions). Safety checks will skip them.

  @Provided
  class ExternalService  // provided by framework at runtime

  @Singleton
  class MyService(val ext: ExternalService)  // no error

Android Framework Whitelist

Common Android types are automatically whitelisted — no @provided needed:
Context, Activity, Application, Fragment, SavedStateHandle, WorkerParameters

@monitor Annotation

Function interception for logging and performance monitoring:

  @Monitor
  class MyService {
      fun fetchData(): Data { ... }  // calls intercepted with timing/logging
  }

skipDefaultValues Option (default: true)

Parameters with Kotlin default values are no longer injected from the DI container by default. Annotated and nullable parameters are still resolved normally.

  class Service(val a: A, val name: String = "default")
  single<Service>()
  // Generated: Service(scope.get())  — name uses Kotlin default

Incremental Compilation Support

Dirty marker / IC recompilation detection ensures the plugin cooperates correctly with Kotlin's incremental compilation.

KMP Improvements

  • Full hint function generation for JVM, JS, and Wasm targets
  • @deprecated(HIDDEN) on generated hints to avoid polluting IDE autocomplete
  • Fix for @configuration and @componentscan detection in multi-target builds
  • KLIB workaround extended to JS and Wasm targets

Configuration

  koinCompiler {
      compileSafety = true       // Compile-time dependency validation (default: true)
      unsafeDslChecks = true     // Validate create() is sole lambda instruction (default: true)
      skipDefaultValues = true   // Skip injection for defaulted params (default: true)
      userLogs = true            // Component detection logs
      debugLogs = true           // Verbose internal logs
  }

Compatibility

  • Kotlin: 2.3.x+ (K2 compiler required)
  • Koin: 4.2.0-RC2+