Repository: evant/kotlin-inject
Pull request #108 (2021-04-14 19:19:08)

Fix invalid variable naming for nested class types


Patch:
diff --git a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/CycleDetector.kt b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/CycleDetector.kt
index 45982de..c841088 100644
--- a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/CycleDetector.kt
+++ b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/CycleDetector.kt
@@ -37,7 +37,7 @@ class CycleDetector {
     fun <T> check(key: TypeKey, element: AstElement, block: (CycleResult) -> T): T {
         val cycleResult = if (entries.any { it is Entry.Element && it.value == element }) {
             if (entries.any { it is Entry.Delayed }) {
-                val name = key.type.simpleName.decapitalize()
+                val name = key.type.toVariableName()
                 resolving.add(Resolving(key, name))
                 CycleResult.Resolvable(name)
             } else {
diff --git a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/InjectGenerator.kt b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/InjectGenerator.kt
index 68e3b1c..90bf30a 100644
--- a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/InjectGenerator.kt
+++ b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/InjectGenerator.kt
@@ -7,6 +7,7 @@ import com.squareup.kotlinpoet.FunSpec
 import com.squareup.kotlinpoet.KModifier
 import com.squareup.kotlinpoet.PropertySpec
 import com.squareup.kotlinpoet.TypeSpec
+import java.util.Locale
 
 private const val ANNOTATION_PACKAGE_NAME = "me.tatarka.inject.annotations"
 val COMPONENT = ClassName(ANNOTATION_PACKAGE_NAME, "Component")
@@ -220,6 +221,10 @@ fun AstMethod.isProvider(): Boolean =
 fun AstClass.toInjectName(): String =
     "Inject${asClassName().simpleNames.joinToString("_")}"
 
+fun AstType.toVariableName(): String =
+    simpleName.split(".")
+        .joinToString("_") { it.decapitalize(Locale.US) }
+
 private fun dumpGraph(astClass: AstClass, entries: List<TypeResult.Provider>): String {
     val out = StringBuilder(astClass.name).append("\n")
     for (entry in entries) {
diff --git a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/TypeResultOptimizer.kt b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/TypeResultOptimizer.kt
index 76c1286..1a3d6b3 100644
--- a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/TypeResultOptimizer.kt
+++ b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/TypeResultOptimizer.kt
@@ -1,7 +1,5 @@
 package me.tatarka.inject.compiler
 
-import java.util.Locale
-
 @Suppress("NestedBlockDepth")
 fun List<TypeResult.Provider>.optimize(context: Context): List<TypeResult.Provider> {
     val newResults = mutableListOf<TypeResult.Provider>()
@@ -27,7 +25,7 @@ fun List<TypeResult.Provider>.optimize(context: Context): List<TypeResult.Provid
         val parents = parentMap[currentResult] ?: emptySet()
         if (currentResult !in visited && parents.size > 1 && currentResult.children.hasNext()) {
             var provider = find { it.result == ref }
-            val name = provider?.name ?: "_${key.type.simpleName.decapitalize(Locale.US)}"
+            val name = provider?.name ?: "_${key.type.toVariableName()}"
             val newResult = TypeResult.Provides(
                 className = context.className,
                 methodName = name,
diff --git a/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/KSAst.kt b/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/KSAst.kt
index 3b740b6..2f3b956 100644
--- a/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/KSAst.kt
+++ b/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/KSAst.kt
@@ -373,7 +373,7 @@ private class KSAstType(provider: KSAstProvider, val type: KSType) : AstType(),
         get() = type.declaration.simplePackageName()
 
     override val simpleName: String
-        get() = type.declaration.simpleName.asString()
+        get() = type.declaration.shortName
 
     override val annotations: List<AstAnnotation>
         get() = TODO("Not yet implemented")
diff --git a/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/Util.kt b/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/Util.kt
index 1281bd8..cd80132 100644
--- a/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/Util.kt
+++ b/kotlin-inject-compiler-ksp/src/main/kotlin/me/tatarka/inject/compiler/ksp/Util.kt
@@ -54,12 +54,17 @@ fun KSDeclaration.simplePackageName(): String {
 }
 
 fun KSDeclaration.asClassName(): ClassName {
-    val name = qualifiedName!!
     val packageName = simplePackageName()
-    val shortName = name.asString().removePrefix("$packageName.")
     return ClassName(packageName, shortName.split('.'))
 }
 
+val KSDeclaration.shortName: String
+    get() {
+        val name = qualifiedName!!
+        val packageName = packageName.asString()
+        return name.asString().removePrefix("$packageName.")
+    }
+
 fun KSType.asTypeName(): TypeName {
     val isFunction = isFunction()
     val isSuspending = isSuspendingFunction()


Test patch:
diff --git a/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/MultipleConstructionTest.kt b/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/MultipleConstructionTest.kt
index 24dac62..07ccd2d 100644
--- a/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/MultipleConstructionTest.kt
+++ b/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/MultipleConstructionTest.kt
@@ -2,6 +2,7 @@ package me.tatarka.inject.test
 
 import assertk.all
 import assertk.assertThat
+import assertk.assertions.any
 import assertk.assertions.containsOnly
 import assertk.assertions.hasSize
 import assertk.assertions.index
@@ -10,6 +11,7 @@ import assertk.assertions.isEqualTo
 import assertk.assertions.isNotNull
 import assertk.assertions.prop
 import me.tatarka.inject.annotations.Component
+import me.tatarka.inject.annotations.Inject
 import me.tatarka.inject.annotations.IntoSet
 import me.tatarka.inject.annotations.Provides
 import kotlin.reflect.KProperty1
@@ -18,11 +20,23 @@ import kotlin.reflect.full.declaredMemberProperties
 import kotlin.reflect.typeOf
 import kotlin.test.Test
 
+class Inner {
+    @Inject class Bar(val foo: Foo)
+}
+
+@Inject class Bar4(val bar: Inner.Bar)
+
+@Inject class Bar5(val bar: Inner.Bar)
+
 @Component
 abstract class CommonGetterComponent {
     abstract val bar2: Bar2
 
     abstract val bar3: Bar3
+
+    abstract val bar4: Bar4
+
+    abstract val bar5: Bar5
 }
 
 @Component
@@ -84,9 +98,12 @@ class MultipleConstructionTest {
         assertThat(component.bar2).isNotNull()
         assertThat(component.bar3).isNotNull()
         assertThat(privateProperties).apply {
-            hasSize(1)
-            index(0).all {
-                prop(KProperty1<*, *>::returnType).isEqualTo(typeOf<Bar>())
+            hasSize(2)
+            any { item ->
+                item.prop(KProperty1<*, *>::returnType).isEqualTo(typeOf<Bar>())
+            }
+            any { item ->
+                item.prop(KProperty1<*, *>::returnType).isEqualTo(typeOf<Inner.Bar>())
             }
         }
     }
diff --git a/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/ProvidesTest.kt b/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/ProvidesTest.kt
index 89ea89f..0530772 100644
--- a/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/ProvidesTest.kt
+++ b/integration-tests/common/src/test/kotlin/me/tatarka/inject/test/ProvidesTest.kt
@@ -269,4 +269,4 @@ class ProvidesTest {
 
         assertThat(component.fooFactory).isNotNull()
     }
-}
+}
\ No newline at end of file