Added XType#superTypes.

Test: tested with XTypeTest
Change-Id: I47af47b60e92707b5b3659035627bc0f1b481e92
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 bec9add..31f9522 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
@@ -46,6 +46,11 @@
     val nullability: XNullability
 
     /**
+     * The resolved types of the super classes/interfaces of this type.
+     */
+    val superTypes: List<XType>
+
+    /**
      * The [XTypeElement] that represents this type.
      *
      * Note that it might be null if the type is not backed by a type element (e.g. if it is a
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 8b860a7..da9da97 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
@@ -21,6 +21,7 @@
 import androidx.room.compiler.processing.XRawType
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.javac.kotlin.KmType
+import androidx.room.compiler.processing.javac.kotlin.KotlinMetadataElement
 import androidx.room.compiler.processing.ksp.ERROR_TYPE_NAME
 import androidx.room.compiler.processing.safeTypeName
 import com.google.auto.common.MoreTypes
@@ -41,6 +42,18 @@
         JavacRawType(env, this)
     }
 
+    override val superTypes by lazy {
+        val superTypes = env.typeUtils.directSupertypes(typeMirror)
+        superTypes.map {
+            val element = MoreTypes.asTypeElement(it)
+            env.wrap<JavacType>(
+                typeMirror = it,
+                kotlinType = KotlinMetadataElement.createFor(element)?.kmType,
+                elementNullability = element.nullability
+            )
+        }
+    }
+
     override val typeElement by lazy {
         val element = try {
             MoreTypes.asTypeElement(typeMirror)
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 464de02..063037a 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
@@ -51,6 +51,16 @@
         }
     }
 
+    override val superTypes: List<XType> by lazy {
+        val declaration = ksType.declaration as? KSClassDeclaration
+        declaration?.superTypes?.toList()?.map {
+            env.wrap(
+                ksType = it.resolve(),
+                allowPrimitives = false
+            )
+        } ?: emptyList()
+    }
+
     override val typeElement by lazy {
         // for primitive types, we could technically return null from here as they are not backed
         // by a type element in javac but in Kotlin we have types for them, hence returning them
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 8b47c88..9a7c759 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
@@ -627,6 +627,34 @@
         }
     }
 
+    @Test
+    fun superTypes() {
+        val libSource = Source.kotlin(
+            "foo.kt",
+            """
+            package foo.bar;
+            class Baz : MyInterface, AbstractClass<String>() {
+            }
+            abstract class AbstractClass<T> {}
+            interface MyInterface {}
+            """.trimIndent()
+        )
+        runProcessorTest(listOf(libSource)) { invocation ->
+            invocation.processingEnv.requireType("foo.bar.Baz").let {
+                val superTypes = it.superTypes
+                assertThat(superTypes).hasSize(2)
+                val superClass = superTypes.first {
+                        type -> type.rawType.toString() == "foo.bar.AbstractClass" }
+                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(superInterface.typeArguments).isEmpty()
+            }
+        }
+    }
+
     /**
      * Dumps the typename with its bounds in a given depth.
      * This makes tests more readable.