Introduce KspPrimitive Type
This CL introduces a new KspPrimitiveType : KspType which is used
to represent java primitives in KSP as primitives do not exist in
Kotlin.
Unfortunately, we cannot decide whether a kotlin type will be a
primitive or not just by looking at the type itself. For instance,
in most cases, a `kotlin.Int!!` is a java `int` but it might also
be mapped to `java.lang.Integer` if the type was resolved from a
type parameter (e.g. List<kotlin.Int>.get returns a boxed Integer).
To support this, I've removed the `wrap(KSType)` method from
KspProcessingEnv and replaced it with a wrap method that also
expects the KSTypeReference. KspProcessingEnv uses that type
reference to see if the references was resolved from a type
parameter. For cases where we always want the boxed type (e.g.
type of a TypeElement, there is a wrapDeclared method).
This is still not fully complete as it will miss overrides but
for overrides, kotlin generates two methods (see aosp/1458703).
I'll tackle that when we can run integration tests.
This CL makes TypeNames a bit inconsistent as the primitive types
are the only TypeNames in java. I'll followup with another CL
where
* TypeNames are always generated in java
* Ksp processing always uses kotlin types (e.g. java.util.List will
be mapped to kotlin.collections.MutableList).
After that CL, consistency will come back and then we'll start
running integration tests.
Bug: 160322705
Test: Existing tests + XProcessingEnvTest#getPrimitives
Change-Id: I271171cf7b35cd8f4249350fbdfadf81f55e6a8a
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt
index 8b3859b..268a5f7 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt
@@ -63,6 +63,28 @@
}
/**
+ * Returns the unboxed TypeName for this if it can be unboxed, otherwise, returns this.
+ */
+internal fun TypeName.tryUnbox(): TypeName {
+ return if (isBoxedPrimitive) {
+ unbox()
+ } else {
+ this
+ }
+}
+
+/**
+ * Returns the boxed TypeName for this if it can be unboxed, otherwise, returns this.
+ */
+internal fun TypeName.tryBox(): TypeName {
+ return try {
+ box()
+ } catch (err: AssertionError) {
+ this
+ }
+}
+
+/**
* Helper class to create overrides for XExecutableElements with final parameters and correct
* parameter names read from Kotlin Metadata.
*/
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
index fe0ba08..7a39e00 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
@@ -118,4 +118,8 @@
return checkNotNull(type?.resolve()) {
"KSTypeArgument.type should not have been null, please file a bug. $this"
}
+}
+
+internal fun KSTypeReference.isTypeParameterReference(): Boolean {
+ return this.resolve().declaration is KSTypeParameter
}
\ No newline at end of file
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 6df5430..4e308fb 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,12 @@
) : XAnnotationBox<T> {
override fun getAsType(methodName: String): XType? {
val value = getFieldValue<KSType>(methodName)
- return value?.let(env::wrap)
+ return value?.let(env::wrapDeclared)
}
override fun getAsTypeList(methodName: String): List<XType> {
val values = getFieldValue<List<KSType>>(methodName) ?: return emptyList()
- return values.map(env::wrap)
+ return values.map(env::wrapDeclared)
}
override fun <R : Annotation> getAsAnnotationBox(methodName: String): XAnnotationBox<R> {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspDeclaredType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspDeclaredType.kt
index 8b630ed..85752cd 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspDeclaredType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspDeclaredType.kt
@@ -18,8 +18,8 @@
import androidx.room.compiler.processing.XDeclaredType
import androidx.room.compiler.processing.XType
-import com.squareup.javapoet.TypeName
import com.google.devtools.ksp.symbol.KSType
+import com.squareup.javapoet.TypeName
internal open class KspDeclaredType(
env: KspProcessingEnv,
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 7e2d647..728033e 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
@@ -43,7 +43,12 @@
resolver = env.resolver,
functionDeclaration = method.declaration,
ksType = method.containing.declaration.asStarProjectedType()
- ).let(env::wrap)
+ ).let {
+ env.wrap(
+ originatingReference = parameter.type!!, // as member of doesn't allow nulls
+ ksType = it
+ )
+ }
}
override fun asMemberOf(other: XDeclaredType): XType {
@@ -55,7 +60,12 @@
resolver = env.resolver,
functionDeclaration = method.declaration,
ksType = other.ksType
- ).let(env::wrap)
+ ).let {
+ env.wrap(
+ originatingReference = parameter.type!!, // as member of doesn't allow nulls
+ ksType = it
+ )
+ }
}
override fun kindName(): String {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
index 5bdbddd..e997671 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
@@ -47,7 +47,10 @@
}
override val type: XType by lazy {
- env.wrap(declaration.typeAsMemberOf(env.resolver, containing.type.ksType))
+ env.wrap(
+ originatingReference = declaration.type,
+ ksType = declaration.typeAsMemberOf(env.resolver, containing.type.ksType)
+ )
}
override fun asMemberOf(other: XDeclaredType): XType {
@@ -56,7 +59,10 @@
}
check(other is KspType)
val asMember = declaration.typeAsMemberOf(env.resolver, other.ksType)
- return env.wrap(asMember)
+ return env.wrap(
+ originatingReference = declaration.type,
+ ksType = asMember
+ )
}
fun copyTo(newContaining: KspTypeElement) = KspFieldElement(
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 74c2e38..ab01a0b 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
@@ -114,7 +114,7 @@
override fun isSuspendFunction() = true
override val returnType: XType by lazy {
- env.wrap(env.resolver.builtIns.anyType.makeNullable())
+ env.wrapDeclared(env.resolver.builtIns.anyType.makeNullable())
}
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 cca29f31..218643a 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
@@ -52,7 +52,8 @@
) : KspMethodType(env, origin, containing) {
override val returnType: XType by lazy {
env.wrap(
- origin.declaration.returnTypeAsMemberOf(
+ originatingReference = origin.declaration.returnType!!,
+ ksType = origin.declaration.returnTypeAsMemberOf(
resolver = env.resolver,
ksType = containing.ksType
)
@@ -70,8 +71,9 @@
get() = origin.returnType
override fun getSuspendFunctionReturnType(): XType {
- return env.wrap(
- origin.declaration.returnTypeAsMemberOf(
+ // suspend functions work w/ continuation so it is always declared
+ return env.wrapDeclared(
+ ksType = origin.declaration.returnTypeAsMemberOf(
resolver = env.resolver,
ksType = containing.ksType
)
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
new file mode 100644
index 0000000..21af989
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspPrimitiveType.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.ksp
+
+import com.google.devtools.ksp.symbol.KSType
+import com.squareup.javapoet.TypeName
+
+/**
+ * This tries to mimic primitive types in Kotlin.
+ *
+ * Primitiveness of a type cannot always be driven from itself (e.g. its nullability).
+ * For instance, a kotlin.Int might be non-null but still be non primitive if it is derived from a
+ * generic type argument or is part of type parameters.
+ */
+internal class KspPrimitiveType(
+ env: KspProcessingEnv,
+ ksType: KSType
+) : KspType(env, ksType) {
+ override val typeName: TypeName by lazy {
+ // TODO once we generate type names in java realm, this custom conversion won't be necessary
+ // for now, temporarily, we only do conversion here in place
+ return@lazy checkNotNull(
+ KspTypeMapper.getPrimitiveJavaTypeName(
+ ksType.declaration.qualifiedName!!.asString()
+ )
+ ) {
+ "Internal error. Should've found a java primitive for " +
+ "${ksType.declaration.qualifiedName}"
+ }
+ }
+}
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 41d2747..c752c97 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
@@ -24,6 +24,7 @@
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.javac.XTypeElementStore
+import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
@@ -32,6 +33,7 @@
import com.google.devtools.ksp.symbol.KSTypeArgument
import com.google.devtools.ksp.symbol.KSTypeParameter
import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.Nullability
import com.google.devtools.ksp.symbol.Variance
internal class KspProcessingEnv(
@@ -44,7 +46,7 @@
private val typeElementStore =
XTypeElementStore { qName ->
resolver.getClassDeclarationByName(
- resolver.getKSNameFromString(qName)
+ KspTypeMapper.swapWithKotlinType(qName)
)?.let {
KspTypeElement(
env = this,
@@ -64,8 +66,12 @@
}
override fun findType(qName: String): XType? {
- return resolver.findClass(qName)?.let {
- wrap(it.asStarProjectedType())
+ val kotlinTypeName = KspTypeMapper.swapWithKotlinType(qName)
+ return resolver.findClass(kotlinTypeName)?.let {
+ wrap(
+ allowPrimitives = KspTypeMapper.isJavaPrimitiveType(qName),
+ ksType = it.asStarProjectedType()
+ )
}
}
@@ -90,7 +96,7 @@
variance = Variance.INVARIANT
)
}
- return wrap(
+ return wrapDeclared(
type.declaration.asType(typeArguments)
)
}
@@ -112,21 +118,44 @@
)
}
- fun wrap(ksType: KSType): KspDeclaredType {
- return if (ksType.declaration.qualifiedName?.asString() == KOTLIN_ARRAY_Q_NAME) {
- KspArrayType(
- env = this,
- ksType = ksType
- )
- } else {
- KspDeclaredType(this, ksType)
- }
+ /**
+ * 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
}
- fun wrap(ksTypeReference: KSTypeReference): KspDeclaredType {
- return wrap(ksTypeReference.resolve())
+ /**
+ * Wraps the given `ksType`.
+ *
+ * The [originatingReference] is used to calculate whether the given [ksType] can be a
+ * primitive or not.
+ */
+ fun wrap(
+ originatingReference: KSTypeReference,
+ ksType: KSType
+ ): KspType {
+ return wrap(
+ ksType = ksType,
+ allowPrimitives = !originatingReference.isTypeParameterReference()
+ )
}
+ /**
+ * Wraps the given [typeReference] in to a [KspType].
+ */
+ fun wrap(
+ typeReference: KSTypeReference
+ ) = wrap(
+ originatingReference = typeReference,
+ ksType = typeReference.resolve()
+ )
+
fun wrap(ksTypeParam: KSTypeParameter, ksTypeArgument: KSTypeArgument): KspTypeArgumentType {
return KspTypeArgumentType(
env = this,
@@ -135,6 +164,33 @@
)
}
+ /**
+ * Wraps the given KSType into a KspType.
+ *
+ * Certain Kotlin types might be primitives in Java but such information cannot be derived
+ * just by looking at the type itself.
+ * 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 {
+ val qName = ksType.declaration.qualifiedName?.asString()
+ if (allowPrimitives && qName != null && ksType.nullability == Nullability.NOT_NULL) {
+ // check for primitives
+ val javaPrimitive = KspTypeMapper.getPrimitiveJavaTypeName(qName)
+ if (javaPrimitive != null) {
+ return KspPrimitiveType(this, ksType)
+ }
+ }
+ return if (qName == KOTLIN_ARRAY_Q_NAME) {
+ KspArrayType(
+ env = this,
+ ksType = ksType
+ )
+ } else {
+ KspDeclaredType(this, ksType)
+ }
+ }
+
fun wrapClassDeclaration(declaration: KSClassDeclaration): KspTypeElement {
return KspTypeElement(
env = this,
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index fecc613..3b825dd 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -118,7 +118,17 @@
override fun isTypeOf(other: KClass<*>): Boolean {
// closest to what MoreTypes#isTypeOf does.
- return rawType.typeName.toString() == other.qualifiedName
+ // TODO once we move TypeNames to java realm, we will be able to check just using that
+ // (+ boxing). Fow now, this code stays flexible and checks for all variations as
+ // only primitives use java types now.
+ val rawTypeName = rawType.typeName
+ // other might be something like Kotlin.Int which would map to primitive int (when
+ // invoked with .java) hence we need to check the qualified name for both.
+ // similar case for lists.
+ val javaQName = other.java.canonicalName
+ val kotlinQName = other.qualifiedName
+ val myQName = rawTypeName.toString()
+ return myQName == javaQName || myQName == kotlinQName
}
override fun isSameType(other: XType): Boolean {
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 8730aa1..c3bfde7 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
@@ -26,7 +26,6 @@
import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticConstructorForJava
import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
-import com.squareup.javapoet.ClassName
import com.google.devtools.ksp.getAllSuperTypes
import com.google.devtools.ksp.getDeclaredFunctions
import com.google.devtools.ksp.getDeclaredProperties
@@ -37,6 +36,7 @@
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.google.devtools.ksp.symbol.Modifier
import com.google.devtools.ksp.symbol.Origin
+import com.squareup.javapoet.ClassName
internal class KspTypeElement(
env: KspProcessingEnv,
@@ -72,7 +72,7 @@
}
override val type: KspDeclaredType by lazy {
- env.wrap(declaration.asStarProjectedType())
+ env.wrapDeclared(declaration.asStarProjectedType())
}
override val superType: XType? by lazy {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt
new file mode 100644
index 0000000..2ffa3e5
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.ksp
+
+import com.squareup.javapoet.TypeName
+
+/**
+ * Maps java specific types to their kotlin counterparts.
+ * see: https://github.com/google/ksp/issues/126
+ * see: https://github.com/google/ksp/issues/125
+ *
+ * `Resolver.getClassDeclarationByName` returns the java representation of a class even when a
+ * kotlin version of the same class exists. e.g. It returns a KSClassDeclaration representing
+ * `java.lang.String` if queried with `java.lang.String`. Even though this makes sense by itself,
+ * it is inconsistent with the kotlin compiler which will resolve all instances of
+ * `java.lang.String` to `kotlin.String` (even if it is in Java source code).
+ *
+ * Until KSP provides compiler consistent behavior, this helper utility does the mapping for us.
+ *
+ * This list is built from https://kotlinlang.org/docs/reference/java-interop.html#mapped-types.
+ * Hopefully, it will be temporary until KSP provides a utility to do the same conversion.
+ */
+object KspTypeMapper {
+ private val mapping = mutableMapOf<String, String>()
+ private val kotlinTypeToJavaPrimitiveMapping = mapOf(
+ "kotlin.Byte" to TypeName.BYTE,
+ "kotlin.Short" to TypeName.SHORT,
+ "kotlin.Int" to TypeName.INT,
+ "kotlin.Long" to TypeName.LONG,
+ "kotlin.Char" to TypeName.CHAR,
+ "kotlin.Float" to TypeName.FLOAT,
+ "kotlin.Double" to TypeName.DOUBLE,
+ "kotlin.Boolean" to TypeName.BOOLEAN
+ )
+
+ init {
+ // https://kotlinlang.org/docs/reference/java-interop.html#mapped-types
+ kotlinTypeToJavaPrimitiveMapping.forEach {
+ mapping[it.value.toString()] = it.key
+ }
+ // TODO Add non primitives after TypeNames move to the java type realm.
+ }
+
+ fun swapWithKotlinType(javaType: String): String = mapping[javaType] ?: javaType
+
+ fun getPrimitiveJavaTypeName(kotlinType: String) = kotlinTypeToJavaPrimitiveMapping[kotlinType]
+
+ fun isJavaPrimitiveType(qName: String) = mapping[qName]?.let {
+ kotlinTypeToJavaPrimitiveMapping[it]
+ } != null
+}
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 1b5f8f4..42deaa39 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,7 @@
)
)
)
- env.wrap(contType)
+ env.wrapDeclared(contType)
}
override fun asMemberOf(other: XDeclaredType): XType {
@@ -83,7 +83,7 @@
Variance.CONTRAVARIANT
)
val contType = continuation.asType(listOf(returnTypeAsTypeArgument))
- return env.wrap(contType)
+ return env.wrapDeclared(contType)
}
override fun kindName(): String {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index 7b15858..dd1b778 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -174,7 +174,7 @@
}
override val returnType: XType by lazy {
- env.wrap(
+ env.wrapDeclared(
env.resolver.builtIns.unitType
)
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
index 92d3afe..0e88d66 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
@@ -25,6 +25,7 @@
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ParameterizedTypeName
+import com.squareup.javapoet.TypeName
import com.squareup.javapoet.WildcardTypeName
import org.junit.Test
import org.junit.runner.RunWith
@@ -202,7 +203,7 @@
invocation.types.string
)
assertThat(method.parameters[1].type.typeName).isEqualTo(
- invocation.types.int
+ TypeName.INT
)
assertThat(method.isSuspendFunction()).isTrue()
assertThat(method.returnType.typeName).isEqualTo(invocation.types.objectOrAny)
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 2ea0df4..a5a7bc6 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
@@ -139,13 +139,16 @@
}
""".trimIndent()
)
- runProcessorTest(
+ runProcessorTestIncludingKsp(
listOf(source)
) { invocation ->
PRIMITIVE_TYPES.forEach {
val targetType = invocation.processingEnv.findType(it.key)
assertThat(targetType?.typeName).isEqualTo(it.value)
- assertThat(targetType?.boxed()?.typeName).isEqualTo(it.value.box())
+ if (!invocation.isKsp) {
+ // TODO re-enable once we move typenames to the java realm
+ assertThat(targetType?.boxed()?.typeName).isEqualTo(it.value.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 3944482..5b6e65f 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
@@ -27,7 +27,7 @@
import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.getDeclaredFunctions
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
-import com.google.devtools.ksp.symbol.KSTypeReference
+import com.squareup.javapoet.TypeName
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -88,14 +88,14 @@
listOf(src),
succeed = false
) { invocation ->
- invocation.requirePropertyType("errorType").let { type ->
+ invocation.requireDeclaredPropertyType("errorType").let { type ->
assertThat(type.isError()).isTrue()
assertThat(type.typeArguments).isEmpty()
assertThat(type.typeName).isEqualTo(ERROR_TYPE_NAME)
assertThat(type.asTypeElement().className).isEqualTo(ERROR_TYPE_NAME)
}
- invocation.requirePropertyType("listOfErrorType").let { type ->
+ invocation.requireDeclaredPropertyType("listOfErrorType").let { type ->
assertThat(type.isError()).isFalse()
assertThat(type.typeArguments).hasSize(1)
type.typeArguments.single().let { typeArg ->
@@ -120,7 +120,7 @@
listOf(src),
succeed = true
) { invocation ->
- invocation.requirePropertyType("listOfNullableStrings").let { type ->
+ invocation.requireDeclaredPropertyType("listOfNullableStrings").let { type ->
assertThat(type.nullability).isEqualTo(NONNULL)
assertThat(type.typeArguments).hasSize(1)
assertThat(type.asTypeElement().className).isEqualTo(
@@ -136,7 +136,7 @@
}
}
- invocation.requirePropertyType("listOfInts").let { type ->
+ invocation.requireDeclaredPropertyType("listOfInts").let { type ->
assertThat(type.nullability).isEqualTo(NONNULL)
assertThat(type.typeArguments).hasSize(1)
type.typeArguments.single().let { typeArg ->
@@ -172,13 +172,17 @@
listOf(src),
succeed = true
) { invocation ->
- val nullableStringList = invocation.requirePropertyType("listOfNullableStrings")
- val nonNullStringList = invocation.requirePropertyType("listOfNonNullStrings")
+ val nullableStringList = invocation
+ .requireDeclaredPropertyType("listOfNullableStrings")
+ val nonNullStringList = invocation
+ .requireDeclaredPropertyType("listOfNonNullStrings")
assertThat(nullableStringList).isNotEqualTo(nonNullStringList)
assertThat(nonNullStringList).isNotEqualTo(nullableStringList)
- val nullableStringList_2 = invocation.requirePropertyType("listOfNullableStrings_2")
- val nonNullStringList_2 = invocation.requirePropertyType("listOfNonNullStrings_2")
+ val nullableStringList_2 = invocation
+ .requireDeclaredPropertyType("listOfNullableStrings_2")
+ val nonNullStringList_2 = invocation
+ .requireDeclaredPropertyType("listOfNonNullStrings_2")
assertThat(nullableStringList).isEqualTo(nullableStringList_2)
assertThat(nonNullStringList).isEqualTo(nonNullStringList_2)
@@ -216,21 +220,21 @@
succeed = true
) { invocation ->
invocation.requirePropertyType("simple").let {
- assertThat(it.rawType.typeName).isEqualTo(ClassName.get("kotlin", "Int"))
+ assertThat(it.rawType.typeName).isEqualTo(TypeName.INT)
}
- invocation.requirePropertyType("list").let { list ->
+ invocation.requireDeclaredPropertyType("list").let { list ->
assertThat(list.rawType).isNotEqualTo(list)
assertThat(list.typeArguments).isNotEmpty()
assertThat(list.rawType.typeName)
.isEqualTo(ClassName.get("kotlin.collections", "List"))
}
- invocation.requirePropertyType("map").let { map ->
+ invocation.requireDeclaredPropertyType("map").let { map ->
assertThat(map.rawType).isNotEqualTo(map)
assertThat(map.typeArguments).hasSize(2)
assertThat(map.rawType.typeName)
.isEqualTo(ClassName.get("kotlin.collections", "Map"))
}
- invocation.requirePropertyType("listOfMaps").let { listOfMaps ->
+ invocation.requireDeclaredPropertyType("listOfMaps").let { listOfMaps ->
assertThat(listOfMaps.rawType).isNotEqualTo(listOfMaps)
assertThat(listOfMaps.typeArguments).hasSize(1)
}
@@ -450,7 +454,7 @@
.single()
.type
.let {
- invocation.wrap(typeRef = it!!)
+ invocation.processingEnv.wrapDeclared(it!!.resolve())
}
}
assertThat(typeArgs["Bar"]!!.typeName)
@@ -486,7 +490,9 @@
?.first {
it.simpleName.asString() == "wildcardMethod"
} ?: throw AssertionError("cannot find test method")
- val paramType = invocation.wrap(method.parameters.first().type!!)
+ val paramType = invocation.processingEnv.wrapDeclared(
+ method.parameters.first().type!!.resolve()
+ )
val arg1 = paramType.typeArguments.single()
assertThat(arg1.typeName)
.isEqualTo(
@@ -498,17 +504,22 @@
}
}
- private fun TestInvocation.requirePropertyType(name: String): KspDeclaredType {
- (processingEnv as KspProcessingEnv).resolver.getAllFiles().forEach { file ->
- val prop = file.declarations.first {
- it.simpleName.asString() == name
- } as KSPropertyDeclaration
- return wrap(prop.type)
- }
- throw IllegalStateException("cannot find any property with name $name")
+ private fun TestInvocation.requirePropertyType(name: String): KspType {
+ val prop = requireProperty(name)
+ return (processingEnv as KspProcessingEnv).wrap(prop.type)
}
- private fun TestInvocation.wrap(typeRef: KSTypeReference): KspDeclaredType {
- return (processingEnv as KspProcessingEnv).wrap(typeRef)
+ private fun TestInvocation.requireDeclaredPropertyType(name: String): KspDeclaredType {
+ val prop = requireProperty(name)
+ return (processingEnv as KspProcessingEnv).wrapDeclared(prop.type.resolve())
+ }
+
+ private fun TestInvocation.requireProperty(name: String): KSPropertyDeclaration {
+ kspResolver.getAllFiles().forEach { file ->
+ return file.declarations.first {
+ it.simpleName.asString() == name
+ } as KSPropertyDeclaration
+ }
+ throw IllegalStateException("cannot find any property with name $name")
}
}
\ No newline at end of file
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt
index 5e0d428..ab5c68a 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt
@@ -42,8 +42,6 @@
voidOrUnit = KotlinTypeNames.UNIT_CLASS_NAME,
objectOrAny = KotlinTypeNames.ANY_CLASS_NAME,
boxedInt = KotlinTypeNames.INT_CLASS_NAME,
- int = KotlinTypeNames.INT_CLASS_NAME,
- long = KotlinTypeNames.LONG_CLASS_NAME,
list = KotlinTypeNames.LIST_CLASS_NAME,
mutableSet = KotlinTypeNames.MUTABLESET_CLASS_NAME
)
@@ -53,8 +51,6 @@
voidOrUnit = TypeName.VOID,
objectOrAny = TypeName.OBJECT,
boxedInt = TypeName.INT.box(),
- int = TypeName.INT,
- long = TypeName.LONG,
list = ClassName.get("java.util", "List"),
mutableSet = ClassName.get("java.util", "Set")
)
@@ -70,8 +66,8 @@
val voidOrUnit: TypeName,
val objectOrAny: ClassName,
val boxedInt: TypeName,
- val int: TypeName,
- val long: TypeName,
+ val int: TypeName = TypeName.INT,
+ val long: TypeName = TypeName.LONG,
val list: ClassName,
val mutableSet: TypeName
)