Merge "Update KSP to 1.4.10-dev-experimental-20201110" into androidx-master-dev
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index bc2e12d..e78fdc2 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -74,7 +74,7 @@
"com.squareup:kotlinpoet-classinspector-elements:1.4.0"
const val KOTLIN_COMPILE_TESTING = "com.github.tschuchortdev:kotlin-compile-testing:1.3.1"
const val KOTLIN_COMPILE_TESTING_KSP = "com.github.tschuchortdev:kotlin-compile-testing-ksp:1.3.1"
-const val KSP_VERSION = "1.4.10-dev-experimental-20201009"
+const val KSP_VERSION = "1.4.10-dev-experimental-20201110"
const val KOTLIN_KSP_API = "com.google.devtools.ksp:symbol-processing-api:$KSP_VERSION"
const val KOTLIN_KSP = "com.google.devtools.ksp:symbol-processing:$KSP_VERSION"
const val KOTLIN_GRADLE_PLUGIN = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0-rc"
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
index be59f1a..ba27191 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
@@ -16,32 +16,20 @@
package androidx.room.compiler.processing.ksp
-import com.google.devtools.ksp.closestClassDeclaration
-import com.google.devtools.ksp.getAllSuperTypes
import com.google.devtools.ksp.processing.Resolver
-import com.google.devtools.ksp.symbol.KSClassDeclaration
-import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
-import com.google.devtools.ksp.symbol.KSName
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.google.devtools.ksp.symbol.KSType
-import com.google.devtools.ksp.symbol.KSTypeArgument
-import com.google.devtools.ksp.symbol.KSTypeParameter
import com.google.devtools.ksp.symbol.KSValueParameter
-import com.google.devtools.ksp.symbol.Nullability
/**
* Returns the type of a property as if it is member of the given [ksType].
- *
- * This is a temporary / inefficient implementation until KSP provides the API. It also does not
- * handle inner classes properly.
- * TODO: remove once https://github.com/android/kotlin/issues/26 is implemented
*/
internal fun KSPropertyDeclaration.typeAsMemberOf(resolver: Resolver, ksType: KSType): KSType {
- val myType: KSType = checkNotNull(type.resolve()) {
- "Cannot find type of Kotlin property: $this"
- }
- return myType.asMemberOf(resolver, this, ksType)
+ return resolver.asMemberOf(
+ property = this,
+ containing = ksType
+ )
}
internal fun KSValueParameter.typeAsMemberOf(
@@ -49,102 +37,22 @@
functionDeclaration: KSFunctionDeclaration,
ksType: KSType
): KSType {
- val myType: KSType = checkNotNull(type?.resolve()) {
- "Cannot find type of method parameter: $this"
- }
- return myType.asMemberOf(resolver, functionDeclaration, ksType)
+ val asMember = resolver.asMemberOf(
+ function = functionDeclaration,
+ containing = ksType
+ )
+ // TODO b/173224718
+ // this is counter intuitive, we should remove asMemberOf from method parameters.
+ val myIndex = functionDeclaration.parameters.indexOf(this)
+ return asMember.parameterTypes[myIndex] ?: type.resolve()
}
internal fun KSFunctionDeclaration.returnTypeAsMemberOf(
resolver: Resolver,
ksType: KSType
): KSType {
- val myType: KSType = checkNotNull(returnType?.resolve()) {
- "Cannot resolve return type of $this"
- }
- return myType.asMemberOf(resolver, this, ksType)
-}
-
-/**
- * Returns `this` type as member of the [other] type.
- *
- * @param resolver The KSP resolver instance
- * @param declaration The KSDeclaration where the owner of this type is defined. Note that this can
- * be different from [KSType.declaration]. For instance, if you have a class `Foo<T>` with property
- * `x : List<T>`, `x`'s type declaration is `kotlin.List` whereas the declaration that
- * should be passed here is `x` (from which the implementation will find `Foo`). On the other hand,
- * `T` of `List<T>`'s declaration is already in `Foo`.
- * @param other The new owner for this type. For instance, if you want to resolve `x` in
- * `Bar<String>`, this would be the star projected type of `Bar`.
- */
-internal fun KSType.asMemberOf(
- resolver: Resolver,
- declaration: KSDeclaration,
- other: KSType
-): KSType {
- val parent = declaration.closestClassDeclaration() ?: return this
- val parentQName = parent.qualifiedName ?: return this
- val matchingParentType: KSType = (other.declaration as? KSClassDeclaration)
- ?.getAllSuperTypes()
- ?.firstOrNull {
- it.starProjection().declaration.qualifiedName == parentQName
- } ?: return this
- // create a map of replacements.
- val replacements = parent.typeParameters.mapIndexed { index, ksTypeParameter ->
- ksTypeParameter.name to matchingParentType.arguments.getOrNull(index)
- }.toMap()
- return replaceFromMap(resolver, replacements)
-}
-
-private fun KSTypeArgument.replaceFromMap(
- resolver: Resolver,
- arguments: Map<KSName, KSTypeArgument?>
-): KSTypeArgument {
- val resolvedType = type?.resolve()
- val myTypeDeclaration = resolvedType?.declaration
- if (myTypeDeclaration is KSTypeParameter) {
- val match = arguments[myTypeDeclaration.name] ?: return this
- // workaround for https://github.com/google/ksp/issues/82
- val explicitNullable = resolvedType.makeNullable() == resolvedType
- return if (explicitNullable) {
- match.makeNullable(resolver)
- } else {
- match
- }
- }
- return this
-}
-
-private fun KSType.replaceFromMap(
- resolver: Resolver,
- arguments: Map<KSName, KSTypeArgument?>
-): KSType {
- val myDeclaration = this.declaration
- if (myDeclaration is KSTypeParameter) {
- val match = arguments[myDeclaration.name]?.type?.resolve() ?: return this
- // workaround for https://github.com/google/ksp/issues/82
- val explicitNullable = this.makeNullable() == this
- return if (explicitNullable) {
- match.makeNullable()
- } else {
- match
- }
- }
- if (this.arguments.isEmpty()) {
- return this
- }
- return replace(
- this.arguments.map {
- it.replaceFromMap(resolver, arguments)
- }
- )
-}
-
-private fun KSTypeArgument.makeNullable(resolver: Resolver): KSTypeArgument {
- val myType = type
- val resolved = myType?.resolve() ?: return this
- if (resolved.nullability == Nullability.NULLABLE) {
- return this
- }
- return resolver.getTypeArgument(myType.swapResolvedType(resolved.makeNullable()), variance)
+ return resolver.asMemberOf(
+ function = this,
+ containing = ksType
+ ).returnType ?: returnType?.resolve() ?: error("cannot find return type for $this")
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
index 4e308fb..edfd964 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
@@ -30,12 +30,22 @@
) : XAnnotationBox<T> {
override fun getAsType(methodName: String): XType? {
val value = getFieldValue<KSType>(methodName)
- return value?.let(env::wrapDeclared)
+ return value?.let {
+ env.wrap(
+ ksType = it,
+ allowPrimitives = true
+ )
+ }
}
override fun getAsTypeList(methodName: String): List<XType> {
val values = getFieldValue<List<KSType>>(methodName) ?: return emptyList()
- return values.map(env::wrapDeclared)
+ return values.map {
+ env.wrap(
+ ksType = it,
+ allowPrimitives = true
+ )
+ }
}
override fun <R : Annotation> getAsAnnotationBox(methodName: String): XAnnotationBox<R> {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt
index 579d447..7831603 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt
@@ -51,8 +51,9 @@
val arg = ksType.arguments.single()
// https://kotlinlang.org/docs/reference/basic-types.html#primitive-type-arrays
// these are always boxed
- env.wrapDeclared(
- checkNotNull(arg.type?.resolve())
+ env.wrap(
+ ksType = checkNotNull(arg.type?.resolve()),
+ allowPrimitives = false
)
}
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
index c0d0099..629d421 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -23,7 +23,6 @@
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.METHOD_PARAMETER
import com.google.devtools.ksp.symbol.KSValueParameter
-import com.google.devtools.ksp.symbol.Origin
internal class KspExecutableParameterElement(
val env: KspProcessingEnv,
@@ -40,22 +39,16 @@
get() = parameter.name?.asString() ?: "_no_param_name"
override val type: XType by lazy {
- val paramType = parameter.typeAsMemberOf(
+ parameter.typeAsMemberOf(
resolver = env.resolver,
functionDeclaration = method.declaration,
ksType = method.containing.declaration.asStarProjectedType()
).let {
env.wrap(
- originatingReference = parameter.type!!, // as member of doesn't allow nulls
+ originatingReference = parameter.type,
ksType = it
)
}
- // if vararg and kotlin source, wrap in an array because thats how it is represented in java
- if (parameter.isVararg && parameter.origin == Origin.KOTLIN) {
- env.getArrayType(paramType)
- } else {
- paramType
- }
}
override fun asMemberOf(other: XDeclaredType): XType {
@@ -69,7 +62,7 @@
ksType = other.ksType
).let {
env.wrap(
- originatingReference = parameter.type!!, // as member of doesn't allow nulls
+ originatingReference = parameter.type,
ksType = it
)
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
index ab01a0b..6088fcc 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
@@ -65,7 +65,6 @@
}
override fun hasKotlinDefaultImpl(): Boolean {
- // see https://github.com/google/ksp/issues/32
val parentDeclaration = declaration.parentDeclaration
// if parent declaration is an interface and we are not marked as an abstract method,
// we should have a default implementation
@@ -114,7 +113,10 @@
override fun isSuspendFunction() = true
override val returnType: XType by lazy {
- env.wrapDeclared(env.resolver.builtIns.anyType.makeNullable())
+ env.wrap(
+ ksType = env.resolver.builtIns.anyType.makeNullable(),
+ allowPrimitives = false
+ )
}
override val parameters: List<XExecutableParameterElement>
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
index cab8045..0ce3d78 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
@@ -70,12 +70,13 @@
get() = origin.returnType
override fun getSuspendFunctionReturnType(): XType {
- // suspend functions work w/ continuation so it is always declared
- return env.wrapDeclared(
+ // suspend functions work w/ continuation so it is always boxed
+ return env.wrap(
ksType = origin.declaration.returnTypeAsMemberOf(
resolver = env.resolver,
ksType = containing.ksType
- )
+ ),
+ allowPrimitives = false
)
}
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspPrimitiveType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspPrimitiveType.kt
index 6a4f357..29fed31 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspPrimitiveType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspPrimitiveType.kt
@@ -36,6 +36,9 @@
get() = ksType.typeName(env.resolver).tryUnbox()
override fun boxed(): XType {
- return env.wrapDeclared(ksType)
+ return env.wrap(
+ ksType = ksType,
+ allowPrimitives = false
+ )
}
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
index e90169b..41cd7e2 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
@@ -16,7 +16,6 @@
package androidx.room.compiler.processing.ksp
-import androidx.room.compiler.processing.XDeclaredType
import androidx.room.compiler.processing.XFiler
import androidx.room.compiler.processing.XMessager
import androidx.room.compiler.processing.XProcessingEnv
@@ -92,7 +91,7 @@
?: findTypeElement("javax.annotation.Generated")
}
- override fun getDeclaredType(type: XTypeElement, vararg types: XType): XDeclaredType {
+ override fun getDeclaredType(type: XTypeElement, vararg types: XType): KspDeclaredType {
check(type is KspTypeElement) {
"Unexpected type element type: $type"
}
@@ -105,9 +104,14 @@
variance = Variance.INVARIANT
)
}
- return wrapDeclared(
- type.declaration.asType(typeArguments)
+ val result = wrap(
+ ksType = type.declaration.asType(typeArguments),
+ allowPrimitives = false
)
+ check(result is KspDeclaredType) {
+ "Expected $type to be a declared type but a non-declared type ($result) is received"
+ }
+ return result
}
override fun getArrayType(type: XType): KspArrayType {
@@ -116,18 +120,6 @@
}
/**
- * Wraps the given `ksType` as a [KspDeclaredType].
- * For the edge cases where `ksType` potentially represents a java primitive, it is always
- * boxed.
- */
- fun wrapDeclared(ksType: KSType): KspDeclaredType {
- return wrap(
- ksType = ksType,
- allowPrimitives = false
- ) as KspDeclaredType
- }
-
- /**
* Wraps the given `ksType`.
*
* The [originatingReference] is used to calculate whether the given [ksType] can be a
@@ -169,7 +161,7 @@
* Instead, it is passed in an argument to this function and public wrap functions make that
* decision.
*/
- private fun wrap(ksType: KSType, allowPrimitives: Boolean): KspType {
+ fun wrap(ksType: KSType, allowPrimitives: Boolean): KspType {
val qName = ksType.declaration.qualifiedName?.asString()
if (allowPrimitives && qName != null && ksType.nullability == Nullability.NOT_NULL) {
// check for primitives
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index 8f31e56..f4575aa 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -73,7 +73,15 @@
}
override val type: KspDeclaredType by lazy {
- env.wrapDeclared(declaration.asStarProjectedType())
+ val result = env.wrap(
+ ksType = declaration.asStarProjectedType(),
+ allowPrimitives = false
+ )
+ check(result is KspDeclaredType) {
+ "Internal error, expected type of $this to resolve to a declared type but it resolved" +
+ " to $result (${result::class})"
+ }
+ result
}
override val superType: XType? by lazy {
@@ -81,7 +89,10 @@
val type = it.resolve().declaration as? KSClassDeclaration ?: return@firstOrNull false
type.classKind == ClassKind.CLASS
}?.let {
- env.wrapDeclared(it.resolve())
+ env.wrap(
+ ksType = it.resolve(),
+ allowPrimitives = false
+ )
}
}
@@ -190,12 +201,7 @@
}
override fun findPrimaryConstructor(): XConstructorElement? {
- val primary = if (declaration.declaredConstructors().isEmpty() && !isInterface()) {
- declaration.primaryConstructor
- } else {
- declaration.getNonSyntheticPrimaryConstructor()
- }
- return primary?.let {
+ return declaration.primaryConstructor?.let {
KspConstructorElement(
env = env,
containing = this,
@@ -288,5 +294,5 @@
private fun KSClassDeclaration.declaredConstructors() = this.getDeclaredFunctions()
.filter {
it.simpleName == this.simpleName
- }.distinct() // workaround for: https://github.com/google/ksp/issues/99
+ }
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
index 42deaa39..68121e3 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
@@ -65,7 +65,10 @@
)
)
)
- env.wrapDeclared(contType)
+ env.wrap(
+ ksType = contType,
+ allowPrimitives = false
+ )
}
override fun asMemberOf(other: XDeclaredType): XType {
@@ -83,7 +86,10 @@
Variance.CONTRAVARIANT
)
val contType = continuation.asType(listOf(returnTypeAsTypeArgument))
- return env.wrapDeclared(contType)
+ return env.wrap(
+ ksType = contType,
+ allowPrimitives = false
+ )
}
override fun kindName(): String {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
index 003e2b1..12f726f 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
@@ -17,8 +17,6 @@
package androidx.room.compiler.processing
import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.TestInvocation
-import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.compiler.processing.util.runProcessorTestForFailedCompilation
import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import com.google.common.truth.Truth.assertThat
@@ -203,17 +201,7 @@
""".trimIndent()
)
listOf(javaSrc, kotlinSrc).forEach { src ->
- fun runTest(block: (TestInvocation) -> Unit) {
- // KSP does not support generated code access in java sources yet
- // TODO remove this check once the bug is fixed.
- // https://github.com/google/ksp/issues/119
- if (src === javaSrc) {
- runProcessorTest(sources = listOf(src), block)
- } else {
- runProcessorTestIncludingKsp(sources = listOf(src), block)
- }
- }
- runTest { invocation ->
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
val className = ClassName.get("foo.bar", "ToBeGenerated")
if (invocation.processingEnv.findTypeElement(className) == null) {
// generate only if it doesn't exist to handle multi-round
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
index dbfc27d..1e3e3c3 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
@@ -100,14 +100,30 @@
val base = invocation.processingEnv.requireTypeElement("Base")
val t = base.getField("t")
val listOfR = base.getField("listOfR")
- assertThat(t.type.typeName).isEqualTo(TypeVariableName.get("T"))
+ if (invocation.isKsp) {
+ // KSP replaces unspecified type parameters with Any? while javac keeps them as is.
+ // This might be an issue when detecting errors but besides that it should be OK.
+ // It other words, it shouldn't be an issue in proper code. It will only have an
+ // impact when Room wants to report `unbound generics` errors as we won't
+ // recognize them and instead assume they were set as Object.
+ // see: UNBOUND_GENERICS errors in ProcessorErrors)
+ assertThat(t.type.typeName).isEqualTo(TypeName.OBJECT)
+ } else {
+ assertThat(t.type.typeName).isEqualTo(TypeVariableName.get("T"))
+ }
+ val typeVariableName = if (invocation.isKsp) {
+ "E" // ksp reads from class declaration
+ } else {
+ "R" // javac reads from variable declaration
+ }
assertThat(listOfR.type.typeName)
.isEqualTo(
ParameterizedTypeName.get(
List::class.className(),
- TypeVariableName.get("R")
+ TypeVariableName.get(typeVariableName)
)
)
+
assertThat(t.enclosingTypeElement).isEqualTo(base)
assertThat(listOfR.enclosingTypeElement).isEqualTo(base)
assertThat(t.asMemberOf(sub.type).typeName).isEqualTo(TypeName.INT.box())
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
index 43950af..10c8f93 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
@@ -241,8 +241,14 @@
}
baseClass.getField("genericProp").let { field ->
- assertThat(field.type.typeName).isEqualTo(TypeVariableName.get("T"))
+ if (invocation.isKsp) {
+ // ksp replaces these with Any?
+ assertThat(field.type.typeName).isEqualTo(TypeName.OBJECT)
+ } else {
+ assertThat(field.type.typeName).isEqualTo(TypeVariableName.get("T"))
+ }
}
+
subClass.getField("genericProp").let { field ->
// this is tricky because even though it is non-null it, it should still be boxed
assertThat(field.type.typeName).isEqualTo(TypeName.INT.box())
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
index cb953a4..5c0a3c6 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
@@ -18,6 +18,7 @@
import androidx.room.compiler.processing.XNullability.NONNULL
import androidx.room.compiler.processing.XNullability.NULLABLE
+import androidx.room.compiler.processing.isDeclared
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.TestInvocation
import androidx.room.compiler.processing.util.className
@@ -459,8 +460,11 @@
.arguments
.single()
.type
- .let {
- invocation.processingEnv.wrapDeclared(it!!.resolve())
+ .let { typeRef ->
+ invocation.processingEnv.wrap(
+ ksType = typeRef!!.resolve(),
+ allowPrimitives = false
+ )
}
}
assertThat(typeArgs["Bar"]!!.typeName)
@@ -496,9 +500,11 @@
?.first {
it.simpleName.asString() == "wildcardMethod"
} ?: throw AssertionError("cannot find test method")
- val paramType = invocation.processingEnv.wrapDeclared(
- method.parameters.first().type!!.resolve()
+ val paramType = invocation.processingEnv.wrap(
+ ksType = method.parameters.first().type.resolve(),
+ allowPrimitives = false
)
+ check(paramType.isDeclared())
val arg1 = paramType.typeArguments.single()
assertThat(arg1.typeName)
.isEqualTo(
@@ -517,7 +523,13 @@
private fun TestInvocation.requireDeclaredPropertyType(name: String): KspDeclaredType {
val prop = requireProperty(name)
- return (processingEnv as KspProcessingEnv).wrapDeclared(prop.type.resolve())
+ val result =
+ (processingEnv as KspProcessingEnv).wrap(
+ ksType = prop.type.resolve(),
+ allowPrimitives = false
+ )
+ check(result is KspDeclaredType)
+ return result
}
private fun TestInvocation.requireProperty(name: String): KSPropertyDeclaration {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
index ae79f1d..c50a9d7 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
@@ -23,7 +23,18 @@
import com.google.testing.compile.CompileTester
import com.google.testing.compile.JavaSourcesSubjectFactory
import com.tschuchort.compiletesting.KotlinCompilation
+import com.tschuchort.compiletesting.SourceFile
+import com.tschuchort.compiletesting.kspSourcesDir
import com.tschuchort.compiletesting.symbolProcessors
+import java.io.File
+
+// TODO get rid of these once kotlin compile testing supports two step compilation for KSP.
+// https://github.com/tschuchortdev/kotlin-compile-testing/issues/72
+private val KotlinCompilation.kspJavaSourceDir: File
+ get() = kspSourcesDir.resolve("java")
+
+private val KotlinCompilation.kspKotlinSourceDir: File
+ get() = kspSourcesDir.resolve("kotlin")
private fun compileSources(
sources: List<Source>,
@@ -66,7 +77,7 @@
private fun compileWithKsp(
sources: List<Source>,
handler: (TestInvocation) -> Unit
-): Pair<SyntheticKspProcessor, KotlinCompilation> {
+): Pair<SyntheticKspProcessor, KotlinCompilation.Result> {
@Suppress("NAME_SHADOWING")
val sources = if (sources.none { it is Source.KotlinSource }) {
// looks like this requires a kotlin source file
@@ -76,23 +87,44 @@
sources
}
val syntheticKspProcessor = SyntheticKspProcessor(handler)
- val compilation = KotlinCompilation()
- sources.forEach {
- compilation.workingDir.resolve("sources")
- .resolve(it.relativePath())
- .parentFile
- .mkdirs()
+ fun prepareCompilation(): KotlinCompilation {
+ val compilation = KotlinCompilation()
+ sources.forEach {
+ compilation.workingDir.resolve("sources")
+ .resolve(it.relativePath())
+ .parentFile
+ .mkdirs()
+ }
+ compilation.sources = sources.map {
+ it.toKotlinSourceFile()
+ }
+ compilation.jvmDefault = "enable"
+ compilation.jvmTarget = "1.8"
+ compilation.inheritClassPath = true
+ compilation.verbose = false
+ return compilation
}
- compilation.sources = sources.map {
- it.toKotlinSourceFile()
- }
- compilation.symbolProcessors = listOf(syntheticKspProcessor)
- compilation.jvmDefault = "enable"
- compilation.jvmTarget = "1.8"
- compilation.inheritClassPath = true
- compilation.verbose = false
+ val kspCompilation = prepareCompilation()
+ kspCompilation.symbolProcessors = listOf(syntheticKspProcessor)
+ kspCompilation.compile()
+ // ignore KSP result for now because KSP stops compilation, which might create false negatives
+ // when java code accesses kotlin code.
+ // TODO: fix once https://github.com/tschuchortdev/kotlin-compile-testing/issues/72 is fixed
- return syntheticKspProcessor to compilation
+ // after ksp, compile without ksp with KSP's output as input
+ val finalCompilation = prepareCompilation()
+ // build source files from generated code
+ finalCompilation.sources += kspCompilation.kspJavaSourceDir.collectSourceFiles() +
+ kspCompilation.kspKotlinSourceDir.collectSourceFiles()
+ return syntheticKspProcessor to finalCompilation.compile()
+}
+
+private fun File.collectSourceFiles(): List<SourceFile> {
+ return walkTopDown().filter {
+ it.isFile
+ }.map { file ->
+ SourceFile.fromPath(file)
+ }.toList()
}
fun runProcessorTest(
@@ -191,8 +223,7 @@
succeed: Boolean,
handler: (TestInvocation) -> Unit
) {
- val (kspProcessor, kotlinCompilation) = compileWithKsp(sources, handler)
- val compilationResult = kotlinCompilation.compile()
+ val (kspProcessor, compilationResult) = compileWithKsp(sources, handler)
if (succeed) {
assertThat(compilationResult.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
} else {