[go: nahoru, domu]

Migrate XProcessing to XTypeName

This changes migrates most of the usages of room-compiler-processing to XTypeName along with a vast majority of tests which further asserts on the correctness of KotlinPoet name creation in KSP.

Bug: 127483380
Test: ./gradlew :room:room-compiler-processing:test
Change-Id: Ifc18c449d1bc88696c578732a630c7ce92d773d4
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt
index e792548..5eae6bfc 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt
@@ -17,8 +17,8 @@
 package androidx.room.compiler.codegen
 
 import androidx.room.compiler.processing.XNullability
-import com.squareup.kotlinpoet.DelicateKotlinPoetApi
 import com.squareup.kotlinpoet.asClassName
+import com.squareup.kotlinpoet.asTypeName
 import com.squareup.kotlinpoet.javapoet.JClassName
 import com.squareup.kotlinpoet.javapoet.JTypeName
 import com.squareup.kotlinpoet.javapoet.KClassName
@@ -44,14 +44,14 @@
         if (this === other) return true
         if (other !is XTypeName) return false
         if (java != other.java) return false
-        if (kotlin != other.kotlin) return false
+        if (kotlin != UNAVAILABLE_KTYPE_NAME && other.kotlin != UNAVAILABLE_KTYPE_NAME) {
+            if (kotlin != other.kotlin) return false
+        }
         return true
     }
 
     override fun hashCode(): Int {
-        var result = java.hashCode()
-        result = 31 * result + kotlin.hashCode()
-        return result
+        return java.hashCode()
     }
 
     override fun toString() = buildString {
@@ -67,6 +67,15 @@
     }
 
     companion object {
+        val PRIMITIVE_BOOLEAN = Boolean::class.asPrimitiveTypeName()
+        val PRIMITIVE_BYTE = Byte::class.asPrimitiveTypeName()
+        val PRIMITIVE_SHORT = Short::class.asPrimitiveTypeName()
+        val PRIMITIVE_INT = Int::class.asPrimitiveTypeName()
+        val PRIMITIVE_LONG = Long::class.asPrimitiveTypeName()
+        val PRIMITIVE_CHAR = Char::class.asPrimitiveTypeName()
+        val PRIMITIVE_FLOAT = Float::class.asPrimitiveTypeName()
+        val PRIMITIVE_DOUBLE = Double::class.asPrimitiveTypeName()
+
         /**
          * The default [KTypeName] returned by xprocessing APIs when the backend is not KSP.
          */
@@ -76,7 +85,7 @@
         operator fun invoke(
             java: JTypeName,
             kotlin: KTypeName,
-            nullability: XNullability
+            nullability: XNullability = XNullability.NONNULL
         ): XTypeName {
             return XTypeName(java, kotlin, nullability)
         }
@@ -101,6 +110,7 @@
     //  But a decision has to be made...
     val packageName: String = java.packageName()
     val simpleNames: List<String> = java.simpleNames()
+    val canonicalName: String = java.canonicalName()
 
     fun copy(nullable: Boolean): XClassName {
         return XClassName(
@@ -111,6 +121,10 @@
     }
 
     companion object {
+        /**
+         * Creates an class name from the given parts.
+         */
+        // TODO(b/248633751): Handle interop types.
         fun get(
             packageName: String,
             vararg names: String
@@ -124,22 +138,75 @@
     }
 }
 
-@OptIn(DelicateKotlinPoetApi::class)
-fun Class<*>.asClassName(): XClassName {
-    return XClassName(
-        java = JClassName.get(this),
-        kotlin = this.asClassName(),
-        nullability = XNullability.NONNULL
-    )
-}
-
+/**
+ * Creates a [XClassName] from the receiver [KClass]
+ *
+ * When the receiver [KClass] is a Kotlin interop primitive, such as [kotlin.Int] then the returned
+ * [XClassName] contains the boxed JavaPoet class name.
+ *
+ * When the receiver [KClass] is a Kotlin interop collection, such as [kotlin.collections.List]
+ * then the returned [XClassName] the corresponding JavaPoet class name. See:
+ * https://kotlinlang.org/docs/reference/java-interop.html#mapped-types.
+ *
+ * When the receiver [KClass] is a Kotlin mutable collection, such as
+ * [kotlin.collections.MutableList] then the non-mutable [XClassName] is returned due to the
+ * mutable interfaces only existing at compile-time, see:
+ * https://youtrack.jetbrains.com/issue/KT-11754.
+ */
 fun KClass<*>.asClassName(): XClassName {
+    val jClassName = if (this.java.isPrimitive) {
+        getBoxedJClassName(this.java)
+    } else {
+        JClassName.get(this.java)
+    }
+    val kClassName = this.asClassName()
     return XClassName(
-        java = JClassName.get(this.java),
-        kotlin = this.asClassName(),
+        java = jClassName,
+        kotlin = kClassName,
         nullability = XNullability.NONNULL
     )
 }
 
-fun XTypeName.toJavaPoet() = this.java
-fun XClassName.toJavaPoet() = this.java
\ No newline at end of file
+private fun getBoxedJClassName(klass: Class<*>): JClassName = when (klass) {
+    java.lang.Void.TYPE -> JTypeName.VOID.box()
+    java.lang.Boolean.TYPE -> JTypeName.BOOLEAN.box()
+    java.lang.Byte.TYPE -> JTypeName.BYTE.box()
+    java.lang.Short.TYPE -> JTypeName.SHORT.box()
+    java.lang.Integer.TYPE -> JTypeName.INT.box()
+    java.lang.Long.TYPE -> JTypeName.LONG.box()
+    java.lang.Character.TYPE -> JTypeName.CHAR.box()
+    java.lang.Float.TYPE -> JTypeName.FLOAT.box()
+    java.lang.Double.TYPE -> JTypeName.DOUBLE.box()
+    else -> error("Can't get JTypeName from java.lang.Class: $klass")
+} as JClassName
+
+/**
+ * Creates a [XTypeName] whose JavaPoet name is a primitive name and KotlinPoet is the interop type.
+ *
+ * This function is useful since [asClassName] only supports creating class names and specifically
+ * only the boxed version of primitives.
+ */
+internal fun KClass<*>.asPrimitiveTypeName(): XTypeName {
+    require(this.java.isPrimitive) {
+        "$this does not represent a primitive."
+    }
+    val jTypeName = getPrimitiveJTypeName(this.java)
+    val kTypeName = this.asTypeName()
+    return XTypeName(jTypeName, kTypeName)
+}
+
+private fun getPrimitiveJTypeName(klass: Class<*>): JTypeName = when (klass) {
+    java.lang.Void.TYPE -> JTypeName.VOID
+    java.lang.Boolean.TYPE -> JTypeName.BOOLEAN
+    java.lang.Byte.TYPE -> JTypeName.BYTE
+    java.lang.Short.TYPE -> JTypeName.SHORT
+    java.lang.Integer.TYPE -> JTypeName.INT
+    java.lang.Long.TYPE -> JTypeName.LONG
+    java.lang.Character.TYPE -> JTypeName.CHAR
+    java.lang.Float.TYPE -> JTypeName.FLOAT
+    java.lang.Double.TYPE -> JTypeName.DOUBLE
+    else -> error("Can't get JTypeName from java.lang.Class: $klass")
+}
+
+fun XTypeName.toJavaPoet(): JTypeName = this.java
+fun XClassName.toJavaPoet(): JClassName = this.java
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt
index ac25598..6d87e42 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/JavaPoetExt.kt
@@ -51,18 +51,18 @@
     requireNotNull(value) { "value == null, constant non-null value expected for $name" }
     require(SourceVersion.isName(name)) { "not a valid name: $name" }
     when {
-      hasListValue() -> asAnnotationValueList().forEach { addAnnotationValue(it) }
-      hasAnnotationValue() -> addMember(name, "\$L", asAnnotation().toAnnotationSpec())
-      hasEnumValue() -> addMember(
-        name, "\$T.\$L", asEnum().enclosingElement.className, asEnum().name
-      )
-      hasTypeValue() -> addMember(name, "\$T.class", asType().typeName)
-      hasStringValue() -> addMember(name, "\$S", asString())
-      hasFloatValue() -> addMember(name, "\$Lf", asFloat())
-      hasCharValue() -> addMember(
-        name, "'\$L'", characterLiteralWithoutSingleQuotes(asChar())
-      )
-      else -> addMember(name, "\$L", value)
+        hasListValue() -> asAnnotationValueList().forEach { addAnnotationValue(it) }
+        hasAnnotationValue() -> addMember(name, "\$L", asAnnotation().toAnnotationSpec())
+        hasEnumValue() -> addMember(
+            name, "\$T.\$L", asEnum().enclosingElement.asClassName().java, asEnum().name
+        )
+        hasTypeValue() -> addMember(name, "\$T.class", asType().asTypeName().java)
+        hasStringValue() -> addMember(name, "\$S", asString())
+        hasFloatValue() -> addMember(name, "\$Lf", asFloat())
+        hasCharValue() -> addMember(
+            name, "'\$L'", characterLiteralWithoutSingleQuotes(asChar())
+        )
+        else -> addMember(name, "\$L", value)
     }
   }
 }
@@ -179,7 +179,7 @@
             resolvedType.parameterTypes.forEachIndexed { index, paramType ->
                 addParameter(
                     ParameterSpec.builder(
-                        paramType.typeName,
+                        paramType.asTypeName().java,
                         executableElement.parameters[index].name,
                         *paramModifiers
                     ).build()
@@ -193,9 +193,9 @@
             addAnnotation(Override::class.java)
             varargs(executableElement.isVarArgs())
             executableElement.thrownTypes.forEach {
-                addException(it.typeName)
+                addException(it.asTypeName().java)
             }
-            returns(resolvedType.returnType.typeName)
+            returns(resolvedType.returnType.asTypeName().java)
         }
     }
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt
index a02f25d..407495d 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt
@@ -17,6 +17,8 @@
 package androidx.room.compiler.processing
 
 import com.squareup.kotlinpoet.OriginatingElementsHolder
+import com.squareup.kotlinpoet.ParameterizedTypeName
+import com.squareup.kotlinpoet.TypeName
 import com.squareup.kotlinpoet.javapoet.KClassName
 
 internal val KOTLIN_NONE_TYPE_NAME: KClassName =
@@ -31,4 +33,12 @@
 ): T {
     element.originatingElementForPoet()?.let(this::addOriginatingElement)
     return this
+}
+
+internal fun TypeName.rawTypeName(): TypeName {
+    return if (this is ParameterizedTypeName) {
+        this.rawType
+    } else {
+        this
+    }
 }
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotation.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotation.kt
index b9325e6..d40c108 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotation.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotation.kt
@@ -66,7 +66,7 @@
      * [name].
      */
     val className: ClassName
-        get() = typeElement.className
+        get() = typeElement.asClassName().java
 
     /** All values declared in the annotation class. */
     val annotationValues: List<XAnnotationValue>
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XConstructorElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XConstructorElement.kt
index 3053849..07d4bd2 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XConstructorElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XConstructorElement.kt
@@ -32,7 +32,7 @@
             append("(")
             append(
                 parameters.joinToString(", ") {
-                    it.type.typeName.toString()
+                    it.type.asTypeName().java.toString()
                 }
             )
             append(")")
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt
index 01bcc24..1e51046 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XClassName
 import com.squareup.javapoet.ClassName
 
 /**
@@ -31,11 +32,27 @@
 
     /**
      * The JVM ClassName for this container.
-     * For top level members of a Kotlin file, you can use this [className] for code generation.
+     *
+     * For top level members of a Kotlin file, you can use this [ClassName] for code generation.
      */
+    // TODO(b/247248619): Deprecate when more progress is made, otherwise -werror fails the build.
+    // @Deprecated(
+    //     message = "Use asClassName().toJavaPoet() to be clear the name is for JavaPoet.",
+    //     replaceWith = ReplaceWith(
+    //         expression = "asClassName().toJavaPoet()",
+    //         imports = ["androidx.room.compiler.codegen.toJavaPoet"]
+    //     )
+    // )
     val className: ClassName
 
     /**
+     * The JVM ClassName for this container.
+     *
+     * For top level members of a Kotlin file, you can use this [XClassName] for code generation.
+     */
+    fun asClassName(): XClassName
+
+    /**
      * The [XType] for the container if this is an [XTypeElement] otherwise `null` if a type
      * representing this container does not exist (e.g. a top level Kotlin source file)
      */
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt
index 96fcfc5..13fb370 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt
@@ -61,7 +61,7 @@
                 parameters.dropLast(
                     if (isSuspendFunction()) 1 else 0
                 ).joinToString(", ") {
-                    it.type.typeName.toString()
+                    it.type.asTypeName().java.toString()
                 }
             )
             append(")")
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XRawType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XRawType.kt
index 7d87fda..38f719c 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XRawType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XRawType.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XTypeName
 import com.squareup.javapoet.TypeName
 
 /**
@@ -32,11 +33,23 @@
  * Instances of XRawType implement equality.
  */
 interface XRawType {
+    // TODO(b/247248619): Deprecate when more progress is made, otherwise -werror fails the build.
+    // @Deprecated(
+    //     message = "Use asTypeName().toJavaPoet() to be clear the name is for JavaPoet.",
+    //     replaceWith = ReplaceWith(
+    //         expression = "asTypeName().toJavaPoet()",
+    //         imports = ["androidx.room.compiler.codegen.toJavaPoet"]
+    //     )
+    // )
     val typeName: TypeName
+
+    fun asTypeName(): XTypeName
+
     /**
      * Returns `true` if this raw type can be assigned from [other].
      */
     fun isAssignableFrom(other: XRawType): Boolean
+
     /**
      * Returns `true` if this raw type can be assigned from [other].
      */
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
index 5636707..cedb6fb6 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
@@ -173,6 +173,7 @@
 /**
  * Returns true if this is a [List] or [Set].
  */
+// TODO(b/248280754): Move to room-compiler, overloaded function name
 fun XType.isCollection(): Boolean {
     return isTypeOf(List::class) || isTypeOf(Set::class)
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
index 3b49f682..80525af 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
@@ -78,7 +78,7 @@
     /**
      * Gets the [XClassName] of the type element.
      */
-    fun asClassName(): XClassName
+    override fun asClassName(): XClassName
 
     /**
      * The [XTypeElement] that contains this [XTypeElement] if it is an inner class/interface.
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacRawType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacRawType.kt
index 4d0baa5..73f52b4 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacRawType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacRawType.kt
@@ -16,9 +16,9 @@
 
 package androidx.room.compiler.processing.javac
 
+import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.processing.XRawType
 import androidx.room.compiler.processing.safeTypeName
-import com.squareup.javapoet.TypeName
 
 internal class JavacRawType(
     env: JavacProcessingEnv,
@@ -27,21 +27,33 @@
     private val erased = env.typeUtils.erasure(original.typeMirror)
     private val typeUtils = env.delegate.typeUtils
 
-    override val typeName: TypeName = erased.safeTypeName()
+    override val typeName by lazy {
+        xTypeName.java
+    }
+
+    private val xTypeName: XTypeName by lazy {
+        XTypeName(
+            erased.safeTypeName(),
+            XTypeName.UNAVAILABLE_KTYPE_NAME,
+            original.nullability
+        )
+    }
+
+    override fun asTypeName() = xTypeName
 
     override fun isAssignableFrom(other: XRawType): Boolean {
         return other is JavacRawType && typeUtils.isAssignable(other.erased, erased)
     }
 
     override fun equals(other: Any?): Boolean {
-        return this === other || typeName == (other as? XRawType)?.typeName
+        return this === other || xTypeName == (other as? XRawType)?.asTypeName()
     }
 
     override fun hashCode(): Int {
-        return typeName.hashCode()
+        return xTypeName.hashCode()
     }
 
     override fun toString(): String {
-        return erased.toString()
+        return xTypeName.java.toString()
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
index 1735ad4..69109d53 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
@@ -68,7 +68,7 @@
     override fun isError(): Boolean {
         return typeMirror.kind == TypeKind.ERROR ||
             // https://kotlinlang.org/docs/reference/kapt.html#non-existent-type-correction
-            (kotlinType != null && typeName == ERROR_JTYPE_NAME)
+            (kotlinType != null && asTypeName().java == ERROR_JTYPE_NAME)
     }
 
     override val typeName by lazy {
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
index 36e6f0a..ab94b8c 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
@@ -16,14 +16,17 @@
 
 package androidx.room.compiler.processing.ksp
 
+import androidx.room.compiler.codegen.XClassName
 import androidx.room.compiler.processing.XAnnotated
 import androidx.room.compiler.processing.XElement
 import androidx.room.compiler.processing.XMemberContainer
+import androidx.room.compiler.processing.XNullability
 import com.google.devtools.ksp.symbol.AnnotationUseSiteTarget
 import com.google.devtools.ksp.symbol.KSDeclaration
 import com.google.devtools.ksp.symbol.KSFile
 import com.google.devtools.ksp.validate
 import com.squareup.javapoet.ClassName
+import com.squareup.kotlinpoet.javapoet.toKClassName
 
 /**
  * [XMemberContainer] implementation for KSFiles.
@@ -42,7 +45,10 @@
     override val declaration: KSDeclaration?
         get() = null
     override val className: ClassName by lazy {
+        xClassName.java
+    }
 
+    private val xClassName: XClassName by lazy {
         val pkgName = ksFile.packageName.asString().let {
             if (it == "<root>") {
                 ""
@@ -50,11 +56,15 @@
                 it
             }
         }
-        ClassName.get(
+        val java = ClassName.get(
             pkgName, ksFile.findClassName()
         )
+        val kotlin = java.toKClassName()
+        XClassName(java, kotlin, XNullability.NONNULL)
     }
 
+    override fun asClassName() = xClassName
+
     override fun kindName(): String {
         return "file"
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspJvmTypeResolver.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspJvmTypeResolver.kt
index eda347f..ba92d38 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspJvmTypeResolver.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspJvmTypeResolver.kt
@@ -61,7 +61,7 @@
         ).let {
             env.wrap(
                 ksType = it,
-                allowPrimitives = delegate.typeName.isPrimitive
+                allowPrimitives = delegate is KspPrimitiveType
             )
         }
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRawType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRawType.kt
index d027fd0..156bf38 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRawType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRawType.kt
@@ -16,9 +16,9 @@
 
 package androidx.room.compiler.processing.ksp
 
+import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.processing.XRawType
 import androidx.room.compiler.processing.rawTypeName
-import com.squareup.javapoet.TypeName
 
 internal class KspRawType constructor(
     private val original: KspType
@@ -27,24 +27,34 @@
         original.ksType.starProjection().makeNotNullable()
     }
 
-    override val typeName: TypeName by lazy {
-        original.typeName.rawTypeName()
+    override val typeName by lazy {
+        xTypeName.java
     }
 
+    private val xTypeName: XTypeName by lazy {
+        XTypeName(
+            original.asTypeName().java.rawTypeName(),
+            original.asTypeName().kotlin.rawTypeName(),
+            original.nullability
+        )
+    }
+
+    override fun asTypeName() = xTypeName
+
     override fun isAssignableFrom(other: XRawType): Boolean {
         check(other is KspRawType)
         return ksType.isAssignableFrom(other.ksType)
     }
 
     override fun equals(other: Any?): Boolean {
-        return this === other || typeName == (other as? XRawType)?.typeName
+        return this === other || xTypeName == (other as? XRawType)?.asTypeName()
     }
 
     override fun hashCode(): Int {
-        return typeName.hashCode()
+        return xTypeName.hashCode()
     }
 
     override fun toString(): String {
-        return typeName.toString()
+        return xTypeName.kotlin.toString()
     }
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index 876c02a..3e072561 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -59,8 +59,8 @@
 
     private val xTypeName: XTypeName by lazy {
         XTypeName(
-            jvmWildcardType?.typeName ?: resolveJTypeName(),
-            resolveKTypeName(),
+            jvmWildcardType?.asTypeName()?.java ?: resolveJTypeName(),
+            jvmWildcardType?.asTypeName()?.kotlin ?: resolveKTypeName(),
             nullability
         )
     }
@@ -75,7 +75,7 @@
         jvmTypeResolver?.resolveJvmType(env)
     }
 
-    val jvmWildcardTypeOrSelf
+    internal val jvmWildcardTypeOrSelf
         get() = jvmWildcardType ?: this
 
     protected abstract fun resolveJTypeName(): JTypeName
@@ -107,9 +107,9 @@
             return@lazy null
         }
 
-        // If the typeName is primitive, return null for consistency since primitives normally imply
+        // If this is a primitive, return null for consistency since primitives normally imply
         // that there isn't an associated type element.
-        if (typeName.isPrimitive) {
+        if (this is KspPrimitiveType) {
             return@lazy null
         }
 
@@ -176,7 +176,7 @@
         if (nullability == XNullability.UNKNOWN || other.nullability == XNullability.UNKNOWN) {
             // if one the nullabilities is unknown, it is coming from java source code or .class.
             // for those cases, use java platform type equality (via typename)
-            return typeName == other.typeName
+            return asTypeName().java == other.asTypeName().java
         }
         // NOTE: this is inconsistent with java where nullability is ignored.
         // it is intentional but might be reversed if it happens to break use cases.
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainer.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainer.kt
index a0e9fd3..82addef 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainer.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainer.kt
@@ -16,14 +16,17 @@
 
 package androidx.room.compiler.processing.ksp.synthetic
 
+import androidx.room.compiler.codegen.XClassName
 import androidx.room.compiler.processing.XAnnotation
 import androidx.room.compiler.processing.XAnnotationBox
 import androidx.room.compiler.processing.XElement
 import androidx.room.compiler.processing.XEquality
+import androidx.room.compiler.processing.XNullability
 import androidx.room.compiler.processing.ksp.KspMemberContainer
 import androidx.room.compiler.processing.ksp.KspType
 import com.google.devtools.ksp.symbol.KSDeclaration
 import com.squareup.javapoet.ClassName
+import com.squareup.kotlinpoet.javapoet.toKClassName
 import kotlin.reflect.KClass
 
 /**
@@ -47,6 +50,10 @@
         get() = null
 
     override val className: ClassName by lazy {
+        xClassName.java
+    }
+
+    private val xClassName: XClassName by lazy {
         val packageName = binaryName.substringBeforeLast(
             delimiter = '.',
             missingDelimiterValue = ""
@@ -56,13 +63,19 @@
         } else {
             binaryName.substring(packageName.length + 1)
         }.split('$')
-        ClassName.get(
+        val java = ClassName.get(
             packageName,
             shortNames.first(),
             *shortNames.drop(1).toTypedArray()
         )
+        // Even though the generated Java class is not referencable from Kotlin code, instead of
+        // using 'Unavailable', for parity we use the same JavaPoet name for KotlinPoet,
+        val kotlin = java.toKClassName()
+        XClassName(java, kotlin, XNullability.NONNULL)
     }
 
+    override fun asClassName() = xClassName
+
     override fun kindName(): String {
         return "synthethic top level file"
     }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/codegen/XTypeNameTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/codegen/XTypeNameTest.kt
new file mode 100644
index 0000000..4a42d64
--- /dev/null
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/codegen/XTypeNameTest.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2022 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.codegen
+
+import com.google.common.truth.Truth.assertThat
+import com.squareup.kotlinpoet.INT
+import com.squareup.kotlinpoet.SHORT
+import com.squareup.kotlinpoet.javapoet.JClassName
+import org.junit.Test
+
+class XTypeNameTest {
+
+    @Test
+    fun equality() {
+        assertThat(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = INT
+            )
+        ).isEqualTo(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = INT
+            )
+        )
+
+        assertThat(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = INT
+            )
+        ).isNotEqualTo(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = SHORT
+            )
+        )
+
+        assertThat(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = SHORT
+            )
+        ).isNotEqualTo(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = INT
+            )
+        )
+    }
+
+    @Test
+    fun equality_kotlinUnavailable() {
+        assertThat(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = INT
+            )
+        ).isEqualTo(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = XTypeName.UNAVAILABLE_KTYPE_NAME
+            )
+        )
+
+        assertThat(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = XTypeName.UNAVAILABLE_KTYPE_NAME
+            )
+        ).isEqualTo(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = INT
+            )
+        )
+
+        assertThat(
+            XTypeName(
+                java = JClassName.SHORT.box(),
+                kotlin = SHORT
+            )
+        ).isNotEqualTo(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = XTypeName.UNAVAILABLE_KTYPE_NAME
+            )
+        )
+
+        assertThat(
+            XTypeName(
+                java = JClassName.INT.box(),
+                kotlin = XTypeName.UNAVAILABLE_KTYPE_NAME
+            )
+        ).isNotEqualTo(
+            XTypeName(
+                java = JClassName.SHORT.box(),
+                kotlin = SHORT
+            )
+        )
+    }
+
+    @Test
+    fun hashCode_kotlinUnavailable() {
+        val expectedClass = XClassName.get("foo", "Bar")
+        assertThat(
+            XTypeName(
+                java = JClassName.get("foo", "Bar"),
+                kotlin = XTypeName.UNAVAILABLE_KTYPE_NAME
+            ).hashCode()
+        ).isEqualTo(expectedClass.hashCode())
+    }
+}
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/InternalModifierTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/InternalModifierTest.kt
index 1364fb3..524fd62 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/InternalModifierTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/InternalModifierTest.kt
@@ -75,7 +75,7 @@
         fun buildSource(pkg: String) = Source.kotlin(
             "Subject.kt",
             """
-            package $pkg;
+            package $pkg
             internal class InternalClass(val value: String)
             inline class InlineClass(val value:String)
             abstract class Subject {
@@ -101,9 +101,9 @@
             """.trimIndent()
         )
 
-        fun XType.toSignature() = this.typeName.toString()
+        fun XType.toSignature() = this.asTypeName().java.toString()
 
-        fun XMemberContainer.toSignature() = className.toString()
+        fun XMemberContainer.toSignature() = asClassName().java.toString()
 
         fun XFieldElement.toSignature() =
             "${closestMemberContainer.toSignature()}.$name : ${type.toSignature()}"
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt
index fbcc78d..ea65ac3 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt
@@ -18,10 +18,10 @@
 
 import androidx.room.compiler.processing.testcode.KotlinTestClass
 import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.asJTypeName
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.getParameter
 import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.typeName
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 
@@ -40,8 +40,8 @@
             val element = it.processingEnv.requireTypeElement(KotlinTestClass::class)
             element.getMethodByJvmName("mySuspendMethod").apply {
                 assertThat(parameters).hasSize(2)
-                assertThat(getParameter("param1").type.typeName)
-                    .isEqualTo(String::class.typeName())
+                assertThat(getParameter("param1").type.asTypeName().java)
+                    .isEqualTo(String::class.asJTypeName())
                 assertThat(isSuspendFunction()).isTrue()
             }
         }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeAliasTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeAliasTest.kt
index 46e2c5b6..ba7cb80 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeAliasTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeAliasTest.kt
@@ -16,17 +16,24 @@
 
 package androidx.room.compiler.processing
 
-import androidx.room.compiler.processing.util.CONTINUATION_CLASS_NAME
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
+import androidx.room.compiler.processing.util.CONTINUATION_JCLASS_NAME
 import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.className
+import androidx.room.compiler.processing.util.asJClassName
+import androidx.room.compiler.processing.util.asKClassName
 import androidx.room.compiler.processing.util.compileFiles
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.common.truth.Truth.assertThat
-import com.squareup.javapoet.ParameterizedTypeName
-import com.squareup.javapoet.TypeName
-import com.squareup.javapoet.WildcardTypeName
+import com.squareup.kotlinpoet.LONG
+import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
+import com.squareup.kotlinpoet.javapoet.JParameterizedTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JWildcardTypeName
+import com.squareup.kotlinpoet.javapoet.KWildcardTypeName
+import kotlin.coroutines.Continuation
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -57,28 +64,40 @@
                 val elm = invocation.processingEnv.requireTypeElement("$pkg.Subject")
                 elm.getField("prop").type.let {
                     assertThat(it.nullability).isEqualTo(XNullability.NONNULL)
-                    assertThat(it.typeName).isEqualTo(TypeName.LONG)
+                    assertThat(it.asTypeName()).isEqualTo(XTypeName.PRIMITIVE_LONG)
                 }
                 elm.getField("nullable").type.let {
                     assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
-                    assertThat(it.typeName).isEqualTo(TypeName.LONG.box())
+                    assertThat(it.asTypeName())
+                        .isEqualTo(Long::class.asClassName().copy(nullable = true))
                 }
                 elm.getField("inGeneric").type.let {
                     assertThat(it.nullability).isEqualTo(XNullability.NONNULL)
-                    assertThat(it.typeName).isEqualTo(
-                        ParameterizedTypeName.get(
-                            List::class.className(),
-                            TypeName.LONG.box()
+                    assertThat(it.asTypeName().java).isEqualTo(
+                        JParameterizedTypeName.get(
+                            List::class.asJClassName(),
+                            JTypeName.LONG.box()
                         )
                     )
+                    if (invocation.isKsp) {
+                        assertThat(it.asTypeName().kotlin).isEqualTo(
+                            List::class.asKClassName().parameterizedBy(LONG)
+                        )
+                    }
                 }
                 elm.getMethodByJvmName("suspendFun").parameters.last().type.let {
-                    assertThat(it.typeName).isEqualTo(
-                        ParameterizedTypeName.get(
-                            CONTINUATION_CLASS_NAME,
-                            WildcardTypeName.supertypeOf(TypeName.LONG.box())
+                    assertThat(it.asTypeName().java).isEqualTo(
+                        JParameterizedTypeName.get(
+                            CONTINUATION_JCLASS_NAME,
+                            JWildcardTypeName.supertypeOf(JTypeName.LONG.box())
                         )
                     )
+                    if (invocation.isKsp) {
+                        assertThat(it.asTypeName().kotlin).isEqualTo(
+                            Continuation::class.asKClassName()
+                                .parameterizedBy(KWildcardTypeName.consumerOf(LONG))
+                        )
+                    }
                 }
             }
         }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeInheritanceTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeInheritanceTest.kt
index 7843716..40d916e 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeInheritanceTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/TypeInheritanceTest.kt
@@ -62,29 +62,42 @@
 
     private fun XTestInvocation.assertFieldType(fieldName: String, expectedTypeName: String) {
         val sub = processingEnv.requireTypeElement("SubClass")
-        val subField = sub.getField(fieldName).asMemberOf(sub.type).typeName.toString()
-        assertThat(subField).isEqualTo(expectedTypeName)
+        val subField = sub.getField(fieldName).asMemberOf(sub.type)
+        assertThat(subField.asTypeName().java.toString()).isEqualTo(expectedTypeName)
+        if (isKsp) {
+            assertThat(subField.asTypeName().kotlin.toString()).isEqualTo(expectedTypeName)
+        }
 
         val base = processingEnv.requireTypeElement("BaseClass")
-        val baseField = base.getField(fieldName).asMemberOf(sub.type).typeName.toString()
-        assertThat(baseField).isEqualTo(expectedTypeName)
+        val baseField = base.getField(fieldName).asMemberOf(sub.type)
+        assertThat(baseField.asTypeName().java.toString()).isEqualTo(expectedTypeName)
+        if (isKsp) {
+            assertThat(baseField.asTypeName().kotlin.toString()).isEqualTo(expectedTypeName)
+        }
     }
 
     private fun XTestInvocation.assertParamType(
         methodName: String,
         paramName: String,
-        expectedTypeName: String,
+        expectedJTypeName: String,
+        expectedKTypeName: String,
     ) {
         val sub = processingEnv.requireTypeElement("SubClass")
         val subMethod = sub.getMethodByJvmName(methodName)
         val paramIndex = subMethod.parameters.indexOf(subMethod.getParameter(paramName))
         val subMethodParam = subMethod.asMemberOf(sub.type).parameterTypes[paramIndex]
-        assertThat(subMethodParam.typeName.toString()).isEqualTo(expectedTypeName)
+        assertThat(subMethodParam.asTypeName().java.toString()).isEqualTo(expectedJTypeName)
+        if (isKsp) {
+            assertThat(subMethodParam.asTypeName().kotlin.toString()).isEqualTo(expectedKTypeName)
+        }
 
         val base = processingEnv.requireTypeElement("BaseClass")
         val baseMethod = base.getMethodByJvmName(methodName)
         val baseMethodParam = baseMethod.asMemberOf(sub.type).parameterTypes[paramIndex]
-        assertThat(baseMethodParam.typeName.toString()).isEqualTo(expectedTypeName)
+        assertThat(baseMethodParam.asTypeName().java.toString()).isEqualTo(expectedJTypeName)
+        if (isKsp) {
+            assertThat(baseMethodParam.asTypeName().kotlin.toString()).isEqualTo(expectedKTypeName)
+        }
     }
 
     private fun XTestInvocation.assertReturnType(methodName: String, expectedTypeName: String) {
@@ -110,9 +123,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -132,9 +145,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -154,9 +167,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -176,9 +189,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -198,9 +211,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -220,9 +233,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -242,9 +255,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -264,9 +277,9 @@
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT2", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -285,9 +298,14 @@
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -313,9 +331,14 @@
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -339,9 +362,24 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -371,9 +409,14 @@
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -397,9 +440,24 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -429,9 +487,14 @@
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -455,9 +518,24 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -485,9 +563,24 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
@@ -516,8 +609,13 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -525,12 +623,22 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<Baz>>",
+                    "Foo<Bar<Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -547,8 +655,13 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -556,12 +669,17 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -578,8 +696,13 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -587,12 +710,17 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -609,7 +737,12 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -617,14 +750,24 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "param",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -641,8 +784,13 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -650,12 +798,22 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<Baz>>",
+                    "Foo<Bar<Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -672,7 +830,12 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -680,14 +843,29 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "param",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<Baz>>",
+                    "Foo<Bar<Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -704,7 +882,12 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<Bar<? extends Baz>>",
+                "Foo<Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -712,14 +895,29 @@
             if (invocation.isKsp) {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "param",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<Baz>>")
+                invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<Baz>>",
+                    "Foo<Bar<Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -758,8 +956,13 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -768,14 +971,22 @@
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT1", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertParamType(
-                    "method", "paramT1", "Foo<? extends Bar<? extends Baz>>"
+                    "method",
+                    "paramT1",
+                    "Foo<? extends Bar<? extends Baz>>",
+                    "Foo<out Bar<out Baz>>"
                 )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
@@ -792,8 +1003,13 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType("method", "param", "Foo<Bar<Baz>>", "Foo<Bar<Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -803,7 +1019,7 @@
                 invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
                 invocation.assertParamType(
-                    "method", "paramT1", "Foo<Bar<? extends Baz>>"
+                    "method", "paramT1", "Foo<Bar<? extends Baz>>", "Foo<Bar<out Baz>>"
                 )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
@@ -811,7 +1027,10 @@
                 invocation.assertFieldType("varFieldT1", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertParamType(
-                    "method", "paramT1", "Foo<? extends Bar<? extends Baz>>"
+                    "method",
+                    "paramT1",
+                    "Foo<? extends Bar<? extends Baz>>",
+                    "Foo<out Bar<out Baz>>"
                 )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
@@ -828,9 +1047,24 @@
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
 
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<? extends Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
 
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
@@ -863,7 +1097,12 @@
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
 
             // TODO(b/237280547): Make KSP type name match KAPT.
             if (invocation.isKsp) {
@@ -871,17 +1110,35 @@
                 invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "param",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varField", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT1", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<? extends Bar<? extends Baz>>")
-                invocation.assertParamType("method", "param", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertParamType(
-                    "method", "paramT1", "Foo<? extends Bar<? extends Baz>>"
+                    "method",
+                    "param",
+                    "Foo<? extends Bar<? extends Baz>>",
+                    "Foo<out Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<? extends Bar<? extends Baz>>",
+                    "Foo<out Bar<out Baz>>"
                 )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
@@ -897,9 +1154,24 @@
         ) { invocation ->
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<? extends Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<Baz>>",
+                "Foo<out Bar<Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -929,7 +1201,12 @@
         ) { invocation ->
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -939,16 +1216,36 @@
                 invocation.assertFieldType("varField", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT1", "Foo<Bar<Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<Bar<Baz>>")
-                invocation.assertParamType("method", "param", "Foo<Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "param",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<Bar<? extends Baz>>",
+                    "Foo<Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<Baz>>")
             } else {
                 invocation.assertFieldType("valFieldT2", "Foo<Bar<? extends Baz>>")
                 invocation.assertFieldType("varField", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT1", "Foo<? extends Bar<? extends Baz>>")
                 invocation.assertFieldType("varFieldT2", "Foo<? extends Bar<? extends Baz>>")
-                invocation.assertParamType("method", "param", "Foo<? extends Bar<? extends Baz>>")
-                invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<? extends Baz>>")
+                invocation.assertParamType(
+                    "method",
+                    "param",
+                    "Foo<? extends Bar<? extends Baz>>",
+                    "Foo<out Bar<out Baz>>"
+                )
+                invocation.assertParamType(
+                    "method",
+                    "paramT1",
+                    "Foo<? extends Bar<? extends Baz>>",
+                    "Foo<out Bar<out Baz>>"
+                )
                 invocation.assertReturnType("methodReturnT2", "Foo<Bar<? extends Baz>>")
             }
         }
@@ -963,9 +1260,24 @@
         ) { invocation ->
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<? extends Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<? extends Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
@@ -995,9 +1307,24 @@
         ) { invocation ->
             invocation.assertFieldType("valField", "Foo<Bar<Baz>>")
             invocation.assertFieldType("valFieldT1", "Foo<Bar<Baz>>")
-            invocation.assertParamType("method", "param", "Foo<? extends Bar<? extends Baz>>")
-            invocation.assertParamType("method", "paramT1", "Foo<? extends Bar<? extends Baz>>")
-            invocation.assertParamType("method", "paramT2", "Foo<? extends Bar<? extends Baz>>")
+            invocation.assertParamType(
+                "method",
+                "param",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT1",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
+            invocation.assertParamType(
+                "method",
+                "paramT2",
+                "Foo<? extends Bar<? extends Baz>>",
+                "Foo<out Bar<out Baz>>"
+            )
             invocation.assertReturnType("methodReturn", "Foo<Bar<Baz>>")
             invocation.assertReturnType("methodReturnT1", "Foo<Bar<Baz>>")
 
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
index c86cdc4..ad37a87 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
 import androidx.room.compiler.processing.testcode.JavaAnnotationWithDefaults
 import androidx.room.compiler.processing.testcode.JavaAnnotationWithEnum
 import androidx.room.compiler.processing.testcode.JavaAnnotationWithEnumArray
@@ -41,7 +43,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
-import java.util.LinkedHashMap
 
 @RunWith(Parameterized::class)
 class XAnnotationBoxTest(
@@ -243,11 +244,11 @@
             element.getAnnotation(MainAnnotation::class)!!.let { annotation ->
                 assertThat(
                     annotation.getAsTypeList("typeList").map {
-                        it.typeName
+                        it.asTypeName()
                     }
                 ).containsExactly(
-                    String::class.typeName(),
-                    Int::class.typeName()
+                    String::class.asClassName(),
+                    XTypeName.PRIMITIVE_INT
                 )
                 assertThat(
                     annotation.getAsType("singleType")
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
index cd8ddde..889a878 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
 import androidx.room.compiler.processing.compat.XConverters.toJavac
 import androidx.room.compiler.processing.testcode.JavaAnnotationWithDefaults
 import androidx.room.compiler.processing.testcode.JavaAnnotationWithEnum
@@ -29,17 +31,18 @@
 import androidx.room.compiler.processing.testcode.TestSuppressWarnings
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.asJTypeName
+import androidx.room.compiler.processing.util.asKTypeName
 import androidx.room.compiler.processing.util.compileFiles
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.getParameter
 import androidx.room.compiler.processing.util.runProcessorTest
 import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
-import androidx.room.compiler.processing.util.typeName
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
-import com.squareup.javapoet.AnnotationSpec
-import com.squareup.javapoet.ClassName
+import com.squareup.kotlinpoet.javapoet.JAnnotationSpec
+import com.squareup.kotlinpoet.javapoet.JClassName
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -136,10 +139,10 @@
         ) { invocation ->
             val element = invocation.processingEnv.requireTypeElement("test.MyClass")
             val annotation =
-                element.requireAnnotation(ClassName.get(TestSuppressWarnings::class.java))
+                element.requireAnnotation(JClassName.get(TestSuppressWarnings::class.java))
             if (!invocation.isKsp) {
                 assertThat(annotation.toAnnotationSpec())
-                    .isEqualTo(AnnotationSpec.get(annotation.toJavac()))
+                    .isEqualTo(JAnnotationSpec.get(annotation.toJavac()))
             }
         }
     }
@@ -188,7 +191,8 @@
 
             annotationsForAnnotations.forEach {
                 val annotations = element.getAnnotationsAnnotatedWith(
-                    ClassName.get("foo.bar", it))
+                    JClassName.get("foo.bar", it)
+                )
                 assertThat(annotations).hasSize(1)
                 val annotation = annotations.first()
                 assertThat(annotation.name)
@@ -273,7 +277,7 @@
         ) { invocation ->
             val element = invocation.processingEnv.requireTypeElement("foo.bar.Baz")
             val annotation =
-                element.requireAnnotation(ClassName.get(TestSuppressWarnings::class.java))
+                element.requireAnnotation(JClassName.get(TestSuppressWarnings::class.java))
 
             val argument = annotation.getAnnotationValue("value")
             assertThat(argument.name).isEqualTo("value")
@@ -404,16 +408,16 @@
 
             assertThat(
                 annotation.get<List<XType>>("typeList").map {
-                    it.typeName
+                    it.asTypeName()
                 }
             ).containsExactly(
-                String::class.typeName(),
-                Int::class.typeName()
+                String::class.asClassName(),
+                XTypeName.PRIMITIVE_INT
             )
             assertThat(
                 annotation.get<XType>("singleType")
             ).isEqualTo(
-                invocation.processingEnv.requireType(Long::class.typeName())
+                invocation.processingEnv.requireType(Long::class)
             )
 
             assertThat(annotation.get<Int>("intMethod")).isEqualTo(3)
@@ -451,8 +455,8 @@
             val subject = invocation.processingEnv.requireTypeElement("Subject")
             val annotation = subject.requireAnnotation<JavaAnnotationWithTypeReferences>()
             val annotationValue = annotation.get<List<XType>>("value").single()
-            assertThat(annotationValue.typeName).isEqualTo(
-                ClassName.get(String::class.java)
+            assertThat(annotationValue.asTypeName().java).isEqualTo(
+                String::class.asJTypeName()
             )
         }
     }
@@ -614,17 +618,27 @@
                     assertThat(annotation.get<String>("stringVal"))
                         .isEqualTo("foo")
                     assertThat(
-                        annotation.getAsType("typeVal").rawType.typeName
-                    ).isEqualTo(
-                        ClassName.get(HashMap::class.java)
-                    )
+                        annotation.getAsType("typeVal").rawType.asTypeName().java
+                    ).isEqualTo(HashMap::class.asJTypeName())
                     assertThat(
                         annotation.getAsTypeList("typeArrayVal").map {
-                            it.rawType.typeName
+                            it.rawType.asTypeName().java
                         }
                     ).isEqualTo(
-                        listOf(ClassName.get(LinkedHashMap::class.java))
+                        listOf(LinkedHashMap::class.asJTypeName())
                     )
+                    if (invocation.isKsp) {
+                        assertThat(
+                            annotation.getAsType("typeVal").rawType.asTypeName().kotlin
+                        ).isEqualTo(HashMap::class.asKTypeName())
+                        assertThat(
+                            annotation.getAsTypeList("typeArrayVal").map {
+                                it.rawType.asTypeName().kotlin
+                            }
+                        ).isEqualTo(
+                            listOf(LinkedHashMap::class.asKTypeName())
+                        )
+                    }
 
                     val enumValueEntry = annotation.getAsEnum("enumVal")
                     assertThat(enumValueEntry.name).isEqualTo("DEFAULT")
@@ -676,7 +690,7 @@
         val kotlinSrc = Source.kotlin(
             "KotlinSubject.kt",
             """
-            import androidx.room.compiler.processing.testcode.*;
+            import androidx.room.compiler.processing.testcode.*
             class KotlinSubject {
                 @JavaAnnotationWithPrimitiveArray(intArray = [1, 2, 3])
                 val annotated1:Any = TODO()
@@ -715,7 +729,7 @@
         val kotlinSrc = Source.kotlin(
             "KotlinSubject.kt",
             """
-            import androidx.room.compiler.processing.testcode.*;
+            import androidx.room.compiler.processing.testcode.*
             class KotlinSubject {
                 @JavaAnnotationWithEnum(JavaEnum.VAL1)
                 val annotated1: Any = TODO()
@@ -938,7 +952,7 @@
         ) { invocation ->
             val element = invocation.processingEnv.requireTypeElement("foo.bar.Baz")
             val annotation =
-                element.requireAnnotation(ClassName.get(JavaAnnotationWithDefaults::class.java))
+                element.requireAnnotation(JClassName.get(JavaAnnotationWithDefaults::class.java))
 
             assertThat(annotation.get<String>("stringVal")).isEqualTo("test")
             assertThat(annotation.get<Int>("intVal")).isEqualTo(3)
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt
index 3a55b34..8393b02 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt
@@ -16,16 +16,38 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.JArrayTypeName
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.asJClassName
+import androidx.room.compiler.processing.util.asKClassName
 import androidx.room.compiler.processing.util.compileFiles
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.common.truth.Truth.assertThat
-import com.squareup.javapoet.ArrayTypeName
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.ParameterizedTypeName
-import com.squareup.javapoet.TypeName
-import com.squareup.javapoet.WildcardTypeName
+import com.squareup.kotlinpoet.ARRAY
+import com.squareup.kotlinpoet.BOOLEAN
+import com.squareup.kotlinpoet.BOOLEAN_ARRAY
+import com.squareup.kotlinpoet.BYTE
+import com.squareup.kotlinpoet.BYTE_ARRAY
+import com.squareup.kotlinpoet.CHAR
+import com.squareup.kotlinpoet.CHAR_ARRAY
+import com.squareup.kotlinpoet.DOUBLE
+import com.squareup.kotlinpoet.DOUBLE_ARRAY
+import com.squareup.kotlinpoet.FLOAT
+import com.squareup.kotlinpoet.FLOAT_ARRAY
+import com.squareup.kotlinpoet.INT
+import com.squareup.kotlinpoet.INT_ARRAY
+import com.squareup.kotlinpoet.LONG
+import com.squareup.kotlinpoet.LONG_ARRAY
+import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
+import com.squareup.kotlinpoet.SHORT
+import com.squareup.kotlinpoet.SHORT_ARRAY
+import com.squareup.kotlinpoet.STAR
+import com.squareup.kotlinpoet.javapoet.JClassName
+import com.squareup.kotlinpoet.javapoet.JParameterizedTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JWildcardTypeName
+import com.squareup.kotlinpoet.javapoet.KClassName
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -113,14 +135,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Boolean) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.BOOLEAN)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.BOOLEAN)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(BOOLEAN)
+                }
                 assertThat(annotationValue.hasBooleanValue()).isTrue()
                 assertThat(annotationValue.asBoolean()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Boolean) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.BOOLEAN))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.BOOLEAN))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(BOOLEAN_ARRAY)
+                }
                 assertThat(annotationValue.hasBooleanListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asBooleanList())
@@ -196,14 +225,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Int) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.INT)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.INT)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(INT)
+                }
                 assertThat(annotationValue.hasIntValue()).isTrue()
                 assertThat(annotationValue.asInt()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Int) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.INT))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.INT))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(INT_ARRAY)
+                }
                 assertThat(annotationValue.hasIntListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asIntList())
@@ -279,14 +315,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Short) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.SHORT)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.SHORT)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(SHORT)
+                }
                 assertThat(annotationValue.hasShortValue()).isTrue()
                 assertThat(annotationValue.asShort()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Short) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.SHORT))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.SHORT))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(SHORT_ARRAY)
+                }
                 assertThat(annotationValue.hasShortListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asShortList())
@@ -362,14 +405,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Long) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.LONG)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.LONG)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(LONG)
+                }
                 assertThat(annotationValue.hasLongValue()).isTrue()
                 assertThat(annotationValue.asLong()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Long) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.LONG))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.LONG))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(LONG_ARRAY)
+                }
                 assertThat(annotationValue.hasLongListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asLongList())
@@ -445,14 +495,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Float) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.FLOAT)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.FLOAT)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(FLOAT)
+                }
                 assertThat(annotationValue.hasFloatValue()).isTrue()
                 assertThat(annotationValue.asFloat()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Float) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.FLOAT))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.FLOAT))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(FLOAT_ARRAY)
+                }
                 assertThat(annotationValue.hasFloatListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asFloatList())
@@ -528,14 +585,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Double) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.DOUBLE)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.DOUBLE)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(DOUBLE)
+                }
                 assertThat(annotationValue.hasDoubleValue()).isTrue()
                 assertThat(annotationValue.asDouble()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Double) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.DOUBLE))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.DOUBLE))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(DOUBLE_ARRAY)
+                }
                 assertThat(annotationValue.hasDoubleListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asDoubleList())
@@ -611,14 +675,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Byte) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.BYTE)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.BYTE)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(BYTE)
+                }
                 assertThat(annotationValue.hasByteValue()).isTrue()
                 assertThat(annotationValue.asByte()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Byte) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.BYTE))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.BYTE))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(BYTE_ARRAY)
+                }
                 assertThat(annotationValue.hasByteListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asByteList())
@@ -694,14 +765,21 @@
             ) as Source.KotlinSource
         ) { invocation ->
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: Char) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(TypeName.CHAR)
+                assertThat(annotationValue.valueType.asTypeName().java).isEqualTo(JTypeName.CHAR)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin).isEqualTo(CHAR)
+                }
                 assertThat(annotationValue.hasCharValue()).isTrue()
                 assertThat(annotationValue.asChar()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: Char) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(TypeName.CHAR))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(JTypeName.CHAR))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(CHAR_ARRAY)
+                }
                 assertThat(annotationValue.hasCharListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asCharList())
@@ -776,17 +854,24 @@
                 """.trimIndent()
             ) as Source.KotlinSource
         ) { invocation ->
-            val stringTypeName = TypeName.get(String::class.java)
-
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: String) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(stringTypeName)
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(String::class.asJClassName())
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(String::class.asKClassName())
+                }
                 assertThat(annotationValue.hasStringValue()).isTrue()
                 assertThat(annotationValue.asString()).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: String) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(stringTypeName))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(String::class.asJClassName()))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(ARRAY.parameterizedBy(String::class.asKClassName()))
+                }
                 assertThat(annotationValue.hasStringListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asStringList())
@@ -863,17 +948,27 @@
                 """.trimIndent()
             ) as Source.KotlinSource
         ) { invocation ->
-            val myEnumTypeName = ClassName.get("", "test.MyEnum")
+            val myEnumJTypeName = JClassName.get("", "test.MyEnum")
+            val myEnumKTypeName = KClassName("", "test.MyEnum")
 
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: String) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(myEnumTypeName)
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(myEnumJTypeName)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(myEnumKTypeName)
+                }
                 assertThat(annotationValue.hasEnumValue()).isTrue()
                 assertThat(annotationValue.asEnum().name).isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: String) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(myEnumTypeName))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(myEnumJTypeName))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(ARRAY.parameterizedBy(myEnumKTypeName))
+                }
                 assertThat(annotationValue.hasEnumListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asEnumList().map { it.name })
@@ -953,20 +1048,25 @@
                 """.trimIndent()
             ) as Source.KotlinSource
         ) { invocation ->
-            val classTypeName = ParameterizedTypeName.get(
-                ClassName.get(Class::class.java),
-                WildcardTypeName.subtypeOf(TypeName.OBJECT)
+            val classJTypeName = JParameterizedTypeName.get(
+                JClassName.get(Class::class.java),
+                JWildcardTypeName.subtypeOf(JTypeName.OBJECT)
             )
-            val kClassTypeName = ParameterizedTypeName.get(
-                ClassName.get(kotlin.reflect.KClass::class.java),
-                WildcardTypeName.subtypeOf(TypeName.OBJECT)
+            val kClassJTypeName = JParameterizedTypeName.get(
+                JClassName.get(kotlin.reflect.KClass::class.java),
+                JWildcardTypeName.subtypeOf(JTypeName.OBJECT)
             )
+            val kClassKTypeName = kotlin.reflect.KClass::class.asKClassName().parameterizedBy(STAR)
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: String) {
                 // TODO(bcorso): Consider making the value types match in this case.
                 if (!invocation.isKsp || (sourceKind == SourceKind.JAVA && !isPreCompiled)) {
-                    assertThat(annotationValue.valueType.typeName).isEqualTo(classTypeName)
+                    assertThat(annotationValue.valueType.asTypeName().java)
+                        .isEqualTo(classJTypeName)
                 } else {
-                    assertThat(annotationValue.valueType.typeName).isEqualTo(kClassTypeName)
+                    assertThat(annotationValue.valueType.asTypeName().java)
+                        .isEqualTo(kClassJTypeName)
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(kClassKTypeName)
                 }
                 assertThat(annotationValue.hasTypeValue()).isTrue()
                 assertThat(annotationValue.asType().typeElement?.name).isEqualTo(expectedValue)
@@ -975,11 +1075,13 @@
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: String) {
                 // TODO(bcorso): Consider making the value types match in this case.
                 if (!invocation.isKsp || (sourceKind == SourceKind.JAVA && !isPreCompiled)) {
-                    assertThat(annotationValue.valueType.typeName)
-                        .isEqualTo(ArrayTypeName.of(classTypeName))
+                    assertThat(annotationValue.valueType.asTypeName().java)
+                        .isEqualTo(JArrayTypeName.of(classJTypeName))
                 } else {
-                    assertThat(annotationValue.valueType.typeName)
-                        .isEqualTo(ArrayTypeName.of(kClassTypeName))
+                    assertThat(annotationValue.valueType.asTypeName().java)
+                        .isEqualTo(JArrayTypeName.of(kClassJTypeName))
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(ARRAY.parameterizedBy(kClassKTypeName))
                 }
                 assertThat(annotationValue.hasTypeListValue()).isTrue()
                 // Check the list of values
@@ -1059,18 +1161,28 @@
                 """.trimIndent()
             ) as Source.KotlinSource
         ) { invocation ->
-            val aTypeName = ClassName.get("", "test.A")
+            val aJTypeName = JClassName.get("", "test.A")
+            val aKTypeName = KClassName("", "test.A")
 
             fun checkSingleValue(annotationValue: XAnnotationValue, expectedValue: String) {
-                assertThat(annotationValue.valueType.typeName).isEqualTo(aTypeName)
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(aJTypeName)
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(aKTypeName)
+                }
                 assertThat(annotationValue.hasAnnotationValue()).isTrue()
                 assertThat(annotationValue.asAnnotation().getAsString("value"))
                     .isEqualTo(expectedValue)
             }
 
             fun checkListValues(annotationValue: XAnnotationValue, vararg expectedValues: String) {
-                assertThat(annotationValue.valueType.typeName)
-                    .isEqualTo(ArrayTypeName.of(aTypeName))
+                assertThat(annotationValue.valueType.asTypeName().java)
+                    .isEqualTo(JArrayTypeName.of(aJTypeName))
+                if (invocation.isKsp) {
+                    assertThat(annotationValue.valueType.asTypeName().kotlin)
+                        .isEqualTo(ARRAY.parameterizedBy(aKTypeName))
+                }
                 assertThat(annotationValue.hasAnnotationListValue()).isTrue()
                 // Check the list of values
                 assertThat(annotationValue.asAnnotationList().map { it.getAsString("value") })
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
index 0c28901..f7c0e52 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
 import androidx.room.compiler.processing.javac.JavacTypeElement
 import androidx.room.compiler.processing.ksp.KspExecutableElement
 import androidx.room.compiler.processing.ksp.KspFieldElement
@@ -24,26 +26,25 @@
 import androidx.room.compiler.processing.testcode.OtherAnnotation
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
-import androidx.room.compiler.processing.util.className
+import androidx.room.compiler.processing.util.asJClassName
 import androidx.room.compiler.processing.util.compileFiles
+import androidx.room.compiler.processing.util.createXTypeVariableName
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.getParameter
 import androidx.room.compiler.processing.util.kspProcessingEnv
 import androidx.room.compiler.processing.util.kspResolver
-import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
 import androidx.room.compiler.processing.util.runProcessorTest
+import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
 import com.google.common.truth.Truth.assertThat
 import com.google.devtools.ksp.KspExperimental
 import com.google.devtools.ksp.symbol.KSFunctionDeclaration
 import com.google.devtools.ksp.symbol.KSPropertyDeclaration
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.TypeName
-import com.squareup.javapoet.TypeVariableName
+import com.squareup.kotlinpoet.javapoet.JClassName
+import kotlin.reflect.KClass
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import kotlin.reflect.KClass
 
 @RunWith(JUnit4::class)
 class XElementTest {
@@ -191,71 +192,75 @@
         ) {
             fun validateMethodElement(
                 element: XTypeElement,
-                tTypeName: TypeName,
-                rTypeName: TypeName
+                tTypeName: XTypeName,
+                rTypeName: XTypeName
             ) {
                 element.getMethodByJvmName("returnT").let { method ->
                     assertThat(method.parameters).isEmpty()
-                    assertThat(method.returnType.typeName).isEqualTo(tTypeName)
+                    assertThat(method.returnType.asTypeName()).isEqualTo(tTypeName)
                 }
                 element.getMethodByJvmName("receiveT").let { method ->
-                    assertThat(method.getParameter("param1").type.typeName).isEqualTo(tTypeName)
-                    assertThat(method.returnType.typeName).isEqualTo(TypeName.INT)
+                    assertThat(method.getParameter("param1").type.asTypeName()).isEqualTo(tTypeName)
+                    assertThat(method.returnType.asTypeName())
+                        .isEqualTo(XTypeName.PRIMITIVE_INT)
                 }
                 element.getMethodByJvmName("receiveR").let { method ->
-                    assertThat(method.getParameter("param1").type.typeName).isEqualTo(rTypeName)
-                    assertThat(method.returnType.typeName).isEqualTo(TypeName.INT)
+                    assertThat(method.getParameter("param1").type.asTypeName()).isEqualTo(rTypeName)
+                    assertThat(method.returnType.asTypeName())
+                        .isEqualTo(XTypeName.PRIMITIVE_INT)
                 }
                 element.getMethodByJvmName("returnR").let { method ->
                     assertThat(method.parameters).isEmpty()
-                    assertThat(method.returnType.typeName).isEqualTo(rTypeName)
+                    assertThat(method.returnType.asTypeName()).isEqualTo(rTypeName)
                 }
             }
             fun validateMethodTypeAsMemberOf(
                 element: XTypeElement,
-                tTypeName: TypeName,
-                rTypeName: TypeName
+                tTypeName: XTypeName,
+                rTypeName: XTypeName
             ) {
                 element.getMethodByJvmName("returnT").asMemberOf(element.type).let { method ->
                     assertThat(method.parameterTypes).isEmpty()
-                    assertThat(method.returnType.typeName).isEqualTo(tTypeName)
+                    assertThat(method.returnType.asTypeName()).isEqualTo(tTypeName)
                 }
                 element.getMethodByJvmName("receiveT").asMemberOf(element.type).let { method ->
                     assertThat(method.parameterTypes).hasSize(1)
-                    assertThat(method.parameterTypes[0].typeName).isEqualTo(tTypeName)
-                    assertThat(method.returnType.typeName).isEqualTo(TypeName.INT)
+                    assertThat(method.parameterTypes[0].asTypeName()).isEqualTo(tTypeName)
+                    assertThat(method.returnType.asTypeName())
+                        .isEqualTo(XTypeName.PRIMITIVE_INT)
                 }
                 element.getMethodByJvmName("receiveR").asMemberOf(element.type).let { method ->
                     assertThat(method.parameterTypes).hasSize(1)
-                    assertThat(method.parameterTypes[0].typeName).isEqualTo(rTypeName)
-                    assertThat(method.returnType.typeName).isEqualTo(TypeName.INT)
+                    assertThat(method.parameterTypes[0].asTypeName()).isEqualTo(rTypeName)
+                    assertThat(method.returnType.asTypeName())
+                        .isEqualTo(XTypeName.PRIMITIVE_INT)
                 }
                 element.getMethodByJvmName("returnR").let { method ->
                     assertThat(method.parameters).isEmpty()
-                    assertThat(method.returnType.typeName).isEqualTo(rTypeName)
+                    assertThat(method.returnType.asTypeName()).isEqualTo(rTypeName)
                 }
             }
 
             validateMethodElement(
                 element = it.processingEnv.requireTypeElement("foo.bar.Base"),
-                tTypeName = TypeVariableName.get("T"),
-                rTypeName = TypeVariableName.get("R")
+                tTypeName = createXTypeVariableName("T"),
+                rTypeName = createXTypeVariableName("R")
             )
             validateMethodElement(
                 element = it.processingEnv.requireTypeElement("foo.bar.Child"),
-                tTypeName = TypeVariableName.get("T"),
-                rTypeName = TypeVariableName.get("R")
+                tTypeName = createXTypeVariableName("T"),
+                rTypeName = createXTypeVariableName("R")
             )
 
             validateMethodTypeAsMemberOf(
                 element = it.processingEnv.requireTypeElement("foo.bar.Base"),
-                tTypeName = TypeVariableName.get("T"),
-                rTypeName = TypeVariableName.get("R")
+                tTypeName = createXTypeVariableName("T"),
+                rTypeName = createXTypeVariableName("R")
             )
             validateMethodTypeAsMemberOf(
                 element = it.processingEnv.requireTypeElement("foo.bar.Child"),
-                tTypeName = String::class.className(),
-                rTypeName = TypeVariableName.get("R")
+                tTypeName = String::class.asClassName(),
+                rTypeName = createXTypeVariableName("R")
             )
         }
     }
@@ -348,36 +353,67 @@
             assertThat(element.hasAllAnnotations(RunWith::class)).isTrue()
             assertThat(element.hasAllAnnotations(RunWith::class, Test::class)).isFalse()
 
-            assertThat(element.hasAllAnnotations(*arrayOf<ClassName>())).isTrue()
-            assertThat(element.hasAllAnnotations(RunWith::class.className())).isTrue()
-            assertThat(element.hasAllAnnotations(RunWith::class.className(),
-                Test::class.className())).isFalse()
+            assertThat(element.hasAllAnnotations(*arrayOf<JClassName>())).isTrue()
+            assertThat(element.hasAllAnnotations(RunWith::class.asJClassName())).isTrue()
+            assertThat(
+                element.hasAllAnnotations(
+                    RunWith::class.asJClassName(),
+                    Test::class.asJClassName()
+                )
+            ).isFalse()
 
-            assertThat(element.hasAllAnnotations(emptyList<ClassName>())).isTrue()
-            assertThat(element.hasAllAnnotations(listOf(RunWith::class.className()))).isTrue()
-            assertThat(element.hasAllAnnotations(listOf(RunWith::class.className(),
-                Test::class.className()))).isFalse()
+            assertThat(element.hasAllAnnotations(emptyList<JClassName>())).isTrue()
+            assertThat(element.hasAllAnnotations(listOf(RunWith::class.asJClassName()))).isTrue()
+            assertThat(
+                element.hasAllAnnotations(
+                    listOf(
+                        RunWith::class.asJClassName(),
+                        Test::class.asJClassName()
+                    )
+                )
+            ).isFalse()
 
             element.getMethodByJvmName("testMethod").let { method ->
                 assertThat(method.hasAllAnnotations(*arrayOf<KClass<Annotation>>())).isTrue()
                 assertThat(method.hasAllAnnotations(Test::class)).isTrue()
                 assertThat(method.hasAllAnnotations(Test::class, OtherAnnotation::class)).isTrue()
-                assertThat(method.hasAllAnnotations(Test::class, OtherAnnotation::class,
-                    RunWith::class)).isFalse()
+                assertThat(
+                    method.hasAllAnnotations(
+                        Test::class, OtherAnnotation::class,
+                        RunWith::class
+                    )
+                ).isFalse()
 
-                assertThat(method.hasAllAnnotations(*arrayOf<ClassName>())).isTrue()
-                assertThat(method.hasAllAnnotations(Test::class.className())).isTrue()
-                assertThat(method.hasAllAnnotations(Test::class.className(),
-                    OtherAnnotation::class.className())).isTrue()
-                assertThat(method.hasAllAnnotations(Test::class.className(),
-                    OtherAnnotation::class.className(), RunWith::class.className())).isFalse()
+                assertThat(method.hasAllAnnotations(*arrayOf<JClassName>())).isTrue()
+                assertThat(method.hasAllAnnotations(Test::class.asJClassName())).isTrue()
+                assertThat(
+                    method.hasAllAnnotations(
+                        Test::class.asJClassName(),
+                        OtherAnnotation::class.asJClassName()
+                    )
+                ).isTrue()
+                assertThat(
+                    method.hasAllAnnotations(
+                        Test::class.asJClassName(),
+                        OtherAnnotation::class.asJClassName(), RunWith::class.asJClassName()
+                    )
+                ).isFalse()
 
-                assertThat(method.hasAllAnnotations(emptyList<ClassName>())).isTrue()
-                assertThat(method.hasAllAnnotations(listOf(Test::class.className()))).isTrue()
-                assertThat(method.hasAllAnnotations(
-                    listOf(Test::class.className(), OtherAnnotation::class.className()))).isTrue()
-                assertThat(method.hasAllAnnotations(listOf(Test::class.className(),
-                    OtherAnnotation::class.className(), RunWith::class.className()))).isFalse()
+                assertThat(method.hasAllAnnotations(emptyList<JClassName>())).isTrue()
+                assertThat(method.hasAllAnnotations(listOf(Test::class.asJClassName()))).isTrue()
+                assertThat(
+                    method.hasAllAnnotations(
+                        listOf(Test::class.asJClassName(), OtherAnnotation::class.asJClassName())
+                    )
+                ).isTrue()
+                assertThat(
+                    method.hasAllAnnotations(
+                        listOf(
+                            Test::class.asJClassName(),
+                            OtherAnnotation::class.asJClassName(), RunWith::class.asJClassName()
+                        )
+                    )
+                ).isFalse()
             }
             element.getField("testField").let { field ->
                 assertThat(field.hasAllAnnotations(*arrayOf<KClass<Annotation>>())).isTrue()
@@ -386,20 +422,40 @@
                 assertThat(field.hasAllAnnotations(OtherAnnotation::class, OtherAnnotation::class))
                     .isTrue()
 
-                assertThat(field.hasAllAnnotations(*arrayOf<ClassName>())).isTrue()
-                assertThat(field.hasAllAnnotations(OtherAnnotation::class.className())).isTrue()
-                assertThat(field.hasAllAnnotations(OtherAnnotation::class.className(),
-                    Test::class.className())).isFalse()
-                assertThat(field.hasAllAnnotations(OtherAnnotation::class.className(),
-                    OtherAnnotation::class.className())).isTrue()
+                assertThat(field.hasAllAnnotations(*arrayOf<JClassName>())).isTrue()
+                assertThat(field.hasAllAnnotations(OtherAnnotation::class.asJClassName())).isTrue()
+                assertThat(
+                    field.hasAllAnnotations(
+                        OtherAnnotation::class.asJClassName(),
+                        Test::class.asJClassName()
+                    )
+                ).isFalse()
+                assertThat(
+                    field.hasAllAnnotations(
+                        OtherAnnotation::class.asJClassName(),
+                        OtherAnnotation::class.asJClassName()
+                    )
+                ).isTrue()
 
-                assertThat(field.hasAllAnnotations(listOf<ClassName>())).isTrue()
-                assertThat(field.hasAllAnnotations(listOf(OtherAnnotation::class.className())))
+                assertThat(field.hasAllAnnotations(listOf<JClassName>())).isTrue()
+                assertThat(field.hasAllAnnotations(listOf(OtherAnnotation::class.asJClassName())))
                     .isTrue()
-                assertThat(field.hasAllAnnotations(listOf(OtherAnnotation::class.className(),
-                    Test::class.className()))).isFalse()
-                assertThat(field.hasAllAnnotations(listOf(OtherAnnotation::class.className(),
-                    OtherAnnotation::class.className()))).isTrue()
+                assertThat(
+                    field.hasAllAnnotations(
+                        listOf(
+                            OtherAnnotation::class.asJClassName(),
+                            Test::class.asJClassName()
+                        )
+                    )
+                ).isFalse()
+                assertThat(
+                    field.hasAllAnnotations(
+                        listOf(
+                            OtherAnnotation::class.asJClassName(),
+                            OtherAnnotation::class.asJClassName()
+                        )
+                    )
+                ).isTrue()
             }
         }
     }
@@ -434,36 +490,67 @@
             assertThat(element.hasAnyAnnotation(RunWith::class)).isTrue()
             assertThat(element.hasAnyAnnotation(RunWith::class, Test::class)).isTrue()
 
-            assertThat(element.hasAnyAnnotation(*arrayOf<ClassName>())).isFalse()
-            assertThat(element.hasAnyAnnotation(RunWith::class.className())).isTrue()
-            assertThat(element.hasAnyAnnotation(RunWith::class.className(),
-                Test::class.className())).isTrue()
+            assertThat(element.hasAnyAnnotation(*arrayOf<JClassName>())).isFalse()
+            assertThat(element.hasAnyAnnotation(RunWith::class.asJClassName())).isTrue()
+            assertThat(
+                element.hasAnyAnnotation(
+                    RunWith::class.asJClassName(),
+                    Test::class.asJClassName()
+                )
+            ).isTrue()
 
-            assertThat(element.hasAnyAnnotation(emptyList<ClassName>())).isFalse()
-            assertThat(element.hasAnyAnnotation(listOf(RunWith::class.className()))).isTrue()
-            assertThat(element.hasAnyAnnotation(listOf(RunWith::class.className(),
-                Test::class.className()))).isTrue()
+            assertThat(element.hasAnyAnnotation(emptyList<JClassName>())).isFalse()
+            assertThat(element.hasAnyAnnotation(listOf(RunWith::class.asJClassName()))).isTrue()
+            assertThat(
+                element.hasAnyAnnotation(
+                    listOf(
+                        RunWith::class.asJClassName(),
+                        Test::class.asJClassName()
+                    )
+                )
+            ).isTrue()
 
             element.getMethodByJvmName("testMethod").let { method ->
                 assertThat(method.hasAnyAnnotation(*arrayOf<KClass<Annotation>>())).isFalse()
                 assertThat(method.hasAnyAnnotation(Test::class)).isTrue()
                 assertThat(method.hasAnyAnnotation(Test::class, OtherAnnotation::class)).isTrue()
-                assertThat(method.hasAnyAnnotation(Test::class, OtherAnnotation::class,
-                    RunWith::class)).isTrue()
+                assertThat(
+                    method.hasAnyAnnotation(
+                        Test::class, OtherAnnotation::class,
+                        RunWith::class
+                    )
+                ).isTrue()
 
-                assertThat(method.hasAnyAnnotation(*arrayOf<ClassName>())).isFalse()
-                assertThat(method.hasAnyAnnotation(Test::class.className())).isTrue()
-                assertThat(method.hasAnyAnnotation(Test::class.className(),
-                    OtherAnnotation::class.className())).isTrue()
-                assertThat(method.hasAnyAnnotation(Test::class.className(),
-                    OtherAnnotation::class.className(), RunWith::class.className())).isTrue()
+                assertThat(method.hasAnyAnnotation(*arrayOf<JClassName>())).isFalse()
+                assertThat(method.hasAnyAnnotation(Test::class.asJClassName())).isTrue()
+                assertThat(
+                    method.hasAnyAnnotation(
+                        Test::class.asJClassName(),
+                        OtherAnnotation::class.asJClassName()
+                    )
+                ).isTrue()
+                assertThat(
+                    method.hasAnyAnnotation(
+                        Test::class.asJClassName(),
+                        OtherAnnotation::class.asJClassName(), RunWith::class.asJClassName()
+                    )
+                ).isTrue()
 
-                assertThat(method.hasAnyAnnotation(emptyList<ClassName>())).isFalse()
-                assertThat(method.hasAnyAnnotation(listOf(Test::class.className()))).isTrue()
-                assertThat(method.hasAnyAnnotation(
-                    listOf(Test::class.className(), OtherAnnotation::class.className()))).isTrue()
-                assertThat(method.hasAnyAnnotation(listOf(Test::class.className(),
-                    OtherAnnotation::class.className(), RunWith::class.className()))).isTrue()
+                assertThat(method.hasAnyAnnotation(emptyList<JClassName>())).isFalse()
+                assertThat(method.hasAnyAnnotation(listOf(Test::class.asJClassName()))).isTrue()
+                assertThat(
+                    method.hasAnyAnnotation(
+                        listOf(Test::class.asJClassName(), OtherAnnotation::class.asJClassName())
+                    )
+                ).isTrue()
+                assertThat(
+                    method.hasAnyAnnotation(
+                        listOf(
+                            Test::class.asJClassName(),
+                            OtherAnnotation::class.asJClassName(), RunWith::class.asJClassName()
+                        )
+                    )
+                ).isTrue()
             }
             element.getField("testField").let { field ->
                 assertThat(field.hasAnyAnnotation(*arrayOf<KClass<Annotation>>())).isFalse()
@@ -472,20 +559,40 @@
                 assertThat(field.hasAnyAnnotation(OtherAnnotation::class, OtherAnnotation::class))
                     .isTrue()
 
-                assertThat(field.hasAnyAnnotation(*arrayOf<ClassName>())).isFalse()
-                assertThat(field.hasAnyAnnotation(OtherAnnotation::class.className())).isTrue()
-                assertThat(field.hasAnyAnnotation(OtherAnnotation::class.className(),
-                    Test::class.className())).isTrue()
-                assertThat(field.hasAnyAnnotation(OtherAnnotation::class.className(),
-                    OtherAnnotation::class.className())).isTrue()
+                assertThat(field.hasAnyAnnotation(*arrayOf<JClassName>())).isFalse()
+                assertThat(field.hasAnyAnnotation(OtherAnnotation::class.asJClassName())).isTrue()
+                assertThat(
+                    field.hasAnyAnnotation(
+                        OtherAnnotation::class.asJClassName(),
+                        Test::class.asJClassName()
+                    )
+                ).isTrue()
+                assertThat(
+                    field.hasAnyAnnotation(
+                        OtherAnnotation::class.asJClassName(),
+                        OtherAnnotation::class.asJClassName()
+                    )
+                ).isTrue()
 
-                assertThat(field.hasAnyAnnotation(listOf<ClassName>())).isFalse()
-                assertThat(field.hasAnyAnnotation(listOf(OtherAnnotation::class.className())))
+                assertThat(field.hasAnyAnnotation(listOf<JClassName>())).isFalse()
+                assertThat(field.hasAnyAnnotation(listOf(OtherAnnotation::class.asJClassName())))
                     .isTrue()
-                assertThat(field.hasAnyAnnotation(listOf(OtherAnnotation::class.className(),
-                    Test::class.className()))).isTrue()
-                assertThat(field.hasAnyAnnotation(listOf(OtherAnnotation::class.className(),
-                    OtherAnnotation::class.className()))).isTrue()
+                assertThat(
+                    field.hasAnyAnnotation(
+                        listOf(
+                            OtherAnnotation::class.asJClassName(),
+                            Test::class.asJClassName()
+                        )
+                    )
+                ).isTrue()
+                assertThat(
+                    field.hasAnyAnnotation(
+                        listOf(
+                            OtherAnnotation::class.asJClassName(),
+                            OtherAnnotation::class.asJClassName()
+                        )
+                    )
+                ).isTrue()
             }
         }
     }
@@ -526,7 +633,7 @@
         runProcessorTest(
             sources = listOf(subject)
         ) {
-            val inner = ClassName.get("foo.bar", "Baz.Inner")
+            val inner = JClassName.get("foo.bar", "Baz.Inner")
             assertThat(
                 it.processingEnv.requireTypeElement(inner).isInterface()
             ).isTrue()
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
index 9233b1a..50ef811 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
@@ -16,11 +16,14 @@
 
 package androidx.room.compiler.processing
 
-import androidx.room.compiler.processing.util.CONTINUATION_CLASS_NAME
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
+import androidx.room.compiler.processing.util.CONTINUATION_JCLASS_NAME
 import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.UNIT_CLASS_NAME
+import androidx.room.compiler.processing.util.UNIT_JCLASS_NAME
 import androidx.room.compiler.processing.util.className
 import androidx.room.compiler.processing.util.compileFiles
+import androidx.room.compiler.processing.util.createXTypeVariableName
 import androidx.room.compiler.processing.util.getDeclaredMethodByJvmName
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.getParameter
@@ -31,13 +34,20 @@
 import com.squareup.javapoet.ClassName
 import com.squareup.javapoet.ParameterizedTypeName
 import com.squareup.javapoet.TypeName
-import com.squareup.javapoet.TypeVariableName
 import com.squareup.javapoet.WildcardTypeName
+import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
+import com.squareup.kotlinpoet.UNIT
+import com.squareup.kotlinpoet.javapoet.JClassName
+import com.squareup.kotlinpoet.javapoet.JParameterizedTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeVariableName
+import com.squareup.kotlinpoet.javapoet.KClassName
+import com.squareup.kotlinpoet.javapoet.KTypeVariableName
+import java.io.File
+import java.io.IOException
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import java.io.File
-import java.io.IOException
 
 @RunWith(JUnit4::class)
 class XExecutableElementTest {
@@ -77,11 +87,11 @@
                 method.getParameter("param1").let { param ->
                     val paramType = param.type
                     check(paramType.isArray())
-                    assertThat(paramType.componentType.typeName)
-                        .isEqualTo(String::class.typeName())
+                    assertThat(paramType.componentType.asTypeName())
+                        .isEqualTo(String::class.asClassName())
                     assertThat(param.enclosingElement).isEqualTo(method)
                 }
-                assertThat(method.returnType.typeName).isEqualTo(String::class.typeName())
+                assertThat(method.returnType.asTypeName()).isEqualTo(String::class.asClassName())
             }
             element.getConstructors().single().let { ctor ->
                 assertThat(ctor.parameters).hasSize(1)
@@ -324,8 +334,8 @@
                 method.executableType.parameterTypes.last().let { cont ->
                     assertThat(cont.typeName).isEqualTo(
                         ParameterizedTypeName.get(
-                            CONTINUATION_CLASS_NAME,
-                            WildcardTypeName.supertypeOf(UNIT_CLASS_NAME)
+                            CONTINUATION_JCLASS_NAME,
+                            WildcardTypeName.supertypeOf(UNIT_JCLASS_NAME)
                         )
                     )
                     assertThat(cont.nullability).isEqualTo(XNullability.NONNULL)
@@ -336,7 +346,7 @@
                 method.parameters.last().let { cont ->
                     assertThat(cont.type.typeName).isEqualTo(
                         ParameterizedTypeName.get(
-                            CONTINUATION_CLASS_NAME,
+                            CONTINUATION_JCLASS_NAME,
                             WildcardTypeName.supertypeOf(Integer::class.java)
                         )
                     )
@@ -347,7 +357,7 @@
                 method.executableType.parameterTypes.last().let { cont ->
                     assertThat(cont.typeName).isEqualTo(
                         ParameterizedTypeName.get(
-                            CONTINUATION_CLASS_NAME,
+                            CONTINUATION_JCLASS_NAME,
                             WildcardTypeName.supertypeOf(Integer::class.java)
                         )
                     )
@@ -366,7 +376,7 @@
                 method.executableType.parameterTypes.last().let { cont ->
                     assertThat(cont.typeName).isEqualTo(
                         ParameterizedTypeName.get(
-                            CONTINUATION_CLASS_NAME,
+                            CONTINUATION_JCLASS_NAME,
                             WildcardTypeName.supertypeOf(
                                 ParameterizedTypeName.get(
                                     Pair::class.className(),
@@ -416,16 +426,20 @@
             listOf("getX", "getProp1", "getProp2", "getProp3", "getProp5", "getProp6",
                 "getProp8\$main").forEach {
                 klass.getMethodByJvmName(it).let { method ->
-                    assertThat(method.returnType.typeName).isEqualTo(String::class.typeName())
+                    assertThat(method.returnType.asTypeName())
+                        .isEqualTo(String::class.asClassName())
                     assertThat(method.parameters).isEmpty()
                     assertThat(method.returnType.nullability).isEqualTo(XNullability.NONNULL)
                 }
             }
             listOf("setY", "setProp2", "setProp8\$main").forEach {
                 klass.getMethodByJvmName(it).let { method ->
-                    assertThat(method.returnType.typeName).isEqualTo(TypeName.VOID)
-                    assertThat(method.parameters.first().type.typeName).isEqualTo(
-                        String::class.typeName()
+                    assertThat(method.returnType.asTypeName().java).isEqualTo(JTypeName.VOID)
+                    if (invocation.isKsp) {
+                        assertThat(method.returnType.asTypeName().kotlin).isEqualTo(UNIT)
+                    }
+                    assertThat(method.parameters.first().type.asTypeName()).isEqualTo(
+                        String::class.asClassName()
                     )
                     assertThat(method.isPublic()).isTrue()
                     assertThat(method.parameters.first().type.nullability).isEqualTo(
@@ -469,11 +483,12 @@
             val method = base.getMethodByJvmName("foo")
             method.getParameter("t").let { param ->
                 param.asMemberOf(subject).let {
-                    assertThat(it.typeName).isEqualTo(String::class.typeName())
+                    assertThat(it.asTypeName()).isEqualTo(String::class.asClassName())
                     assertThat(it.nullability).isEqualTo(XNullability.NONNULL)
                 }
                 param.asMemberOf(nullableSubject).let {
-                    assertThat(it.typeName).isEqualTo(String::class.typeName())
+                    assertThat(it.asTypeName())
+                        .isEqualTo(String::class.asClassName().copy(nullable = true))
                     if (invocation.isKsp) {
                         // kapt implementation is unable to read this properly
                         assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
@@ -482,11 +497,13 @@
             }
             method.getParameter("nullableT").let { param ->
                 param.asMemberOf(subject).let {
-                    assertThat(it.typeName).isEqualTo(String::class.typeName())
+                    assertThat(it.asTypeName())
+                        .isEqualTo(String::class.asClassName().copy(nullable = true))
                     assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
                 }
                 param.asMemberOf(nullableSubject).let {
-                    assertThat(it.typeName).isEqualTo(String::class.typeName())
+                    assertThat(it.asTypeName())
+                        .isEqualTo(String::class.asClassName().copy(nullable = true))
                     assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
                 }
             }
@@ -542,7 +559,7 @@
             }
             listOf(impl, javaImpl).forEach { subject ->
                 listOf("getY", "getX", "setY").forEach { methodName ->
-                    assertWithMessage("${subject.className}:$methodName").that(
+                    assertWithMessage("${subject.asClassName().canonicalName}:$methodName").that(
                         overrides(
                             owner = subject,
                             ownerMethodName = methodName,
@@ -551,7 +568,7 @@
                     ).isTrue()
                 }
 
-                assertWithMessage(subject.className.canonicalName()).that(
+                assertWithMessage(subject.asClassName().canonicalName).that(
                     overrides(
                         owner = subject,
                         ownerMethodName = "getY",
@@ -560,7 +577,7 @@
                     )
                 ).isFalse()
 
-                assertWithMessage(subject.className.canonicalName()).that(
+                assertWithMessage(subject.asClassName().canonicalName).that(
                     overrides(
                         owner = subject,
                         ownerMethodName = "getY",
@@ -569,7 +586,7 @@
                     )
                 ).isFalse()
 
-                assertWithMessage(subject.className.canonicalName()).that(
+                assertWithMessage(subject.asClassName().canonicalName).that(
                     overrides(
                         owner = base,
                         ownerMethodName = "getX",
@@ -578,7 +595,7 @@
                     )
                 ).isFalse()
 
-                assertWithMessage(subject.className.canonicalName()).that(
+                assertWithMessage(subject.asClassName().canonicalName).that(
                     overrides(
                         owner = subject,
                         ownerMethodName = "setY",
@@ -587,7 +604,7 @@
                     )
                 ).isFalse()
 
-                assertWithMessage(subject.className.canonicalName()).that(
+                assertWithMessage(subject.asClassName().canonicalName).that(
                     overrides(
                         owner = subject,
                         ownerMethodName = "setY",
@@ -679,14 +696,14 @@
         ) { invocation ->
             val elm = invocation.processingEnv.requireTypeElement("JavaImpl")
             assertThat(
-                elm.getMethodByJvmName("getX").returnType.typeName
-            ).isEqualTo(TypeName.INT)
+                elm.getMethodByJvmName("getX").returnType.asTypeName()
+            ).isEqualTo(XTypeName.PRIMITIVE_INT)
             assertThat(
-                elm.getMethodByJvmName("getY").returnType.typeName
-            ).isEqualTo(TypeName.INT)
+                elm.getMethodByJvmName("getY").returnType.asTypeName()
+            ).isEqualTo(XTypeName.PRIMITIVE_INT)
             assertThat(
-                elm.getMethodByJvmName("setY").parameters.first().type.typeName
-            ).isEqualTo(TypeName.INT)
+                elm.getMethodByJvmName("setY").parameters.first().type.asTypeName()
+            ).isEqualTo(XTypeName.PRIMITIVE_INT)
         }
     }
 
@@ -721,14 +738,14 @@
         ) { invocation ->
             val elm = invocation.processingEnv.requireTypeElement("JavaImpl")
             assertThat(
-                elm.getMethodByJvmName("getX").returnType.typeName
-            ).isEqualTo(TypeName.INT.box())
+                elm.getMethodByJvmName("getX").returnType.asTypeName()
+            ).isEqualTo(Int::class.asClassName())
             assertThat(
-                elm.getMethodByJvmName("getY").returnType.typeName
-            ).isEqualTo(TypeName.INT.box())
+                elm.getMethodByJvmName("getY").returnType.asTypeName()
+            ).isEqualTo(Int::class.asClassName())
             assertThat(
-                elm.getMethodByJvmName("setY").parameters.first().type.typeName
-            ).isEqualTo(TypeName.INT.box())
+                elm.getMethodByJvmName("setY").parameters.first().type.asTypeName()
+            ).isEqualTo(Int::class.asClassName())
         }
     }
 
@@ -876,7 +893,7 @@
             sources = buildSources("app"),
             classpath = compileFiles(sources = buildSources("lib"))
         ) { invocation ->
-            fun collectExceptions(subject: XTypeElement): List<Pair<String, Set<TypeName>>> {
+            fun collectExceptions(subject: XTypeElement): List<Pair<String, Set<XTypeName>>> {
                 return (subject.getConstructors() + subject.getDeclaredMethods()).mapNotNull {
                     val throwTypes = it.thrownTypes
                     val name = if (it is XMethodElement) {
@@ -887,16 +904,16 @@
                     if (throwTypes.isEmpty()) {
                         null
                     } else {
-                        name to throwTypes.map { it.typeName }.toSet()
+                        name to throwTypes.map { it.asTypeName() }.toSet()
                     }
                 }
             }
             listOf("app", "lib").forEach { pkg ->
                 val expectedConstructor =
-                    "<init>" to setOf(ClassName.get(IllegalArgumentException::class.java))
+                    "<init>" to setOf(IllegalArgumentException::class.asClassName())
                 val expectedMethod = "multipleThrows" to setOf(
-                    ClassName.get(IOException::class.java),
-                    ClassName.get(IllegalStateException::class.java)
+                    IOException::class.asClassName(),
+                    IllegalStateException::class.asClassName()
                 )
                 invocation.processingEnv.requireTypeElement("$pkg.KotlinSubject").let { subject ->
                     assertWithMessage(subject.qualifiedName).that(
@@ -918,17 +935,17 @@
                         collectExceptions(subject)
                     ).containsExactly(
                         "getGetterThrows" to setOf(
-                            ClassName.get(IllegalArgumentException::class.java)
+                            IllegalArgumentException::class.asClassName()
                         ),
                         "setSetterThrows" to setOf(
-                            ClassName.get(IllegalStateException::class.java)
+                            IllegalStateException::class.asClassName()
                         ),
                         "getBothThrows" to setOf(
-                            ClassName.get(IOException::class.java)
+                            IOException::class.asClassName()
                         ),
                         "setBothThrows" to setOf(
-                            ClassName.get(IllegalStateException::class.java),
-                            ClassName.get(IllegalArgumentException::class.java)
+                            IllegalStateException::class.asClassName(),
+                            IllegalArgumentException::class.asClassName()
                         ),
                     )
                 }
@@ -966,14 +983,14 @@
                     assertThat(method.isExtensionFunction()).isTrue()
                     assertThat(method.parameters.size).isEqualTo(1)
                     assertThat(method.parameters[0].name).isEqualTo("\$this\$ext1")
-                    assertThat(method.parameters[0].type.typeName)
-                        .isEqualTo(String::class.typeName())
+                    assertThat(method.parameters[0].type.asTypeName())
+                        .isEqualTo(String::class.asClassName())
                 }
                 element.getDeclaredMethodByJvmName("ext2").let { method ->
                     assertThat(method.parameters.size).isEqualTo(2)
                     assertThat(method.parameters[0].name).isEqualTo("\$this\$ext2")
-                    assertThat(method.parameters[0].type.typeName)
-                        .isEqualTo(String::class.typeName())
+                    assertThat(method.parameters[0].type.asTypeName())
+                        .isEqualTo(String::class.asClassName())
                     assertThat(method.parameters[1].name).isEqualTo("inputParam")
                 }
                 element.getDeclaredMethodByJvmName("ext3").let { method ->
@@ -985,23 +1002,28 @@
                     )
                 }
                 element.getDeclaredMethodByJvmName("ext4").let { method ->
-                    assertThat(method.parameters[0].type.typeName).isEqualTo(
-                        ParameterizedTypeName.get(
-                            ClassName.get(pkg, "Foo"),
-                            TypeVariableName.get("T")
+                    assertThat(method.parameters[0].type.asTypeName().java).isEqualTo(
+                        JParameterizedTypeName.get(
+                            JClassName.get(pkg, "Foo"),
+                            JTypeVariableName.get("T")
                         )
                     )
+                    if (it.isKsp) {
+                        assertThat(method.parameters[0].type.asTypeName().kotlin).isEqualTo(
+                            KClassName(pkg, "Foo").parameterizedBy(KTypeVariableName("T"))
+                        )
+                    }
                 }
                 element.getDeclaredMethodByJvmName("ext5").let { method ->
-                    assertThat(method.parameters[0].type.typeName)
-                        .isEqualTo(TypeVariableName.get("T"))
+                    assertThat(method.parameters[0].type.asTypeName())
+                        .isEqualTo(createXTypeVariableName("T"))
                 }
                 element.getDeclaredMethodByJvmName("ext6").let { method ->
                     assertThat(method.isSuspendFunction()).isTrue()
                     assertThat(method.isExtensionFunction()).isTrue()
                     assertThat(method.parameters.size).isEqualTo(2)
-                    assertThat(method.parameters[0].type.typeName)
-                        .isEqualTo(String::class.typeName())
+                    assertThat(method.parameters[0].type.asTypeName())
+                        .isEqualTo(String::class.asClassName())
                     assertThat(method.parameters[1].type.typeName).isEqualTo(
                         ParameterizedTypeName.get(
                             ClassName.get("kotlin.coroutines", "Continuation"),
@@ -1013,24 +1035,24 @@
                 element.getDeclaredMethodByJvmName("ext7").let { method ->
                     assertThat(method.isAbstract()).isTrue()
                     assertThat(method.isExtensionFunction()).isTrue()
-                    assertThat(method.parameters[0].type.typeName)
-                        .isEqualTo(TypeVariableName.get("T"))
+                    assertThat(method.parameters[0].type.asTypeName())
+                        .isEqualTo(createXTypeVariableName("T"))
 
                     val fooImpl = it.processingEnv.requireTypeElement("$pkg.FooImpl")
-                    assertThat(method.parameters[0].asMemberOf(fooImpl.type).typeName)
-                        .isEqualTo(TypeName.INT.box())
+                    assertThat(method.parameters[0].asMemberOf(fooImpl.type).asTypeName())
+                        .isEqualTo(Int::class.asClassName())
                 }
                 // Verify non-overridden Foo.ext1() asMemberOf FooImpl
                 element.getDeclaredMethodByJvmName("ext1").let { method ->
                     val fooImpl = it.processingEnv.requireTypeElement("$pkg.FooImpl")
-                    assertThat(method.parameters[0].asMemberOf(fooImpl.type).typeName)
-                        .isEqualTo(String::class.typeName())
+                    assertThat(method.parameters[0].asMemberOf(fooImpl.type).asTypeName())
+                        .isEqualTo(String::class.asClassName())
                 }
                 // Verify non-overridden Foo.ext5() asMemberOf FooImpl
                 element.getDeclaredMethodByJvmName("ext5").let { method ->
                     val fooImpl = it.processingEnv.requireTypeElement("$pkg.FooImpl")
-                    assertThat(method.parameters[0].asMemberOf(fooImpl.type).typeName)
-                        .isEqualTo(TypeName.INT.box())
+                    assertThat(method.parameters[0].asMemberOf(fooImpl.type).asTypeName())
+                        .isEqualTo(Int::class.asClassName())
                 }
             }
         }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
index 4bdc27b..bc037bc 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
@@ -16,9 +16,9 @@
 
 package androidx.room.compiler.processing
 
-import androidx.room.compiler.processing.util.CONTINUATION_CLASS_NAME
+import androidx.room.compiler.processing.util.CONTINUATION_JCLASS_NAME
 import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.UNIT_CLASS_NAME
+import androidx.room.compiler.processing.util.UNIT_JCLASS_NAME
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.runProcessorTest
 import androidx.room.compiler.processing.util.typeName
@@ -120,7 +120,7 @@
             checkMethods("suspendGetT", subject) { type ->
                 assertThat(type.parameterTypes.first().typeName).isEqualTo(
                     ParameterizedTypeName.get(
-                        CONTINUATION_CLASS_NAME,
+                        CONTINUATION_JCLASS_NAME,
                         WildcardTypeName.supertypeOf(String::class.java)
                     )
                 )
@@ -132,8 +132,8 @@
                 )
                 assertThat(type.parameterTypes[1].typeName).isEqualTo(
                     ParameterizedTypeName.get(
-                        CONTINUATION_CLASS_NAME,
-                        WildcardTypeName.supertypeOf(UNIT_CLASS_NAME)
+                        CONTINUATION_JCLASS_NAME,
+                        WildcardTypeName.supertypeOf(UNIT_JCLASS_NAME)
                     )
                 )
                 assertThat(type.returnType.typeName).isEqualTo(TypeName.OBJECT)
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
index 9a28341..4786cff 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
@@ -23,10 +23,13 @@
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.getParameter
-import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
 import androidx.room.compiler.processing.util.runProcessorTest
+import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
 import com.google.common.truth.Truth.assertThat
-import com.squareup.javapoet.TypeName
+import com.squareup.kotlinpoet.INT
+import com.squareup.kotlinpoet.UNIT
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import org.junit.Assert.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -258,22 +261,29 @@
     @Test
     fun changeNullability_primitives() {
         runProcessorTest { invocation ->
-            PRIMITIVE_TYPES.forEach { primitiveTypeName ->
-                val primitive = invocation.processingEnv.requireType(primitiveTypeName)
+            PRIMITIVE_JTYPE_NAMES.forEachIndexed { index, primitiveJTypeName ->
+                val primitive = invocation.processingEnv.requireType(primitiveJTypeName)
                 assertThat(primitive.nullability).isEqualTo(NONNULL)
                 val nullable = primitive.makeNullable()
                 assertThat(nullable.nullability).isEqualTo(NULLABLE)
-                assertThat(nullable.typeName).isEqualTo(primitiveTypeName.box())
+                assertThat(nullable.asTypeName().java).isEqualTo(primitiveJTypeName.box())
+                if (invocation.isKsp) {
+                    assertThat(nullable.asTypeName().kotlin)
+                        .isEqualTo(PRIMITIVE_KTYPE_NAMES[index].copy(nullable = true))
+                }
 
                 // When a boxed primitive is marked as non-null, it should stay as boxed primitive
                 // Even though this might be counter-intutive (because making it nullable will box
                 // it) it is more consistent as it is completely valid to annotate a boxed primitive
                 // with non-null while you cannot annoteted a primitive with nullable as it is not
                 // a valid state.
-                val boxedPrimitive = invocation.processingEnv.requireType(primitiveTypeName.box())
+                val boxedPrimitive = invocation.processingEnv.requireType(primitiveJTypeName.box())
                 val nonNull = boxedPrimitive.makeNonNullable()
                 assertThat(nonNull.nullability).isEqualTo(NONNULL)
-                assertThat(nonNull.typeName).isEqualTo(primitiveTypeName.box())
+                assertThat(nonNull.asTypeName().java).isEqualTo(primitiveJTypeName.box())
+                if (invocation.isKsp) {
+                    assertThat(nonNull.asTypeName().kotlin).isEqualTo(PRIMITIVE_KTYPE_NAMES[index])
+                }
             }
         }
     }
@@ -300,15 +310,33 @@
                 val subject = invocation.processingEnv.requireTypeElement(it)
                     .getField("subject").type
                 val typeArg = subject.typeArguments.first()
-                assertThat(typeArg.typeName).isEqualTo(TypeName.INT.box())
+                assertThat(typeArg.asTypeName().java).isEqualTo(JTypeName.INT.box())
                 typeArg.makeNonNullable().let {
-                    assertThat(it.typeName).isEqualTo(TypeName.INT.box())
+                    assertThat(it.asTypeName().java).isEqualTo(JTypeName.INT.box())
                     assertThat(it.nullability).isEqualTo(NONNULL)
                 }
                 typeArg.makeNonNullable().makeNullable().let {
-                    assertThat(it.typeName).isEqualTo(TypeName.INT.box())
+                    assertThat(it.asTypeName().java).isEqualTo(JTypeName.INT.box())
                     assertThat(it.nullability).isEqualTo(NULLABLE)
                 }
+                if (invocation.isKsp) {
+                    assertThat(typeArg.asTypeName().kotlin).isEqualTo(
+                        when (it) {
+                            "KotlinClass" -> INT.copy(nullable = true)
+                            // A type arg from Java has unknown nullability,
+                            // so name defaults to not-null
+                            "JavaClass" -> INT
+                            else -> fail("Unknown src $it")
+                        }
+                    )
+
+                    typeArg.makeNonNullable().let {
+                        assertThat(it.asTypeName().kotlin).isEqualTo(INT)
+                    }
+                    typeArg.makeNonNullable().makeNullable().let {
+                        assertThat(it.asTypeName().kotlin).isEqualTo(INT.copy(nullable = true))
+                    }
+                }
             }
         }
     }
@@ -367,24 +395,42 @@
         runProcessorTest(sources = listOf(src)) { invocation ->
             val voidType = invocation.processingEnv.requireTypeElement("Foo")
                 .getMethodByJvmName("subject").returnType
-            assertThat(voidType.typeName).isEqualTo(TypeName.VOID)
+            assertThat(voidType.asTypeName().java).isEqualTo(JTypeName.VOID)
             voidType.makeNullable().let {
                 assertThat(it.nullability).isEqualTo(NULLABLE)
-                assertThat(it.typeName).isEqualTo(TypeName.VOID.box())
+                assertThat(it.asTypeName().java).isEqualTo(JTypeName.VOID.box())
+            }
+            if (invocation.isKsp) {
+                assertThat(voidType.asTypeName().kotlin).isEqualTo(UNIT)
+                voidType.makeNullable().let {
+                    // `Unit?` does not make sense so XTypeName's KotlinPoet is non-null Unit
+                    assertThat(it.asTypeName().kotlin).isEqualTo(UNIT)
+                }
             }
         }
     }
 
     companion object {
-        val PRIMITIVE_TYPES = listOf(
-            TypeName.BOOLEAN,
-            TypeName.BYTE,
-            TypeName.SHORT,
-            TypeName.INT,
-            TypeName.LONG,
-            TypeName.CHAR,
-            TypeName.FLOAT,
-            TypeName.DOUBLE,
+        val PRIMITIVE_JTYPE_NAMES = listOf(
+            JTypeName.BOOLEAN,
+            JTypeName.BYTE,
+            JTypeName.SHORT,
+            JTypeName.INT,
+            JTypeName.LONG,
+            JTypeName.CHAR,
+            JTypeName.FLOAT,
+            JTypeName.DOUBLE,
+        )
+
+        val PRIMITIVE_KTYPE_NAMES = listOf(
+            com.squareup.kotlinpoet.BOOLEAN,
+            com.squareup.kotlinpoet.BYTE,
+            com.squareup.kotlinpoet.SHORT,
+            com.squareup.kotlinpoet.INT,
+            com.squareup.kotlinpoet.LONG,
+            com.squareup.kotlinpoet.CHAR,
+            com.squareup.kotlinpoet.FLOAT,
+            com.squareup.kotlinpoet.DOUBLE,
         )
     }
 }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
index a66452a..daad3ba 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XClassName
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.common.truth.Truth.assertThat
@@ -23,11 +24,12 @@
 import com.squareup.javapoet.JavaFile
 import com.squareup.javapoet.TypeName
 import com.squareup.javapoet.TypeSpec
+import com.squareup.kotlinpoet.javapoet.JClassName
+import javax.lang.model.element.Modifier
+import javax.tools.Diagnostic
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import javax.lang.model.element.Modifier
-import javax.tools.Diagnostic
 
 @RunWith(JUnit4::class)
 class XProcessingEnvTest {
@@ -38,20 +40,20 @@
                 Source.java(
                     "foo.bar.Baz",
                     """
-                package foo.bar;
-                public class Baz {
-                }
+                    package foo.bar;
+                    public class Baz {
+                    }
                     """.trimIndent()
                 )
             )
         ) {
             val qName = "java.util.List"
-            val className = ClassName.get("java.util", "List")
+            val jClassName = JClassName.get("java.util", "List")
             val klass = List::class
             val element = it.processingEnv.requireTypeElement(qName)
             assertThat(element).isNotNull()
-            assertThat(element.className).isEqualTo(
-                className
+            assertThat(element.asClassName().java).isEqualTo(
+                jClassName
             )
 
             val type = element.type
@@ -60,14 +62,14 @@
                 it.processingEnv.findTypeElement(qName)
             ).isEqualTo(element)
             assertThat(
-                it.processingEnv.findTypeElement(className)
+                it.processingEnv.findTypeElement(jClassName)
             ).isEqualTo(element)
             assertThat(
                 it.processingEnv.findTypeElement(klass)
             ).isEqualTo(element)
 
             assertThat(
-                it.processingEnv.requireTypeElement(className)
+                it.processingEnv.requireTypeElement(jClassName)
             ).isEqualTo(element)
             assertThat(
                 it.processingEnv.requireTypeElement(klass)
@@ -77,14 +79,14 @@
                 it.processingEnv.findType(qName)
             ).isEqualTo(type)
             assertThat(
-                it.processingEnv.findType(className)
+                it.processingEnv.findType(jClassName)
             ).isEqualTo(type)
             assertThat(
                 it.processingEnv.findType(klass)
             ).isEqualTo(type)
 
             assertThat(
-                it.processingEnv.requireType(className)
+                it.processingEnv.requireType(jClassName)
             ).isEqualTo(type)
             assertThat(
                 it.processingEnv.requireType(klass)
@@ -116,8 +118,8 @@
             val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
             assertThat(element.packageName).isEqualTo("foo.bar")
             assertThat(element.name).isEqualTo("Baz")
-            assertThat(element.className)
-                .isEqualTo(ClassName.get("foo.bar", "Baz"))
+            assertThat(element.asClassName())
+                .isEqualTo(XClassName.get("foo.bar", "Baz"))
             assertThat(element.findPrimaryConstructor()).isNull()
             assertThat(element.getConstructors()).hasSize(1)
             assertThat(element.getDeclaredMethods()).hasSize(2)
@@ -164,10 +166,9 @@
         )
         runProcessorTest(sources = listOf(src)) {
             it.processingEnv.requireTypeElement("foo.bar.Outer.Inner").let {
-                val className = it.className
-                assertThat(className.packageName()).isEqualTo("foo.bar")
-                assertThat(className.simpleNames()).containsExactly("Outer", "Inner")
-                assertThat(className.simpleName()).isEqualTo("Inner")
+                val className = it.asClassName()
+                assertThat(className.packageName).isEqualTo("foo.bar")
+                assertThat(className.simpleNames).containsExactly("Outer", "Inner")
             }
         }
     }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
index 97a8b97..036604c 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
@@ -25,7 +25,7 @@
 import androidx.room.compiler.processing.testcode.SingleTypeValueAnnotation
 import androidx.room.compiler.processing.util.CompilationTestCapabilities
 import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.className
+import androidx.room.compiler.processing.util.asJClassName
 import androidx.room.compiler.processing.util.compiler.TestCompilationArguments
 import androidx.room.compiler.processing.util.compiler.compile
 import com.google.common.truth.Truth.assertAbout
@@ -40,13 +40,12 @@
 import com.squareup.javapoet.AnnotationSpec
 import com.squareup.javapoet.ClassName
 import com.squareup.javapoet.JavaFile
-import com.squareup.javapoet.TypeName
 import com.squareup.javapoet.TypeSpec
+import javax.tools.Diagnostic
+import kotlin.reflect.KClass
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TemporaryFolder
-import javax.tools.Diagnostic
-import kotlin.reflect.KClass
 
 class XProcessingStepTest {
     @field:Rule
@@ -130,7 +129,7 @@
 
     @Test
     fun multiStepProcessing() {
-        val otherAnnotatedElements = mutableListOf<TypeName>()
+        val otherAnnotatedElements = mutableListOf<String>()
         // create a scenario where we run multi-step processing so that we can test caching
         val processingStep = object : XProcessingStep {
             override fun process(
@@ -161,7 +160,7 @@
                 elementsByAnnotation[OtherAnnotation::class.qualifiedName]
                     ?.filterIsInstance<XTypeElement>()
                     ?.forEach {
-                        otherAnnotatedElements.add(it.type.typeName)
+                        otherAnnotatedElements.add(it.type.toString())
                     }
                 return emptySet()
             }
@@ -197,9 +196,7 @@
                 override fun processingSteps() = listOf(processingStep)
             }
         ).compilesWithoutError()
-        assertThat(otherAnnotatedElements).containsExactly(
-            ClassName.get("foo.bar", "Main_Impl")
-        )
+        assertThat(otherAnnotatedElements).containsExactly("foo.bar.Main_Impl")
     }
 
     @Test
@@ -848,14 +845,15 @@
                     elementsByAnnotation[MainAnnotation::class.qualifiedName!!]!!.single()
                 try {
                     val otherElement = env.requireTypeElement(
-                        mainElement.requireAnnotation(MainAnnotation::class.className())
-                            .getAsType("singleType")
-                            .typeName
+                        mainElement.requireAnnotation(
+                            MainAnnotation::class.asJClassName()
+                        ).getAsType("singleType").asTypeName().java
                     )
                     val generatedType =
-                        otherElement.requireAnnotation(SingleTypeValueAnnotation::class.className())
-                            .getAsType("value")
-                    assertThat(generatedType.typeName).isEqualTo(genClassName)
+                        otherElement.requireAnnotation(
+                            SingleTypeValueAnnotation::class.asJClassName()
+                        ).getAsType("value")
+                    assertThat(generatedType.asTypeName().java).isEqualTo(genClassName)
                     return emptySet()
                 } catch (ex: TypeNotPresentException) {
                     return setOf(mainElement)
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt
index 181755d..9fba451 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XClassName
+import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.processing.testcode.OtherAnnotation
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.getDeclaredMethodByJvmName
@@ -24,8 +26,9 @@
 import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.common.truth.Truth.assertThat
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.TypeName
+import com.squareup.kotlinpoet.INT
+import com.squareup.kotlinpoet.UNIT
+import com.squareup.kotlinpoet.javapoet.JTypeName
 import org.junit.Test
 
 class XRoundEnvTest {
@@ -35,7 +38,7 @@
         val source = Source.kotlin(
             "Baz.kt",
             """
-            import androidx.room.compiler.processing.testcode.OtherAnnotation;
+            import androidx.room.compiler.processing.testcode.OtherAnnotation
             @OtherAnnotation(value="xx")
             class Baz {
                 @OtherAnnotation(value="xx")
@@ -80,7 +83,7 @@
         val source = Source.kotlin(
             "Baz.kt",
             """
-            import androidx.room.compiler.processing.testcode.OtherAnnotation;
+            import androidx.room.compiler.processing.testcode.OtherAnnotation
             class Baz {
                 @get:OtherAnnotation(value="xx")
                 var myProperty1: Int = 0
@@ -116,7 +119,7 @@
         val source = Source.kotlin(
             "Baz.kt",
             """
-            import androidx.room.compiler.processing.XRoundEnvTest.PropertyAnnotation;
+            import androidx.room.compiler.processing.XRoundEnvTest.PropertyAnnotation
             class Baz {
                 @PropertyAnnotation
                 fun myFun(): Int = 0
@@ -147,8 +150,8 @@
             assertThat(annotatedElements).hasSize(1)
             val subject = annotatedElements.filterIsInstance<XMethodElement>().first()
             assertThat(subject.jvmName).isEqualTo("myFun")
-            assertThat(subject.enclosingElement.className).isEqualTo(
-                ClassName.get("", "BazKt")
+            assertThat(subject.enclosingElement.asClassName()).isEqualTo(
+                XClassName.get("", "BazKt")
             )
             assertThat(subject.isStatic()).isTrue()
         }
@@ -183,34 +186,31 @@
                     else -> error("unexpected type $it")
                 }
             }
-            val containerClassName = ClassName.get("foo.bar", "MyCustomClass")
+            val containerClassName = XClassName.get("foo.bar", "MyCustomClass")
             assertThat(byName.keys).containsExactly(
                 "getMyPropertyGetter",
                 "setMyPropertySetter",
                 "myProperty"
             )
             (byName["getMyPropertyGetter"] as XMethodElement).let {
-                assertThat(it.returnType.typeName).isEqualTo(TypeName.INT)
+                assertThat(it.returnType.asTypeName()).isEqualTo(XTypeName.PRIMITIVE_INT)
                 assertThat(it.parameters).hasSize(0)
-                assertThat(it.enclosingElement.className).isEqualTo(
-                    containerClassName
-                )
+                assertThat(it.enclosingElement.asClassName()).isEqualTo(containerClassName)
                 assertThat(it.isStatic()).isTrue()
             }
             (byName["setMyPropertySetter"] as XMethodElement).let {
-                assertThat(it.returnType.typeName).isEqualTo(TypeName.VOID)
+                assertThat(it.returnType.asTypeName().java).isEqualTo(JTypeName.VOID)
+                assertThat(it.returnType.asTypeName().kotlin).isEqualTo(UNIT)
                 assertThat(it.parameters).hasSize(1)
-                assertThat(it.parameters.first().type.typeName).isEqualTo(TypeName.INT)
-                assertThat(it.enclosingElement.className).isEqualTo(
-                    containerClassName
-                )
+                assertThat(it.parameters.first().type.asTypeName())
+                    .isEqualTo(XTypeName.PRIMITIVE_INT)
+                assertThat(it.enclosingElement.asClassName()).isEqualTo(containerClassName)
                 assertThat(it.isStatic()).isTrue()
             }
             (byName["myProperty"] as XFieldElement).let {
-                assertThat(it.type.typeName).isEqualTo(TypeName.INT)
-                assertThat(it.enclosingElement.className).isEqualTo(
-                    containerClassName
-                )
+                assertThat(it.type.asTypeName().java).isEqualTo(JTypeName.INT)
+                assertThat(it.type.asTypeName().kotlin).isEqualTo(INT)
+                assertThat(it.enclosingElement.asClassName()).isEqualTo(containerClassName)
                 assertThat(it.isStatic()).isTrue()
             }
         }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
index 248cb25..243f014 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
@@ -16,23 +16,29 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XClassName
 import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.asKClassName
+import androidx.room.compiler.processing.util.asMutableKClassName
 import androidx.room.compiler.processing.util.compileFiles
+import androidx.room.compiler.processing.util.createXTypeVariableName
 import androidx.room.compiler.processing.util.getAllFieldNames
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.ParameterizedTypeName
-import com.squareup.javapoet.TypeName
-import com.squareup.javapoet.TypeVariableName
+import com.squareup.kotlinpoet.INT
+import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
 import com.squareup.kotlinpoet.javapoet.JClassName
+import com.squareup.kotlinpoet.javapoet.JParameterizedTypeName
 import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeVariableName
 import com.squareup.kotlinpoet.javapoet.KClassName
+import com.squareup.kotlinpoet.javapoet.KTypeVariableName
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -77,6 +83,7 @@
                     assertThat(it.asClassName().kotlin)
                         .isEqualTo(KClassName("", "TopLevel"))
                 } else {
+                    // In javac / kapt we don't have KotlinPoet names
                     assertThat(it.asClassName().kotlin)
                         .isEqualTo(XTypeName.UNAVAILABLE_KTYPE_NAME)
                 }
@@ -85,38 +92,20 @@
                 assertThat(it.packageName).isEqualTo("foo.bar")
                 assertThat(it.name).isEqualTo("InFooBar")
                 assertThat(it.qualifiedName).isEqualTo("foo.bar.InFooBar")
-                assertThat(it.asClassName().java)
-                    .isEqualTo(ClassName.get("foo.bar", "InFooBar"))
-                if (invocation.isKsp) {
-                    assertThat(it.asClassName().kotlin)
-                        .isEqualTo(KClassName("foo.bar", "InFooBar"))
-                }
+                assertThat(it.asClassName()).isEqualTo(XClassName.get("foo.bar", "InFooBar"))
             }
             invocation.processingEnv.requireTypeElement("foo.bar.Outer").let {
                 assertThat(it.packageName).isEqualTo("foo.bar")
                 assertThat(it.name).isEqualTo("Outer")
                 assertThat(it.qualifiedName).isEqualTo("foo.bar.Outer")
-                assertThat(it.asClassName().java).isEqualTo(
-                    ClassName.get("foo.bar", "Outer")
-                )
-                if (invocation.isKsp) {
-                    assertThat(it.asClassName().kotlin).isEqualTo(
-                        KClassName("foo.bar", "Outer")
-                    )
-                }
+                assertThat(it.asClassName()).isEqualTo(XClassName.get("foo.bar", "Outer"))
             }
             invocation.processingEnv.requireTypeElement("foo.bar.Outer.Nested").let {
                 assertThat(it.packageName).isEqualTo("foo.bar")
                 assertThat(it.name).isEqualTo("Nested")
                 assertThat(it.qualifiedName).isEqualTo("foo.bar.Outer.Nested")
-                assertThat(it.asClassName().java).isEqualTo(
-                    ClassName.get("foo.bar", "Outer", "Nested")
-                )
-                if (invocation.isKsp) {
-                    assertThat(it.asClassName().kotlin).isEqualTo(
-                        KClassName("foo.bar", "Outer", "Nested")
-                    )
-                }
+                assertThat(it.asClassName())
+                    .isEqualTo(XClassName.get("foo.bar", "Outer", "Nested"))
             }
             if (invocation.isKsp) {
                 // these are KSP specific tests, typenames are tested elsewhere
@@ -126,18 +115,14 @@
                     assertThat(it.name).isEqualTo("Int")
                     assertThat(it.qualifiedName).isEqualTo("kotlin.Int")
                     assertThat(it.asClassName().java).isEqualTo(JTypeName.INT.box())
-                    if (invocation.isKsp) {
-                        assertThat(it.asClassName().kotlin).isEqualTo(com.squareup.kotlinpoet.INT)
-                    }
+                    assertThat(it.asClassName().kotlin).isEqualTo(INT)
                 }
                 invocation.processingEnv.requireTypeElement("kotlin.Int").let {
                     assertThat(it.packageName).isEqualTo("kotlin")
                     assertThat(it.name).isEqualTo("Int")
                     assertThat(it.qualifiedName).isEqualTo("kotlin.Int")
                     assertThat(it.asClassName().java).isEqualTo(JTypeName.INT.box())
-                    if (invocation.isKsp) {
-                        assertThat(it.asClassName().kotlin).isEqualTo(com.squareup.kotlinpoet.INT)
-                    }
+                    assertThat(it.asClassName().kotlin).isEqualTo(INT)
                 }
             }
         }
@@ -148,12 +133,11 @@
         val src = Source.kotlin(
             "foo.kt",
             """
-            package foo.bar;
-            class Baz : MyInterface, AbstractClass() {
-            }
-            abstract class AbstractClass {}
-            interface MyInterface {}
-            interface AnotherInterface : MyInterface {}
+            package foo.bar
+            class Baz : MyInterface, AbstractClass()
+            abstract class AbstractClass
+            interface MyInterface
+            interface AnotherInterface : MyInterface
             """.trimIndent()
         )
         runProcessorTest(sources = listOf(src)) { invocation ->
@@ -174,10 +158,10 @@
             }
             invocation.processingEnv.requireTypeElement("foo.bar.AbstractClass").let {
                 assertThat(it.superClass).isEqualTo(
-                    invocation.processingEnv.requireType(TypeName.OBJECT)
+                    invocation.processingEnv.requireType(JTypeName.OBJECT)
                 )
                 assertThat(it.superTypes).containsExactly(
-                    invocation.processingEnv.requireType(TypeName.OBJECT)
+                    invocation.processingEnv.requireType(JTypeName.OBJECT)
                 )
                 assertThat(it.isAbstract()).isTrue()
                 assertThat(it.isInterface()).isFalse()
@@ -188,7 +172,7 @@
             invocation.processingEnv.requireTypeElement("foo.bar.MyInterface").let {
                 assertThat(it.superClass).isNull()
                 assertThat(it.superTypes).containsExactly(
-                    invocation.processingEnv.requireType(TypeName.OBJECT)
+                    invocation.processingEnv.requireType(JTypeName.OBJECT)
                 )
                 assertThat(it.isInterface()).isTrue()
                 assertThat(it.type).isEqualTo(
@@ -213,11 +197,10 @@
         val src = Source.kotlin(
             "foo.kt",
             """
-            package foo.bar;
-            class Baz : MyInterface<String>, AbstractClass() {
-            }
-            abstract class AbstractClass {}
-            interface MyInterface<E> {}
+            package foo.bar
+            class Baz : MyInterface<String>, AbstractClass()
+            abstract class AbstractClass
+            interface MyInterface<E>
             """.trimIndent()
         )
         runProcessorTest(sources = listOf(src)) { invocation ->
@@ -227,8 +210,12 @@
                     type.rawType.toString() == "foo.bar.MyInterface"
                 }
                 assertThat(superInterface.typeArguments).hasSize(1)
-                assertThat(superInterface.typeArguments[0].typeName)
-                    .isEqualTo(ClassName.get("java.lang", "String"))
+                assertThat(superInterface.typeArguments[0].asTypeName().java)
+                    .isEqualTo(JClassName.get("java.lang", "String"))
+                if (invocation.isKsp) {
+                    assertThat(superInterface.typeArguments[0].asTypeName().kotlin)
+                        .isEqualTo(KClassName("kotlin", "String"))
+                }
             }
         }
     }
@@ -238,7 +225,7 @@
         val src = Source.kotlin(
             "Foo.kt",
             """
-            package foo.bar;
+            package foo.bar
             class Outer {
                 class Inner
             }
@@ -246,12 +233,14 @@
         )
         runProcessorTest(sources = listOf(src)) { invocation ->
             invocation.processingEnv.requireTypeElement("foo.bar.Outer").let {
-                assertThat(it.className).isEqualTo(ClassName.get("foo.bar", "Outer"))
+                assertThat(it.asClassName())
+                    .isEqualTo(XClassName.get("foo.bar", "Outer"))
                 assertThat(it.isNested()).isFalse()
                 assertThat(it.enclosingTypeElement).isNull()
             }
             invocation.processingEnv.requireTypeElement("foo.bar.Outer.Inner").let {
-                assertThat(it.className).isEqualTo(ClassName.get("foo.bar", "Outer", "Inner"))
+                assertThat(it.asClassName())
+                    .isEqualTo(XClassName.get("foo.bar", "Outer", "Inner"))
                 assertThat(it.packageName).isEqualTo("foo.bar")
                 assertThat(it.name).isEqualTo("Inner")
                 assertThat(it.isNested()).isTrue()
@@ -421,16 +410,17 @@
             val baseMethod = baseClass.getMethodByJvmName("baseMethod")
             baseMethod.asMemberOf(subClass.type).let { methodType ->
                 val genericArg = methodType.parameterTypes.first()
-                assertThat(genericArg.typeName).isEqualTo(TypeName.INT.box())
+                assertThat(genericArg.asTypeName()).isEqualTo(Int::class.asClassName())
             }
 
             baseClass.getField("genericProp").let { field ->
-                assertThat(field.type.typeName).isEqualTo(TypeVariableName.get("T"))
+                assertThat(field.type.asTypeName()).isEqualTo(createXTypeVariableName("T"))
             }
 
             subClass.getField("genericProp").let { field ->
                 // this is tricky because even though it is non-null it, it should still be boxed
-                assertThat(field.asMemberOf(subClass.type).typeName).isEqualTo(TypeName.INT.box())
+                assertThat(field.asMemberOf(subClass.type).asTypeName())
+                    .isEqualTo(Int::class.asClassName())
             }
         }
     }
@@ -453,16 +443,22 @@
             assertThat(baseClass.getAllFieldNames()).containsExactly("value")
             val subClass = invocation.processingEnv.requireTypeElement("SubClass")
             assertThat(subClass.getAllFieldNames()).containsExactly("value")
-            assertThat(
-                baseClass.getField("value").type.typeName
-            ).isEqualTo(
-                ParameterizedTypeName.get(List::class.java, Integer::class.java)
+            val baseFieldType = baseClass.getField("value").type
+            val subFieldType = subClass.getField("value").type
+            assertThat(baseFieldType.asTypeName().java).isEqualTo(
+                JParameterizedTypeName.get(List::class.java, Integer::class.java)
             )
-            assertThat(
-                subClass.getField("value").type.typeName
-            ).isEqualTo(
-                ParameterizedTypeName.get(List::class.java, Integer::class.java)
+            assertThat(subFieldType.asTypeName().java).isEqualTo(
+                JParameterizedTypeName.get(List::class.java, Integer::class.java)
             )
+            if (invocation.isKsp) {
+                assertThat(baseFieldType.asTypeName().kotlin).isEqualTo(
+                    List::class.asKClassName().parameterizedBy(INT)
+                )
+                assertThat(subFieldType.asTypeName().kotlin).isEqualTo(
+                    List::class.asMutableKClassName().parameterizedBy(INT)
+                )
+            }
         }
     }
 
@@ -471,7 +467,7 @@
         fun buildSrc(pkg: String) = Source.kotlin(
             "Foo.kt",
             """
-            package $pkg;
+            package $pkg
             class Subject {
                 val realField: String = ""
                     get() = field
@@ -530,7 +526,7 @@
         fun buildSource(pkg: String) = Source.kotlin(
             "Foo.kt",
             """
-            package $pkg;
+            package $pkg
             abstract class Subject {
                 val value: String = ""
                 abstract val abstractValue: String
@@ -781,7 +777,7 @@
         fun buildSrc(pkg: String) = Source.kotlin(
             "Foo.kt",
             """
-            package $pkg;
+            package $pkg
             interface Parent<T> {
                 fun parent(t: T)
             }
@@ -1450,7 +1446,7 @@
                     VAL1(1),
                     VAL2(2);
 
-                    fun enumMethod():Unit {}
+                    fun enumMethod(): Unit {}
                 }
                 """.trimIndent()
             ),
@@ -1603,7 +1599,7 @@
                 Source.kotlin(
                     "test.ConcreteClass.kt",
                     """
-                    package test;
+                    package test
                     class ConcreteClass: AbstractClass<Foo, Bar>() {}
                     abstract class AbstractClass<T1, T2> {
                         fun method(t1: T1, t2: T2): T2 {
@@ -1628,23 +1624,32 @@
                     method = method,
                     name = "method",
                     enclosingElement = abstractClass,
-                    returnType = TypeVariableName.get("T2"),
-                    parameterTypes = arrayOf(TypeVariableName.get("T1"), TypeVariableName.get("T2"))
+                    returnType = createXTypeVariableName("T2"),
+                    parameterTypes = arrayOf(
+                        createXTypeVariableName("T1"),
+                        createXTypeVariableName("T2")
+                    )
                 )
                 checkMethodType(
                     methodType = method.executableType,
-                    returnType = TypeVariableName.get("T2"),
-                    parameterTypes = arrayOf(TypeVariableName.get("T1"), TypeVariableName.get("T2"))
+                    returnType = createXTypeVariableName("T2"),
+                    parameterTypes = arrayOf(
+                        createXTypeVariableName("T1"),
+                        createXTypeVariableName("T2")
+                    )
                 )
                 checkMethodType(
                     methodType = method.asMemberOf(abstractClass.type),
-                    returnType = TypeVariableName.get("T2"),
-                    parameterTypes = arrayOf(TypeVariableName.get("T1"), TypeVariableName.get("T2"))
+                    returnType = createXTypeVariableName("T2"),
+                    parameterTypes = arrayOf(
+                        createXTypeVariableName("T1"),
+                        createXTypeVariableName("T2")
+                    )
                 )
                 checkMethodType(
                     methodType = method.asMemberOf(concreteClass.type),
-                    returnType = barType.typeName,
-                    parameterTypes = arrayOf(fooType.typeName, barType.typeName)
+                    returnType = barType.asTypeName(),
+                    parameterTypes = arrayOf(fooType.asTypeName(), barType.asTypeName())
                 )
             }
 
@@ -1661,7 +1666,7 @@
                 Source.kotlin(
                     "test.ConcreteClass.kt",
                     """
-                    package test;
+                    package test
                     class ConcreteClass: AbstractClass<Foo, Bar>() {
                         override fun method(t1: Foo, t2: Bar): Bar {
                           return t2
@@ -1691,23 +1696,32 @@
                 method = abstractClassMethod,
                 name = "method",
                 enclosingElement = abstractClass,
-                returnType = TypeVariableName.get("T2"),
-                parameterTypes = arrayOf(TypeVariableName.get("T1"), TypeVariableName.get("T2"))
+                returnType = createXTypeVariableName("T2"),
+                parameterTypes = arrayOf(
+                    createXTypeVariableName("T1"),
+                    createXTypeVariableName("T2")
+                )
             )
             checkMethodType(
                 methodType = abstractClassMethod.executableType,
-                returnType = TypeVariableName.get("T2"),
-                parameterTypes = arrayOf(TypeVariableName.get("T1"), TypeVariableName.get("T2"))
+                returnType = createXTypeVariableName("T2"),
+                parameterTypes = arrayOf(
+                    createXTypeVariableName("T1"),
+                    createXTypeVariableName("T2")
+                )
             )
             checkMethodType(
                 methodType = abstractClassMethod.asMemberOf(abstractClass.type),
-                returnType = TypeVariableName.get("T2"),
-                parameterTypes = arrayOf(TypeVariableName.get("T1"), TypeVariableName.get("T2"))
+                returnType = createXTypeVariableName("T2"),
+                parameterTypes = arrayOf(
+                    createXTypeVariableName("T1"),
+                    createXTypeVariableName("T2"),
+                )
             )
             checkMethodType(
                 methodType = abstractClassMethod.asMemberOf(concreteClass.type),
-                returnType = barType.typeName,
-                parameterTypes = arrayOf(fooType.typeName, barType.typeName)
+                returnType = barType.asTypeName(),
+                parameterTypes = arrayOf(fooType.asTypeName(), barType.asTypeName())
             )
 
             // Check the concrete method and method type
@@ -1715,18 +1729,18 @@
                 method = concreteClassMethod,
                 name = "method",
                 enclosingElement = concreteClass,
-                returnType = barType.typeName,
-                parameterTypes = arrayOf(fooType.typeName, barType.typeName)
+                returnType = barType.asTypeName(),
+                parameterTypes = arrayOf(fooType.asTypeName(), barType.asTypeName())
             )
             checkMethodType(
                 methodType = concreteClassMethod.executableType,
-                returnType = barType.typeName,
-                parameterTypes = arrayOf(fooType.typeName, barType.typeName)
+                returnType = barType.asTypeName(),
+                parameterTypes = arrayOf(fooType.asTypeName(), barType.asTypeName())
             )
             checkMethodType(
                 methodType = concreteClassMethod.asMemberOf(concreteClass.type),
-                returnType = barType.typeName,
-                parameterTypes = arrayOf(fooType.typeName, barType.typeName)
+                returnType = barType.asTypeName(),
+                parameterTypes = arrayOf(fooType.asTypeName(), barType.asTypeName())
             )
         }
     }
@@ -1735,23 +1749,23 @@
         method: XMethodElement,
         name: String,
         enclosingElement: XTypeElement,
-        returnType: TypeName,
-        parameterTypes: Array<TypeName>
+        returnType: XTypeName,
+        parameterTypes: Array<XTypeName>
     ) {
         assertThat(method.name).isEqualTo(name)
         assertThat(method.enclosingElement).isEqualTo(enclosingElement)
-        assertThat(method.returnType.typeName).isEqualTo(returnType)
-        assertThat(method.parameters.map { it.type.typeName })
+        assertThat(method.returnType.asTypeName()).isEqualTo(returnType)
+        assertThat(method.parameters.map { it.type.asTypeName() })
             .containsExactly(*parameterTypes)
             .inOrder()
     }
     private fun checkMethodType(
         methodType: XMethodType,
-        returnType: TypeName,
-        parameterTypes: Array<TypeName>
+        returnType: XTypeName,
+        parameterTypes: Array<XTypeName>
     ) {
-        assertThat(methodType.returnType.typeName).isEqualTo(returnType)
-        assertThat(methodType.parameterTypes.map { it.typeName })
+        assertThat(methodType.returnType.asTypeName()).isEqualTo(returnType)
+        assertThat(methodType.parameterTypes.map { it.asTypeName() })
             .containsExactly(*parameterTypes)
             .inOrder()
     }
@@ -1763,7 +1777,7 @@
                 Source.kotlin(
                     "test.ConcreteClass.kt",
                     """
-                    package test;
+                    package test
                     class ConcreteClass(foo: Foo): AbstractClass<Foo>(foo) {}
                     abstract class AbstractClass<T>(t: T)
                     class Foo
@@ -1777,17 +1791,25 @@
 
             fun checkConstructorParameters(
                 typeElement: XTypeElement,
-                expectedParameters: Array<TypeName>
+                expectedParameters: Array<XTypeName>
             ) {
                 assertThat(typeElement.getConstructors()).hasSize(1)
                 val constructor = typeElement.getConstructors()[0]
-                assertThat(constructor.parameters.map { it.type.typeName })
+                assertThat(constructor.parameters.map { it.type.asTypeName() })
                     .containsExactly(*expectedParameters)
                     .inOrder()
             }
 
-            checkConstructorParameters(abstractClass, arrayOf(TypeVariableName.get("T")))
-            checkConstructorParameters(concreteClass, arrayOf(fooType.typeName))
+            checkConstructorParameters(
+                typeElement = abstractClass,
+                expectedParameters = arrayOf(
+                    createXTypeVariableName("T")
+                )
+            )
+            checkConstructorParameters(
+                typeElement = concreteClass,
+                expectedParameters = arrayOf(fooType.asTypeName())
+            )
         }
     }
 
@@ -1798,7 +1820,7 @@
                 Source.kotlin(
                     "test.ConcreteClass.kt",
                     """
-                    package test;
+                    package test
                     class ConcreteClass: AbstractClass<Foo>()
                     abstract class AbstractClass<T> {
                         val field: T = TODO()
@@ -1816,11 +1838,18 @@
 
             fun checkFieldElement(field: XFieldElement) {
                 assertThat(field.name).isEqualTo("field")
-                assertThat(field.type.typeName).isEqualTo(TypeVariableName.get("T"))
-                assertThat(field.asMemberOf(abstractClass.type).typeName)
-                    .isEqualTo(TypeVariableName.get("T"))
-                assertThat(field.asMemberOf(concreteClass.type).typeName)
-                    .isEqualTo(fooType.typeName)
+                assertThat(field.type.asTypeName().java).isEqualTo(JTypeVariableName.get("T"))
+                assertThat(field.asMemberOf(abstractClass.type).asTypeName().java)
+                    .isEqualTo(JTypeVariableName.get("T"))
+                assertThat(field.asMemberOf(concreteClass.type).asTypeName().java)
+                    .isEqualTo(fooType.asTypeName().java)
+                if (invocation.isKsp) {
+                    assertThat(field.type.asTypeName().kotlin).isEqualTo(KTypeVariableName("T"))
+                    assertThat(field.asMemberOf(abstractClass.type).asTypeName().kotlin)
+                        .isEqualTo(KTypeVariableName("T"))
+                    assertThat(field.asMemberOf(concreteClass.type).asTypeName().kotlin)
+                        .isEqualTo(fooType.asTypeName().kotlin)
+                }
             }
 
             assertThat(concreteClassField).isEqualTo(abstractClassField)
@@ -1849,9 +1878,9 @@
     private fun XMethodElement.signature(owner: XType): String {
         val methodType = this.asMemberOf(owner)
         val params = methodType.parameterTypes.joinToString(",") {
-            it.typeName.toString()
+            it.asTypeName().java.toString()
         }
-        return "$jvmName($params):${returnType.typeName}"
+        return "$jvmName($params):${returnType.asTypeName().java}"
     }
 
     private fun XTestInvocation.nonObjectMethodSignatures(typeElement: XTypeElement): List<String> =
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeParameterElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeParameterElementTest.kt
index 2b63704..48a219f 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeParameterElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeParameterElementTest.kt
@@ -56,12 +56,18 @@
 
             assertThat(t1.bounds).hasSize(1)
             val t1Bound = t1.bounds[0]
-            assertThat(t1Bound.typeName.toString()).isEqualTo("java.lang.Object")
+            assertThat(t1Bound.asTypeName().java.toString()).isEqualTo("java.lang.Object")
+            if (invocation.isKsp) {
+                assertThat(t1Bound.asTypeName().kotlin.toString()).isEqualTo("kotlin.Any?")
+            }
             assertThat(t1Bound.isSameType(expectedBoundType)).isTrue()
 
             assertThat(t2.bounds).hasSize(1)
             val t2Bound = t2.bounds[0]
-            assertThat(t2Bound.typeName.toString()).isEqualTo("java.lang.Object")
+            assertThat(t2Bound.asTypeName().java.toString()).isEqualTo("java.lang.Object")
+            if (invocation.isKsp) {
+                assertThat(t2Bound.asTypeName().kotlin.toString()).isEqualTo("kotlin.Any?")
+            }
             assertThat(t2Bound.isSameType(expectedBoundType)).isTrue()
         }
     }
@@ -91,13 +97,19 @@
 
             assertThat(t1.bounds).hasSize(1)
             val t1Bound = t1.bounds[0]
-            assertThat(t1Bound.typeName.toString()).isEqualTo("Bar")
+            assertThat(t1Bound.asTypeName().java.toString()).isEqualTo("Bar")
+            if (invocation.isKsp) {
+                assertThat(t1Bound.asTypeName().kotlin.toString()).isEqualTo("Bar")
+            }
             val bar = invocation.processingEnv.requireType("Bar")
             assertThat(t1Bound.isSameType(bar)).isTrue()
 
             assertThat(t2.bounds).hasSize(1)
             val t2Bound = t2.bounds[0]
-            assertThat(t2Bound.typeName.toString()).isEqualTo("Baz")
+            assertThat(t2Bound.asTypeName().java.toString()).isEqualTo("Baz")
+            if (invocation.isKsp) {
+                assertThat(t2Bound.asTypeName().kotlin.toString()).isEqualTo("Baz?")
+            }
             val nullableBar = invocation.processingEnv.requireType("Baz").makeNullable()
             assertThat(t2Bound.isSameType(nullableBar)).isTrue()
         }
@@ -128,13 +140,19 @@
 
             assertThat(t1.bounds).hasSize(1)
             val t1Bound = t1.bounds[0]
-            assertThat(t1Bound.typeName.toString()).isEqualTo("Bar")
+            assertThat(t1Bound.asTypeName().java.toString()).isEqualTo("Bar")
+            if (invocation.isKsp) {
+                assertThat(t1Bound.asTypeName().kotlin.toString()).isEqualTo("Bar?")
+            }
             val nullableBar = invocation.processingEnv.requireType("Bar").makeNullable()
             assertThat(t1Bound.isSameType(nullableBar)).isTrue()
 
             assertThat(t2.bounds).hasSize(1)
             val t2Bound = t2.bounds[0]
-            assertThat(t2Bound.typeName.toString()).isEqualTo("Baz")
+            assertThat(t2Bound.asTypeName().java.toString()).isEqualTo("Baz")
+            if (invocation.isKsp) {
+                assertThat(t2Bound.asTypeName().kotlin.toString()).isEqualTo("Baz")
+            }
             val baz = invocation.processingEnv.requireType("Baz")
             assertThat(t2Bound.isSameType(baz)).isTrue()
         }
@@ -162,13 +180,19 @@
             assertThat(t.bounds).hasSize(2)
 
             val bound0 = t.bounds[0]
-            assertThat(bound0.typeName.toString()).isEqualTo("Bar")
+            assertThat(bound0.asTypeName().java.toString()).isEqualTo("Bar")
+            if (invocation.isKsp) {
+                assertThat(bound0.asTypeName().kotlin.toString()).isEqualTo("Bar")
+            }
             val bar = invocation.processingEnv.requireType("Bar")
             assertThat(bound0.isSameType(bar)).isTrue()
             assertThat(bound0.nullability).isEqualTo(XNullability.UNKNOWN)
 
             val bound1 = t.bounds[1]
-            assertThat(bound1.typeName.toString()).isEqualTo("Baz")
+            assertThat(bound1.asTypeName().java.toString()).isEqualTo("Baz")
+            if (invocation.isKsp) {
+                assertThat(bound1.asTypeName().kotlin.toString()).isEqualTo("Baz")
+            }
             val baz = invocation.processingEnv.requireType("Baz")
             assertThat(bound1.isSameType(baz)).isTrue()
             assertThat(bound1.nullability).isEqualTo(XNullability.UNKNOWN)
@@ -212,12 +236,18 @@
 
             assertThat(t1.bounds).hasSize(1)
             val t1Bound = t1.bounds[0]
-            assertThat(t1Bound.typeName.toString()).isEqualTo("java.lang.Object")
+            assertThat(t1Bound.asTypeName().java.toString()).isEqualTo("java.lang.Object")
+            if (invocation.isKsp) {
+                assertThat(t1Bound.asTypeName().kotlin.toString()).isEqualTo("kotlin.Any?")
+            }
             assertThat(t1Bound.isSameType(expectedBoundType)).isTrue()
 
             assertThat(t2.bounds).hasSize(1)
             val t2Bound = t2.bounds[0]
-            assertThat(t2Bound.typeName.toString()).isEqualTo("java.lang.Object")
+            assertThat(t2Bound.asTypeName().java.toString()).isEqualTo("java.lang.Object")
+            if (invocation.isKsp) {
+                assertThat(t2Bound.asTypeName().kotlin.toString()).isEqualTo("kotlin.Any?")
+            }
             assertThat(t2Bound.isSameType(expectedBoundType)).isTrue()
         }
     }
@@ -254,13 +284,19 @@
 
             assertThat(t1.bounds).hasSize(1)
             val t1Bound = t1.bounds[0]
-            assertThat(t1Bound.typeName.toString()).isEqualTo("Bar")
+            assertThat(t1Bound.asTypeName().java.toString()).isEqualTo("Bar")
+            if (invocation.isKsp) {
+                assertThat(t1Bound.asTypeName().kotlin.toString()).isEqualTo("Bar")
+            }
             val bar = invocation.processingEnv.requireType("Bar")
             assertThat(t1Bound.isSameType(bar)).isTrue()
 
             assertThat(t2.bounds).hasSize(1)
             val t2Bound = t2.bounds[0]
-            assertThat(t2Bound.typeName.toString()).isEqualTo("Baz")
+            assertThat(t2Bound.asTypeName().java.toString()).isEqualTo("Baz")
+            if (invocation.isKsp) {
+                assertThat(t2Bound.asTypeName().kotlin.toString()).isEqualTo("Baz?")
+            }
             val nullableBar = invocation.processingEnv.requireType("Baz").makeNullable()
             assertThat(t2Bound.isSameType(nullableBar)).isTrue()
         }
@@ -295,13 +331,19 @@
             assertThat(t.bounds).hasSize(2)
 
             val bound0 = t.bounds[0]
-            assertThat(bound0.typeName.toString()).isEqualTo("Bar")
+            assertThat(bound0.asTypeName().java.toString()).isEqualTo("Bar")
+            if (invocation.isKsp) {
+                assertThat(bound0.asTypeName().kotlin.toString()).isEqualTo("Bar")
+            }
             val bar = invocation.processingEnv.requireType("Bar")
             assertThat(bound0.isSameType(bar)).isTrue()
             assertThat(bound0.nullability).isEqualTo(XNullability.UNKNOWN)
 
             val bound1 = t.bounds[1]
-            assertThat(bound1.typeName.toString()).isEqualTo("Baz")
+            assertThat(bound1.asTypeName().java.toString()).isEqualTo("Baz")
+            if (invocation.isKsp) {
+                assertThat(bound1.asTypeName().kotlin.toString()).isEqualTo("Baz")
+            }
             val baz = invocation.processingEnv.requireType("Baz")
             assertThat(bound1.isSameType(baz)).isTrue()
             assertThat(bound1.nullability).isEqualTo(XNullability.UNKNOWN)
@@ -337,13 +379,19 @@
             assertThat(t.bounds).hasSize(2)
 
             val bound0 = t.bounds[0]
-            assertThat(bound0.typeName.toString()).isEqualTo("Bar")
+            assertThat(bound0.asTypeName().java.toString()).isEqualTo("Bar")
+            if (invocation.isKsp) {
+                assertThat(bound0.asTypeName().kotlin.toString()).isEqualTo("Bar")
+            }
             val bar = invocation.processingEnv.requireType("Bar")
             assertThat(bound0.isSameType(bar)).isTrue()
             assertThat(bound0.nullability).isEqualTo(XNullability.UNKNOWN)
 
             val bound1 = t.bounds[1]
-            assertThat(bound1.typeName.toString()).isEqualTo("Baz")
+            assertThat(bound1.asTypeName().java.toString()).isEqualTo("Baz")
+            if (invocation.isKsp) {
+                assertThat(bound1.asTypeName().kotlin.toString()).isEqualTo("Baz")
+            }
             val baz = invocation.processingEnv.requireType("Baz")
             assertThat(bound1.isSameType(baz)).isTrue()
             assertThat(bound1.nullability).isEqualTo(XNullability.UNKNOWN)
@@ -351,7 +399,10 @@
             assertThat(constructor.parameters).hasSize(1)
             val parameter = constructor.parameters[0]
             assertThat(parameter.name).isEqualTo("t")
-            assertThat(parameter.type.typeName.toString()).isEqualTo("T")
+            assertThat(parameter.type.asTypeName().java.toString()).isEqualTo("T")
+            if (invocation.isKsp) {
+                assertThat(parameter.type.asTypeName().kotlin.toString()).isEqualTo("T")
+            }
         }
     }
 }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index f83ebeb..b42a29c 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -16,10 +16,14 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.codegen.XTypeName.Companion.UNAVAILABLE_KTYPE_NAME
 import androidx.room.compiler.processing.ksp.ERROR_JTYPE_NAME
+import androidx.room.compiler.processing.ksp.ERROR_KTYPE_NAME
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
-import androidx.room.compiler.processing.util.className
+import androidx.room.compiler.processing.util.asJClassName
+import androidx.room.compiler.processing.util.asKClassName
+import androidx.room.compiler.processing.util.dumpToString
 import androidx.room.compiler.processing.util.getDeclaredMethodByJvmName
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
@@ -27,14 +31,23 @@
 import androidx.room.compiler.processing.util.kspResolver
 import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.typeName
-import com.google.common.truth.Truth
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import com.google.devtools.ksp.getClassDeclarationByName
 import com.squareup.javapoet.ClassName
 import com.squareup.javapoet.ParameterizedTypeName
-import com.squareup.javapoet.TypeName
 import com.squareup.javapoet.TypeVariableName
+import com.squareup.kotlinpoet.INT
+import com.squareup.kotlinpoet.MUTABLE_SET
+import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
+import com.squareup.kotlinpoet.STAR
+import com.squareup.kotlinpoet.javapoet.JClassName
+import com.squareup.kotlinpoet.javapoet.JParameterizedTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeVariableName
+import com.squareup.kotlinpoet.javapoet.JWildcardTypeName
+import com.squareup.kotlinpoet.javapoet.KClassName
+import com.squareup.kotlinpoet.javapoet.KTypeVariableName
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -59,39 +72,73 @@
             sources = listOf(parent)
         ) {
             val type = it.processingEnv.requireType("foo.bar.Parent")
-            val className = ClassName.get("foo.bar", "Parent")
-            assertThat(type.typeName).isEqualTo(
-                ParameterizedTypeName.get(
-                    className,
-                    ClassName.get("", "InputStreamType")
+            assertThat(type.asTypeName().java).isEqualTo(
+                JParameterizedTypeName.get(
+                    JClassName.get("foo.bar", "Parent"),
+                    JClassName.get("", "InputStreamType")
                 )
             )
+            if (it.isKsp) {
+                assertThat(type.asTypeName().kotlin).isEqualTo(
+                    KClassName("foo.bar", "Parent")
+                        .parameterizedBy(KClassName("", "InputStreamType"))
+                )
+            }
 
             val typeArguments = type.typeArguments
             assertThat(typeArguments).hasSize(1)
-            val inputStreamClassName = ClassName.get("java.io", "InputStream")
             typeArguments.first().let { firstType ->
                 val expected = TypeVariableName.get(
                     "InputStreamType",
-                    inputStreamClassName
+                    JClassName.get("java.io", "InputStream")
                 )
-                assertThat(firstType.typeName).isEqualTo(expected)
+                assertThat(firstType.asTypeName().java).isEqualTo(expected)
                 // equals in TypeVariableName just checks the string representation but we want
                 // to assert the upper bound as well
                 assertThat(
-                    (firstType.typeName as TypeVariableName).bounds
+                    (firstType.asTypeName().java as JTypeVariableName).bounds
                 ).containsExactly(
-                    inputStreamClassName
+                    JClassName.get("java.io", "InputStream")
                 )
             }
+            if (it.isKsp) {
+                typeArguments.first().let { firstType ->
+                    val expected = KTypeVariableName(
+                        "InputStreamType",
+                        KClassName("java.io", "InputStream")
+                    )
+                    assertThat(firstType.asTypeName().kotlin).isEqualTo(expected)
+                    assertThat(
+                        (firstType.asTypeName().kotlin as KTypeVariableName).bounds
+                    ).containsExactly(
+                        KClassName("java.io", "InputStream")
+                    )
+                }
+            }
 
             type.typeElement!!.getMethodByJvmName("wildcardParam").let { method ->
                 val wildcardParam = method.parameters.first()
                 val extendsBoundOrSelf = wildcardParam.type.extendsBoundOrSelf()
-                assertThat(extendsBoundOrSelf.rawType)
-                    .isEqualTo(
-                        it.processingEnv.requireType(Set::class).rawType
+                assertThat(wildcardParam.type.asTypeName().java).isEqualTo(
+                    JParameterizedTypeName.get(
+                        JClassName.get("java.util", "Set"),
+                        JWildcardTypeName.subtypeOf(Any::class.java)
                     )
+                )
+                if (it.isKsp) {
+                    assertThat(wildcardParam.type.asTypeName().kotlin).isEqualTo(
+                        MUTABLE_SET.parameterizedBy(STAR)
+                    )
+                    assertThat(extendsBoundOrSelf.rawType)
+                        .isEqualTo(
+                            it.processingEnv.requireType("kotlin.collections.MutableSet").rawType
+                        )
+                } else {
+                    assertThat(extendsBoundOrSelf.rawType)
+                        .isEqualTo(
+                            it.processingEnv.requireType("java.util.Set").rawType
+                        )
+                }
             }
             type.typeElement!!.getMethodByJvmName("rawTypeParam").let { method ->
                 val rawTypeParam = method.parameters.first()
@@ -118,21 +165,29 @@
         runProcessorTest(
             sources = listOf(missingTypeRef)
         ) {
-            val errorTypeName = if (it.isKsp) {
-                // in ksp, we lose the name when resolving the type.
-                // b/175246617
+            val errorJTypeName = if (it.isKsp) {
+                // In ksp, we lose the name when resolving the type. b/175246617
                 ERROR_JTYPE_NAME
             } else {
                 ClassName.get("", "NotExistingType")
             }
+            val errorKTypeName = if (it.isKsp) {
+                // In ksp, we lose the name when resolving the type. b/175246617
+                // But otherwise the name is not available in javac / kapt
+                ERROR_KTYPE_NAME
+            } else {
+                UNAVAILABLE_KTYPE_NAME
+            }
             val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
             element.getField("badField").let { field ->
                 assertThat(field.type.isError()).isTrue()
-                assertThat(field.type.typeName).isEqualTo(errorTypeName)
+                assertThat(field.type.asTypeName().java).isEqualTo(errorJTypeName)
+                assertThat(field.type.asTypeName().kotlin).isEqualTo(errorKTypeName)
             }
             element.getDeclaredMethodByJvmName("badMethod").let { method ->
                 assertThat(method.returnType.isError()).isTrue()
-                assertThat(method.returnType.typeName).isEqualTo(errorTypeName)
+                assertThat(method.returnType.asTypeName().java).isEqualTo(errorJTypeName)
+                assertThat(method.returnType.asTypeName().kotlin).isEqualTo(errorKTypeName)
             }
             it.assertCompilationResult {
                 compilationDidFail()
@@ -235,11 +290,19 @@
     @Test
     fun isCollection_kotlin() {
         runKspTest(sources = emptyList()) { invocation ->
-            val subjects = listOf("Map" to false, "List" to true, "Set" to true)
+            val subjects = listOf(
+                "Map" to false,
+                "List" to true,
+                "Set" to true
+            )
             subjects.forEach { (subject, expected) ->
                 invocation.processingEnv.requireType("kotlin.collections.$subject").let { type ->
-                    Truth.assertWithMessage(type.typeName.toString())
+                    assertWithMessage(type.asTypeName().java.toString())
                         .that(type.isCollection()).isEqualTo(expected)
+                    if (invocation.isKsp) {
+                        assertWithMessage(type.asTypeName().kotlin.toString())
+                            .that(type.isCollection()).isEqualTo(expected)
+                    }
                 }
             }
         }
@@ -310,12 +373,18 @@
     @Test
     fun boxed() {
         runProcessorTest {
-            assertThat(
-                it.processingEnv.requireType("int").boxed().typeName
-            ).isEqualTo(java.lang.Integer::class.className())
-            assertThat(
-                it.processingEnv.requireType("java.lang.String").boxed().typeName
-            ).isEqualTo(String::class.className())
+            val intBoxed = it.processingEnv.requireType("int").boxed()
+            val stringBoxed = it.processingEnv.requireType("java.lang.String").boxed()
+            assertThat(intBoxed.asTypeName().java)
+                .isEqualTo(java.lang.Integer::class.asJClassName())
+            assertThat(stringBoxed.asTypeName().java)
+                .isEqualTo(String::class.asJClassName())
+            if (it.isKsp) {
+                assertThat(intBoxed.asTypeName().kotlin)
+                    .isEqualTo(Integer::class.asKClassName())
+                assertThat(stringBoxed.asTypeName().kotlin)
+                    .isEqualTo(String::class.asKClassName())
+            }
         }
     }
 
@@ -326,11 +395,21 @@
                 it.processingEnv.requireTypeElement(List::class),
                 it.processingEnv.requireType(String::class)
             )
-            val listClassName = List::class.className()
-            assertThat(subject.typeName).isEqualTo(
-                ParameterizedTypeName.get(listClassName, String::class.typeName())
+            assertThat(subject.asTypeName().java).isEqualTo(
+                ParameterizedTypeName.get(List::class.asJClassName(), String::class.asJClassName())
             )
-            assertThat(subject.rawType.typeName).isEqualTo(listClassName)
+            assertThat(subject.rawType.asTypeName().java)
+                .isEqualTo(List::class.asJClassName())
+            if (it.isKsp) {
+                assertThat(subject.asTypeName().kotlin).isEqualTo(
+                    KClassName(
+                        "kotlin.collections",
+                        "MutableList"
+                    ).parameterizedBy(String::class.asKClassName())
+                )
+                assertThat(subject.rawType.asTypeName().kotlin)
+                    .isEqualTo(KClassName("kotlin.collections", "MutableList"))
+            }
 
             val listOfInts = it.processingEnv.getDeclaredType(
                 it.processingEnv.requireTypeElement(List::class),
@@ -437,8 +516,7 @@
         ) { invocation ->
             val typeElement = invocation.processingEnv.requireTypeElement("SelfReferencing")
             val parameter = typeElement.getMethodByJvmName("method").parameters.single()
-            assertThat(typeElement.type.typeName.dumpToString(5)).isEqualTo(
-                """
+            val expectedTypeStringDump = """
                 SelfReferencing<T>
                 | T
                 | > SelfReferencing<T>
@@ -446,13 +524,28 @@
                 | > | > SelfReferencing<T>
                 | > | > | T
                 """.trimIndent()
-            )
-            assertThat(parameter.type.typeName.dumpToString(5)).isEqualTo(
-                """
+            assertThat(typeElement.type.asTypeName().java.dumpToString(5))
+                .isEqualTo(expectedTypeStringDump)
+            if (invocation.isKsp) {
+                assertThat(typeElement.type.asTypeName().kotlin.dumpToString(5))
+                    .isEqualTo(expectedTypeStringDump)
+            }
+            assertThat(parameter.type.asTypeName().java.dumpToString(5))
+                .isEqualTo(
+                    """
                 SelfReferencing<?>
                 | ?
                 """.trimIndent()
-            )
+                )
+            if (invocation.isKsp) {
+                assertThat(parameter.type.asTypeName().kotlin.dumpToString(5))
+                    .isEqualTo(
+                        """
+                    SelfReferencing<*>
+                    | *
+                    """.trimIndent()
+                    )
+            }
         }
     }
 
@@ -471,8 +564,7 @@
         ) { invocation ->
             val typeElement = invocation.processingEnv.requireTypeElement("SelfReferencing")
             val parameter = typeElement.getMethodByJvmName("method").parameters.single()
-            assertThat(typeElement.type.typeName.dumpToString(5)).isEqualTo(
-                """
+            val expectedTypeStringDump = """
                 SelfReferencing<T>
                 | T
                 | > SelfReferencing<T>
@@ -480,12 +572,21 @@
                 | > | > SelfReferencing<T>
                 | > | > | T
                 """.trimIndent()
-            )
-            assertThat(parameter.type.typeName.dumpToString(5)).isEqualTo(
-                """
+            assertThat(typeElement.type.asTypeName().java.dumpToString(5))
+                .isEqualTo(expectedTypeStringDump)
+            if (invocation.isKsp) {
+                assertThat(typeElement.type.asTypeName().kotlin.dumpToString(5))
+                    .isEqualTo(expectedTypeStringDump)
+            }
+            val expectedParamStringDump = """
                 SelfReferencing
                 """.trimIndent()
-            )
+            assertThat(parameter.type.asTypeName().java.dumpToString(5))
+                .isEqualTo(expectedParamStringDump)
+            if (invocation.isKsp) {
+                assertThat(parameter.type.asTypeName().kotlin.dumpToString(5))
+                    .isEqualTo(expectedParamStringDump)
+            }
         }
     }
 
@@ -506,9 +607,7 @@
             sources = listOf(src)
         ) { invocation ->
             val nodeElm = invocation.processingEnv.requireTypeElement("Node")
-            val nodeTypeName = nodeElm.type.typeName
-            assertThat(nodeTypeName.dumpToString(5)).isEqualTo(
-                """
+            val expectedStringDump = """
                 Node<TX, RX>
                 | TX
                 | > Node<TX, RX>
@@ -531,18 +630,19 @@
                 | > | > | TX
                 | > | > | RX
                 """.trimIndent()
-            )
-            val paramTypeNames = nodeElm.getDeclaredMethods().associate {
-                it.name to it.parameters.single().type.typeName.dumpToString(5)
+            assertThat(nodeElm.type.asTypeName().java.dumpToString(5))
+                .isEqualTo(expectedStringDump)
+            if (invocation.isKsp) {
+                assertThat(nodeElm.type.asTypeName().kotlin.dumpToString(5))
+                    .isEqualTo(expectedStringDump)
             }
-            assertThat(paramTypeNames).containsExactlyEntriesIn(
-                mapOf(
-                    "allStar" to """
+            val expectedStringDumps = mapOf(
+                "allStar" to """
                         Node<?, ?>
                         | ?
                         | ?
                         """.trimIndent(),
-                    "firstStar" to """
+                "firstStar" to """
                         Node<?, RX>
                         | ?
                         | RX
@@ -556,7 +656,7 @@
                         | > | > | TX
                         | > | > | RX
                     """.trimIndent(),
-                    "secondStar" to """
+                "secondStar" to """
                         Node<TX, ?>
                         | TX
                         | > Node<TX, RX>
@@ -570,7 +670,7 @@
                         | > | > | TX
                         | ?
                     """.trimIndent(),
-                    "noStar" to """
+                "noStar" to """
                         Node<TX, RX>
                         | TX
                         | > Node<TX, RX>
@@ -593,8 +693,22 @@
                         | > | > | TX
                         | > | > | RX
                     """.trimIndent()
-                )
             )
+            nodeElm.getDeclaredMethods().associate {
+                it.name to it.parameters.single().type.asTypeName()
+            }.let {
+                assertThat(it.mapValues { entry -> entry.value.java.dumpToString(5) })
+                    .containsExactlyEntriesIn(expectedStringDumps)
+                if (invocation.isKsp) {
+                    assertThat(it.mapValues { entry -> entry.value.kotlin.dumpToString(5) })
+                        .containsExactlyEntriesIn(
+                            // Quick replace ? to * to correctly compare with KotlinPoet
+                            expectedStringDumps.mapValues { entry ->
+                                entry.value.replace('?', '*')
+                            }
+                        )
+                }
+            }
         }
     }
 
@@ -675,9 +789,7 @@
             sources = listOf(src)
         ) { invocation ->
             val elm = invocation.processingEnv.requireTypeElement("SelfReferencing")
-            val typeName = elm.type.typeName
-            assertThat(typeName.dumpToString(5)).isEqualTo(
-                """
+            val expected = """
                 SelfReferencing<TX, RX>
                 | TX
                 | > SelfReferencing<TX, RX>
@@ -695,7 +807,12 @@
                 | > | > | TX
                 | > | > | RX
                 """.trimIndent()
-            )
+            assertThat(elm.type.asTypeName().java.dumpToString(5))
+                .isEqualTo(expected)
+            if (invocation.isKsp) {
+                assertThat(elm.type.asTypeName().kotlin.dumpToString(5))
+                    .isEqualTo(expected)
+            }
         }
     }
 
@@ -801,10 +918,18 @@
         runProcessorTest(listOf(libSource)) { invocation ->
             val actual = invocation.processingEnv.requireTypeElement("MyClass")
                 .getDeclaredMethodByJvmName("setLists").parameters.associate {
-                    it.name to it.type.typeName.toString()
+                    it.name to it.type.asTypeName()
                 }
-            assertThat(actual["starList"]).isEqualTo("java.util.List<?>")
-            assertThat(actual["rList"]).isEqualTo("java.util.List<? extends R>")
+            assertThat(actual["starList"]?.java.toString())
+                .isEqualTo("java.util.List<?>")
+            assertThat(actual["rList"]?.java.toString())
+                .isEqualTo("java.util.List<? extends R>")
+            if (invocation.isKsp) {
+                assertThat(actual["starList"]?.kotlin.toString())
+                    .isEqualTo("kotlin.collections.List<*>")
+                assertThat(actual["rList"]?.kotlin.toString())
+                    .isEqualTo("kotlin.collections.List<out R>")
+            }
         }
     }
 
@@ -829,8 +954,12 @@
                 val superInterface =
                     superTypes.first { type -> type.rawType.toString() == "foo.bar.MyInterface" }
                 assertThat(superClass.typeArguments).hasSize(1)
-                assertThat(superClass.typeArguments[0].typeName)
-                    .isEqualTo(ClassName.get("java.lang", "String"))
+                assertThat(superClass.typeArguments[0].asTypeName().java)
+                    .isEqualTo(JClassName.get("java.lang", "String"))
+                if (invocation.isKsp) {
+                    assertThat(superClass.typeArguments[0].asTypeName().kotlin)
+                        .isEqualTo(KClassName("kotlin", "String"))
+                }
                 assertThat(superInterface.typeArguments).isEmpty()
             }
         }
@@ -881,7 +1010,10 @@
         fun XTestInvocation.checkPrimitiveType() {
             val fooElement = processingEnv.requireTypeElement("foo.bar.Foo")
             val primitiveType = fooElement.getField("i").type
-            assertThat(primitiveType.typeName).isEqualTo(TypeName.INT)
+            assertThat(primitiveType.asTypeName().java).isEqualTo(JTypeName.INT)
+            if (isKsp) {
+                assertThat(primitiveType.asTypeName().kotlin).isEqualTo(INT)
+            }
             assertThat(primitiveType.typeElement).isNull()
         }
 
@@ -905,45 +1037,4 @@
             """.trimIndent()
         ))) { it.checkPrimitiveType() }
     }
-
-    /**
-     * Dumps the typename with its bounds in a given depth.
-     * This makes tests more readable.
-     */
-    private fun TypeName.dumpToString(depth: Int): String {
-        return dump(depth).toString()
-    }
-
-    private fun TypeName.dump(depth: Int): TypeNameNode? {
-        if (depth < 0) return null
-        return when (this) {
-            is ParameterizedTypeName -> TypeNameNode(
-                text = this.toString(),
-                typeArgs = this.typeArguments.mapNotNull { it.dump(depth - 1) }
-            )
-            is TypeVariableName -> TypeNameNode(
-                text = this.toString(),
-                bounds = bounds.map { it.dump(depth - 1) }.filterNotNull()
-            )
-            else -> TypeNameNode(text = toString())
-        }
-    }
-
-    private data class TypeNameNode(
-        val text: String,
-        val bounds: List<TypeNameNode> = emptyList(),
-        val typeArgs: List<TypeNameNode> = emptyList()
-    ) {
-        override fun toString(): String {
-            return buildString {
-                appendLine(text)
-                bounds.forEach {
-                    appendLine(it.toString().prependIndent("> "))
-                }
-                typeArgs.forEach {
-                    appendLine(it.toString().prependIndent("| "))
-                }
-            }.trim()
-        }
-    }
 }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/compat/XConvertersTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/compat/XConvertersTest.kt
index fc35d13..a55e28f 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/compat/XConvertersTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/compat/XConvertersTest.kt
@@ -39,13 +39,12 @@
 import com.squareup.javapoet.ClassName
 import com.squareup.javapoet.JavaFile
 import com.squareup.javapoet.TypeSpec
-import org.junit.Test
-import java.lang.IllegalStateException
 import javax.annotation.processing.Filer
 import javax.annotation.processing.Messager
 import javax.lang.model.type.TypeMirror
 import javax.lang.model.util.ElementFilter
 import javax.tools.Diagnostic
+import org.junit.Test
 
 class XConvertersTest {
 
@@ -113,9 +112,9 @@
                     assertThat(tFromXConverters).isNull()
                     return
                 }
-                assertThat(t.typeName).isEqualTo(tFromXConverters.typeName)
+                assertThat(t.asTypeName()).isEqualTo(tFromXConverters.asTypeName())
                 assertThat(t.typeElement).isEqualTo(tFromXConverters.typeElement)
-                assertThat(t.rawType.typeName).isEqualTo(tFromXConverters.rawType.typeName)
+                assertThat(t.rawType.asTypeName()).isEqualTo(tFromXConverters.rawType.asTypeName())
                 assertThat(t.typeArguments.size).isEqualTo(tFromXConverters.typeArguments.size)
                 for (i in 0..t.typeArguments.size) {
                     assertEqualTypes(t.typeArguments[i], tFromXConverters.typeArguments[i])
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
index f9c6d5f..ef0ec14 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
@@ -16,6 +16,9 @@
 
 package androidx.room.compiler.processing.ksp
 
+import androidx.room.compiler.codegen.XClassName
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
 import androidx.room.compiler.processing.XNullability.NONNULL
 import androidx.room.compiler.processing.XNullability.NULLABLE
 import androidx.room.compiler.processing.XType
@@ -24,17 +27,19 @@
 import androidx.room.compiler.processing.isLong
 import androidx.room.compiler.processing.isVoid
 import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.className
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.typeName
 import com.google.common.truth.Truth.assertThat
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.TypeName
-import com.squareup.javapoet.TypeVariableName
-import com.squareup.javapoet.WildcardTypeName
+import com.squareup.kotlinpoet.UNIT
+import com.squareup.kotlinpoet.javapoet.JClassName
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JTypeVariableName
+import com.squareup.kotlinpoet.javapoet.JWildcardTypeName
+import com.squareup.kotlinpoet.javapoet.KClassName
+import com.squareup.kotlinpoet.javapoet.KTypeVariableName
+import com.squareup.kotlinpoet.javapoet.KWildcardTypeName
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -46,7 +51,7 @@
         val src = Source.kotlin(
             "foo.kt",
             """
-            package foo.bar;
+            package foo.bar
             class Baz : AbstractClass(), MyInterface {
             }
             abstract class AbstractClass {}
@@ -55,8 +60,8 @@
         )
         runProcessorTest(listOf(src)) {
             val subject = it.processingEnv.requireType("foo.bar.Baz")
-            assertThat(subject.typeName).isEqualTo(
-                ClassName.get("foo.bar", "Baz")
+            assertThat(subject.asTypeName()).isEqualTo(
+                XClassName.get("foo.bar", "Baz")
             )
             // basic assertions for abstract class
             val abstractSubject = it.processingEnv.requireType("foo.bar.AbstractClass")
@@ -99,8 +104,12 @@
             subject.getField("errorType").type.let { type ->
                 assertThat(type.isError()).isTrue()
                 assertThat(type.typeArguments).isEmpty()
-                assertThat(type.typeName).isEqualTo(ERROR_JTYPE_NAME)
-                assertThat(type.typeElement!!.className).isEqualTo(ERROR_JTYPE_NAME)
+                assertThat(type.asTypeName().java).isEqualTo(ERROR_JTYPE_NAME)
+                assertThat(type.typeElement!!.asClassName().java).isEqualTo(ERROR_JTYPE_NAME)
+                if (invocation.isKsp) {
+                    assertThat(type.asTypeName().kotlin).isEqualTo(ERROR_KTYPE_NAME)
+                    assertThat(type.typeElement!!.asClassName().kotlin).isEqualTo(ERROR_KTYPE_NAME)
+                }
             }
 
             subject.getField("listOfErrorType").type.let { type ->
@@ -108,7 +117,10 @@
                 assertThat(type.typeArguments).hasSize(1)
                 type.typeArguments.single().let { typeArg ->
                     assertThat(typeArg.isError()).isTrue()
-                    assertThat(typeArg.typeName).isEqualTo(ERROR_JTYPE_NAME)
+                    assertThat(typeArg.asTypeName().java).isEqualTo(ERROR_JTYPE_NAME)
+                    if (invocation.isKsp) {
+                        assertThat(typeArg.asTypeName().kotlin).isEqualTo(ERROR_KTYPE_NAME)
+                    }
                 }
             }
             invocation.assertCompilationResult {
@@ -135,8 +147,8 @@
             subject.getField("listOfNullableStrings").type.let { type ->
                 assertThat(type.nullability).isEqualTo(NONNULL)
                 assertThat(type.typeArguments).hasSize(1)
-                assertThat(type.typeElement!!.className).isEqualTo(
-                    List::class.typeName()
+                assertThat(type.typeElement!!.asClassName()).isEqualTo(
+                    List::class.asClassName()
                 )
                 type.typeArguments.single().let { typeArg ->
                     assertThat(typeArg.nullability).isEqualTo(NULLABLE)
@@ -160,8 +172,8 @@
                         )
                     ).isTrue()
                 }
-                assertThat(type.typeElement!!.className).isEqualTo(
-                    List::class.className()
+                assertThat(type.typeElement!!.asClassName()).isEqualTo(
+                    List::class.asClassName()
                 )
             }
         }
@@ -238,19 +250,18 @@
         ) { invocation ->
             val subject = invocation.processingEnv.requireTypeElement("Subject")
             subject.getField("simple").type.let {
-                assertThat(it.rawType.typeName).isEqualTo(TypeName.INT)
+                assertThat(it.rawType.asTypeName()).isEqualTo(XTypeName.PRIMITIVE_INT)
             }
             subject.getField("list").type.let { list ->
                 assertThat(list.rawType).isNotEqualTo(list)
                 assertThat(list.typeArguments).isNotEmpty()
-                assertThat(list.rawType.typeName)
-                    .isEqualTo(ClassName.get("java.util", "List"))
+                assertThat(list.rawType.asTypeName()).isEqualTo(List::class.asClassName())
             }
             subject.getField("map").type.let { map ->
                 assertThat(map.rawType).isNotEqualTo(map)
                 assertThat(map.typeArguments).hasSize(2)
-                assertThat(map.rawType.typeName)
-                    .isEqualTo(ClassName.get("java.util", "Map"))
+                assertThat(map.rawType.asTypeName())
+                    .isEqualTo(Map::class.asClassName())
             }
             subject.getField("listOfMaps").type.let { listOfMaps ->
                 assertThat(listOfMaps.rawType).isNotEqualTo(listOfMaps)
@@ -275,11 +286,12 @@
             val voidMethod = invocation.processingEnv.requireTypeElement("foo.bar.Baz")
                 .getMethodByJvmName("voidMethod")
             val returnType = voidMethod.returnType
-            assertThat(
-                returnType.typeName
-            ).isEqualTo(
-                TypeName.VOID
-            )
+            assertThat(returnType.asTypeName().java)
+                .isEqualTo(JTypeName.VOID)
+            if (invocation.isKsp) {
+                assertThat(returnType.asTypeName().kotlin)
+                    .isEqualTo(UNIT)
+            }
             assertThat(returnType.isVoid()).isTrue()
         }
     }
@@ -469,7 +481,7 @@
         val src = Source.kotlin(
             "foo.kt",
             """
-            open class Foo;
+            open class Foo
             class Bar<T : Foo> {
             }
             class Bar_NullableFoo<T : Foo?>
@@ -485,16 +497,29 @@
                     .typeArguments
                     .single()
             }
-            val typeName = typeArgs["Bar"]!!.typeName
-            assertThat(typeName)
+            assertThat(typeArgs["Bar"]!!.asTypeName().java)
                 .isEqualTo(
-                    TypeVariableName.get("T", ClassName.get("", "Foo"))
+                    JTypeVariableName.get("T", JClassName.get("", "Foo"))
                 )
+            if (invocation.isKsp) {
+                assertThat(typeArgs["Bar"]!!.asTypeName().kotlin)
+                    .isEqualTo(
+                        KTypeVariableName("T", KClassName("", "Foo"))
+                    )
+            }
             assertThat(typeArgs["Bar"]!!.nullability).isEqualTo(NONNULL)
-            assertThat(typeArgs["Bar_NullableFoo"]!!.typeName)
+            assertThat(typeArgs["Bar_NullableFoo"]!!.asTypeName().java)
                 .isEqualTo(
-                    TypeVariableName.get("T", ClassName.get("", "Foo"))
+                    JTypeVariableName.get("T", JClassName.get("", "Foo"))
                 )
+            if (invocation.isKsp) {
+                assertThat(typeArgs["Bar_NullableFoo"]!!.asTypeName().kotlin)
+                    .isEqualTo(
+                        KTypeVariableName(
+                            "T", KClassName("", "Foo").copy(nullable = true)
+                        )
+                    )
+            }
             assertThat(typeArgs["Bar_NullableFoo"]!!.nullability).isEqualTo(NULLABLE)
         }
     }
@@ -515,21 +540,27 @@
         runProcessorTest(
             listOf(src)
         ) { invocation ->
-
             val typeElement = invocation.processingEnv.requireTypeElement("foo.bar.Baz")
             val method = typeElement.getMethodByJvmName("wildcardMethod")
             val asMember = method.asMemberOf(typeElement.type)
             fun assertParamType(paramType: XType) {
                 val arg1 = paramType.typeArguments.single()
-                assertThat(arg1.typeName)
+                assertThat(arg1.asTypeName().java)
                     .isEqualTo(
-                        WildcardTypeName.subtypeOf(
-                            Number::class.java
-                        )
+                        JWildcardTypeName.subtypeOf(Number::class.java)
                     )
-                assertThat(arg1.extendsBound()?.typeName).isEqualTo(
-                    ClassName.get("java.lang", "Number")
+                assertThat(arg1.extendsBound()?.asTypeName()?.java).isEqualTo(
+                    JClassName.get("java.lang", "Number")
                 )
+                if (invocation.isKsp) {
+                    assertThat(arg1.asTypeName().kotlin)
+                        .isEqualTo(
+                            KWildcardTypeName.producerOf(Number::class)
+                        )
+                    assertThat(arg1.extendsBound()?.asTypeName()?.kotlin).isEqualTo(
+                        KClassName("kotlin", "Number")
+                    )
+                }
                 assertThat(
                     arg1.extendsBound()?.extendsBound()
                 ).isNull()
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainerTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainerTest.kt
index 1ef355a..7ff027c 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainerTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticFileMemberContainerTest.kt
@@ -136,7 +136,8 @@
                     val owner = invocation.kspResolver.getOwnerJvmClassName(field.declaration)
                     assertWithMessage(qName).that(owner).isNotNull()
                     val synthetic = KspSyntheticFileMemberContainer(owner!!)
-                    assertWithMessage(qName).that(target.className).isEqualTo(synthetic.className)
+                    assertWithMessage(qName).that(target.asClassName())
+                        .isEqualTo(synthetic.asClassName())
                 }
             }
             listOf("lib", "app").forEach { pkg ->
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/util/PoetTestExt.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/util/PoetTestExt.kt
index df6eeec..86942af 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/util/PoetTestExt.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/util/PoetTestExt.kt
@@ -16,42 +16,72 @@
 
 package androidx.room.compiler.processing.util
 
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.TypeName
+import androidx.room.compiler.codegen.XTypeName
+import com.squareup.kotlinpoet.MUTABLE_COLLECTION
+import com.squareup.kotlinpoet.MUTABLE_ITERABLE
+import com.squareup.kotlinpoet.MUTABLE_LIST
+import com.squareup.kotlinpoet.MUTABLE_MAP
+import com.squareup.kotlinpoet.MUTABLE_MAP_ENTRY
+import com.squareup.kotlinpoet.MUTABLE_SET
 import com.squareup.kotlinpoet.asClassName
 import com.squareup.kotlinpoet.asTypeName
+import com.squareup.kotlinpoet.javapoet.JClassName
 import com.squareup.kotlinpoet.javapoet.JParameterizedTypeName
 import com.squareup.kotlinpoet.javapoet.JTypeName
 import com.squareup.kotlinpoet.javapoet.JTypeVariableName
+import com.squareup.kotlinpoet.javapoet.KClassName
 import com.squareup.kotlinpoet.javapoet.KParameterizedTypeName
 import com.squareup.kotlinpoet.javapoet.KTypeName
 import com.squareup.kotlinpoet.javapoet.KTypeVariableName
 import kotlin.reflect.KClass
 
-val UNIT_CLASS_NAME = ClassName.get("kotlin", "Unit")
-val CONTINUATION_CLASS_NAME = ClassName.get("kotlin.coroutines", "Continuation")
+val UNIT_JCLASS_NAME = JClassName.get("kotlin", "Unit")
+val CONTINUATION_JCLASS_NAME = JClassName.get("kotlin.coroutines", "Continuation")
 
 // TODO(b/247242378): Migrate usages to asJTypeName() and asJClassName()
 // @Deprecated(
 //     message = "Use asJTypeName() to be clear it's a JavaPoet converter",
 //     replaceWith = ReplaceWith("asJTypeName()")
 // )
-fun KClass<*>.typeName() = TypeName.get(this.java)
+fun KClass<*>.typeName() = JTypeName.get(this.java)
 
 // TODO(b/247242378): Migrate usages to asJTypeName() and asJClassName()
 // @Deprecated(
 //     message = "Use asJClassName() to be clear it's a JavaPoet converter",
 //     replaceWith = ReplaceWith("asJClassName()")
 // )
-fun KClass<*>.className() = ClassName.get(this.java)
+fun KClass<*>.className() = JClassName.get(this.java)
 
-fun KClass<*>.asJTypeName() = TypeName.get(this.java)
-fun KClass<*>.asJClassName() = ClassName.get(this.java)
+fun KClass<*>.asJTypeName() = JTypeName.get(this.java)
+fun KClass<*>.asJClassName() = JClassName.get(this.java)
 
 fun KClass<*>.asKTypeName() = this.asTypeName()
 fun KClass<*>.asKClassName() = this.asClassName()
 
 /**
+ * Workaround for:
+ * https://github.com/square/kotlinpoet/issues/279
+ * https://youtrack.jetbrains.com/issue/KT-11754
+ */
+fun KClass<*>.asMutableKClassName(): KClassName = when (this) {
+    Iterator::class -> MUTABLE_ITERABLE
+    Collection::class -> MUTABLE_COLLECTION
+    List::class -> MUTABLE_LIST
+    Set::class -> MUTABLE_SET
+    Map::class -> MUTABLE_MAP
+    Map.Entry::class -> MUTABLE_MAP_ENTRY
+    else -> this.asKClassName()
+}
+
+// Creates a simple XTypeName wrapping JTypeVariableName and KTypeVariableName without bounds.
+fun createXTypeVariableName(name: String): XTypeName {
+    return XTypeName(
+        java = JTypeVariableName.get(name),
+        kotlin = KTypeVariableName(name)
+    )
+}
+
+/**
  * Dumps the typename with its bounds in a given depth, making tests more readable.
  */
 fun JTypeName.dumpToString(depth: Int): String {