Move XType.is checks to extension methods

This CL moves XType.is checks for known types to extension methods and
uses the TypeName (thats what JavacType did).

Initially, they were put into the interface because I wasn't sure how
well the typeName will work in KSP. At this point, it is one of the more
reliable parts of the KSP implementation (e.g. we do very well in
deciding whether we want it to be a primitive or not).

By moving them to extension methods, KSP and Javac implementations get
closer and becomes more consistent.

While creating a test case (KSP impl used to fail to detect boxed Void),
I hit a bug in KSP. Added a workaround for now.
https://github.com/google/ksp/issues/200

Bug: 160322705
Test: XTypeTest & existing tests
Change-Id: I2ece2a9738faeef9a8530475f9f96330b35abaf3
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
index 1f71b15..13d02ef 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing
 
+import com.squareup.javapoet.ClassName
 import com.squareup.javapoet.TypeName
 import kotlin.contracts.contract
 import kotlin.reflect.KClass
@@ -96,41 +97,11 @@
     fun boxed(): XType
 
     /**
-     * Returns `true` if this is a primitive or boxed it
-     */
-    fun isInt(): Boolean
-
-    /**
-     * Returns `true` if this is a primitive or boxed long
-     */
-    fun isLong(): Boolean
-
-    /**
      * Returns `true` if this is a [List]
      */
     fun isList(): Boolean = isTypeOf(List::class)
 
     /**
-     * Returns `true` if this is `void`
-     */
-    fun isVoid() = typeName == TypeName.VOID
-
-    /**
-     * Returns `true` if this is a [Void]
-     */
-    fun isVoidObject(): Boolean = isTypeOf(Void::class)
-
-    /**
-     * Returns `true` if this is the kotlin [Unit] type.
-     */
-    fun isKotlinUnit(): Boolean = isTypeOf(Unit::class)
-
-    /**
-     * Returns `true` if this represents a `byte`.
-     */
-    fun isByte(): Boolean
-
-    /**
      * Returns `true` if this is the None type.
      */
     fun isNone(): Boolean
@@ -231,3 +202,40 @@
         )
     }
 }
+
+/**
+ * Returns `true` if this is a primitive or boxed it
+ */
+fun XType.isInt(): Boolean = typeName == TypeName.INT || typeName == KnownTypeNames.BOXED_INT
+
+/**
+ * Returns `true` if this is a primitive or boxed long
+ */
+fun XType.isLong(): Boolean = typeName == TypeName.LONG || typeName == KnownTypeNames.BOXED_LONG
+/**
+ * Returns `true` if this is `void`
+ */
+fun XType.isVoid() = typeName == TypeName.VOID
+
+/**
+ * Returns `true` if this is a [Void]
+ */
+fun XType.isVoidObject(): Boolean = typeName == KnownTypeNames.BOXED_VOID
+
+/**
+ * Returns `true` if this is the kotlin [Unit] type.
+ */
+fun XType.isKotlinUnit(): Boolean = typeName == KnownTypeNames.KOTLIN_UNIT
+
+/**
+ * Returns `true` if this represents a `byte`.
+ */
+fun XType.isByte(): Boolean = typeName == TypeName.BYTE || typeName == KnownTypeNames.BOXED_BYTE
+
+internal object KnownTypeNames {
+    val BOXED_VOID = TypeName.VOID.box()
+    val BOXED_INT = TypeName.INT.box()
+    val BOXED_LONG = TypeName.LONG.box()
+    val BOXED_BYTE = TypeName.BYTE.box()
+    val KOTLIN_UNIT = ClassName.get("kotlin", "Unit")
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
index 041e917..13889f5 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
@@ -24,7 +24,6 @@
 import androidx.room.compiler.processing.ksp.ERROR_TYPE_NAME
 import androidx.room.compiler.processing.safeTypeName
 import com.google.auto.common.MoreTypes
-import com.squareup.javapoet.TypeName
 import javax.lang.model.element.ElementKind
 import javax.lang.model.type.TypeKind
 import javax.lang.model.type.TypeMirror
@@ -58,18 +57,6 @@
             (kotlinType != null && typeName == ERROR_TYPE_NAME)
     }
 
-    override fun isInt(): Boolean {
-        return typeName == TypeName.INT || typeName == BOXED_INT
-    }
-
-    override fun isLong(): Boolean {
-        return typeName == TypeName.LONG || typeName == BOXED_LONG
-    }
-
-    override fun isByte(): Boolean {
-        return typeName == TypeName.BYTE || typeName == BOXED_BYTE
-    }
-
     override val typeName by lazy {
         typeMirror.safeTypeName()
     }
@@ -181,12 +168,6 @@
         return copyWithNullability(XNullability.NONNULL)
     }
 
-    companion object {
-        private val BOXED_INT = TypeName.INT.box()
-        private val BOXED_LONG = TypeName.LONG.box()
-        private val BOXED_BYTE = TypeName.BYTE.box()
-    }
-
     override fun isEnum() = typeMirror.kind == TypeKind.DECLARED &&
         MoreTypes.asElement(typeMirror).kind == ElementKind.ENUM
 }
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
index 7e84d7c..2c9b601 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
@@ -84,9 +84,17 @@
             // object
             resolved
         }
-        else -> resolver.asMemberOf(
-            function = this,
-            containing = ksType
-        ).returnType
+        else -> {
+            // workaround for https://github.com/google/ksp/issues/200
+            val resolvedReturnType = resolver.asMemberOf(
+                function = this,
+                containing = ksType
+            ).returnType
+            if (resolvedReturnType == null || resolvedReturnType.isError) {
+                resolved
+            } else {
+                resolvedReturnType
+            }
+        }
     } ?: error("cannot find return type for $this")
 }
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index 23db79e..dcdfca1 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -91,18 +91,6 @@
         }
     }
 
-    override fun isInt(): Boolean {
-        return env.commonTypes.nullableInt.isAssignableFrom(ksType)
-    }
-
-    override fun isLong(): Boolean {
-        return env.commonTypes.nullableLong.isAssignableFrom(ksType)
-    }
-
-    override fun isByte(): Boolean {
-        return env.commonTypes.nullableByte.isAssignableFrom(ksType)
-    }
-
     override fun isNone(): Boolean {
         // even void is converted to Unit so we don't have none type in KSP
         // see: KspTypeTest.noneType
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
index a285ebf..6e7b5bc 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
@@ -142,6 +142,14 @@
         // TODO remove this catch once that issue is fixed.
         // workaround for https://github.com/google/ksp/issues/164
         return declaration.simpleName.asString()
+    } catch (cannotFindDeclaration: IllegalStateException) {
+        // workaround for https://github.com/google/ksp/issues/200
+        val name = declaration.simpleName.asString()
+        if (name.startsWith("get") or name.startsWith("set")) {
+            return name
+        }
+        // we don't know why it happened so we better throw
+        throw cannotFindDeclaration
     }
 }
 
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index ab62de0..901d901 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -359,4 +359,48 @@
             }
         }
     }
+
+    @Test
+    fun isVoidObject() {
+        val javaBase = Source.java(
+            "JavaInterface.java",
+            """
+            import java.lang.Void;
+            interface JavaInterface {
+                // get void triggers a bug in KSP, which is why we keep it here.
+                // https://github.com/google/ksp/issues/200
+                Void getVoid();
+                Void anotherVoid();
+            }
+            """.trimIndent()
+        )
+        val kotlinSubject = Source.kotlin(
+            "Subject.kt",
+            """
+            abstract class KotlinSubject: JavaInterface {
+                fun voidMethod() {}
+            }
+            """.trimIndent()
+        )
+        runProcessorTest(sources = listOf(javaBase, kotlinSubject)) { invocation ->
+            invocation.processingEnv.requireTypeElement("KotlinSubject").let {
+                it.getMethod("voidMethod").returnType.let {
+                    assertThat(it.isVoidObject()).isFalse()
+                    assertThat(it.isVoid()).isTrue()
+                    assertThat(it.isKotlinUnit()).isFalse()
+                }
+                val method = it.getMethod("getVoid")
+                method.returnType.let {
+                    assertThat(it.isVoidObject()).isTrue()
+                    assertThat(it.isVoid()).isFalse()
+                    assertThat(it.isKotlinUnit()).isFalse()
+                }
+                it.getMethod("anotherVoid").returnType.let {
+                    assertThat(it.isVoidObject()).isTrue()
+                    assertThat(it.isVoid()).isFalse()
+                    assertThat(it.isKotlinUnit()).isFalse()
+                }
+            }
+        }
+    }
 }
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
index 71454de..69caa37 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
@@ -19,6 +19,10 @@
 import androidx.room.compiler.processing.XNullability.NONNULL
 import androidx.room.compiler.processing.XNullability.NULLABLE
 import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.isByte
+import androidx.room.compiler.processing.isInt
+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
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/xtype_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/xtype_ext.kt
index a2c674c..bd1eac6 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/xtype_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/xtype_ext.kt
@@ -17,6 +17,8 @@
 package androidx.room.ext
 
 import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.isByte
+import androidx.room.compiler.processing.isVoid
 
 fun XType.isNotVoid() = !isVoid()
 
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
index ee95aa1..8cff604 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
@@ -23,6 +23,7 @@
 import androidx.room.compiler.processing.XMethodElement
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.isVoid
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_BAD_RETURN_TYPE
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_EMPTY_CLASS
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
index 35716e8..8747d0d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -28,6 +28,7 @@
 import androidx.room.compiler.processing.XTypeElement
 import androidx.room.compiler.processing.XVariableElement
 import androidx.room.compiler.processing.isCollection
+import androidx.room.compiler.processing.isVoid
 import androidx.room.ext.isNotVoid
 import androidx.room.processor.ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD
 import androidx.room.processor.ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/KotlinDefaultMethodDelegateBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/KotlinDefaultMethodDelegateBinder.kt
index 1a6334b..5c36524 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/KotlinDefaultMethodDelegateBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/KotlinDefaultMethodDelegateBinder.kt
@@ -21,6 +21,7 @@
 import androidx.room.ext.N
 import androidx.room.ext.T
 import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.isVoid
 import com.squareup.javapoet.ClassName
 
 /**
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/result/PreparedQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/result/PreparedQueryResultAdapter.kt
index a60aae1..b4d2f88 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/result/PreparedQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/result/PreparedQueryResultAdapter.kt
@@ -22,6 +22,11 @@
 import androidx.room.ext.T
 import androidx.room.parser.QueryType
 import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.isInt
+import androidx.room.compiler.processing.isKotlinUnit
+import androidx.room.compiler.processing.isLong
+import androidx.room.compiler.processing.isVoid
+import androidx.room.compiler.processing.isVoidObject
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
 import com.squareup.javapoet.FieldSpec
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt
index dffe5b7..1531de9 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt
@@ -21,6 +21,10 @@
 import androidx.room.ext.N
 import androidx.room.ext.T
 import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.isInt
+import androidx.room.compiler.processing.isKotlinUnit
+import androidx.room.compiler.processing.isVoid
+import androidx.room.compiler.processing.isVoidObject
 import androidx.room.solver.CodeGenScope
 import androidx.room.vo.ShortcutQueryParameter
 import com.squareup.javapoet.FieldSpec
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt
index 91e98c7..ad230db 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt
@@ -18,6 +18,10 @@
 
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.isArray
+import androidx.room.compiler.processing.isKotlinUnit
+import androidx.room.compiler.processing.isLong
+import androidx.room.compiler.processing.isVoid
+import androidx.room.compiler.processing.isVoidObject
 import androidx.room.ext.KotlinTypeNames
 import androidx.room.ext.L
 import androidx.room.ext.N
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/RawQueryMethod.kt b/room/compiler/src/main/kotlin/androidx/room/vo/RawQueryMethod.kt
index a19be5e..95948ef 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/RawQueryMethod.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/RawQueryMethod.kt
@@ -20,6 +20,7 @@
 import androidx.room.ext.SupportDbTypeNames
 import androidx.room.compiler.processing.XMethodElement
 import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.isKotlinUnit
 import androidx.room.ext.isNotVoid
 import androidx.room.solver.query.result.QueryResultBinder
 import com.squareup.javapoet.TypeName
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
index a59e860..5642211 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
@@ -22,6 +22,7 @@
 import androidx.room.compiler.processing.XProcessingEnv
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.addOriginatingElement
+import androidx.room.compiler.processing.isVoid
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.L
 import androidx.room.ext.N