Merge changes I271171cf,I8d690387 into androidx-master-dev

* changes:
  Introduce KspPrimitive Type
  Add ability to get TypeName from JVM signature
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/javac/kotlin/JvmDescriptorUtils.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtils.kt
index 2105173..05f2e59 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtils.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtils.kt
@@ -17,6 +17,9 @@
 package androidx.room.compiler.processing.javac.kotlin
 
 import com.google.auto.common.MoreTypes
+import com.squareup.javapoet.ArrayTypeName
+import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.TypeName
 import javax.lang.model.element.Element
 import javax.lang.model.element.ExecutableElement
 import javax.lang.model.element.NestingKind
@@ -95,6 +98,53 @@
         else -> error("Unknown primitive type $this")
     }
 
+// see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.2-200
+internal fun String.typeNameFromJvmSignature(): TypeName {
+    check(isNotEmpty())
+    return when (this[0]) {
+        'B' -> TypeName.BYTE
+        'C' -> TypeName.CHAR
+        'D' -> TypeName.DOUBLE
+        'F' -> TypeName.FLOAT
+        'I' -> TypeName.INT
+        'J' -> TypeName.LONG
+        'S' -> TypeName.SHORT
+        'Z' -> TypeName.BOOLEAN
+        'L' -> {
+            val end = lastIndexOf(";")
+            check(end > 0) {
+                "invalid input $this"
+            }
+            val simpleNamesSeparator = lastIndexOf('/')
+            val simpleNamesStart = if (simpleNamesSeparator < 0) {
+                1 // first char is 'L'
+            } else {
+                simpleNamesSeparator + 1
+            }
+            val packageName = if (simpleNamesSeparator < 0) {
+                // no package name
+                ""
+            } else {
+                substring(1, simpleNamesSeparator).replace('/', '.')
+            }
+            val firstSimpleNameSeparator = indexOf('$', startIndex = simpleNamesStart)
+            return if (firstSimpleNameSeparator < 0) {
+                // not nested
+                ClassName.get(packageName, substring(simpleNamesStart, end))
+            } else {
+                // nested class
+                val firstSimpleName = substring(simpleNamesStart, firstSimpleNameSeparator)
+                val restOfSimpleNames = substring(firstSimpleNameSeparator + 1, end)
+                    .split('$')
+                    .toTypedArray()
+                ClassName.get(packageName, firstSimpleName, *restOfSimpleNames)
+            }
+        }
+        '[' -> ArrayTypeName.of(substring(1).typeNameFromJvmSignature())
+        else -> error("unexpected jvm signature $this")
+    }
+}
+
 internal fun TypeMirror.descriptor(): String = accept(JvmDescriptorTypeVisitor, Unit)
 
 @Suppress("unused")
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/javac/kotlin/JvmDescriptorUtilsTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt
index 8a3c47f..2c297e0 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt
@@ -19,9 +19,11 @@
 import com.google.auto.common.MoreElements
 import com.google.common.truth.Truth
 import com.google.common.truth.Truth.assertThat
-import com.google.testing.compile.CompileTester
 import com.google.testing.compile.JavaFileObjects
 import com.google.testing.compile.JavaSourcesSubjectFactory
+import com.squareup.javapoet.ArrayTypeName
+import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.TypeName
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -96,7 +98,7 @@
                     "field4:Ljava/util/List;"
                 )
             )
-        }.compilesWithoutError()
+        }
     }
 
     @Test
@@ -153,7 +155,7 @@
                     "method9()Ljava/lang/String;"
                 )
             )
-        }.compilesWithoutError()
+        }
     }
 
     @Test
@@ -179,7 +181,7 @@
         ) { descriptors ->
             assertThat(descriptors)
                 .isEqualTo(setOf("method1(ZI)V", "method2(C)B", "method3(DF)V", "method4(JS)V"))
-        }.compilesWithoutError()
+        }
     }
 
     @Test
@@ -215,7 +217,7 @@
                     "method4()Ljava/util/Map;"
                 )
             )
-        }.compilesWithoutError()
+        }
     }
 
     @Test
@@ -247,7 +249,7 @@
                     "method2()Landroidx/room/test/DataClass;"
                 )
             )
-        }.compilesWithoutError()
+        }
     }
 
     @Test
@@ -296,7 +298,7 @@
                     "method4()Landroidx/room/test/DataClass\$StaticInnerData;"
                 )
             )
-        }.compilesWithoutError()
+        }
     }
 
     @Test
@@ -336,7 +338,72 @@
                     "method4([I)V"
                 )
             )
-        }.compilesWithoutError()
+        }
+    }
+
+    @Test
+    fun typeNameFromDescriptor() {
+        val extraJfo =
+            """
+            import androidx.room.test.Describe;
+            class Custom {
+                static class Nested1 {
+                    static class Nested2 {
+                        @Describe
+                        Custom c;
+                        @Describe
+                        Custom.Nested1 n1;
+                        @Describe
+                        Custom.Nested1.Nested2 n2;
+                    }
+                }
+            }
+            """.toJFO("Custom")
+        singleRun(
+            """
+            package androidx.room.test;
+
+            class Foo {
+                @Describe
+                int x;
+
+                @Describe
+                java.util.Map map;
+
+                @Describe
+                java.util.Map.Entry entry;
+
+                @Describe
+                int[] intArray;
+
+                @Describe
+                int[][] intArrayOfArray;
+            }
+            """.toJFO("androidx.room.test.Foo"),
+            extraJfo
+        ) {
+            assertThat(
+                it.map {
+                    // the format is name:type so we strip everything before `:`
+                    it.split(':')[1].typeNameFromJvmSignature()
+                }
+            ).containsExactly(
+                TypeName.INT,
+                ClassName.get(Map::class.java),
+                ClassName.get(Map.Entry::class.java),
+                ArrayTypeName.of(
+                    TypeName.INT
+                ),
+                ArrayTypeName.of(
+                    ArrayTypeName.of(
+                        TypeName.INT
+                    )
+                ),
+                ClassName.get("", "Custom"),
+                ClassName.get("", "Custom", "Nested1"),
+                ClassName.get("", "Custom", "Nested1", "Nested2"),
+            )
+        }
     }
 
     private fun String.toJFO(qName: String): JavaFileObject =
@@ -346,27 +413,31 @@
     private fun singleRun(
         vararg jfo: JavaFileObject,
         handler: (Set<String>) -> Unit
-    ): CompileTester {
-        return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
+    ) {
+        Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
             .that(listOf(describeAnnotation) + jfo)
             .processedWith(object : AbstractProcessor() {
                 override fun process(
                     annotations: Set<TypeElement>,
                     roundEnv: RoundEnvironment
                 ): Boolean {
-                    roundEnv.getElementsAnnotatedWith(annotations.first()).map { element ->
-                        when (element.kind) {
-                            FIELD -> MoreElements.asVariable(element).descriptor()
-                            METHOD, CONSTRUCTOR -> MoreElements.asExecutable(element).descriptor()
-                            else -> error("Unsupported element to describe.")
-                        }
-                    }.toSet().let(handler)
+                    if (annotations.isNotEmpty()) {
+                        roundEnv.getElementsAnnotatedWith(annotations.first()).map { element ->
+                            when (element.kind) {
+                                FIELD ->
+                                    MoreElements.asVariable(element).descriptor()
+                                METHOD, CONSTRUCTOR ->
+                                    MoreElements.asExecutable(element).descriptor()
+                                else -> error("Unsupported element to describe.")
+                            }
+                        }.toSet().let(handler)
+                    }
                     return true
                 }
 
-                override fun getSupportedOptions(): Set<String> {
+                override fun getSupportedAnnotationTypes(): Set<String> {
                     return setOf("androidx.room.test.Describe")
                 }
-            })
+            }).compilesWithoutError()
     }
 }
\ No newline at end of file
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
     )