Project status, completed work, and future plans.
- Implement reified type parameter syntax
single<T>(),factory<T>(), etc. - Implement
Scope.create(::T)constructor reference syntax - Implement
worker<T>()DSL for Android WorkManager - Make
plugin-supporta full KMP library (all Koin targets, requires Koin 4.2.0-beta3+) - Create stub classes for ViewModel and ListenableWorker (avoid runtime dependencies)
- Gradle plugin auto-injects
koin-annotationsdependency (needs KMP support) - Move samples to separate folder for independent Kotlin version
- Add Kotlin 2.2.x workarounds (stdlib for JS/WASM, disable metadata compilation)
- Deprecate
org.koin.android.annotation.KoinViewModel - Implement
@Configurationcross-module discovery via hint functions - Fix KMP multi-phase FIR compilation (unique synthetic file names per class)
- Fix expect/actual class handling (skip expect classes in FIR)
- Fix K/Native synthetic file generation (skip on Native targets)
- Fix cross-source-set module resolution (fallback via context.referenceFunctions)
- Fix object module support (use irGetObject instead of constructor)
- Add configurable logging (userLogs for component detection, debugLogs for internal processing)
- Implement
koinConfiguration<T>()DSL transformation - Implement
KoinApplication.withConfiguration<T>()extension transformation - Implement
@PropertyValueannotation for property defaults - Support definition annotations on top-level functions (discovered by
@ComponentScan)
Prepared for public release on Maven Central.
- Review and finalize artifact coordinates
- Ensure proper module structure for publishing
- Add LICENSE file (Apache 2.0)
- Add README.md with usage instructions
- Configure
maven-publishplugin for all modules - Set up GPG signing for artifacts
- Configure Sonatype OSSRH credentials
- Add POM metadata (description, license, developers, SCM URLs)
- Publish artifacts:
compiler-plugin,gradle-plugin- Note:
plugin-supportis included in Koin (koin-annotations), not published separately
- Note:
- Register plugin ID on Gradle Plugin Portal
- Configure
java-gradle-pluginpublishing - Test plugin resolution via
plugins { id("io.insert-koin.compiler.plugin") }
- Set up GitHub Actions for CI (build, test)
- Automated release workflow (tag -> publish)
- Version management strategy (semver)
- Deferred: Will follow latest Kotlin versions and adapt as needed
- No complex versioning scheme required for now
Advanced features for production reliability.
Support default values for property injection:
-
@PropertyValue("key")annotation on constant - Generate
getProperty("key", defaultValue)calls
@PropertyValue("api.timeout")
val DEFAULT_TIMEOUT = 30000
@Factory
class ApiClient(@Property("api.timeout") val timeout: Int)
// Generates: factory { ApiClient(getProperty("api.timeout", DEFAULT_TIMEOUT)) }Skip DI injection for parameters with Kotlin default values:
-
skipDefaultValuesoption inkoinCompiler { }DSL (default:true) - Non-nullable parameters with defaults use Kotlin default value
- Nullable parameters still use
getOrNull()regardless - Annotated parameters (
@Named,@Qualifier, etc.) always injected - User log traces when parameters are skipped
class Service(val a: A, val name: String = "default")
single<Service>()
// With skipDefaultValues=true: Service(scope.get()) -- name uses default
// With skipDefaultValues=false: Service(scope.get(), scope.get())Detect missing dependencies at compile time instead of runtime crashes.
- Per-module validation (A1): local definitions + explicit includes
- Validate non-nullable parameters have definitions
- Validate
Lazy<T>inner type is provided - Validate
@Named/@Qualifierqualifiers match (with hints for mismatches) - Validate scoped dependencies are in correct scope
- Skip safe parameters: nullable,
@InjectedParam,@Property,List<T>, defaults - Clear error messages with module/parameter context
- Configuration group validation (A2):
@Configurationsibling modules share definitions - startKoin full-graph validation (A3): validates all modules assembled by
startKoin<T>() - Cross-Gradle-module validation (C): definitions from dependency JARs via hint functions
-
@Providedannotation: marks types as externally available, skips safety validation - Android framework whitelist:
Context,Activity,Application,Fragment,SavedStateHandle,WorkerParameters - Cross-module function hint metadata (C2): encode qualifier, scope, bindings in hint parameters
- Qualifier propagation:
@Named/@Qualifierviaqualifier_<name>orqualifierTypehint params - Scope propagation:
@Scope(MyScope::class)viascopehint parameter - Bindings propagation: return type supertypes via
binding0,binding1, ... hint params
- Qualifier propagation:
- DSL validation (B): validate
single<T>(),factory<T>()in hand-written modules - Call-site validation (A4): validates
get<T>(),inject<T>(),koinViewModel<T>()call sites with deferred cross-module hints - Cross-module custom qualifier discovery via qualifier hint functions
- See COMPILE_TIME_SAFETY.md for detailed design and implementation
Done:
- Package filtering: scan now matches both function's package and return type's package
Remaining for 1.0:
- Property validation (D):
@Property/@PropertyValuematching — see §2.7 -
@ScopeIdsupport — see §2.8 -
Scopeparameter injection — see §2.9
Function interception for logging and performance capture:
-
@Monitorannotation on class or function - Generate wrapper code to intercept function calls
- Log function entry/exit with parameters
- Capture execution time and performance metrics
- Integration with Koin's logging/monitoring API
@Monitor
class MyService {
fun fetchData(): Data { ... } // Calls will be intercepted
}
// Or on specific functions
class MyService {
@Monitor
fun fetchData(): Data { ... } // Only this function intercepted
}Allow enabling/disabling JSR-330 annotation support via Gradle property:
- Add
jsr330option tokoinCompiler { }DSL (default:true) - Pass option to compiler plugin via
CommandLineProcessor - Skip
jakarta.inject.*andjavax.inject.*annotation processing when disabled - Document in README
// build.gradle.kts
koinCompiler {
jsr330 = false // Disable jakarta.inject/javax.inject support
}Generate pre-populated HashMap for instant startup — see PREBUILT_INDEX.md.
- Design finalized (static KoinIndex, buildEntry, indexedModule)
- koin-core API additions (KoinIndex, buildEntry, indexedModule, loadIndex)
- Compiler: generate
buildKoinIndex { buildEntry(...) }instead ofmodule { buildSingle(...) } - Compiler: transform
startKoin<T>()to useloadIndex()/ map assignment - Unsafe DSL detection (hand-written lambdas → compiler error when
prebuiltIndex = true) -
prebuiltIndexGradle option (default:falsein 1.x,truein 2.x)
Validates that @Property("key") parameters have a corresponding @PropertyValue("key") default.
Emits a warning (not error) since properties can be set at runtime via properties().
-
PropertyValueRegistryalready collects@PropertyValue("key")registrations -
BindingRegistry.validatePropertyKeys(): warns for@Property("key")without matching@PropertyValue - Called from
CompileSafetyValidator.validate()after module validation - Box test:
property_value_ok— @PropertyValue matches @Property key
Supports @ScopeId annotation for injecting values from a named Koin scope.
Generates getScope("scopeId").get<T>(). Validation skips @ScopeId parameters.
-
KoinAnnotationFqNames.SCOPE_IDregistered -
QualifierExtractor.getScopeIdAnnotationName(): handles@ScopeId(MyScope::class)and@ScopeId(name = "id") -
ParameterAnalyzer: classifies asisScopeId = true -
KoinArgumentGenerator.createGetFromNamedScopeCall(): generatesscope.getScope("id").get<T>() -
Requirement.requiresValidation(): returns false forisScopeId - Box test:
scope_id_ok
@Factory
class ProfileService(@ScopeId(name = "user_session") val session: UserSession)
// Generates: ProfileService(scope.getScope("user_session").get<UserSession>())Constructor parameters of type org.koin.core.scope.Scope are injected with the scope receiver itself.
Compile safety validation automatically skips Scope parameters (can't statically validate dynamic lookups).
-
KoinArgumentGenerator: detect param typeorg.koin.core.scope.Scope→ passscopeReceiverdirectly -
ParameterAnalyzer: detect Scope type → skip validation (treated as implicitly@Provided) - Add tests (
scope_param_okbox test)
@Scoped
class ScopedService(val scope: Scope) {
fun dynamicLookup() = scope.get<SomeDep>() // Not validated at compile time
}Current approach: Follow latest Kotlin versions and adapt as needed. No complex versioning scheme required.
Background: Kotlin compiler plugins are not binary compatible across minor versions. A plugin compiled with Kotlin 2.2.21 won't work with Kotlin 2.3.x. If needed in the future, version-aligned releases (0.1.0-kotlin-2.2.21) can be implemented.