InsertKoinIO / InsertKoinIO/koin-compiler-plugin

@ScopeId can't resolve classes annotated with @Scoped and @Named

Open
#87 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status:checking 🤔 type:issue
Dominant language
Kotlin
Stars
82
Forks
15
Avg merge
1m
Merged PRs (30d)
1

Description

When using @ScopeId to retrieve classes annotated with @Scoped and @Named, Koin cannot resolve them. If the Koin tree contains a class that is not annotated with @Named, it will use that class instead of throwing an error.

Used Versions
compiler-plugin 1.1.0
koin-annotation 4.2.2

This works with ksp-plugin and koin-annotation 2.3.1.

Example

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Factory
import org.koin.core.annotation.Module
import org.koin.core.annotation.Named
import org.koin.core.annotation.Scope
import org.koin.core.annotation.ScopeId
import org.koin.core.annotation.Scoped
import org.koin.core.context.startKoin
import org.koin.core.qualifier.named
import org.koin.plugin.module.dsl.module
import org.koin.plugin.module.dsl.modules
import org.koin.test.junit5.ClosingKoinTest

const val scope = "testScope"
const val scopeId = "testScopeId"
const val named1 = "string1"
const val named2 = "string2"

@Factory
class UseCaseNamed(
    @ScopeId(name = scopeId)
    @Named(named1)
    val string1: String,
    @ScopeId(name = scopeId)
    @Named(named2)
    val string2: String,
)

@Module
@ComponentScan
class KoinModuleNamed {
    @Scope(name = scope)
    @Scoped
    @Named(named1)
    fun provideString1(): String = "String1"

    @Scope(name = scope)
    @Scoped
    @Named(named2)
    fun provideString2(): String = "String2"
}

@Factory
class UseCaseUnnamed(
    @ScopeId(name = scopeId)
    private val string: String,
)

@Module
@ComponentScan
class KoinModuleUnnamed {
    @Scope(name = scope)
    @Scoped
    fun provideStringUnnamed(): String = "StringUnnamed"
}

class KoinTest : ClosingKoinTest {

    @Test
    fun `scoped + named`() {
        startKoin {
            module<KoinModuleNamed>()
        }
        val scope = getKoin().createScope(scopeId, named(scope))

        // This works
        val string1: String = scope.get(named(named1))
        assertEquals("String1", string1)
        val string2: String = scope.get(named(named2))
        assertEquals("String2", string2)

        // No definition found for type 'java.lang.String' on scope '['testScopeId']'. Searched scopes: ['testScopeId'] -> [['_root_']].
        getKoin().get<UseCaseNamed>()
    }

    @Test
    fun `scoped + unnamed`() {
        startKoin {
            module<KoinModuleUnnamed>()
        }
        val scope = getKoin().createScope(scopeId, named(scope))

        // This works
        val stringUnnamed: String = scope.get()
        assertEquals("StringUnnamed", stringUnnamed)

        // This works
        getKoin().get<UseCaseUnnamed>()
    }

    @Test
    fun `scoped + both`() {
        startKoin {
            modules(KoinModuleNamed::class, KoinModuleUnnamed::class)
        }
        val scope = getKoin().createScope(scopeId, named(scope))

        // This works
        val string1: String = scope.get(named(named1))
        assertEquals("String1", string1)
        val string2: String = scope.get(named(named2))
        assertEquals("String2", string2)
        val stringUnnamed: String = scope.get()
        assertEquals("StringUnnamed", stringUnnamed)

        // This "works"
        val useCase = getKoin().get<UseCaseNamed>()

        // This fails: Expected <String1>, actual <StringUnnamed>.
        assertEquals("String1", useCase.string1)
        // This fails: Expected <String2>, actual <StringUnnamed>.
        assertEquals("String2", useCase.string2)
    }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the supplied KoinTest reproduction and run the three tests covering scoped and named dependencies with compiler-plugin 1.1.0 and koin-annotation 4.2.2. Trace how @ScopeId, @Scoped, and @Named are processed for UseCaseNamed, then add a regression test showing that named scoped values are injected correctly without falling back to the unnamed String; the existing assertions define done.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.