Merge "Add synthetic element in Ksp corresponds to @JvmStatic annotated companion method copied to enclosing class by Compiler in KAPT" into androidx-main
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
index 4cc1c25..3aa3852 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
@@ -159,12 +159,40 @@
     }
 
     private val _declaredMethods by lazy {
-        ElementFilter.methodsIn(element.enclosedElements).map {
+      val companionObjectMethodDescriptors =
+        getEnclosedTypeElements()
+          .firstOrNull {
+            it.isCompanionObject()
+          }?.getDeclaredMethods()
+          ?.map { it.jvmDescriptor } ?: emptyList()
+
+      val declaredMethods =
+        ElementFilter.methodsIn(element.enclosedElements)
+          .map {
             JavacMethodElement(
                 env = env,
                 element = it
             )
         }.filterMethodsByConfig(env)
+      if (companionObjectMethodDescriptors.isEmpty()) {
+        declaredMethods
+      } else {
+        buildList {
+          addAll(
+            declaredMethods.filterNot { method ->
+              companionObjectMethodDescriptors.any { it == method.jvmDescriptor }
+            }
+          )
+          companionObjectMethodDescriptors.forEach {
+            for (method in declaredMethods) {
+              if (method.jvmDescriptor == it) {
+                add(method)
+                break
+              }
+            }
+          }
+        }
+      }
     }
 
     override fun getDeclaredMethods(): List<JavacMethodElement> {
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
index a840aa4..8aaabb3 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -110,7 +110,7 @@
                     )
                 }
                 is KSPropertySetter -> KspSyntheticPropertyMethodElement.create(
-                    env, parent
+                    env, parent, isSyntheticStatic = false
                 ).parameters.single()
                 else -> error(
                     "Don't know how to create a parameter element whose parent is a " +
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
index beab250..aec7c3c 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
@@ -78,7 +78,8 @@
                         KspSyntheticPropertyMethodElement.create(
                             env = env,
                             field = this,
-                            accessor = accessor
+                            accessor = accessor,
+                            isSyntheticStatic = false
                         )
                     }.toList()
             }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
index 841154a..11719f1 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
@@ -31,7 +31,8 @@
 
 internal sealed class KspMethodElement(
     env: KspProcessingEnv,
-    declaration: KSFunctionDeclaration
+    declaration: KSFunctionDeclaration,
+    val isSyntheticStatic: Boolean
 ) : KspExecutableElement(env, declaration), XMethodElement {
 
     override val name: String
@@ -72,6 +73,18 @@
         }
     }
 
+    override val enclosingElement: KspMemberContainer by lazy {
+        if (isSyntheticStatic) {
+            actualEnclosingElement.declaration!!.requireEnclosingMemberContainer(env)
+        } else {
+            actualEnclosingElement
+        }
+    }
+
+    private val actualEnclosingElement: KspMemberContainer by lazy {
+        declaration.requireEnclosingMemberContainer(env)
+    }
+
     override val executableType: XMethodType by lazy {
         KspMethodType.create(
             env = env,
@@ -116,8 +129,9 @@
 
     private class KspNormalMethodElement(
         env: KspProcessingEnv,
-        declaration: KSFunctionDeclaration
-    ) : KspMethodElement(env, declaration) {
+        declaration: KSFunctionDeclaration,
+        isSyntheticStatic: Boolean
+    ) : KspMethodElement(env, declaration, isSyntheticStatic) {
         override val returnType: KspType by lazy {
             declaration.returnKspType(
                 env = env,
@@ -134,8 +148,9 @@
 
     private class KspSuspendMethodElement(
         env: KspProcessingEnv,
-        declaration: KSFunctionDeclaration
-    ) : KspMethodElement(env, declaration) {
+        declaration: KSFunctionDeclaration,
+        isSyntheticStatic: Boolean
+    ) : KspMethodElement(env, declaration, isSyntheticStatic) {
         override fun isSuspendFunction() = true
 
         override val returnType: KspType by lazy {
@@ -160,12 +175,13 @@
     companion object {
         fun create(
             env: KspProcessingEnv,
-            declaration: KSFunctionDeclaration
+            declaration: KSFunctionDeclaration,
+            isSyntheticStatic: Boolean = false
         ): KspMethodElement {
             return if (declaration.modifiers.contains(Modifier.SUSPEND)) {
-                KspSuspendMethodElement(env, declaration)
+                KspSuspendMethodElement(env, declaration, isSyntheticStatic)
             } else {
-                KspNormalMethodElement(env, declaration)
+                KspNormalMethodElement(env, declaration, isSyntheticStatic)
             }
         }
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRoundEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRoundEnv.kt
index f884671..094650c 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRoundEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspRoundEnv.kt
@@ -44,30 +44,60 @@
         if (annotationQualifiedName == "*") {
             return emptySet()
         }
-        return env.resolver.getSymbolsWithAnnotation(annotationQualifiedName)
-            .map { symbol ->
-                when (symbol) {
-                    is KSPropertyDeclaration -> {
-                        KspFieldElement.create(env, symbol)
-                    }
-                    is KSClassDeclaration -> {
-                        when (symbol.classKind) {
-                            ClassKind.ENUM_ENTRY -> KspEnumEntry.create(env, symbol)
-                            else -> KspTypeElement.create(env, symbol)
+        return buildSet {
+            env.resolver.getSymbolsWithAnnotation(annotationQualifiedName)
+                .forEach { symbol ->
+                    when (symbol) {
+                        is KSPropertyDeclaration -> {
+                           add(KspFieldElement.create(env, symbol))
                         }
+                        is KSClassDeclaration -> {
+                            when (symbol.classKind) {
+                                ClassKind.ENUM_ENTRY ->
+                                    add(KspEnumEntry.create(env, symbol))
+                                else -> add(KspTypeElement.create(env, symbol))
+                            }
+                        }
+                        is KSFunctionDeclaration -> {
+                            add(KspExecutableElement.create(env, symbol))
+                        }
+                        is KSPropertyAccessor -> {
+                            if (symbol.receiver.isStatic() &&
+                                symbol.receiver.parentDeclaration is KSClassDeclaration &&
+                                (symbol.receiver.hasJvmStaticAnnotation() ||
+                                    symbol.hasJvmStaticAnnotation())) {
+                                // Getter/setter can be copied from companion object to its
+                                // outer class if the field is annotated with @JvmStatic.
+                                add(
+                                    KspSyntheticPropertyMethodElement.create(
+                                        env, symbol, isSyntheticStatic = true
+                                    )
+                                )
+                            }
+                            // static fields are the properties that are coming from the companion.
+                            // Whether we'll generate method for it or not depends on the JVMStatic
+                            // annotation
+                            if (!symbol.receiver.isStatic() ||
+                                symbol.receiver.hasJvmStaticAnnotation() ||
+                                symbol.hasJvmStaticAnnotation() ||
+                                symbol.receiver.parentDeclaration !is KSClassDeclaration
+                            ) {
+                                add(
+                                    KspSyntheticPropertyMethodElement.create(
+                                        env, symbol, isSyntheticStatic = false
+                                    )
+                                )
+                            }
+                        }
+                        is KSValueParameter -> {
+                            add(KspExecutableParameterElement.create(env, symbol))
+                        }
+                        else ->
+                            error("Unsupported $symbol with annotation $annotationQualifiedName")
                     }
-                    is KSFunctionDeclaration -> {
-                        KspExecutableElement.create(env, symbol)
-                    }
-                    is KSPropertyAccessor -> {
-                        KspSyntheticPropertyMethodElement.create(env, symbol)
-                    }
-                    is KSValueParameter -> {
-                        KspExecutableParameterElement.create(env, symbol)
-                    }
-                    else -> error("Unsupported $symbol with annotation $annotationQualifiedName")
                 }
-            }.filter {
+            }
+            .filter {
                 // Due to the bug in https://github.com/google/ksp/issues/1198, KSP may incorrectly
                 // copy annotations from a constructor KSValueParameter to its KSPropertyDeclaration
                 // which we remove manually, so check here to make sure this is in sync with the
@@ -75,4 +105,4 @@
                 it.getAllAnnotations().any { it.qualifiedName == annotationQualifiedName }
             }.toSet()
     }
-}
\ No newline at end of file
+}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index 2318b4d..54e64ab 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -33,6 +33,7 @@
 import androidx.room.compiler.processing.collectFieldsIncludingPrivateSupers
 import androidx.room.compiler.processing.filterMethodsByConfig
 import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
+import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
 import androidx.room.compiler.processing.tryBox
 import androidx.room.compiler.processing.util.MemoizedSequence
 import com.google.devtools.ksp.KspExperimental
@@ -184,25 +185,27 @@
         }
     }
 
-    private val syntheticGetterSetterMethods: List<XMethodElement> by lazy {
-        if (declaration.isCompanionObject) {
-            _declaredProperties.flatMap { field ->
-                field.syntheticAccessors
-            }
-        } else {
-            _declaredProperties.flatMap { field ->
-                // static fields are the properties that are coming from the
-                // companion. Whether we'll generate method for it or not depends on
-                // the JVMStatic annotation
-                if (field.isStatic() && !field.declaration.hasJvmStaticAnnotation()) {
-                    field.syntheticAccessors.filter {
-                        it.accessor.hasJvmStaticAnnotation()
-                    }
-                } else {
-                    field.syntheticAccessors
-                }
-            }
-        }.filterMethodsByConfig(env)
+    private fun syntheticGetterSetterMethods(field: KspFieldElement): List<XMethodElement> {
+      if (declaration.isCompanionObject) {
+        return field.syntheticAccessors
+      }
+      if (field.isStatic() && !field.declaration.hasJvmStaticAnnotation()) {
+        return field.syntheticAccessors.filter {
+          it.accessor.hasJvmStaticAnnotation()
+        }
+      }
+      if (field.isStatic() && field.declaration.hasJvmStaticAnnotation()) {
+        // Getter and setter are copied from companion object into current type
+        // element by Compiler in KAPT when @JvmStatic is present, in this case, the
+        // copied over method element should swap its enclosing element to be
+        // current type element instead of companion object.
+        return field.syntheticAccessors.map { element ->
+          KspSyntheticPropertyMethodElement.create(
+            env, field, element.accessor, isSyntheticStatic = true
+          )
+        }
+      }
+      return field.syntheticAccessors
     }
 
     override fun isNested(): Boolean {
@@ -266,22 +269,51 @@
     }
 
     private val _declaredMethods by lazy {
-        val declaredMethods = buildList {
-            addAll(declaration.getDeclarationsInSourceOrder())
-            addAll(
-                declaration.findCompanionObject().getDeclarationsInSourceOrder()
-                    .filter { it.hasJvmStaticAnnotation() }
-            )
-        }.filterIsInstance(KSFunctionDeclaration::class.java)
-            .filterNot { it.isConstructor() }
-            .map {
-                KspMethodElement.create(
+      buildList {
+          declaration.getDeclarationsInSourceOrder()
+            .forEach {
+              if (it is KSFunctionDeclaration && !it.isConstructor()) {
+                add(
+                  KspMethodElement.create(
                     env = env,
                     declaration = it
+                  )
+                )
+             } else if (it is KSPropertyDeclaration) {
+                addAll(
+                  syntheticGetterSetterMethods(
+                    KspFieldElement(
+                      env = env,
+                      declaration = it
+                    )
+                  )
                 )
             }
-            .filterMethodsByConfig(env)
-        declaredMethods + syntheticGetterSetterMethods
+          }
+          declaration.findCompanionObject().getDeclarationsInSourceOrder()
+            .forEach {
+              if (it.hasJvmStaticAnnotation() &&
+                  it is KSFunctionDeclaration &&
+                  !it.isConstructor()) {
+                add(
+                  KspMethodElement.create(
+                    env = env,
+                    declaration = it,
+                    isSyntheticStatic = true
+                  )
+                )
+              } else if (it is KSPropertyDeclaration) {
+                addAll(
+                  syntheticGetterSetterMethods(
+                    KspFieldElement(
+                      env = env,
+                      declaration = it
+                    )
+                  )
+                )
+              }
+            }
+        }.filterMethodsByConfig(env)
     }
 
     override fun getDeclaredMethods(): List<XMethodElement> {
@@ -343,6 +375,13 @@
         env.resolver.getDeclarationsInSourceOrder(it)
     } ?: emptySequence()
 
+    @OptIn(KspExperimental::class)
+    fun KSDeclarationContainer?.getDeclaredMethods(): Sequence<KSFunctionDeclaration> {
+        return this.getDeclarationsInSourceOrder()
+            .filterIsInstance(KSFunctionDeclaration::class.java)
+            .filterNot { it.isConstructor() }
+    }
+
     companion object {
         fun create(
             env: KspProcessingEnv,
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index 2067b96..ec93a24 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -40,6 +40,7 @@
 import androidx.room.compiler.processing.ksp.findEnclosingMemberContainer
 import androidx.room.compiler.processing.ksp.jvmDescriptor
 import androidx.room.compiler.processing.ksp.overrides
+import androidx.room.compiler.processing.ksp.requireEnclosingMemberContainer
 import androidx.room.compiler.processing.util.sanitizeAsJavaParameterName
 import com.google.devtools.ksp.KspExperimental
 import com.google.devtools.ksp.symbol.KSPropertyAccessor
@@ -57,6 +58,7 @@
 internal sealed class KspSyntheticPropertyMethodElement(
     val env: KspProcessingEnv,
     val field: KspFieldElement,
+    val isSyntheticStatic: Boolean,
     open val accessor: KSPropertyAccessor
 ) : XMethodElement,
     XEquality,
@@ -71,7 +73,7 @@
     }
 
     override val equalityItems: Array<out Any?> by lazy {
-        arrayOf(field, accessor)
+        arrayOf(field, accessor, isSyntheticStatic)
     }
 
     // NOTE: modifiers of the property are not necessarily my modifiers.
@@ -86,6 +88,14 @@
     final override fun isExtensionFunction() = false
 
     final override val enclosingElement: KspMemberContainer
+        get() = if (isSyntheticStatic) {
+          actualEnclosingElement.declaration!!
+            .requireEnclosingMemberContainer(env)
+        } else {
+          actualEnclosingElement
+        }
+
+    private val actualEnclosingElement: KspMemberContainer
         get() = this.field.enclosingElement
 
     final override val closestMemberContainer: XMemberContainer by lazy {
@@ -149,11 +159,14 @@
     internal class Getter(
         env: KspProcessingEnv,
         field: KspFieldElement,
-        override val accessor: KSPropertyGetter
+        override val accessor: KSPropertyGetter,
+        isSyntheticStatic: Boolean
     ) : KspSyntheticPropertyMethodElement(
         env = env,
         field = field,
-        accessor = accessor
+        accessor = accessor,
+        isSyntheticStatic = isSyntheticStatic
+
     ),
         XAnnotated by KspAnnotated.create(
             env = env,
@@ -191,11 +204,13 @@
     internal class Setter(
         env: KspProcessingEnv,
         field: KspFieldElement,
-        override val accessor: KSPropertySetter
+        override val accessor: KSPropertySetter,
+        isSyntheticStatic: Boolean
     ) : KspSyntheticPropertyMethodElement(
         env = env,
         field = field,
-        accessor = accessor
+        accessor = accessor,
+        isSyntheticStatic = isSyntheticStatic
     ),
         XAnnotated by KspAnnotated.create(
             env = env,
@@ -299,7 +314,8 @@
     companion object {
         fun create(
             env: KspProcessingEnv,
-            accessor: KSPropertyAccessor
+            accessor: KSPropertyAccessor,
+            isSyntheticStatic: Boolean
         ): KspSyntheticPropertyMethodElement {
             val enclosingType = accessor.receiver.findEnclosingMemberContainer(env)
 
@@ -315,28 +331,32 @@
             return create(
                 env = env,
                 field = field,
-                accessor = accessor
+                accessor = accessor,
+                isSyntheticStatic = isSyntheticStatic
             )
         }
 
         fun create(
             env: KspProcessingEnv,
             field: KspFieldElement,
-            accessor: KSPropertyAccessor
+            accessor: KSPropertyAccessor,
+            isSyntheticStatic: Boolean
         ): KspSyntheticPropertyMethodElement {
             return when (accessor) {
                 is KSPropertyGetter -> {
                     Getter(
                         env = env,
                         field = field,
-                        accessor = accessor
+                        accessor = accessor,
+                        isSyntheticStatic = isSyntheticStatic
                     )
                 }
                 is KSPropertySetter -> {
                     Setter(
                         env = env,
                         field = field,
-                        accessor = accessor
+                        accessor = accessor,
+                        isSyntheticStatic = isSyntheticStatic
                     )
                 }
                 else -> error("Unsupported property accessor $accessor")
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 f7c0e52..03d1b39 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
@@ -854,11 +854,7 @@
                     "companionObjectFunctionJvmStatic"
                 )
                 methods.forEach {
-                    if (invocation.isKsp && it.name.lowercase().contains("companion")) {
-                        assertThat(it.enclosingElement).isEqualTo(companionObj)
-                    } else {
-                        assertThat(it.enclosingElement).isEqualTo(enclosingElement)
-                    }
+                    assertThat(it.enclosingElement).isEqualTo(enclosingElement)
                 }
             }
 
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 9fba451..3630e49 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
@@ -26,6 +26,7 @@
 import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import com.squareup.kotlinpoet.INT
 import com.squareup.kotlinpoet.UNIT
 import com.squareup.kotlinpoet.javapoet.JTypeName
@@ -91,6 +92,13 @@
                 var myProperty2: Int = 0
                 @field:OtherAnnotation(value="xx")
                 var myProperty3: Int = 0
+                companion object {
+                    @get:OtherAnnotation(value="xx")
+                    @JvmStatic
+                    val myProperty4: String = ""
+                    @get:OtherAnnotation(value="xx")
+                    const val myProperty5: String = ""
+                }
             }
             """.trimIndent()
         )
@@ -100,16 +108,21 @@
                 OtherAnnotation::class
             )
 
-            val targetElement = testInvocation.processingEnv.requireTypeElement("Baz")
+            val baz = testInvocation.processingEnv.requireTypeElement("Baz")
 
             assertThat(
-                annotatedElements
-            ).apply {
-                hasSize(3)
-
-                contains(targetElement.getDeclaredMethodByJvmName("getMyProperty1"))
-                contains(targetElement.getDeclaredMethodByJvmName("setMyProperty2"))
-                contains(targetElement.getField("myProperty3"))
+                annotatedElements.map { it.name }
+            ).containsExactly(
+                "getMyProperty4",
+                "myProperty3",
+                "getMyProperty1",
+                "setMyProperty2",
+                "getMyProperty4"
+            )
+            baz.getDeclaredMethods().forEach { method ->
+              assertWithMessage("Enclosing element of method ${method.jvmName}")
+                .that(method.enclosingElement.name)
+                .isEqualTo("Baz")
             }
         }
     }
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 e4f68fba..079024d 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
@@ -780,12 +780,15 @@
             open class Base(x:Int) {
                 open fun baseFun(): Int = TODO()
                 suspend fun suspendFun(): Int = TODO()
-                private fun privateBaseFun(): Int = TODO()
                 companion object {
                     @JvmStatic
                     fun staticBaseFun(): Int = TODO()
                     fun companionMethod(): Int = TODO()
+                    @JvmStatic val name: String get() = "hello"
+                    @JvmStatic suspend fun suspendFun2():Int = TODO()
+                    @JvmStatic fun String.extFun(): Int = TODO()
                 }
+                private fun privateBaseFun(): Int = TODO()
             }
             open class SubClass : Base {
                 constructor(y:Int): super(y) {
@@ -804,10 +807,28 @@
         )
         runTest(sources = listOf(src)) { invocation ->
             val base = invocation.processingEnv.requireTypeElement("Base")
+            val baseCompanion = invocation.processingEnv.requireTypeElement("Base.Companion")
             val objectMethodNames = invocation.objectMethodNames()
-            assertThat(base.getDeclaredMethods().jvmNames()).containsExactly(
-                "baseFun", "suspendFun", "privateBaseFun", "staticBaseFun"
-            )
+            val declaredMethods = base.getDeclaredMethods()
+            assertThat(declaredMethods.jvmNames()).containsExactly(
+                "baseFun",
+                "suspendFun",
+                "privateBaseFun",
+                "staticBaseFun",
+                "getName",
+                "suspendFun2",
+                "extFun"
+            ).inOrder()
+            declaredMethods.forEach { method ->
+              assertWithMessage("Enclosing element of method ${method.jvmName}")
+                .that(method.enclosingElement.name)
+                .isEqualTo("Base")
+            }
+            baseCompanion.getDeclaredMethods().forEach { method ->
+              assertWithMessage("Enclosing element of method ${method.jvmName}")
+                .that(method.enclosingElement.name)
+                .isEqualTo("Companion")
+            }
 
             val sub = invocation.processingEnv.requireTypeElement("SubClass")
             assertThat(sub.getDeclaredMethods().jvmNames()).containsExactly(