Remove Element.asType calls
These calls are not really reasonable as Element can be anything
(e.g. package) where type would be a NoType.
Instead of that undefined case, this CL replace asType calls with
an extension property (.type) and certain element where it makes
sense.
Even though we cannot enforse it right now, after the migration,
these fields will only exist in specific XElement subclasses so
we'll be able to enforse never getting type from XElement.
Bug: 160323720
Test: existing test suite
Change-Id: Ide734f49b3f6fe25c3022530927407cf10a5d857
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 89ab8c2..57119b5 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
@@ -404,7 +404,7 @@
}
ourParams.forEachIndexed { i, variableElement ->
// Plus 1 to their index because their first param is a self object.
- if (!typeUtils.isSameType(theirParams[i + 1].asType(), variableElement.asType())) {
+ if (!typeUtils.isSameType(theirParams[i + 1].type, variableElement.type)) {
return false
}
}
@@ -523,4 +523,16 @@
/**
* Returns the string representation of the element kind.
*/
-fun Element.kindName() = kind.name.toLowerCase(Locale.US)
\ No newline at end of file
+fun Element.kindName() = kind.name.toLowerCase(Locale.US)
+
+// instead of using asType on Element, we should use a specific Element subclass's .type
+// it is not enforce-able until migrating to the abstraction but still a step in the right direction
+// of safety
+val VariableElement.type: TypeMirror
+ get() = asType()
+
+val TypeElement.type: DeclaredType
+ get() = MoreTypes.asDeclared(asType())
+
+val ExecutableElement.executableType: ExecutableType
+ get() = MoreTypes.asExecutable(asType())
\ No newline at end of file
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 4ab6d2b..0e0626a 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
@@ -87,7 +87,7 @@
*/
fun ProcessingEnvironment.requireTypeMirror(
qName: String
-): TypeMirror = requireTypeElement(qName).asType()
+): TypeMirror = requireTypeElement(qName).type
/**
* Query a type mirror by KClass and return null if it does not exist
@@ -108,7 +108,7 @@
*/
fun ProcessingEnvironment.findTypeMirror(
qName: String
-): TypeMirror? = findTypeElement(qName)?.asType()
+): TypeMirror? = findTypeElement(qName)?.type
fun ProcessingEnvironment.getGeneratedAnnotation(): TypeElement? {
val element = GeneratedAnnotations.generatedAnnotation(elementUtils, sourceVersion)
diff --git a/room/compiler/src/main/kotlin/androidx/room/kotlin/JvmDescriptorUtils.kt b/room/compiler/src/main/kotlin/androidx/room/kotlin/JvmDescriptorUtils.kt
index 7757f79..09cf3f2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/kotlin/JvmDescriptorUtils.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/kotlin/JvmDescriptorUtils.kt
@@ -16,6 +16,8 @@
package androidx.room.kotlin
+import androidx.room.ext.executableType
+import androidx.room.ext.type
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.NestingKind
@@ -42,14 +44,14 @@
*
* For reference, see the [JVM specification, section 4.3.2](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.2)
*/
-fun VariableElement.descriptor() = "$simpleName:${asType().descriptor()}"
+fun VariableElement.descriptor() = "$simpleName:${type.descriptor()}"
/**
* Returns the method descriptor of this [ExecutableElement].
*
* For reference, see the [JVM specification, section 4.3.3](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3)
*/
-fun ExecutableElement.descriptor() = "$simpleName${asType().descriptor()}"
+fun ExecutableElement.descriptor() = "$simpleName${executableType.descriptor()}"
/**
* Returns the name of this [TypeElement] in its "internal form".
diff --git a/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt b/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
index 4d817c7..2843611 100644
--- a/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
@@ -18,6 +18,7 @@
import androidx.room.ColumnInfo
import androidx.room.ext.requireTypeMirror
+import androidx.room.ext.type
import org.antlr.v4.runtime.tree.ParseTree
import org.antlr.v4.runtime.tree.TerminalNode
import javax.annotation.processing.ProcessingEnvironment
@@ -211,7 +212,7 @@
List<TypeMirror> {
return primitives.flatMap {
val primitiveType = env.typeUtils.getPrimitiveType(it)
- listOf(primitiveType, env.typeUtils.boxedClass(primitiveType).asType())
+ listOf(primitiveType, env.typeUtils.boxedClass(primitiveType).type)
}
}
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 4f3518c..0badc78 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
@@ -30,6 +30,7 @@
import androidx.room.ext.hasAnnotation
import androidx.room.ext.isAbstract
import androidx.room.ext.isInterface
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.verifier.DatabaseVerifier
import androidx.room.vo.Dao
@@ -158,10 +159,10 @@
val typeUtils = context.processingEnv.typeUtils
val goodConstructor = constructors.firstOrNull {
it.parameters.size == 1 &&
- it.parameters[0].asType().isAssignableFrom(typeUtils, dbType)
+ it.parameters[0].type.isAssignableFrom(typeUtils, dbType)
}
val constructorParamType = if (goodConstructor != null) {
- goodConstructor.parameters[0].asType().typeName()
+ goodConstructor.parameters[0].type.typeName()
} else {
validateEmptyConstructor(constructors)
null
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 cb7cb70..e74899c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -28,6 +28,7 @@
import androidx.room.ext.isType
import androidx.room.ext.requireTypeMirror
import androidx.room.ext.toAnnotationBox
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.verifier.DatabaseVerificationErrors
import androidx.room.verifier.DatabaseVerifier
@@ -74,7 +75,7 @@
val typeUtils = context.processingEnv.typeUtils
val extendsRoomDb = roomDatabaseType.isAssignableFrom(
typeUtils,
- element.asTypeElement().asType()
+ element.type
)
context.checker.check(extendsRoomDb, element, ProcessorErrors.DB_MUST_EXTEND_ROOM_DB)
@@ -98,7 +99,7 @@
// remove methods that belong to room
val containing = it.enclosingElement
containing.isType() &&
- containing.asType().typeName() == RoomTypeNames.ROOM_DB
+ containing.type.typeName() == RoomTypeNames.ROOM_DB
}.map {
val executable = it.asExecutableElement()
// TODO when we add support for non Dao return types (e.g. database), this code needs
@@ -117,7 +118,7 @@
val database = Database(
version = dbAnnotation.value.version,
element = element,
- type = element.asTypeElement().asType(),
+ type = element.type,
entities = entities,
views = views,
daoMethods = daoMethods,
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
index 0ebde8c..f2326e1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
@@ -19,6 +19,7 @@
import androidx.room.DatabaseView
import androidx.room.Entity
import androidx.room.ext.hasAnnotation
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.vo.EntityOrView
import androidx.room.vo.Fields
@@ -54,7 +55,7 @@
override val tableName: String
get() = typeName.toString()
override val typeName: TypeName
- get() = element.asType().typeName()
+ get() = element.type.typeName()
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt b/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
index 8a00f05..0df183a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
@@ -25,6 +25,7 @@
import androidx.room.ext.findTypeElement
import androidx.room.ext.getSuspendFunctionReturnType
import androidx.room.ext.requireTypeMirror
+import androidx.room.ext.type
import androidx.room.kotlin.KotlinMetadataElement
import androidx.room.parser.ParsedQuery
import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
@@ -182,7 +183,7 @@
.requireTypeMirror(KotlinTypeNames.CONTINUATION.toString())
)
executableElement.parameters.last {
- typesUtil.isSameType(typesUtil.erasure(it.asType()), continuationType)
+ typesUtil.isSameType(typesUtil.erasure(it.type), continuationType)
}
}
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 a0d959d..c6614a5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -41,6 +41,7 @@
import androidx.room.ext.isTransient
import androidx.room.ext.kindName
import androidx.room.ext.toAnnotationBox
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.kotlin.KotlinMetadataElement
import androidx.room.kotlin.descriptor
@@ -304,7 +305,7 @@
val parameterNames = getParamNames(constructor)
val params = constructor.parameters.mapIndexed param@{ index, param ->
val paramName = parameterNames[index]
- val paramType = param.asType()
+ val paramType = param.type
val matches = fun(field: Field?): Boolean {
return if (field == null) {
@@ -730,7 +731,7 @@
element = field.element,
msg = ProcessorErrors.mismatchedGetter(
fieldName = field.name,
- ownerType = element.asType().typeName(),
+ ownerType = element.type.typeName(),
getterType = field.getter.type.typeName(),
fieldType = field.typeName
))
@@ -798,7 +799,7 @@
element = field.element,
msg = ProcessorErrors.mismatchedSetter(
fieldName = field.name,
- ownerType = element.asType().typeName(),
+ ownerType = element.type.typeName(),
setterType = field.setter.type.typeName(),
fieldType = field.typeName
))
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
index 084b19e..832af1e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
@@ -24,6 +24,7 @@
import androidx.room.ext.isEntityElement
import androidx.room.ext.requireTypeMirror
import androidx.room.ext.toAnnotationBox
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.parser.SqlParser
import androidx.room.processor.ProcessorErrors.RAW_QUERY_STRING_PARAMETER_REMOVED
@@ -96,7 +97,7 @@
// if it is empty, report error as it does not make sense
if (tableNames.isEmpty()) {
context.logger.e(executableElement,
- ProcessorErrors.rawQueryBadEntity(it.asType().typeName()))
+ ProcessorErrors.rawQueryBadEntity(it.type.typeName()))
}
tableNames
}
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 baa79ca..aa2d9a3 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
@@ -27,6 +27,7 @@
import androidx.room.ext.isPrivate
import androidx.room.ext.isStatic
import androidx.room.ext.kindName
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.processor.Context
import androidx.room.processor.PojoProcessor
@@ -88,7 +89,7 @@
it.isStatic() &&
!it.hasAnnotation(Ignore::class) &&
!it.isPrivate() &&
- typeUtils.isSameType(it.returnType, autoValueElement.asType())
+ typeUtils.isSameType(it.returnType, autoValueElement.type)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
index 49b4780..b3034af 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
@@ -17,6 +17,7 @@
package androidx.room.solver.types
import androidx.room.ext.L
+import androidx.room.ext.type
import androidx.room.solver.CodeGenScope
import asPrimitive
import javax.annotation.processing.ProcessingEnvironment
@@ -38,7 +39,7 @@
return primitiveAdapters.map {
BoxedPrimitiveColumnTypeAdapter(
processingEnvironment.typeUtils
- .boxedClass(it.out.asPrimitive()).asType(),
+ .boxedClass(it.out.asPrimitive()).type,
it
)
}
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 d1e7852..45b2fde 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
@@ -18,6 +18,7 @@
import androidx.room.ext.L
import androidx.room.ext.T
+import androidx.room.ext.asDeclaredType
import androidx.room.ext.isConstructor
import androidx.room.ext.isMethod
import androidx.room.ext.kindName
@@ -46,11 +47,11 @@
when {
element.isConstructor() -> {
builder.addStatement("$L = new $T($L)", outVar,
- element.enclosingElement.asType().typeName(), args)
+ element.enclosingElement.asDeclaredType().typeName(), args)
}
element.isMethod() -> {
builder.addStatement("$L = $T.$L($L)", outVar,
- element.enclosingElement.asType().typeName(),
+ element.enclosingElement.asDeclaredType().typeName(),
element.simpleName.toString(), args)
}
else -> throw IllegalStateException("Invalid constructor kind ${element.kindName()}")
diff --git a/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt b/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
index b61b312..40c776e 100644
--- a/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
@@ -18,6 +18,8 @@
import com.google.common.truth.Truth.assertThat
import com.google.testing.compile.JavaFileObjects
+import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.TypeName
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -170,6 +172,38 @@
}.compilesWithoutError()
}
+ @Test
+ fun types() {
+ val testCode = JavaFileObjects.forSourceLines(
+ "foo.bar.Baz", """
+ package foo.bar;
+
+ public class Baz {
+ public int field;
+ public int method() {
+ return 3;
+ }
+ }
+ """.trimIndent()
+ )
+ simpleRun(
+ jfos = *arrayOf(testCode)
+ ) {
+ val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
+ val field = element.getAllFieldsIncludingPrivateSupers(it.processingEnv)
+ .first {
+ it.simpleName.toString() == "field"
+ }
+ val method = element.getDeclaredMethods()
+ .first {
+ it.simpleName.toString() == "method"
+ }
+ assertThat(field.type.typeName()).isEqualTo(TypeName.INT)
+ assertThat(method.returnType.typeName()).isEqualTo(TypeName.INT)
+ assertThat(element.type.typeName()).isEqualTo(ClassName.get("foo.bar", "Baz"))
+ }.compilesWithoutError()
+ }
+
private fun assertThat(executables: Iterable<ExecutableElement>) = assertThat(
executables.map { it.simpleName.toString() }
)
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
index 583aa37..2053565 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
@@ -17,6 +17,7 @@
package androidx.room.solver
import androidx.room.ext.requireTypeMirror
+import androidx.room.ext.type
import androidx.room.ext.typeName
import androidx.room.processor.Context
import androidx.room.testing.TestInvocation
@@ -186,7 +187,7 @@
return if (typeKind.isPrimitive) {
processingEnv.typeUtils
.boxedClass(getTypeMirror(processingEnv) as PrimitiveType)
- .asType()
+ .type
} else {
getTypeMirror(processingEnv)
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
index 8596df1..00f55d1 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
@@ -19,6 +19,7 @@
import androidx.room.ext.getAllFieldsIncludingPrivateSupers
import androidx.room.ext.isAssignableFromWithoutVariance
import androidx.room.ext.requireTypeElement
+import androidx.room.ext.type
import androidx.room.testing.TestInvocation
import com.google.testing.compile.JavaFileObjects
import org.hamcrest.CoreMatchers.`is`
@@ -55,8 +56,8 @@
val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
val string = testObject.getField(processingEnv, "mString")
val integer = testObject.getField(processingEnv, "mInteger")
- assertThat( integer.asType()
- .isAssignableFromWithoutVariance(typeUtils, string.asType()),
+ assertThat( integer.type
+ .isAssignableFromWithoutVariance(typeUtils, string.type),
`is`(false))
}
}
@@ -65,8 +66,8 @@
fun generics() {
runTest {
val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
- val set = testObject.getField(processingEnv, "mSet").asType()
- val hashSet = testObject.getField(processingEnv, "mHashSet").asType()
+ val set = testObject.getField(processingEnv, "mSet").type
+ val hashSet = testObject.getField(processingEnv, "mHashSet").type
assertThat(hashSet.isAssignableFromWithoutVariance(typeUtils, set), `is`(false))
assertThat(set.isAssignableFromWithoutVariance(typeUtils, hashSet), `is`(true))
}
@@ -82,8 +83,8 @@
*/
runTest {
val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
- val set = testObject.getField(processingEnv, "mSet").asType()
- val varianceSet = testObject.getField(processingEnv, "mVarianceSet").asType()
+ val set = testObject.getField(processingEnv, "mSet").type
+ val varianceSet = testObject.getField(processingEnv, "mVarianceSet").type
assertThat(varianceSet.isAssignableFromWithoutVariance(typeUtils, set), `is`(true))
assertThat(set.isAssignableFromWithoutVariance(typeUtils, varianceSet), `is`(true))
}
@@ -93,8 +94,8 @@
fun unboundedVariance() {
runTest {
val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
- val unbounded = testObject.getField(processingEnv, "mUnboundedMap").asType()
- val objectMap = testObject.getField(processingEnv, "mStringMap").asType()
+ val unbounded = testObject.getField(processingEnv, "mUnboundedMap").type
+ val objectMap = testObject.getField(processingEnv, "mStringMap").type
assertThat(objectMap.isAssignableFromWithoutVariance(typeUtils, unbounded), `is`(false))
assertThat(unbounded.isAssignableFromWithoutVariance(typeUtils, objectMap), `is`(true))
}