From 084404c3c430b761f12c3e95d0c7b870069f19ed Mon Sep 17 00:00:00 2001 From: "harry.tumalewa" Date: Sun, 26 Apr 2026 00:21:28 +0700 Subject: [PATCH] feat(runtime): Add enum overload for named qualifier --- stitch/api/stitch.api | 1 + .../com/harrytmthy/stitch/api/Qualifier.kt | 5 ++ .../com/harrytmthy/stitch/StitchTest.kt | 59 +++++++++++++++++++ .../com/harrytmthy/stitch/TestFixtures.kt | 2 + 4 files changed, 67 insertions(+) diff --git a/stitch/api/stitch.api b/stitch/api/stitch.api index 62f7243..6efb952 100644 --- a/stitch/api/stitch.api +++ b/stitch/api/stitch.api @@ -54,6 +54,7 @@ public abstract interface class com/harrytmthy/stitch/api/Qualifier { } public final class com/harrytmthy/stitch/api/QualifierKt { + public static final fun named (Ljava/lang/Enum;)Lcom/harrytmthy/stitch/api/Named; public static final fun named (Ljava/lang/String;)Lcom/harrytmthy/stitch/api/Named; public static final fun typed (Lkotlin/reflect/KClass;)Lcom/harrytmthy/stitch/api/Typed; } diff --git a/stitch/src/commonMain/kotlin/com/harrytmthy/stitch/api/Qualifier.kt b/stitch/src/commonMain/kotlin/com/harrytmthy/stitch/api/Qualifier.kt index 089d041..60dddb4 100644 --- a/stitch/src/commonMain/kotlin/com/harrytmthy/stitch/api/Qualifier.kt +++ b/stitch/src/commonMain/kotlin/com/harrytmthy/stitch/api/Qualifier.kt @@ -97,6 +97,11 @@ internal object QualifierManager { */ fun named(value: String): Named = QualifierManager.getOrCreate(value) +/** + * Returns a pooled [Named] qualifier for the given enum [value], creating one if it doesn't exist. + */ +fun named(value: Enum<*>): Named = QualifierManager.getOrCreate(value.name) + /** * Returns a pooled [Typed] qualifier for the given type, creating one if it doesn't exist. */ diff --git a/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/StitchTest.kt b/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/StitchTest.kt index b9e58ac..5491b30 100644 --- a/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/StitchTest.kt +++ b/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/StitchTest.kt @@ -22,6 +22,7 @@ import com.harrytmthy.stitch.api.dependsOn import com.harrytmthy.stitch.api.module import com.harrytmthy.stitch.api.named import com.harrytmthy.stitch.api.scope +import com.harrytmthy.stitch.api.typed import com.harrytmthy.stitch.exception.CycleException import com.harrytmthy.stitch.exception.MissingBindingException import com.harrytmthy.stitch.exception.ScopeClosedException @@ -844,4 +845,62 @@ class StitchTest { assertSame(fragmentScopedC.b, fragmentScopeInstance.get()) assertSame(activityScopeInstance.get(), Stitch.get()) } + + @Test + fun `named enum qualifier should resolve the same instance as its string equivalent`() { + module { + singleton(qualifier = named(Environment.Prod)) { Logger() } + }.register() + + val loggerFromEnum = Stitch.get(named(Environment.Prod)) + val loggerFromString = Stitch.get(named("Prod")) + assertSame(loggerFromEnum, loggerFromString) + } + + @Test + fun `named enum qualifiers with different values should not clash`() { + module { + singleton(qualifier = named(Environment.Prod)) { Logger() } + singleton(qualifier = named(Environment.Staging)) { Logger() } + }.register() + + val prodLogger = Stitch.get(named(Environment.Prod)) + val stagingLogger = Stitch.get(named(Environment.Staging)) + assertNotSame(prodLogger, stagingLogger) + } + + @Test + fun `typed qualifier should resolve the same instance across calls`() { + module { + singleton(qualifier = typed()) { Logger() } + }.register() + + val first = Stitch.get(typed()) + val second = Stitch.get(typed()) + assertSame(first, second) + } + + @Test + fun `default singleton and typed qualified singleton should not clash`() { + module { + singleton { Logger() } + singleton(qualifier = typed()) { Logger() } + }.register() + + val default = Stitch.get() + val typed = Stitch.get(typed()) + assertNotSame(default, typed) + } + + @Test + fun `typed and named qualifiers of same type should not clash`() { + module { + singleton(qualifier = typed()) { Logger() } + singleton(qualifier = named("Environment")) { Logger() } + }.register() + + val typedLogger = Stitch.get(typed()) + val namedLogger = Stitch.get(named("Environment")) + assertNotSame(typedLogger, namedLogger) + } } diff --git a/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/TestFixtures.kt b/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/TestFixtures.kt index 3e6e13f..6911c4c 100644 --- a/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/TestFixtures.kt +++ b/stitch/src/commonTest/kotlin/com/harrytmthy/stitch/TestFixtures.kt @@ -38,6 +38,8 @@ class C(val a: A, val b: B) class UsesLazyFactory(val barLazy: Lazy) class Bar +enum class Environment { Prod, Staging } + interface LifecycleTracker class ViewModelLifecycleTracker : LifecycleTracker class ActivityLifecycleTracker : LifecycleTracker