Model top level functions and properties

This CL adds support for top level functions/properties in KSP.

KSP does not generate synthetic class for files that include top
level methods or properites.
see: https://github.com/google/ksp/issues/396

For XProcessing, i decided the follow through and not create a fake
XTypeElement for them. Instead, this CL introduces a new XElement
type called XMemberContainer. This interface defines two properties:
className:ClassName and type:XType.
ClassName is mandatory whereas XType is optional (to denote that it
does not have an accessible type in KSP but ClassName can be accessed
for code generation).
This was enough to make the rest of the codebase happy.

For Room, I also removed `XMethod/FieldElement.requireEnclosingTypeElement`
as we didn't really need it once we have className.

XMemberContainer might be extended to provide access to more declarations
but we don't yet have a use case for that.

By not modeling fake XTypeElements, we avoid creating a fake XType for it,
which prevents lots of pitfalls since the type does not really exist in
kotlin world.

Bug: 160322705
Fixes: 184526463
Test: XRoundEnvTest, TopLevelMembersTest
Change-Id: Iea60d2587c9373a96a56f7721d5ea2782b66ba2e
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/MethodCollector.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/MethodCollector.kt
index e3be1a9..7cac32a 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/MethodCollector.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/MethodCollector.kt
@@ -78,7 +78,7 @@
             return false
         }
         // check package
-        return packageName == other.requireEnclosingTypeElement().packageName
+        return packageName == other.enclosingElement.className.packageName()
     }
 }
 
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableElement.kt
index 3df684f..0bc4dd0 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableElement.kt
@@ -25,9 +25,15 @@
     /**
      * The element that declared this executable.
      *
-     * @see requireEnclosingTypeElement
+     * For methods declared as top level functions in Kotlin:
+     *   * When running with KAPT, the value will be an [XTypeElement].
+     *   * When running with KSP, if this function is coming from the classpath, the value will
+     *   be an [XTypeElement].
+     *   * When running with KSP, if this function is in source, the value will **NOT** be an
+     *   [XTypeElement]. If you need the generated synthetic java class name, you can use
+     *   [XMemberContainer.className] property.
      */
-    val enclosingElement: XElement
+    val enclosingElement: XMemberContainer
     /**
      * The list of parameters that should be passed into this method.
      *
@@ -39,12 +45,3 @@
      */
     fun isVarArgs(): Boolean
 }
-
-/**
- * Checks the enclosing element is a TypeElement and returns it, otherwise,
- * throws [IllegalStateException].
- */
-fun XExecutableElement.requireEnclosingTypeElement(): XTypeElement {
-    return enclosingElement as? XTypeElement
-        ?: error("Required enclosing type element for $this but found $enclosingElement")
-}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFieldElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFieldElement.kt
index bb3701a..6d9540f 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFieldElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFieldElement.kt
@@ -22,16 +22,18 @@
 interface XFieldElement : XVariableElement, XHasModifiers {
     /**
      * The element that declared this field.
+     * For fields declared in classes, this will be an [XTypeElement].
      *
-     * @see requireEnclosingTypeElement
+     * For fields declared as top level properties in Kotlin:
+     *   * When running with KAPT, the value will be an [XTypeElement].
+     *   * When running with KSP, if this property is coming from the classpath, the value will
+     *   be an [XTypeElement].
+     *   * When running with KSP, if this property is in source, the value will **NOT** be an
+     *   [XTypeElement]. If you need the generated synthetic java class name, you can use
+     *   [XMemberContainer.className] property.
      */
-    val enclosingElement: XElement
+    val enclosingElement: XMemberContainer
 
     override val fallbackLocationText: String
         get() = "$name in ${enclosingElement.fallbackLocationText}"
 }
-
-fun XFieldElement.requireEnclosingTypeElement(): XTypeElement {
-    return enclosingElement as? XTypeElement
-        ?: error("Required enclosing type element for $this but found $enclosingElement")
-}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt
new file mode 100644
index 0000000..86aa1d2
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMemberContainer.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing
+
+import com.squareup.javapoet.ClassName
+
+/**
+ * Common interface for elements that can contain methods and properties.
+ *
+ * This is especially important for handling top level methods / properties in KSP where the
+ * synthetic container class does not exist
+ */
+interface XMemberContainer : XElement {
+    /**
+     * The JVM ClassName for this container.
+     * For top level members of a Kotlin file, you can use this [className] for code generation.
+     */
+    val className: ClassName
+
+    /**
+     * 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)
+     */
+    val type: XType?
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
index 76e1e96..5109aff 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
@@ -18,7 +18,7 @@
 
 import com.squareup.javapoet.ClassName
 
-interface XTypeElement : XHasModifiers, XElement {
+interface XTypeElement : XHasModifiers, XElement, XMemberContainer {
     /**
      * The qualified name of the Class/Interface.
      */
@@ -39,7 +39,7 @@
     /**
      * The type represented by this [XTypeElement].
      */
-    val type: XType
+    override val type: XType
 
     /**
      * The super type of this element if it represents a class.
@@ -49,7 +49,7 @@
     /**
      * Javapoet [ClassName] of the type.
      */
-    val className: ClassName
+    override val className: ClassName
 
     /**
      * The [XTypeElement] that contains this [XTypeElement] if it is an inner class/interface.
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..37a3569 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
@@ -25,13 +25,16 @@
 /**
  * Returns the type of a property as if it is member of the given [ksType].
  */
-internal fun KSPropertyDeclaration.typeAsMemberOf(resolver: Resolver, ksType: KSType): KSType {
+internal fun KSPropertyDeclaration.typeAsMemberOf(resolver: Resolver, ksType: KSType?): KSType {
     val resolved = type.resolve()
     if (isStatic()) {
         // calling as member with a static would throw as it might be a member of the companion
         // object
         return resolved
     }
+    if (ksType == null) {
+        return resolved
+    }
     // see: https://github.com/google/ksp/issues/107
     // as member of might lose the `isError` information hence we should check before calling
     // asMemberOf.
@@ -47,7 +50,7 @@
 internal fun KSValueParameter.typeAsMemberOf(
     resolver: Resolver,
     functionDeclaration: KSFunctionDeclaration,
-    ksType: KSType
+    ksType: KSType?
 ): KSType {
     val resolved = type.resolve()
     if (functionDeclaration.isStatic()) {
@@ -61,6 +64,9 @@
         // asMemberOf.
         return resolved
     }
+    if (ksType == null) {
+        return resolved
+    }
     val asMember = resolver.asMemberOf(
         function = functionDeclaration,
         containing = ksType
@@ -73,11 +79,12 @@
 
 internal fun KSFunctionDeclaration.returnTypeAsMemberOf(
     resolver: Resolver,
-    ksType: KSType
+    ksType: KSType?
 ): KSType {
     val resolved = returnType?.resolve()
     return when {
         resolved == null -> null
+        ksType == null -> resolved
         resolved.isError -> resolved
         isStatic() -> {
             // calling as member with a static would throw as it might be a member of the companion
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSDeclarationExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSDeclarationExt.kt
index 054c840..2b59a34 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSDeclarationExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSDeclarationExt.kt
@@ -18,6 +18,9 @@
 
 import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration
+import com.google.devtools.ksp.symbol.KSPropertyAccessor
+import com.google.devtools.ksp.symbol.KSPropertyDeclaration
 import com.google.devtools.ksp.symbol.Modifier
 
 /**
@@ -25,8 +28,10 @@
  * be found.
  * @see [findEnclosingAncestorClassDeclaration]
  */
-internal fun KSDeclaration.requireEnclosingTypeElement(env: KspProcessingEnv): KspTypeElement {
-    return checkNotNull(findEnclosingTypeElement(env)) {
+internal fun KSDeclaration.requireEnclosingMemberContainer(
+    env: KspProcessingEnv
+): KspMemberContainer {
+    return checkNotNull(findEnclosingMemberContainer(env)) {
         "Cannot find required enclosing type for $this"
     }
 }
@@ -37,13 +42,17 @@
  * Node that this is not necessarily the parent declaration. e.g. when a property is declared in
  * a constructor, its containing type is actual two levels up.
  */
-internal fun KSDeclaration.findEnclosingTypeElement(env: KspProcessingEnv): KspTypeElement? {
+internal fun KSDeclaration.findEnclosingMemberContainer(
+    env: KspProcessingEnv
+): KspMemberContainer? {
     return findEnclosingAncestorClassDeclaration()?.let {
         env.wrapClassDeclaration(it)
+    } ?: this.containingFile?.let {
+        env.wrapKSFile(it)
     }
 }
 
-internal fun KSDeclaration.findEnclosingAncestorClassDeclaration(): KSClassDeclaration? {
+private fun KSDeclaration.findEnclosingAncestorClassDeclaration(): KSClassDeclaration? {
     var parent = parentDeclaration
     while (parent != null && parent !is KSClassDeclaration) {
         parent = parent.parentDeclaration
@@ -52,7 +61,13 @@
 }
 
 internal fun KSDeclaration.isStatic(): Boolean {
-    return modifiers.contains(Modifier.JAVA_STATIC) || hasJvmStaticAnnotation()
+    return modifiers.contains(Modifier.JAVA_STATIC) || hasJvmStaticAnnotation() ||
+        when (this) {
+            is KSPropertyAccessor -> this.receiver.findEnclosingAncestorClassDeclaration() == null
+            is KSPropertyDeclaration -> this.findEnclosingAncestorClassDeclaration() == null
+            is KSFunctionDeclaration -> this.findEnclosingAncestorClassDeclaration() == null
+            else -> false
+        }
 }
 
 internal fun KSDeclaration.isTransient(): Boolean {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
index 180ceec..708e243 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
@@ -112,11 +112,16 @@
         fun accept(annotation: KSAnnotation): Boolean
 
         private class Impl(
-            val acceptedTarget: AnnotationUseSiteTarget
+            val acceptedTarget: AnnotationUseSiteTarget,
+            private val acceptNoTarget: Boolean = true,
         ) : UseSiteFilter {
             override fun accept(annotation: KSAnnotation): Boolean {
                 val target = annotation.useSiteTarget
-                return target == null || acceptedTarget == target
+                return if (target == null) {
+                    acceptNoTarget
+                } else {
+                    acceptedTarget == target
+                }
             }
         }
 
@@ -132,6 +137,10 @@
             val NO_USE_SITE_OR_GETTER: UseSiteFilter = Impl(AnnotationUseSiteTarget.GET)
             val NO_USE_SITE_OR_SETTER: UseSiteFilter = Impl(AnnotationUseSiteTarget.SET)
             val NO_USE_SITE_OR_SET_PARAM: UseSiteFilter = Impl(AnnotationUseSiteTarget.SETPARAM)
+            val FILE: UseSiteFilter = Impl(
+                acceptedTarget = AnnotationUseSiteTarget.FILE,
+                acceptNoTarget = false
+            )
         }
     }
 
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt
index 7417435..fb3ff2c 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt
@@ -21,11 +21,16 @@
 
 internal class KspConstructorElement(
     env: KspProcessingEnv,
-    containing: KspTypeElement,
+    override val containing: KspTypeElement,
     declaration: KSFunctionDeclaration
 ) : KspExecutableElement(
     env = env,
     containing = containing,
     declaration = declaration
 ),
-    XConstructorElement
+    XConstructorElement {
+    override val enclosingElement: KspTypeElement by lazy {
+        declaration.requireEnclosingMemberContainer(env) as? KspTypeElement
+            ?: error("Constructor parent must be a type element $this")
+    }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt
index 3d3b83a..cb4ee5f 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt
@@ -20,7 +20,6 @@
 import androidx.room.compiler.processing.XExecutableElement
 import androidx.room.compiler.processing.XExecutableParameterElement
 import androidx.room.compiler.processing.XHasModifiers
-import androidx.room.compiler.processing.XTypeElement
 import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
 import com.google.devtools.ksp.isConstructor
 import com.google.devtools.ksp.symbol.KSFunctionDeclaration
@@ -28,7 +27,7 @@
 
 internal abstract class KspExecutableElement(
     env: KspProcessingEnv,
-    val containing: KspTypeElement,
+    open val containing: KspMemberContainer,
     override val declaration: KSFunctionDeclaration
 ) : KspElement(
     env = env,
@@ -46,8 +45,8 @@
         arrayOf(containing, declaration)
     }
 
-    override val enclosingElement: XTypeElement by lazy {
-        declaration.requireEnclosingTypeElement(env)
+    override val enclosingElement: KspMemberContainer by lazy {
+        declaration.requireEnclosingMemberContainer(env)
     }
 
     override val parameters: List<XExecutableParameterElement> by lazy {
@@ -74,9 +73,9 @@
             env: KspProcessingEnv,
             declaration: KSFunctionDeclaration
         ): KspExecutableElement {
-            val enclosingType = declaration.findEnclosingTypeElement(env)
+            val enclosingContainer = declaration.findEnclosingMemberContainer(env)
 
-            checkNotNull(enclosingType) {
+            checkNotNull(enclosingContainer) {
                 "XProcessing does not currently support annotations on top level " +
                     "functions with KSP. Cannot process $declaration."
             }
@@ -85,14 +84,16 @@
                 declaration.isConstructor() -> {
                     KspConstructorElement(
                         env = env,
-                        containing = enclosingType,
+                        containing = enclosingContainer as? KspTypeElement ?: error(
+                            "The container for $declaration should be a type element"
+                        ),
                         declaration = declaration
                     )
                 }
                 else -> {
                     KspMethodElement.create(
                         env = env,
-                        containing = enclosingType,
+                        containing = enclosingContainer,
                         declaration = declaration
                     )
                 }
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
index 8d5f6ac..883efc3 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -40,7 +40,7 @@
         parameter.typeAsMemberOf(
             resolver = env.resolver,
             functionDeclaration = method.declaration,
-            ksType = method.containing.declaration.asStarProjectedType()
+            ksType = method.containing.type?.ksType
         ).let {
             env.wrap(
                 originatingReference = parameter.type,
@@ -53,7 +53,7 @@
         get() = "$name in ${method.fallbackLocationText}"
 
     override fun asMemberOf(other: XType): KspType {
-        if (method.containing.type.isSameType(other)) {
+        if (method.containing.type?.isSameType(other) != false) {
             return type
         }
         check(other is KspType)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
index 8955362..5418300 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
@@ -20,14 +20,13 @@
 import androidx.room.compiler.processing.XFieldElement
 import androidx.room.compiler.processing.XHasModifiers
 import androidx.room.compiler.processing.XType
-import androidx.room.compiler.processing.XTypeElement
 import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_FIELD
 import com.google.devtools.ksp.symbol.KSPropertyDeclaration
 
 internal class KspFieldElement(
     env: KspProcessingEnv,
     override val declaration: KSPropertyDeclaration,
-    val containing: KspTypeElement
+    val containing: KspMemberContainer
 ) : KspElement(env, declaration),
     XFieldElement,
     XHasModifiers by KspHasModifiers.create(declaration),
@@ -37,8 +36,8 @@
         arrayOf(declaration, containing)
     }
 
-    override val enclosingElement: XTypeElement by lazy {
-        declaration.requireEnclosingTypeElement(env)
+    override val enclosingElement: KspMemberContainer by lazy {
+        declaration.requireEnclosingMemberContainer(env)
     }
 
     override val name: String by lazy {
@@ -48,12 +47,12 @@
     override val type: KspType by lazy {
         env.wrap(
             originatingReference = declaration.type,
-            ksType = declaration.typeAsMemberOf(env.resolver, containing.type.ksType)
+            ksType = declaration.typeAsMemberOf(env.resolver, containing.type?.ksType)
         )
     }
 
     override fun asMemberOf(other: XType): XType {
-        if (containing.type.isSameType(other)) {
+        if (containing.type?.isSameType(other) != false) {
             return type
         }
         check(other is KspType)
@@ -78,7 +77,7 @@
             return KspFieldElement(
                 env = env,
                 declaration = declaration,
-                containing = declaration.requireEnclosingTypeElement(env)
+                containing = declaration.requireEnclosingMemberContainer(env)
             )
         }
     }
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
new file mode 100644
index 0000000..9d91bb4
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.ksp
+
+import androidx.room.compiler.processing.XAnnotated
+import com.google.devtools.ksp.symbol.AnnotationUseSiteTarget
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSFile
+import com.squareup.javapoet.ClassName
+
+/**
+ * [XMemberContainer] implementation for KSFiles.
+ */
+internal class KspFileMemberContainer(
+    private val env: KspProcessingEnv,
+    private val ksFile: KSFile
+) : KspMemberContainer,
+    XAnnotated by KspAnnotated.create(
+        env = env,
+        delegate = ksFile,
+        filter = KspAnnotated.UseSiteFilter.FILE
+    ) {
+    override val type: KspType?
+        get() = null
+    override val declaration: KSDeclaration?
+        get() = null
+    override val className: ClassName by lazy {
+
+        val pkgName = ksFile.packageName.asString().let {
+            if (it == "<root>") {
+                ""
+            } else {
+                it
+            }
+        }
+        ClassName.get(
+            pkgName, ksFile.findClassName()
+        )
+    }
+
+    override fun kindName(): String {
+        return "file"
+    }
+
+    override val fallbackLocationText: String = ksFile.filePath
+
+    companion object {
+        private fun KSFile.findClassName(): String {
+            return annotations.firstOrNull {
+                it.useSiteTarget == AnnotationUseSiteTarget.FILE &&
+                    it.annotationType.resolve().declaration.qualifiedName?.asString() ==
+                    JvmName::class.qualifiedName
+            }?.arguments?.firstOrNull {
+                it.name?.asString() == "name"
+            }?.value?.toString() ?: fileName.replace(".kt", "Kt")
+        }
+    }
+}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMemberContainer.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMemberContainer.kt
new file mode 100644
index 0000000..a6d0a79
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMemberContainer.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.ksp
+
+import androidx.room.compiler.processing.XMemberContainer
+import com.google.devtools.ksp.symbol.KSDeclaration
+
+internal interface KspMemberContainer : XMemberContainer {
+    override val type: KspType?
+    val declaration: KSDeclaration?
+}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
index 1303247..c4df7a0 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
@@ -30,7 +30,7 @@
 
 internal sealed class KspMethodElement(
     env: KspProcessingEnv,
-    containing: KspTypeElement,
+    containing: KspMemberContainer,
     declaration: KSFunctionDeclaration
 ) : KspExecutableElement(
     env = env,
@@ -90,7 +90,7 @@
 
     private class KspNormalMethodElement(
         env: KspProcessingEnv,
-        containing: KspTypeElement,
+        containing: KspMemberContainer,
         declaration: KSFunctionDeclaration
     ) : KspMethodElement(
         env, containing, declaration
@@ -103,7 +103,7 @@
             env.wrap(
                 ksType = declaration.returnTypeAsMemberOf(
                     resolver = env.resolver,
-                    ksType = containing.type.ksType
+                    ksType = containing.type?.ksType
                 ),
                 originatingReference = checkNotNull(overridee?.returnType ?: declaration.returnType)
             )
@@ -113,7 +113,7 @@
 
     private class KspSuspendMethodElement(
         env: KspProcessingEnv,
-        containing: KspTypeElement,
+        containing: KspMemberContainer,
         declaration: KSFunctionDeclaration
     ) : KspMethodElement(
         env, containing, declaration
@@ -137,7 +137,7 @@
     companion object {
         fun create(
             env: KspProcessingEnv,
-            containing: KspTypeElement,
+            containing: KspMemberContainer,
             declaration: KSFunctionDeclaration
         ): KspMethodElement {
             return if (declaration.modifiers.contains(Modifier.SUSPEND)) {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
index 1b84172..ec69fdd 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
@@ -24,11 +24,17 @@
 internal sealed class KspMethodType(
     val env: KspProcessingEnv,
     val origin: KspMethodElement,
-    val containing: KspType
+    val containing: KspType?
 ) : XMethodType {
     override val parameterTypes: List<XType> by lazy {
-        origin.parameters.map {
-            it.asMemberOf(containing)
+        if (containing == null) {
+            origin.parameters.map {
+                it.type
+            }
+        } else {
+            origin.parameters.map {
+                it.asMemberOf(containing)
+            }
         }
     }
 
@@ -56,7 +62,7 @@
     private class KspNormalMethodType(
         env: KspProcessingEnv,
         origin: KspMethodElement,
-        containing: KspType
+        containing: KspType?
     ) : KspMethodType(env, origin, containing) {
         override val returnType: XType by lazy {
             // b/160258066
@@ -67,7 +73,7 @@
                 originatingReference = (overridee?.returnType ?: origin.declaration.returnType)!!,
                 ksType = origin.declaration.returnTypeAsMemberOf(
                     resolver = env.resolver,
-                    ksType = containing.ksType
+                    ksType = containing?.ksType
                 )
             )
         }
@@ -76,7 +82,7 @@
     private class KspSuspendMethodType(
         env: KspProcessingEnv,
         origin: KspMethodElement,
-        containing: KspType
+        containing: KspType?
     ) : KspMethodType(env, origin, containing), XSuspendMethodType {
         override val returnType: XType
             // suspend functions always return Any?, no need to call asMemberOf
@@ -87,7 +93,7 @@
             return env.wrap(
                 ksType = origin.declaration.returnTypeAsMemberOf(
                     resolver = env.resolver,
-                    ksType = containing.ksType
+                    ksType = containing?.ksType
                 ),
                 allowPrimitives = false
             )
@@ -98,7 +104,7 @@
         fun create(
             env: KspProcessingEnv,
             origin: KspMethodElement,
-            containing: KspType
+            containing: KspType?
         ) = if (origin.isSuspendFunction()) {
             KspSuspendMethodType(env, origin, containing)
         } else {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
index febd6cc..499634e 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
@@ -27,6 +27,7 @@
 import com.google.devtools.ksp.processing.KSPLogger
 import com.google.devtools.ksp.processing.Resolver
 import com.google.devtools.ksp.symbol.KSClassDeclaration
+import com.google.devtools.ksp.symbol.KSFile
 import com.google.devtools.ksp.symbol.KSType
 import com.google.devtools.ksp.symbol.KSTypeAlias
 import com.google.devtools.ksp.symbol.KSTypeArgument
@@ -42,6 +43,7 @@
     val resolver: Resolver
 ) : XProcessingEnv {
     override val backend: XProcessingEnv.Backend = XProcessingEnv.Backend.KSP
+    private val ksFileMemberContainers = mutableMapOf<KSFile, KspFileMemberContainer>()
 
     private val typeElementStore =
         XTypeElementStore(
@@ -212,6 +214,15 @@
         return typeElementStore[declaration]
     }
 
+    fun wrapKSFile(file: KSFile): KspMemberContainer {
+        return ksFileMemberContainers.getOrPut(file) {
+            KspFileMemberContainer(
+                env = this,
+                ksFile = file
+            )
+        }
+    }
+
     class CommonTypes(resolver: Resolver) {
         val nullableInt by lazy {
             resolver.builtIns.intType.makeNullable()
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index f4d111c..c7f17c6 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -47,7 +47,8 @@
 ) : KspElement(env, declaration),
     XTypeElement,
     XHasModifiers by KspHasModifiers.create(declaration),
-    XAnnotated by KspAnnotated.create(env, declaration, NO_USE_SITE) {
+    XAnnotated by KspAnnotated.create(env, declaration, NO_USE_SITE),
+    KspMemberContainer {
 
     /**
      * The true origin of this class file. This may not match `declaration.origin` when declaration
@@ -68,7 +69,8 @@
     }
 
     override val enclosingTypeElement: XTypeElement? by lazy {
-        declaration.findEnclosingTypeElement(env)
+        // if it is a file, don't return it
+        declaration.findEnclosingMemberContainer(env) as? XTypeElement
     }
 
     override val equalityItems: Array<out Any?> by lazy {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OverrideVarianceResolver.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OverrideVarianceResolver.kt
index 9453e19..505ec1f 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OverrideVarianceResolver.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OverrideVarianceResolver.kt
@@ -96,7 +96,7 @@
             containing = env.wrapClassDeclaration(declaredIn),
             declaration = funDeclaration.findOverridee() ?: funDeclaration
         )
-        val containing = overrideeElm.enclosingElement.type as? KspType ?: return null
+        val containing = overrideeElm.enclosingElement.type ?: return null
         return KspMethodType.create(
             env = env,
             origin = overrideeElm,
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index 25613b0..7ad376f 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -20,6 +20,7 @@
 import androidx.room.compiler.processing.XEquality
 import androidx.room.compiler.processing.XExecutableParameterElement
 import androidx.room.compiler.processing.XHasModifiers
+import androidx.room.compiler.processing.XMemberContainer
 import androidx.room.compiler.processing.XMethodElement
 import androidx.room.compiler.processing.XMethodType
 import androidx.room.compiler.processing.XType
@@ -32,7 +33,7 @@
 import androidx.room.compiler.processing.ksp.KspHasModifiers
 import androidx.room.compiler.processing.ksp.KspProcessingEnv
 import androidx.room.compiler.processing.ksp.KspTypeElement
-import androidx.room.compiler.processing.ksp.findEnclosingTypeElement
+import androidx.room.compiler.processing.ksp.findEnclosingMemberContainer
 import androidx.room.compiler.processing.ksp.overrides
 import com.google.devtools.ksp.KspExperimental
 import com.google.devtools.ksp.symbol.KSPropertyAccessor
@@ -67,7 +68,7 @@
 
     final override fun isSuspendFunction() = false
 
-    final override val enclosingElement: XTypeElement
+    final override val enclosingElement: XMemberContainer
         get() = this.field.enclosingElement
 
     final override fun isVarArgs() = false
@@ -248,7 +249,7 @@
             env: KspProcessingEnv,
             propertyAccessor: KSPropertyAccessor
         ): KspSyntheticPropertyMethodElement {
-            val enclosingType = propertyAccessor.receiver.findEnclosingTypeElement(env)
+            val enclosingType = propertyAccessor.receiver.findEnclosingMemberContainer(env)
 
             checkNotNull(enclosingType) {
                 "XProcessing does not currently support annotations on top level " +
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
index b8c5bd5..8d442b5 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
@@ -25,12 +25,18 @@
  */
 internal sealed class KspSyntheticPropertyMethodType(
     val origin: KspSyntheticPropertyMethodElement,
-    val containing: XType
+    val containing: XType?
 ) : XMethodType {
 
     override val parameterTypes: List<XType> by lazy {
-        origin.parameters.map {
-            it.asMemberOf(containing)
+        if (containing == null) {
+            origin.parameters.map {
+                it.type
+            }
+        } else {
+            origin.parameters.map {
+                it.asMemberOf(containing)
+            }
         }
     }
 
@@ -40,7 +46,7 @@
     companion object {
         fun create(
             element: KspSyntheticPropertyMethodElement,
-            container: XType
+            container: XType?
         ): XMethodType {
             return when (element) {
                 is KspSyntheticPropertyMethodElement.Getter ->
@@ -59,19 +65,23 @@
 
     private class Getter(
         origin: KspSyntheticPropertyMethodElement.Getter,
-        containingType: XType
+        containingType: XType?
     ) : KspSyntheticPropertyMethodType(
         origin = origin,
         containing = containingType
     ) {
         override val returnType: XType by lazy {
-            origin.field.asMemberOf(containingType)
+            if (containingType == null) {
+                origin.field.type
+            } else {
+                origin.field.asMemberOf(containingType)
+            }
         }
     }
 
     private class Setter(
         origin: KspSyntheticPropertyMethodElement.Setter,
-        containingType: XType
+        containingType: XType?
     ) : KspSyntheticPropertyMethodType(
         origin = origin,
         containing = containingType
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/TopLevelMembersTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/TopLevelMembersTest.kt
new file mode 100644
index 0000000..5a38d57
--- /dev/null
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/TopLevelMembersTest.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing
+
+import androidx.room.compiler.processing.ksp.KspExecutableElement
+import androidx.room.compiler.processing.ksp.KspFieldElement
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.compileFiles
+import androidx.room.compiler.processing.util.kspProcessingEnv
+import androidx.room.compiler.processing.util.kspResolver
+import androidx.room.compiler.processing.util.runKspTest
+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 org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+@OptIn(KspExperimental::class)
+class TopLevelMembersTest {
+    @Test
+    fun topLevelInDependency() {
+        val libSrc = Source.kotlin(
+            "lib/Foo.kt",
+            """
+                package lib
+                fun topLevelFun() {
+                }
+                val topLevelVal: String = ""
+                var topLevelVar: String = ""
+            """.trimIndent()
+        )
+        val classpath = compileFiles(listOf(libSrc))
+        val appSrc = Source.kotlin(
+            "app/Foo.kt",
+            """
+                package app
+                fun topLevelFun() {
+                }
+                val topLevelVal: String = ""
+                var topLevelVar: String = ""
+            """.trimIndent()
+        )
+        runKspTest(
+            sources = listOf(appSrc),
+            classpath = listOf(classpath)
+        ) { invocation ->
+            // TODO add lib package here once Room updates to a version that includes the
+            //  https://github.com/google/ksp/issues/396 fix (1.5.0-1.0.0-alpha09)
+            val declarations = invocation.kspResolver.getDeclarationsFromPackage("app")
+            declarations.filterIsInstance<KSFunctionDeclaration>()
+                .toList().let { methods ->
+                    assertThat(methods).hasSize(1)
+                    methods.forEach { method ->
+                        val element = KspExecutableElement.create(
+                            env = invocation.kspProcessingEnv,
+                            declaration = method
+                        )
+                        assertThat(element.containing.isTypeElement()).isFalse()
+                        assertThat(element.isStatic()).isTrue()
+                    }
+                }
+            declarations.filterIsInstance<KSPropertyDeclaration>()
+                .toList().let { properties ->
+                    assertThat(properties).hasSize(2)
+                    properties.forEach {
+                        val element = KspFieldElement.create(
+                            env = invocation.kspProcessingEnv,
+                            declaration = it
+                        )
+                        assertThat(element.containing.isTypeElement()).isFalse()
+                        assertThat(element.isStatic()).isTrue()
+                    }
+                }
+        }
+    }
+}
\ No newline at end of file
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt
index 30c7953..3b79246 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XRoundEnvTest.kt
@@ -21,8 +21,11 @@
 import androidx.room.compiler.processing.util.getDeclaredMethod
 import androidx.room.compiler.processing.util.getField
 import androidx.room.compiler.processing.util.getMethod
+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 org.junit.Test
 
 class XRoundEnvTest {
@@ -138,39 +141,16 @@
         )
 
         runProcessorTest(listOf(source)) { testInvocation ->
-            if (testInvocation.isKsp) {
-                // Currently not supported
-                // https://issuetracker.google.com/issues/184526463
-                val exception = try {
-                    testInvocation.roundEnv.getElementsAnnotatedWith(
-                        TopLevelAnnotation::class
-                    )
-                    null
-                } catch (e: Throwable) {
-                    e
-                }
-
-                assertThat(exception).isNotNull()
-                assertThat(exception)
-                    .hasMessageThat()
-                    .contains(
-                        "XProcessing does not currently support annotations on top level functions"
-                    )
-            } else {
-
-                val annotatedElements = testInvocation.roundEnv.getElementsAnnotatedWith(
-                    TopLevelAnnotation::class
-                )
-
-                val targetElement = testInvocation.processingEnv.requireTypeElement("BazKt")
-
-                assertThat(
-                    annotatedElements
-                ).apply {
-                    hasSize(1)
-                    contains(targetElement.getDeclaredMethod("myFun"))
-                }
-            }
+            val annotatedElements = testInvocation.roundEnv.getElementsAnnotatedWith(
+                TopLevelAnnotation::class
+            )
+            assertThat(annotatedElements).hasSize(1)
+            val subject = annotatedElements.filterIsInstance<XMethodElement>().first()
+            assertThat(subject.name).isEqualTo("myFun")
+            assertThat(subject.enclosingElement.className).isEqualTo(
+                ClassName.get("", "BazKt")
+            )
+            assertThat(subject.isStatic()).isTrue()
         }
     }
 
@@ -179,51 +159,66 @@
         val source = Source.kotlin(
             "Baz.kt",
             """
+            @file:JvmName("MyCustomClass")
+            package foo.bar
             import androidx.room.compiler.processing.XRoundEnvTest.TopLevelAnnotation
             @get:TopLevelAnnotation
+            var myPropertyGetter: Int = 0
+            @set:TopLevelAnnotation
+            var myPropertySetter: Int = 0
+            @field:TopLevelAnnotation
             var myProperty: Int = 0
             """.trimIndent()
         )
 
-        runProcessorTest(listOf(source)) { testInvocation ->
-            if (testInvocation.isKsp) {
-                // Currently not supported
-                // https://issuetracker.google.com/issues/184526463
-                val exception = try {
-                    testInvocation.roundEnv.getElementsAnnotatedWith(
-                        TopLevelAnnotation::class
-                    )
-                    null
-                } catch (e: Throwable) {
-                    e
+        runKspTest(listOf(source)) { testInvocation ->
+            val annotatedElements = testInvocation.roundEnv.getElementsAnnotatedWith(
+                TopLevelAnnotation::class
+            )
+            assertThat(annotatedElements).hasSize(3)
+            val byName = annotatedElements.associateBy {
+                when (it) {
+                    is XMethodElement -> it.name
+                    is XFieldElement -> it.name
+                    else -> error("unexpected type $it")
                 }
-
-                assertThat(exception).isNotNull()
-                assertThat(exception)
-                    .hasMessageThat()
-                    .contains(
-                        "XProcessing does not currently support annotations on top level properties"
-                    )
-            } else {
-
-                val annotatedElements = testInvocation.roundEnv.getElementsAnnotatedWith(
-                    TopLevelAnnotation::class
+            }
+            val containerClassName = ClassName.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.parameters).hasSize(0)
+                assertThat(it.enclosingElement.className).isEqualTo(
+                    containerClassName
                 )
-
-                val targetElement = testInvocation.processingEnv.requireTypeElement("BazKt")
-
-                assertThat(
-                    annotatedElements
-                ).apply {
-                    hasSize(1)
-                    contains(targetElement.getDeclaredMethod("getMyProperty"))
-                }
+                assertThat(it.isStatic()).isTrue()
+            }
+            (byName["setMyPropertySetter"] as XMethodElement).let {
+                assertThat(it.returnType.typeName).isEqualTo(TypeName.VOID)
+                assertThat(it.parameters).hasSize(1)
+                assertThat(it.parameters.first().type.typeName).isEqualTo(TypeName.INT)
+                assertThat(it.enclosingElement.className).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.isStatic()).isTrue()
             }
         }
     }
 
     annotation class TopLevelAnnotation
 
+    @Suppress("unused") // used in tests
     @Target(AnnotationTarget.PROPERTY)
     annotation class PropertyAnnotation
 }
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/XTestInvocationExt.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/XTestInvocationExt.kt
index 1e24f10..b98e232 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/XTestInvocationExt.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/XTestInvocationExt.kt
@@ -22,6 +22,9 @@
 import javax.lang.model.util.Elements
 import javax.lang.model.util.Types
 
+internal val XTestInvocation.kspProcessingEnv: KspProcessingEnv
+    get() = (processingEnv as KspProcessingEnv)
+
 val XTestInvocation.kspResolver: Resolver
     get() = (processingEnv as KspProcessingEnv).resolver
 
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
index de7ea10..855dc4d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -22,7 +22,6 @@
 import androidx.room.compiler.processing.XElement
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
-import androidx.room.compiler.processing.requireEnclosingTypeElement
 import androidx.room.ext.RoomTypeNames
 import androidx.room.migration.bundle.DatabaseBundle
 import androidx.room.migration.bundle.SchemaBundle
@@ -91,7 +90,7 @@
             it.isAbstract()
         }.filterNot {
             // remove methods that belong to room
-            it.requireEnclosingTypeElement().className == RoomTypeNames.ROOM_DB
+            it.enclosingElement.className == RoomTypeNames.ROOM_DB
         }.mapNotNull { executable ->
             // TODO when we add support for non Dao return types (e.g. database), this code needs
             // to change
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
index 8e1e745..030e56f 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
@@ -20,7 +20,6 @@
 import androidx.room.parser.SqlParser
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
-import androidx.room.compiler.processing.requireEnclosingTypeElement
 import androidx.room.ext.isNotNone
 import androidx.room.processor.EntityProcessor.Companion.createIndexName
 import androidx.room.processor.EntityProcessor.Companion.extractForeignKeys
@@ -110,7 +109,7 @@
                         Warning.INDEX_FROM_PARENT_FIELD_IS_DROPPED,
                         ProcessorErrors.droppedSuperClassFieldIndex(
                             it.columnName, element.qualifiedName,
-                            it.element.requireEnclosingTypeElement().qualifiedName
+                            it.element.enclosingElement.className.toString()
                         )
                     )
                     null
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
index 3d5855b..9545f48 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
@@ -21,7 +21,6 @@
 import androidx.room.compiler.processing.XExecutableElement
 import androidx.room.compiler.processing.isConstructor
 import androidx.room.compiler.processing.isMethod
-import androidx.room.compiler.processing.requireEnclosingTypeElement
 import com.squareup.javapoet.CodeBlock
 
 /**
@@ -54,7 +53,7 @@
                 //  elements.
                 builder.addStatement(
                     "$L = $T.$L($L)", outVar,
-                    element.requireEnclosingTypeElement().className,
+                    element.enclosingElement.className,
                     element.name, args
                 )
             }