Fix getter/setter/field logic for abstract properties

This CL fixes a few issues in KspTypeElement:
* We would report fields for abstract properties, which we shouldn't.
* We would NOT report getters/setters for abstract properties, we should.
* We should NOT report getters/setters for JVMField annotated properties but
we were because KSP generates synthetic accessors for them.

Bug: 160322705
Test: KspTypeElementTest.fieldsInAbstractClass
Change-Id: I64e939544701e895f14d24a124c086e4b33139d6
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 f9605db..d733e31 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
@@ -31,6 +31,7 @@
 import com.google.devtools.ksp.getDeclaredFunctions
 import com.google.devtools.ksp.getDeclaredProperties
 import com.google.devtools.ksp.isOpen
+import com.google.devtools.ksp.isPrivate
 import com.google.devtools.ksp.symbol.ClassKind
 import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSFunctionDeclaration
@@ -132,7 +133,7 @@
                 it.isStatic()
             }
         } else {
-            _declaredProperties
+            _declaredProperties.filter { !it.isAbstract() }
         }
         val selectedNames = myPropertyFields.mapTo(mutableSetOf()) {
             it.name
@@ -167,12 +168,17 @@
                 // until room generates kotlin code
                 return@mapNotNull null
             }
+
             val setter = it.declaration.setter
-            val needsSetter = if (setter != null) {
-                // kapt does not generate synthetics for private fields/setters so we won't either
-                !setter.modifiers.contains(Modifier.PRIVATE)
-            } else {
-                isInterface() && it.declaration.isMutable
+            val needsSetter = when {
+                it.declaration.hasJvmFieldAnnotation() -> {
+                    // jvm fields cannot have accessors but KSP generates synthetic accessors for
+                    // them. We check for JVM field first before checking the setter
+                    false
+                }
+                it.declaration.isPrivate() -> false
+                setter != null -> !setter.modifiers.contains(Modifier.PRIVATE)
+                else -> it.declaration.isMutable
             }
             if (needsSetter) {
                 KspSyntheticPropertyMethodElement.Setter(
@@ -190,12 +196,17 @@
                 return@mapNotNull null
             }
             val getter = it.declaration.getter
-            val needsGetter = if (getter != null) {
-                // kapt does not generate synthetics for private fields/getters so we won't either]
-                !getter.modifiers.contains(Modifier.PRIVATE)
-            } else {
-                isInterface()
+            val needsGetter = when {
+                it.declaration.hasJvmFieldAnnotation() -> {
+                    // jvm fields cannot have accessors but KSP generates synthetic accessors for
+                    // them. We check for JVM field first before checking the getter
+                    false
+                }
+                it.declaration.isPrivate() -> false
+                getter != null -> !getter.modifiers.contains(Modifier.PRIVATE)
+                else -> true
             }
+
             if (needsGetter) {
                 KspSyntheticPropertyMethodElement.Getter(
                     env = env,
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
index 869c1b1..6780ed9 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
@@ -329,6 +329,48 @@
     }
 
     @Test
+    fun fieldsInAbstractClass() {
+        val src = Source.kotlin(
+            "Foo.kt",
+            """
+            abstract class MyAbstractClass {
+                @JvmField
+                var jvmVar: Int = 0
+                abstract var abstractVar: Int
+                var nonAbstractVar: Int = 0
+            }
+            """.trimIndent()
+        )
+        runProcessorTest(sources = listOf(src)) { invocation ->
+            val element = invocation.processingEnv.requireTypeElement("MyAbstractClass")
+            assertThat(
+                element.getAllFieldNames()
+            ).containsExactly(
+                "nonAbstractVar", "jvmVar"
+            )
+            assertThat(
+                element.getDeclaredMethods().map { it.name }
+            ).containsExactly(
+                "getAbstractVar", "setAbstractVar",
+                "getNonAbstractVar", "setNonAbstractVar"
+            )
+            element.getMethod("getAbstractVar").let {
+                assertThat(it.isAbstract()).isTrue()
+            }
+            element.getMethod("setAbstractVar").let {
+                assertThat(it.isAbstract()).isTrue()
+            }
+
+            element.getMethod("getNonAbstractVar").let {
+                assertThat(it.isAbstract()).isFalse()
+            }
+            element.getMethod("setNonAbstractVar").let {
+                assertThat(it.isAbstract()).isFalse()
+            }
+        }
+    }
+
+    @Test
     fun declaredAndInstanceMethods() {
         val src = Source.kotlin(
             "Foo.kt",