Isolate access to ElementFilters
This CL attempts to isolate access to ElementFilters into extension
methods.
As part of it, I've also removed all access to ElementUtils except for
the extension files.
Unfortunately, the difference between declared methods / methods
including supers / instance methods is not super clear in our codebase.
I tried a best effort to group them in 3 sections but I'm not 100% sure
if this is correct.
Added an additional test for element extensions (probably needs to be
further extended).
Bug: 160323720
Test: existing test suite, ElementExtTest
Change-Id: I962758128d3123b4c120fe48630ad54202047833
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index 59634ee..22d60b8 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -15,6 +15,8 @@
*/
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.BuildOnServerKt
import androidx.build.CompilationTarget
@@ -240,6 +242,13 @@
tasks.findByName("compileKotlin").dependsOn(":room:room-runtime:jarDebug")
tasks.findByName("compileKotlin").dependsOn(":sqlite:sqlite:jarDebug")
+tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions {
+ freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn",
+ "-Xopt-in=kotlin.contracts.ExperimentalContracts"]
+ }
+}
+
androidx {
name = "Android Room Compiler"
publish = Publish.SNAPSHOT_AND_RELEASE
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt
index fdd7a8d..53fdaa8 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt
@@ -44,6 +44,7 @@
import javax.lang.model.util.SimpleAnnotationValueVisitor6
import javax.lang.model.util.SimpleTypeVisitor7
import javax.lang.model.util.Types
+import kotlin.contracts.contract
import kotlin.reflect.KClass
fun Element.hasAnyOf(vararg modifiers: Modifier): Boolean {
@@ -69,6 +70,10 @@
fun Element.isEntityElement() = this.hasAnnotation(androidx.room.Entity::class)
+fun TypeElement.getConstructors(): List<ExecutableElement> {
+ return ElementFilter.constructorsIn(enclosedElements)
+}
+
/**
* gets all members including super privates. does not handle duplicate field names!!!
*/
@@ -89,7 +94,7 @@
}
fun TypeElement.getAllMethodsIncludingSupers(): Set<ExecutableElement> {
- val myMethods = ElementFilter.methodsIn(this.enclosedElements).toSet()
+ val myMethods = getDeclaredMethods().toSet()
val interfaceMethods = interfaces.flatMap {
it.asTypeElement().getAllMethodsIncludingSupers()
}
@@ -387,10 +392,10 @@
}
val parent = this.enclosingElement as TypeElement
- val innerClass = parent.enclosedElements.find {
- it.kind == ElementKind.CLASS && it.simpleName.contentEquals(DEFAULT_IMPLS_CLASS_NAME)
- } ?: return null
- return ElementFilter.methodsIn(innerClass.enclosedElements).find {
+ val innerClass: TypeElement = parent.enclosedElements.find {
+ it.isType() && it.simpleName.contentEquals(DEFAULT_IMPLS_CLASS_NAME)
+ } as? TypeElement ?: return null
+ return innerClass.getDeclaredMethods().find {
it.simpleName == this.simpleName && paramsMatch(this.parameters, it.parameters)
}
}
@@ -415,11 +420,42 @@
fun Element.asExecutableElement() = MoreElements.asExecutable(this)
-fun Element.isType() = MoreElements.isType(this)
+fun Element.isType(): Boolean {
+ contract {
+ returns(true) implies (this@isType is TypeElement)
+ }
+ return MoreElements.isType(this)
+}
fun Element.asDeclaredType() = asType().asDeclaredType()
-fun TypeElement.getLocalAndInheritedMethods(
+/**
+ * methods declared in this type
+ * includes all instance/static methods in this
+ */
+fun TypeElement.getDeclaredMethods() = ElementFilter.methodsIn(
+ enclosedElements
+)
+
+/**
+ * Methods declared in this type and its parents
+ * includes all instance/static methods in this
+ * includes all instance/static methods in parent CLASS if they are accessible from this (e.g. not
+ * private).
+ * does not include static methods in parent interfaces
+ */
+fun TypeElement.getAllMethods(
+ processingEnv: ProcessingEnvironment
+) = ElementFilter.methodsIn(
+ processingEnv.elementUtils.getAllMembers(this)
+)
+
+/**
+ * Instance methods declared in this and supers
+ * include non private instance methods
+ * also includes non-private instance methods from supers
+ */
+fun TypeElement.getAllNonPrivateInstanceMethods(
processingEnvironment: ProcessingEnvironment
) = MoreElements.getLocalAndInheritedMethods(
this,
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt
index 101bdcd..4ab6d2b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt
@@ -15,6 +15,7 @@
*/
package androidx.room.ext
+import com.google.auto.common.GeneratedAnnotations
import com.squareup.javapoet.TypeName
import javax.annotation.processing.ProcessingEnvironment
import javax.lang.model.element.TypeElement
@@ -108,3 +109,12 @@
fun ProcessingEnvironment.findTypeMirror(
qName: String
): TypeMirror? = findTypeElement(qName)?.asType()
+
+fun ProcessingEnvironment.getGeneratedAnnotation(): TypeElement? {
+ val element = GeneratedAnnotations.generatedAnnotation(elementUtils, sourceVersion)
+ return if (element.isPresent) {
+ element.get()
+ } else {
+ null
+ }
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt
index 6829d3a..ff2e46c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt
@@ -109,7 +109,6 @@
this
)
-@OptIn(ExperimentalContracts::class)
fun TypeMirror.isArray(): Boolean {
contract {
returns(true) implies (this@isArray is ArrayType)
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
index 7f2aeaf..0e1cdc0 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
@@ -20,6 +20,8 @@
import androidx.room.TypeConverters
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asMemberOf
+import androidx.room.ext.getAllMethods
+import androidx.room.ext.getConstructors
import androidx.room.ext.hasAnnotation
import androidx.room.ext.hasAnyOf
import androidx.room.ext.toAnnotationBox
@@ -46,7 +48,6 @@
import javax.lang.model.element.TypeElement
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
-import javax.lang.model.util.ElementFilter
/**
* Processes classes that are referenced in TypeConverters annotations.
@@ -87,17 +88,14 @@
fun process(): List<CustomTypeConverter> {
// using element utils instead of MoreElements to include statics.
- val methods = ElementFilter
- .methodsIn(context.processingEnv.elementUtils.getAllMembers(element))
+ val methods = element.getAllMethods(context.processingEnv)
val declaredType = element.asDeclaredType()
val converterMethods = methods.filter {
it.hasAnnotation(TypeConverter::class)
}
context.checker.check(converterMethods.isNotEmpty(), element, TYPE_CONVERTER_EMPTY_CLASS)
val allStatic = converterMethods.all { it.modifiers.contains(Modifier.STATIC) }
- val constructors = ElementFilter.constructorsIn(
- context.processingEnv.elementUtils.getAllMembers(element)
- )
+ val constructors = element.getConstructors()
val kotlinMetadata = KotlinMetadataElement.createFor(context, element)
val isKotlinObjectDeclaration = kotlinMetadata?.isObject() == true
context.checker.check(
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
index a15359f..ffadc85 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
@@ -25,6 +25,8 @@
import androidx.room.Update
import androidx.room.ext.asDeclaredType
import androidx.room.ext.findKotlinDefaultImpl
+import androidx.room.ext.getAllMethods
+import androidx.room.ext.getConstructors
import androidx.room.ext.hasAnnotation
import androidx.room.ext.hasAnyOf
import androidx.room.ext.typeName
@@ -38,7 +40,6 @@
import javax.lang.model.element.Modifier.ABSTRACT
import javax.lang.model.element.TypeElement
import javax.lang.model.type.DeclaredType
-import javax.lang.model.util.ElementFilter
class DaoProcessor(
baseContext: Context,
@@ -60,8 +61,8 @@
element, ProcessorErrors.DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE)
val declaredType = element.asDeclaredType()
- val allMembers = context.processingEnv.elementUtils.getAllMembers(element)
- val methods = ElementFilter.methodsIn(allMembers)
+ val allMethods = element.getAllMethods(context.processingEnv)
+ val methods = allMethods
.filter {
it.hasAnyOf(ABSTRACT) &&
it.findKotlinDefaultImpl(context.processingEnv.typeUtils) == null
@@ -128,7 +129,7 @@
executableElement = it).process()
} ?: emptyList()
- val transactionMethods = ElementFilter.methodsIn(allMembers).filter { member ->
+ val transactionMethods = allMethods.filter { member ->
member.hasAnnotation(Transaction::class) &&
PROCESSED_ANNOTATIONS.none { member.hasAnnotation(it) }
}.map {
@@ -141,7 +142,7 @@
val kotlinDefaultMethodDelegates = if (element.kind == ElementKind.INTERFACE) {
val allProcessedMethods =
methods.values.flatten() + transactionMethods.map { it.element }
- ElementFilter.methodsIn(allMembers).filterNot {
+ allMethods.filterNot {
allProcessedMethods.contains(it)
}.mapNotNull { method ->
method.findKotlinDefaultImpl(context.processingEnv.typeUtils)?.let { delegate ->
@@ -155,7 +156,7 @@
emptyList()
}
- val constructors = ElementFilter.constructorsIn(allMembers)
+ val constructors = element.getConstructors()
val typeUtils = context.processingEnv.typeUtils
val goodConstructor = constructors.firstOrNull {
it.parameters.size == 1 &&
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 3684df7..9bceb2a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -22,6 +22,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
import androidx.room.ext.hasAnnotation
import androidx.room.ext.hasAnyOf
import androidx.room.ext.isType
@@ -42,7 +43,6 @@
import isAssignableFrom
import java.util.Locale
import javax.lang.model.element.Element
-import javax.lang.model.element.ElementKind
import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement
import javax.lang.model.type.TypeMirror
@@ -78,8 +78,6 @@
)
context.checker.check(extendsRoomDb, element, ProcessorErrors.DB_MUST_EXTEND_ROOM_DB)
- val allMembers = context.processingEnv.elementUtils.getAllMembers(element)
-
val views = resolveDatabaseViews(viewsMap.values.toList())
val dbVerifier = if (element.hasAnnotation(SkipQueryVerification::class)) {
null
@@ -94,8 +92,8 @@
validateUniqueTableAndViewNames(element, entities, views)
val declaredType = element.asDeclaredType()
- val daoMethods = allMembers.filter {
- it.hasAnyOf(Modifier.ABSTRACT) && it.kind == ElementKind.METHOD
+ val daoMethods = element.getAllMethods(context.processingEnv).filter {
+ it.hasAnyOf(Modifier.ABSTRACT)
}.filterNot {
// remove methods that belong to room
val containing = it.enclosingElement
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
index ed0c696..60e3d76 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -28,7 +28,8 @@
import androidx.room.ext.findTypeElement
import androidx.room.ext.getAllFieldsIncludingPrivateSupers
import androidx.room.ext.getAllMethodsIncludingSupers
-import androidx.room.ext.getLocalAndInheritedMethods
+import androidx.room.ext.getConstructors
+import androidx.room.ext.getAllNonPrivateInstanceMethods
import androidx.room.ext.hasAnnotation
import androidx.room.ext.hasAnyOf
import androidx.room.ext.isAssignableFromWithoutVariance
@@ -74,7 +75,6 @@
import javax.lang.model.element.VariableElement
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
-import javax.lang.model.util.ElementFilter
/**
* Processes any class as if it is a Pojo.
@@ -228,17 +228,17 @@
}
}
- val methods = element.getLocalAndInheritedMethods(context.processingEnv)
- .filter {
- !it.hasAnyOf(PRIVATE, ABSTRACT, STATIC) &&
- !it.hasAnnotation(Ignore::class)
- }.map {
- PojoMethodProcessor(
- context = context,
- element = it,
- owner = declaredType
- ).process()
- }
+ val methods = element.getAllNonPrivateInstanceMethods(context.processingEnv)
+ .asSequence()
+ .filter {
+ !it.hasAnyOf(ABSTRACT) && !it.hasAnnotation(Ignore::class)
+ }.map {
+ PojoMethodProcessor(
+ context = context,
+ element = it,
+ owner = declaredType
+ ).process()
+ }.toList()
val getterCandidates = methods.filter {
it.element.parameters.size == 0 && it.resolvedType.returnType.isNotVoid()
@@ -904,8 +904,7 @@
}
}
- override fun findConstructors(element: TypeElement) = ElementFilter.constructorsIn(
- element.enclosedElements).filterNot {
+ override fun findConstructors(element: TypeElement) = element.getConstructors().filterNot {
it.hasAnnotation(Ignore::class) || it.hasAnyOf(PRIVATE)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
index 5b0da19..d41dfdf 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
@@ -18,17 +18,17 @@
import androidx.room.ext.asMemberOf
import androidx.room.ext.extendsBound
+import androidx.room.ext.getAllNonPrivateInstanceMethods
import androidx.room.ext.requireTypeMirror
import androidx.room.vo.ShortcutQueryParameter
import asDeclaredType
+import asTypeElement
import isAssignableFrom
import isType
-import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.type.ArrayType
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
-import javax.lang.model.util.ElementFilter
/**
* Processes parameters of methods that are annotated with Insert, Update or Delete.
@@ -62,7 +62,6 @@
private fun extractPojoType(typeMirror: TypeMirror): Pair<TypeMirror?, Boolean> {
val processingEnv = context.processingEnv
- val elementUtils = context.processingEnv.elementUtils
val typeUtils = context.processingEnv.typeUtils
fun verifyAndPair(pojoType: TypeMirror, isMultiple: Boolean): Pair<TypeMirror?, Boolean> {
@@ -77,8 +76,7 @@
}
fun extractPojoTypeFromIterator(iterableType: DeclaredType): TypeMirror {
- ElementFilter.methodsIn(elementUtils
- .getAllMembers(typeUtils.asElement(iterableType) as TypeElement)).forEach {
+ iterableType.asTypeElement().getAllNonPrivateInstanceMethods(processingEnv).forEach {
if (it.simpleName.toString() == "iterator") {
return it.asMemberOf(typeUtils, iterableType)
.returnType
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt b/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt
index 6c5cca9..a20c5e5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt
@@ -19,6 +19,7 @@
import androidx.room.Ignore
import androidx.room.ext.asDeclaredType
import androidx.room.ext.getAllMethodsIncludingSupers
+import androidx.room.ext.getDeclaredMethods
import androidx.room.ext.getPackage
import androidx.room.ext.hasAnnotation
import androidx.room.ext.hasAnyOf
@@ -37,7 +38,6 @@
import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement
import javax.lang.model.type.DeclaredType
-import javax.lang.model.util.ElementFilter
/**
* Delegate to process generated AutoValue class as a Pojo.
@@ -81,7 +81,7 @@
override fun findConstructors(element: TypeElement): List<ExecutableElement> {
val typeUtils = context.processingEnv.typeUtils
- return ElementFilter.methodsIn(autoValueElement.enclosedElements).filter {
+ return autoValueElement.getDeclaredMethods().filter {
it.hasAnyOf(Modifier.STATIC) &&
!it.hasAnnotation(Ignore::class) &&
!it.hasAnyOf(Modifier.PRIVATE) &&
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
index c22f108..0fdcd22 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
@@ -18,9 +18,9 @@
import androidx.room.RoomProcessor
import androidx.room.ext.S
+import androidx.room.ext.getGeneratedAnnotation
import androidx.room.ext.typeName
import androidx.room.solver.CodeGenScope.Companion.CLASS_PROPERTY_PREFIX
-import com.google.auto.common.GeneratedAnnotations
import com.squareup.javapoet.AnnotationSpec
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.FieldSpec
@@ -66,9 +66,7 @@
adapterTypeSpecBuilder: TypeSpec.Builder,
processingEnv: ProcessingEnvironment
) {
- GeneratedAnnotations.generatedAnnotation(
- processingEnv.elementUtils, processingEnv.sourceVersion
- ).ifPresent {
+ processingEnv.getGeneratedAnnotation()?.let {
val generatedAnnotationSpec =
AnnotationSpec.builder(ClassName.get(it))
.addMember("value", S, RoomProcessor::class.java.canonicalName)
diff --git a/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt b/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
new file mode 100644
index 0000000..b61b312
--- /dev/null
+++ b/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 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.ext
+
+import com.google.common.truth.Truth.assertThat
+import com.google.testing.compile.JavaFileObjects
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import simpleRun
+import javax.lang.model.element.ExecutableElement
+
+@RunWith(JUnit4::class)
+class ElementExtTest {
+ @Test
+ fun methodsInClass() {
+ val parentCode = JavaFileObjects.forSourceLines(
+ "foo.bar.Parent", """
+ package foo.bar;
+
+ public class Parent {
+ public Parent() {}
+ private void parentPrivate() {}
+ public void parentPublic() {}
+ public void overridden() {}
+ private static void parentStaticPrivate() {}
+ public static void parentStaticPublic() {}
+ }
+ """.trimIndent()
+ )
+ val childCode = JavaFileObjects.forSourceLines(
+ "foo.bar.Child", """
+ package foo.bar;
+
+ public class Child extends Parent {
+ public Child() {}
+ private void childPrivate() {}
+ public void childPublic() {}
+ public void overridden() {}
+ private static void childStaticPrivate() {}
+ public static void childStaticPublic() {}
+ }
+ """.trimIndent()
+ )
+ simpleRun(
+ jfos = *arrayOf(parentCode, childCode)
+ ) {
+ val parent = it.processingEnv.requireTypeElement("foo.bar.Parent")
+ val child = it.processingEnv.requireTypeElement("foo.bar.Child")
+ val objectMethods = it.processingEnv.requireTypeElement("java.lang.Object")
+ .getAllMethods(it.processingEnv).map {
+ it.simpleName.toString()
+ } - "registerNatives"
+ val parentMethods = listOf(
+ "parentPrivate", "parentPublic", "parentStaticPrivate",
+ "parentStaticPublic", "overridden"
+ )
+ val childMethods = listOf(
+ "childPrivate", "childPublic", "childStaticPrivate",
+ "childStaticPublic", "overridden"
+ )
+ assertThat(parent.getDeclaredMethods()).containsExactlyElementsIn(parentMethods)
+ assertThat(parent.getAllMethods(it.processingEnv))
+ .containsExactlyElementsIn(parentMethods + objectMethods)
+ assertThat(parent.getAllNonPrivateInstanceMethods(it.processingEnv))
+ .containsExactlyElementsIn(
+ parentMethods + objectMethods -
+ listOf("parentPrivate", "parentStaticPrivate", "parentStaticPublic")
+ )
+
+ assertThat(child.getDeclaredMethods()).containsExactlyElementsIn(
+ childMethods
+ )
+ assertThat(child.getAllMethods(it.processingEnv)).containsExactlyElementsIn(
+ childMethods + parentMethods + objectMethods -
+ listOf("parentPrivate", "parentStaticPrivate", "overridden") +
+ "overridden" // add 1 overridden back
+ )
+ assertThat(child.getAllNonPrivateInstanceMethods(it.processingEnv))
+ .containsExactlyElementsIn(
+ childMethods + parentMethods + objectMethods -
+ listOf(
+ "parentPrivate", "parentStaticPrivate", "parentStaticPublic",
+ "childPrivate", "childStaticPrivate", "childStaticPublic",
+ "overridden"
+ ) + "overridden" // add 1 overridden back
+ )
+
+ assertThat(child.getConstructors()).containsExactly("<init>")
+ assertThat(parent.getConstructors()).containsExactly("<init>")
+ }.compilesWithoutError()
+ }
+
+ @Test
+ fun methodsInInterface() {
+ val parentCode = JavaFileObjects.forSourceLines(
+ "foo.bar.Parent", """
+ package foo.bar;
+
+ public interface Parent {
+ public void parentPublic();
+ public void overridden();
+ private static void parentStaticPrivate() {}
+ public static void parentStaticPublic() {}
+ }
+ """.trimIndent()
+ )
+ val childCode = JavaFileObjects.forSourceLines(
+ "foo.bar.Child", """
+ package foo.bar;
+
+ public interface Child extends Parent {
+ public void childPublic();
+ public void overridden();
+ private static void childStaticPrivate() {}
+ public static void childStaticPublic() {}
+ }
+ """.trimIndent()
+ )
+ simpleRun(
+ jfos = *arrayOf(parentCode, childCode)
+ ) {
+ val parent = it.processingEnv.requireTypeElement("foo.bar.Parent")
+ val child = it.processingEnv.requireTypeElement("foo.bar.Child")
+ val objectMethods = it.processingEnv.requireTypeElement("java.lang.Object")
+ .getAllMethods(it.processingEnv).map {
+ it.simpleName.toString()
+ } - listOf("registerNatives", "clone", "finalize")
+ val parentMethods = listOf(
+ "parentPublic", "parentStaticPrivate", "parentStaticPublic", "overridden"
+ )
+ val childMethods = listOf(
+ "childPublic", "childStaticPrivate", "childStaticPublic", "overridden"
+ )
+ assertThat(parent.getDeclaredMethods())
+ .containsExactlyElementsIn(parentMethods)
+ assertThat(parent.getAllMethods(it.processingEnv))
+ .containsExactlyElementsIn(parentMethods + objectMethods)
+ assertThat(parent.getAllNonPrivateInstanceMethods(it.processingEnv))
+ .containsExactly("parentPublic", "overridden")
+
+ assertThat(child.getDeclaredMethods())
+ .containsExactlyElementsIn(childMethods)
+ assertThat(child.getAllMethods(it.processingEnv)).containsExactlyElementsIn(
+ childMethods + parentMethods + objectMethods -
+ listOf("parentStaticPrivate", "parentStaticPublic", "overridden") +
+ "overridden" // add 1 overridden back
+ )
+ assertThat(child.getAllNonPrivateInstanceMethods(it.processingEnv))
+ .containsExactly(
+ "childPublic", "parentPublic", "overridden"
+ )
+
+ assertThat(child.getConstructors()).isEmpty()
+ assertThat(parent.getConstructors()).isEmpty()
+ }.compilesWithoutError()
+ }
+
+ private fun assertThat(executables: Iterable<ExecutableElement>) = assertThat(
+ executables.map { it.simpleName.toString() }
+ )
+}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt b/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
index bf1fb1c..c99a86d 100644
--- a/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
@@ -16,8 +16,10 @@
package androidx.room.kotlin
-import androidx.room.ext.requireTypeElement
import androidx.room.ext.asExecutableElement
+import androidx.room.ext.getConstructors
+import androidx.room.ext.getDeclaredMethods
+import androidx.room.ext.requireTypeElement
import androidx.room.processor.Context
import androidx.room.testing.TestInvocation
import com.google.common.truth.Truth.assertThat
@@ -25,7 +27,6 @@
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import simpleRun
-import javax.lang.model.util.ElementFilter
import kotlin.reflect.KClass
@RunWith(JUnit4::class)
@@ -38,7 +39,7 @@
invocation,
TestData::class
)
- assertThat(ElementFilter.methodsIn(testClassElement.enclosedElements)
+ assertThat(testClassElement.getDeclaredMethods()
.first { it.simpleName.toString() == "functionWithParams" }
.let { metadataElement.getParameterNames(it.asExecutableElement()) }
).isEqualTo(
@@ -55,7 +56,7 @@
TestData::class
)
assertThat(
- ElementFilter.constructorsIn(testClassElement.enclosedElements).map {
+ testClassElement.getConstructors().map {
val desc = it.asExecutableElement().descriptor()
desc to (desc == metadataElement.findPrimaryConstructorSignature())
}
@@ -73,7 +74,7 @@
invocation,
TestData::class
)
- assertThat(ElementFilter.methodsIn(testClassElement.enclosedElements).map {
+ assertThat(testClassElement.getDeclaredMethods().map {
val executableElement = it.asExecutableElement()
executableElement.simpleName.toString() to metadataElement.isSuspendFunction(
executableElement
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
index c2e98ff..5fef51b 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
@@ -20,8 +20,7 @@
import androidx.room.ext.requireTypeElement
import androidx.room.ext.typeName
import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_EMPTY_CLASS
-import androidx.room.processor.ProcessorErrors
- .TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
+import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_MUST_BE_PUBLIC
import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_UNBOUND_GENERIC
import androidx.room.testing.TestInvocation
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
index 8f186bc..f35bdf5 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
@@ -20,6 +20,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asTypeElement
import androidx.room.ext.asVariableElement
+import androidx.room.ext.getAllFieldsIncludingPrivateSupers
import androidx.room.ext.requireTypeMirror
import androidx.room.parser.Collate
import androidx.room.parser.SQLTypeAffinity
@@ -41,7 +42,6 @@
import org.mockito.Mockito.mock
import simpleRun
import javax.lang.model.element.Element
-import javax.lang.model.element.ElementKind
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
@@ -440,9 +440,10 @@
val (owner, fieldElement) = invocation.roundEnv
.getElementsAnnotatedWith(Entity::class.java)
.map {
- Pair(it, invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .firstOrNull { it.kind == ElementKind.FIELD })
+ Pair(it, it.asTypeElement()
+ .getAllFieldsIncludingPrivateSupers(
+ invocation.processingEnv
+ ).firstOrNull())
}
.first { it.second != null }
val entityContext =
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
index ea9d973..e146b71 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
@@ -26,6 +26,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
import androidx.room.ext.hasAnnotation
import androidx.room.ext.typeName
import androidx.room.solver.shortcut.result.InsertMethodAdapter
@@ -761,16 +762,16 @@
.forAnnotations(Insert::class, Dao::class)
.nextRunHandler { invocation ->
val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .filter {
- it.hasAnnotation(Insert::class.java)
- }
- )
- }.first { it.second.isNotEmpty() }
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(it,
+ it.asTypeElement().getAllMethods(
+ invocation.processingEnv
+ ).filter {
+ it.hasAnnotation(Insert::class.java)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
val processor = InsertionMethodProcessor(
baseContext = invocation.context,
containing = owner.asDeclaredType(),
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
index c884e24..711e36a 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
@@ -26,6 +26,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
import androidx.room.ext.hasAnnotation
import androidx.room.ext.requireTypeMirror
import androidx.room.ext.typeName
@@ -984,11 +985,11 @@
.getElementsAnnotatedWith(Dao::class.java)
.map {
Pair(it,
- invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .filter {
- it.hasAnnotation(Query::class)
- }
+ it.asTypeElement().getAllMethods(
+ invocation.processingEnv
+ ).filter {
+ it.hasAnnotation(Query::class)
+ }
)
}.first { it.second.isNotEmpty() }
val verifier = if (enableVerification) {
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
index 77765ac..60f2877 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
@@ -28,6 +28,8 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
+import androidx.room.ext.getDeclaredMethods
import androidx.room.ext.hasAnnotation
import androidx.room.ext.requireTypeElement
import androidx.room.ext.typeName
@@ -47,7 +49,6 @@
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
import simpleRun
-import javax.lang.model.util.ElementFilter
class RawQueryMethodProcessorTest {
@Test
@@ -200,7 +201,7 @@
simpleRun { invocation ->
val daoElement =
invocation.processingEnv.requireTypeElement(RawQuerySuspendUnitDao::class)
- val daoFunctionElement = ElementFilter.methodsIn(daoElement.enclosedElements).first()
+ val daoFunctionElement = daoElement.getDeclaredMethods().first()
RawQueryMethodProcessor(
baseContext = invocation.context,
containing = daoElement.asDeclaredType(),
@@ -315,11 +316,11 @@
.getElementsAnnotatedWith(Dao::class.java)
.map {
Pair(it,
- invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .filter {
- it.hasAnnotation(RawQuery::class)
- }
+ it.asTypeElement().getAllMethods(
+ invocation.processingEnv
+ ).filter {
+ it.hasAnnotation(RawQuery::class)
+ }
)
}.first { it.second.isNotEmpty() }
val parser = RawQueryMethodProcessor(
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt
index 8a7fe70..c534f7a 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt
@@ -25,6 +25,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
import androidx.room.ext.hasAnnotation
import androidx.room.ext.typeName
import androidx.room.testing.TestInvocation
@@ -473,11 +474,11 @@
.getElementsAnnotatedWith(Dao::class.java)
.map {
Pair(it,
- invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .filter {
- it.hasAnnotation(annotation)
- }
+ it.asTypeElement().getAllMethods(
+ invocation.processingEnv
+ ).filter {
+ it.hasAnnotation(annotation)
+ }
)
}.first { it.second.isNotEmpty() }
val processed = process(
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt
index 67c7a61..1e46eb3 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt
@@ -22,6 +22,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
import androidx.room.ext.hasAnnotation
import androidx.room.testing.TestInvocation
import androidx.room.testing.TestProcessor
@@ -240,11 +241,11 @@
.getElementsAnnotatedWith(Dao::class.java)
.map {
Pair(it,
- invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .filter {
- it.hasAnnotation(Transaction::class)
- }
+ it.asTypeElement().getAllMethods(
+ invocation.processingEnv
+ ).filter {
+ it.hasAnnotation(Transaction::class)
+ }
)
}.first { it.second.isNotEmpty() }
val processor = TransactionMethodProcessor(
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt
index 68754ec..793b2de 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt
@@ -23,6 +23,7 @@
import androidx.room.ext.asDeclaredType
import androidx.room.ext.asExecutableElement
import androidx.room.ext.asTypeElement
+import androidx.room.ext.getAllMethods
import androidx.room.ext.hasAnnotation
import androidx.room.processor.QueryMethodProcessor
import androidx.room.testing.TestProcessor
@@ -305,11 +306,11 @@
.getElementsAnnotatedWith(Dao::class.java)
.map {
Pair(it,
- invocation.processingEnv.elementUtils
- .getAllMembers(it.asTypeElement())
- .filter {
- it.hasAnnotation(Query::class)
- }
+ it.asTypeElement().getAllMethods(
+ invocation.processingEnv
+ ).filter {
+ it.hasAnnotation(Query::class)
+ }
)
}.first { it.second.isNotEmpty() }
val parser = QueryMethodProcessor(