Skip to content

Commit

Permalink
fix: fix generation of factories for injected Kotlin objects
Browse files Browse the repository at this point in the history
  • Loading branch information
outadoc committed Dec 6, 2022
1 parent 8c9c156 commit 3b76313
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.google.devtools.ksp.isPrivate
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.FunctionKind
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
Expand Down Expand Up @@ -277,6 +278,7 @@ class FactoryProcessor(
return ConstructorInjectionTarget(
sourceClass = parentClass,
scopeName = scopeName,
isObject = parentClass.classKind == ClassKind.OBJECT,
hasSingletonAnnotation = parentClass.isAnnotationPresent(Singleton::class),
hasReleasableAnnotation = parentClass.isAnnotationPresent(Releasable::class),
hasProvidesSingletonAnnotation = parentClass.isAnnotationPresent(ProvidesSingleton::class),
Expand Down Expand Up @@ -349,6 +351,7 @@ class FactoryProcessor(
return ConstructorInjectionTarget(
sourceClass = this,
scopeName = scopeName,
isObject = classKind == ClassKind.OBJECT,
hasSingletonAnnotation = isAnnotationPresent(Singleton::class),
hasReleasableAnnotation = isAnnotationPresent(Releasable::class),
hasProvidesSingletonAnnotation = isAnnotationPresent(ProvidesSingleton::class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,16 @@ internal class FactoryGenerator(
)
}

addStatement(
"return %T(%L)",
sourceClassName,
List(constructorInjectionTarget.parameters.size) { i -> "param${i + 1}" }
.joinToString(", ")
)
if (!constructorInjectionTarget.isObject) {
addStatement(
"return %T(%L)",
sourceClassName,
List(constructorInjectionTarget.parameters.size) { i -> "param${i + 1}" }
.joinToString(", ")
)
} else {
addStatement("return %T", sourceClassName)
}

if (constructorInjectionTarget.superClassThatNeedsMemberInjection != null) {
beginControlFlow(".apply")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import toothpick.compiler.common.generators.targets.VariableInjectionTarget
data class ConstructorInjectionTarget(
val sourceClass: KSClassDeclaration,
val scopeName: KSName?,
val isObject: Boolean,
val hasSingletonAnnotation: Boolean,
val hasReleasableAnnotation: Boolean,
val hasProvidesSingletonAnnotation: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,72 @@ class FactoryAndMemberInjectorTests {
"""
)

@Test
fun testAnObjectThatNeedsInjection_shouldHaveAFactoryThatInjectsIt_whenItHasAnInjectedField_kt() {
val source = ktSource(
"TestAnObjectThatNeedsInjection",
"""
package test
import javax.inject.Inject
object TestAnObjectThatNeedsInjection {
@Inject lateinit var s: String
}
"""
)

compilationAssert()
.that(source)
.processedWith(FactoryProcessorProvider(), MemberInjectorProcessorProvider())
.compilesWithoutError()
.generatesSources(
testAnObjectThatNeedsInjection_shouldHaveAFactoryThatInjectsIt_whenItHasAnInjectedField_expected
)
}

private val testAnObjectThatNeedsInjection_shouldHaveAFactoryThatInjectsIt_whenItHasAnInjectedField_expected =
expectedKtSource(
"test/TestAnObjectThatNeedsInjection__Factory",
"""
package test
import kotlin.Boolean
import kotlin.Suppress
import toothpick.Factory
import toothpick.MemberInjector
import toothpick.Scope
@Suppress(
"ClassName",
"RedundantVisibilityModifier",
)
public class TestAnObjectThatNeedsInjection__Factory : Factory<TestAnObjectThatNeedsInjection> {
private val memberInjector: MemberInjector<TestAnObjectThatNeedsInjection> =
TestAnObjectThatNeedsInjection__MemberInjector()
@Suppress("NAME_SHADOWING")
public override fun createInstance(scope: Scope): TestAnObjectThatNeedsInjection {
val scope = getTargetScope(scope)
return TestAnObjectThatNeedsInjection
.apply {
memberInjector.inject(this, scope)
}
}
public override fun getTargetScope(scope: Scope): Scope = scope
public override fun hasScopeAnnotation(): Boolean = false
public override fun hasSingletonAnnotation(): Boolean = false
public override fun hasReleasableAnnotation(): Boolean = false
public override fun hasProvidesSingletonAnnotation(): Boolean = false
public override fun hasProvidesReleasableAnnotation(): Boolean = false
}
"""
)

@Test
@Ignore("https://github.com/tschuchortdev/kotlin-compile-testing/issues/105")
fun testAInnerClassThatNeedsInjection_shouldHaveAFactoryThatInjectsIt_whenItHasAnInjectedField_java() {
Expand Down

0 comments on commit 3b76313

Please sign in to comment.