Repository: evant/kotlin-inject
Pull request #61 (2020-09-17 23:04:48)

Allow annotating interfaces with @Component (#60)


Patch:
diff --git a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/Ast.kt b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/Ast.kt
index 7a6bda9..03da341 100644
--- a/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/Ast.kt
+++ b/kotlin-inject-compiler-core/src/main/kotlin/me/tatarka/inject/compiler/Ast.kt
@@ -195,7 +195,7 @@ abstract class AstParam : AstElement() {
 }
 
 enum class AstModifier {
-    PRIVATE, ABSTRACT
+    PRIVATE, ABSTRACT, INTERFACE
 }
 
 fun ParameterSpec.Companion.parametersOf(constructor: AstConstructor) =
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 2016c24..bab3bdd 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
@@ -1,16 +1,13 @@
 package me.tatarka.inject.compiler
 
-import com.squareup.kotlinpoet.ANY
 import com.squareup.kotlinpoet.ClassName
 import com.squareup.kotlinpoet.CodeBlock
 import com.squareup.kotlinpoet.FileSpec
 import com.squareup.kotlinpoet.FunSpec
 import com.squareup.kotlinpoet.KModifier
 import com.squareup.kotlinpoet.ParameterSpec
-import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
 import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.plusParameter
 import com.squareup.kotlinpoet.PropertySpec
-import com.squareup.kotlinpoet.STRING
 import com.squareup.kotlinpoet.TypeSpec
 import com.squareup.kotlinpoet.asClassName
 import me.tatarka.inject.annotations.Component
@@ -49,8 +46,12 @@ class InjectGenerator(provider: AstProvider, private val options: Options) :
 
         return TypeSpec.classBuilder("Inject${astClass.name}")
             .addOriginatingElement(astClass)
-            .superclass(astClass.asClassName())
             .apply {
+                if (AstModifier.INTERFACE in astClass.modifiers) {
+                    addSuperinterface(astClass.asClassName())
+                } else {
+                    superclass(astClass.asClassName())
+                }
                 if (scope != null) {
                     addSuperinterface(ClassName("me.tatarka.inject.internal", "ScopedComponent"))
                 }
diff --git a/kotlin-inject-compiler-kapt/src/main/kotlin/me/tatarka/inject/compiler/kapt/ModelAst.kt b/kotlin-inject-compiler-kapt/src/main/kotlin/me/tatarka/inject/compiler/kapt/ModelAst.kt
index acf8d8e..bcc549f 100644
--- a/kotlin-inject-compiler-kapt/src/main/kotlin/me/tatarka/inject/compiler/kapt/ModelAst.kt
+++ b/kotlin-inject-compiler-kapt/src/main/kotlin/me/tatarka/inject/compiler/kapt/ModelAst.kt
@@ -611,6 +611,9 @@ private fun collectModifiers(flags: Flags?): Set<AstModifier> {
     if (Flag.Common.IS_ABSTRACT(flags)) {
         result.add(AstModifier.ABSTRACT)
     }
+    if (Flag.Class.IS_INTERFACE(flags)) {
+        result.add(AstModifier.INTERFACE)
+    }
     return result
 }
 
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 cb0949f..caf5dad 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
@@ -176,7 +176,7 @@ private class KSAstClass(provider: KSAstProvider, override val declaration: KSCl
 
 private class KSAstConstructor(
     provider: KSAstProvider,
-    private val parent: AstClass,
+    parent: AstClass,
     override val declaration: KSFunctionDeclaration
 ) : AstConstructor(parent), KSAstAnnotated, KSAstProvider by provider {
 
@@ -404,5 +404,8 @@ private fun collectModifiers(declaration: KSDeclaration): Set<AstModifier> {
         if (declaration.isAbstract()) {
             add(AstModifier.ABSTRACT)
         }
+        if (declaration is KSClassDeclaration && declaration.classKind == ClassKind.INTERFACE) {
+            add(AstModifier.INTERFACE)
+        }
     }
 }


Test patch:
diff --git a/integration-tests/src/test/kotlin/me/tatarka/inject/test/ComponentTest.kt b/integration-tests/src/test/kotlin/me/tatarka/inject/test/ComponentTest.kt
index f51b71d..b8a7cf5 100644
--- a/integration-tests/src/test/kotlin/me/tatarka/inject/test/ComponentTest.kt
+++ b/integration-tests/src/test/kotlin/me/tatarka/inject/test/ComponentTest.kt
@@ -14,6 +14,10 @@ import kotlin.test.Test
     abstract val bar: Bar
 }
 
+@Component interface Component3 {
+    val bar: Bar
+}
+
 class ComponentTest {
 
     @Test
@@ -30,4 +34,12 @@ class ComponentTest {
         assertThat(component.bar).isNotNull()
         assertThat(component.bar.foo).isNotNull()
     }
+
+    @Test
+    fun generates_a_component_from_an_interface_that_provides_a_dep_with_an_argument() {
+        val component = Component3::class.create()
+
+        assertThat(component.bar).isNotNull()
+        assertThat(component.bar.foo).isNotNull()
+    }
 }
\ No newline at end of file