Start generating Kotlin for FieldReadWriteWriter.readFromCursor()
To enable partial migration to XPoet this CL makes it so that the Pojo cursor reading code is generated in a separate Kotlin class that is then called from the Java Dao impl. This partial migration moves PrimitiveColumnTypeAdapter to XPoet, other type adapters will follow.
Additionally, this CL moves various JavaPoet TypeName usages in Room's value objects to XTypeName, mainly Pojo.typeName, most of the move is a refactor using toJavaPoet() that is a temporary compatibility API to be removed.
Due to the amount of type converters used in the integration test app this change only validates that the Java runtime behaves as expected and that the Kotlin generated code compiles (via KotlinCodeGenTest) but does not validate the runtime behaviour of the Kotlin codegen. We need to have all type converters and cursor readers migrated to run the integration tests.
As more of Room is migrated more XPoet APIs are added, in this CL we now have:
* begin, next and end control flow
* code block of a new instance, using the 'new' keyword in Java, but not in Kotlin
* code block of an unsafe cast, using the parenthesis syntax in Java and the 'as' keyword in Kotlin
* addLocalVariable is fixed (now that is being used)
Test: Existing tests + KotlinCodeGenTest
Change-Id: Id25a6e874fe9a03768ceca7e2c2a606ac2f469a2
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/PoetExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/PoetExt.kt
index a425abc..03d4446 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/PoetExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/PoetExt.kt
@@ -18,7 +18,9 @@
import androidx.room.compiler.processing.XNullability
import com.squareup.kotlinpoet.javapoet.JClassName
+import com.squareup.kotlinpoet.javapoet.JTypeName
import com.squareup.kotlinpoet.javapoet.toKClassName
+import com.squareup.kotlinpoet.javapoet.toKTypeName
typealias JCodeBlock = com.squareup.javapoet.CodeBlock
typealias JCodeBlockBuilder = com.squareup.javapoet.CodeBlock.Builder
@@ -31,11 +33,12 @@
typealias JArrayTypeName = com.squareup.javapoet.ArrayTypeName
// TODO(b/127483380): Recycle to room-compiler?
-val L = "\$L"
-val T = "\$T"
-val N = "\$N"
-val S = "\$S"
-val W = "\$W"
+internal val L = "\$L"
+internal val T = "\$T"
+internal val N = "\$N"
+internal val S = "\$S"
+internal val W = "\$W"
// TODO(b/247247366): Temporary migration API, delete me plz!
+fun JTypeName.toXTypeName() = XTypeName(this, this.toKTypeName(), XNullability.NONNULL)
fun JClassName.toXClassName() = XClassName(this, this.toKClassName(), XNullability.NONNULL)
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XCodeBlock.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XCodeBlock.kt
index 4b16c2b6..c681bed 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XCodeBlock.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XCodeBlock.kt
@@ -31,11 +31,15 @@
fun addLocalVariable(
name: String,
- type: XTypeName,
+ typeName: XTypeName,
isMutable: Boolean = false,
- assignExpr: XCodeBlock
+ assignExpr: XCodeBlock? = null
): Builder
+ fun beginControlFlow(controlFlow: String, vararg args: Any?): Builder
+ fun nextControlFlow(controlFlow: String, vararg args: Any?): Builder
+ fun endControlFlow(): Builder
+
fun build(): XCodeBlock
companion object {
@@ -68,5 +72,45 @@
fun of(language: CodeLanguage, format: String, vararg args: Any?): XCodeBlock {
return builder(language).add(format, *args).build()
}
+
+ /**
+ * Convenience code block of a new instantiation expression.
+ *
+ * Shouldn't contain parenthesis.
+ */
+ fun ofNewInstance(
+ language: CodeLanguage,
+ typeName: XTypeName,
+ argsFormat: String = "",
+ vararg args: Any?
+ ): XCodeBlock {
+ return builder(language).apply {
+ val newKeyword = when (language) {
+ CodeLanguage.JAVA -> "new "
+ CodeLanguage.KOTLIN -> ""
+ }
+ add("$newKeyword%T($argsFormat)", typeName, *args)
+ }.build()
+ }
+
+ /**
+ * Convenience code block of an unsafe cast expression.
+ */
+ fun ofCast(
+ language: CodeLanguage,
+ typeName: XTypeName,
+ expressionBlock: XCodeBlock
+ ): XCodeBlock {
+ return builder(language).apply {
+ when (language) {
+ CodeLanguage.JAVA -> {
+ add("(%T) (%L)", typeName, expressionBlock)
+ }
+ CodeLanguage.KOTLIN -> {
+ add("(%L) as %T", expressionBlock, typeName)
+ }
+ }
+ }.build()
+ }
}
}
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt
index 5eae6bfc..67c01fc 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XTypeName.kt
@@ -39,6 +39,8 @@
internal open val kotlin: KTypeName,
internal val nullability: XNullability
) {
+ val isPrimitive: Boolean
+ get() = java.isPrimitive
override fun equals(other: Any?): Boolean {
if (this === other) return true
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaCodeBlock.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaCodeBlock.kt
index a5e9cff..937afb5 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaCodeBlock.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaCodeBlock.kt
@@ -50,13 +50,38 @@
override fun addLocalVariable(
name: String,
- type: XTypeName,
+ typeName: XTypeName,
isMutable: Boolean,
- assignExpr: XCodeBlock
+ assignExpr: XCodeBlock?
) = apply {
- require(assignExpr is JavaCodeBlock)
- val finalKeyword = if (isMutable) "final " else ""
- actual.addStatement("$finalKeyword\$T \$L = \$L", type, name, assignExpr.actual)
+ val finalKeyword = if (isMutable) "" else "final "
+ if (assignExpr != null) {
+ require(assignExpr is JavaCodeBlock)
+ actual.addStatement(
+ "$finalKeyword\$T \$L = \$L",
+ typeName.java,
+ name,
+ assignExpr.actual
+ )
+ } else {
+ actual.addStatement("$finalKeyword\$T \$L", typeName.java, name)
+ }
+ }
+
+ override fun beginControlFlow(controlFlow: String, vararg args: Any?) = apply {
+ val processedControlFlow = processFormatString(controlFlow)
+ val processedArgs = processArgs(args)
+ actual.beginControlFlow(processedControlFlow, *processedArgs)
+ }
+
+ override fun nextControlFlow(controlFlow: String, vararg args: Any?) = apply {
+ val processedControlFlow = processFormatString(controlFlow)
+ val processedArgs = processArgs(args)
+ actual.nextControlFlow(processedControlFlow, *processedArgs)
+ }
+
+ override fun endControlFlow() = apply {
+ actual.endControlFlow()
}
override fun build(): XCodeBlock {
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinCodeBlock.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinCodeBlock.kt
index ede67d2..1daab89 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinCodeBlock.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinCodeBlock.kt
@@ -39,37 +39,70 @@
}
override fun add(format: String, vararg args: Any?) = apply {
- // No need to process 'format' since we use '%' as placeholders.
+ val processedFormat = processFormatString(format)
val processedArgs = processArgs(args)
- actual.add(format, *processedArgs)
+ actual.add(processedFormat, *processedArgs)
}
override fun addStatement(format: String, vararg args: Any?) = apply {
- // No need to process 'format' since we use '%' as placeholders.
+ val processedFormat = processFormatString(format)
val processedArgs = processArgs(args)
- actual.addStatement(format, *processedArgs)
+ actual.addStatement(processedFormat, *processedArgs)
}
override fun addLocalVariable(
name: String,
- type: XTypeName,
+ typeName: XTypeName,
isMutable: Boolean,
- assignExpr: XCodeBlock
+ assignExpr: XCodeBlock?
) = apply {
- require(assignExpr is KotlinCodeBlock)
val varOrVal = if (isMutable) "var" else "val"
- actual.addStatement(
- "$varOrVal %L: %T = %L",
- type.kotlin,
- name,
- assignExpr.actual
- )
+ if (assignExpr != null) {
+ require(assignExpr is KotlinCodeBlock)
+ actual.addStatement(
+ "$varOrVal %L: %T = %L",
+ name,
+ typeName.kotlin,
+ assignExpr.actual
+ )
+ } else {
+ actual.addStatement(
+ "$varOrVal %L: %T",
+ name,
+ typeName.kotlin,
+ )
+ }
+ }
+
+ override fun beginControlFlow(controlFlow: String, vararg args: Any?) = apply {
+ val processedControlFlow = processFormatString(controlFlow)
+ val processedArgs = processArgs(args)
+ actual.beginControlFlow(processedControlFlow, *processedArgs)
+ }
+
+ override fun nextControlFlow(controlFlow: String, vararg args: Any?) = apply {
+ val processedControlFlow = processFormatString(controlFlow)
+ val processedArgs = processArgs(args)
+ actual.nextControlFlow(processedControlFlow, *processedArgs)
+ }
+
+ override fun endControlFlow() = apply {
+ actual.endControlFlow()
}
override fun build(): XCodeBlock {
return KotlinCodeBlock(actual.build())
}
+ // No need to really process 'format' since we use '%' as placeholders, but check for
+ // JavaPoet placeholders to hunt down bad migrations to XPoet.
+ private fun processFormatString(format: String): String {
+ JAVA_POET_PLACEHOLDER_REGEX.find(format)?.let {
+ error("Bad JavaPoet placeholder in XPoet at range ${it.range} of input: '$format'")
+ }
+ return format
+ }
+
// Unwraps room.compiler.codegen types to their KotlinPoet actual
// TODO(b/247242375): Consider improving by wrapping args.
private fun processArgs(args: Array<out Any?>): Array<Any?> {
@@ -88,4 +121,9 @@
}
}
}
+
+ companion object {
+ private val JAVA_POET_PLACEHOLDER_REGEX =
+ "(\\\$L)|(\\\$T)|(\\\$N)|(\\\$S)|(\\\$W)".toRegex()
+ }
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
index ff411fc..1f71ce4 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
@@ -16,6 +16,7 @@
package androidx.room.compiler.processing
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.processing.javac.JavacProcessingEnv
import androidx.room.compiler.processing.ksp.KspProcessingEnv
import com.google.devtools.ksp.processing.CodeGenerator
@@ -112,6 +113,16 @@
"cannot find required type $typeName"
}
+ fun requireType(typeName: XTypeName): XType {
+ if (typeName.isPrimitive) {
+ return requireType(typeName.java)
+ }
+ return when (backend) {
+ Backend.JAVAC -> requireType(typeName.java)
+ Backend.KSP -> requireType(typeName.kotlin.toString())
+ }
+ }
+
fun requireType(klass: KClass<*>) = requireType(klass.java.canonicalName!!)
fun findType(typeName: TypeName): XType? {
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
index daad3ba..4e4fe97 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
@@ -17,6 +17,8 @@
package androidx.room.compiler.processing
import androidx.room.compiler.codegen.XClassName
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.asClassName
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.runProcessorTest
import com.google.common.truth.Truth.assertThat
@@ -283,6 +285,35 @@
}
}
+ @Test
+ fun requireTypeWithXTypeName() {
+ runProcessorTest { invocation ->
+ invocation.processingEnv.requireType(String::class.asClassName()).let {
+ val name = it.typeElement!!.qualifiedName
+ if (invocation.isKsp) {
+ assertThat(name).isEqualTo("kotlin.String")
+ } else {
+ assertThat(name).isEqualTo("java.lang.String")
+ }
+ }
+ invocation.processingEnv.requireType(Int::class.asClassName()).let {
+ val name = it.typeElement!!.qualifiedName
+ if (invocation.isKsp) {
+ assertThat(name).isEqualTo("kotlin.Int")
+ } else {
+ assertThat(name).isEqualTo("java.lang.Integer")
+ }
+ }
+ invocation.processingEnv.requireType(XTypeName.PRIMITIVE_INT).let {
+ assertThat(it.typeElement).isNull() // No element is an indicator of primitive type
+ assertThat(it.asTypeName().java.toString()).isEqualTo("int")
+ if (invocation.isKsp) {
+ assertThat(it.asTypeName().kotlin.toString()).isEqualTo("kotlin.Int")
+ }
+ }
+ }
+ }
+
companion object {
val PRIMITIVE_TYPES = listOf(
TypeName.BOOLEAN,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
index a93964d..dbabd96 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
@@ -16,6 +16,7 @@
package androidx.room.ext
+import androidx.room.compiler.codegen.XClassName
import com.squareup.javapoet.ArrayTypeName
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.CodeBlock
@@ -132,7 +133,7 @@
}
object AndroidTypeNames {
- val CURSOR: ClassName = ClassName.get("android.database", "Cursor")
+ val CURSOR: XClassName = XClassName.get("android.database", "Cursor")
val BUILD: ClassName = ClassName.get("android.os", "Build")
val CANCELLATION_SIGNAL: ClassName = ClassName.get("android.os", "CancellationSignal")
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
index 473928d..52f0e4a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -319,12 +319,14 @@
.filter { it.value.size > 1 } // get the ones with duplicate names
.forEach {
// do not report duplicates from the same entity
- if (it.value.distinctBy { it.second.typeName }.size > 1) {
+ if (it.value.distinctBy { it.second.typeName.toJavaPoet() }.size > 1) {
context.logger.e(
element,
ProcessorErrors.duplicateIndexInDatabase(
it.key,
- it.value.map { "${it.second.typeName} > ${it.first}" }
+ it.value.map {
+ "${it.second.typeName.toJavaPoet()} > ${it.first}"
+ }
)
)
}
@@ -336,7 +338,7 @@
daoMethods: List<DaoMethod>,
entities: List<Entity>
) {
- val entityTypeNames = entities.map { it.typeName }.toSet()
+ val entityTypeNames = entities.map { it.typeName.toJavaPoet() }.toSet()
daoMethods.groupBy { it.dao.typeName }
.forEach {
if (it.value.size > 1) {
@@ -391,10 +393,18 @@
views: List<DatabaseView>
) {
val entitiesInfo = entities.map {
- Triple(it.tableName.lowercase(Locale.US), it.typeName.toString(), it.element)
+ Triple(
+ it.tableName.lowercase(Locale.US),
+ it.typeName.toJavaPoet().toString(),
+ it.element
+ )
}
val viewsInfo = views.map {
- Triple(it.viewName.lowercase(Locale.US), it.typeName.toString(), it.element)
+ Triple(
+ it.viewName.lowercase(Locale.US),
+ it.typeName.toJavaPoet().toString(),
+ it.element
+ )
}
(entitiesInfo + viewsInfo)
.groupBy { (name, _, _) -> name }
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
index 51956a5..f9a26ea 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
@@ -18,10 +18,10 @@
import androidx.room.DatabaseView
import androidx.room.Entity
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.processing.XTypeElement
import androidx.room.vo.EntityOrView
import androidx.room.vo.Fields
-import com.squareup.javapoet.TypeName
interface EntityOrViewProcessor {
fun process(): EntityOrView
@@ -51,8 +51,8 @@
override val fields: Fields = Fields()
override val tableName: String
get() = typeName.toString()
- override val typeName: TypeName
- get() = element.type.typeName
+ override val typeName: XTypeName
+ get() = element.type.asTypeName()
}
}
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt
index e05cf9e..f75be97 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt
@@ -20,6 +20,7 @@
import androidx.room.Insert
import androidx.room.OnConflictStrategy
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.vo.InsertionMethod
@@ -63,7 +64,7 @@
entity.primaryKey.autoGenerateId || !missingPrimaryKeys,
executableElement,
ProcessorErrors.missingPrimaryKeysInPartialEntityForInsert(
- partialEntityName = pojo.typeName.toString(),
+ partialEntityName = pojo.typeName.toJavaPoet().toString(),
primaryKeyNames = entity.primaryKey.fields.columnNames
)
)
@@ -78,7 +79,7 @@
missingRequiredFields.isEmpty(),
executableElement,
ProcessorErrors.missingRequiredColumnsInPartialEntity(
- partialEntityName = pojo.typeName.toString(),
+ partialEntityName = pojo.typeName.toJavaPoet().toString(),
missingColumnNames = missingRequiredFields.map { it.columnName }
)
)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
index 30f1f9c..90189d4 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -22,6 +22,7 @@
import androidx.room.Junction
import androidx.room.PrimaryKey
import androidx.room.Relation
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XExecutableElement
import androidx.room.compiler.processing.XFieldElement
import androidx.room.compiler.processing.XType
@@ -511,7 +512,7 @@
context.logger.e(
relationElement,
ProcessorErrors.relationCannotFindEntityField(
- entityName = entity.typeName.toString(),
+ entityName = entity.typeName.toJavaPoet().toString(),
columnName = annotation.value.entityColumn,
availableColumns = entity.columnNames
)
@@ -557,7 +558,7 @@
context.logger.w(
Warning.MISSING_INDEX_ON_JUNCTION, field.element,
ProcessorErrors.junctionColumnWithoutIndex(
- entityName = entityOrView.typeName.toString(),
+ entityName = entityOrView.typeName.toJavaPoet().toString(),
columnName = columnName
)
)
@@ -577,7 +578,7 @@
context.logger.e(
junctionElement,
ProcessorErrors.relationCannotFindJunctionParentField(
- entityName = entityOrView.typeName.toString(),
+ entityName = entityOrView.typeName.toJavaPoet().toString(),
columnName = junctionParentColumn,
availableColumns = entityOrView.columnNames
)
@@ -596,7 +597,7 @@
context.logger.e(
junctionElement,
ProcessorErrors.relationCannotFindJunctionEntityField(
- entityName = entityOrView.typeName.toString(),
+ entityName = entityOrView.typeName.toJavaPoet().toString(),
columnName = junctionEntityColumn,
availableColumns = entityOrView.columnNames
)
@@ -653,7 +654,7 @@
context.logger.e(
relationElement,
ProcessorErrors.relationBadProject(
- entity.typeName.toString(),
+ entity.typeName.toJavaPoet().toString(),
missingColumns, entity.columnNames
)
)
@@ -676,7 +677,7 @@
entityField: Field,
typeArgElement: XTypeElement
): List<String> {
- return if (inferEntity || typeArg.typeName == entity.typeName) {
+ return if (inferEntity || typeArg.typeName == entity.typeName.toJavaPoet()) {
entity.columnNames
} else {
val columnAdapter = context.typeAdapterStore.findCursorValueReader(typeArg, null)
@@ -772,7 +773,7 @@
fieldName = field.name,
ownerType = element.type.typeName,
getterType = field.getter.type.typeName,
- fieldType = field.typeName
+ fieldType = field.typeName.toJavaPoet()
)
)
field.statementBinder = context.typeAdapterStore.findStatementValueBinder(
@@ -848,7 +849,7 @@
fieldName = field.name,
ownerType = element.type.typeName,
setterType = field.setter.type.typeName,
- fieldType = field.typeName
+ fieldType = field.typeName.toJavaPoet()
)
)
field.cursorValueReader = context.typeAdapterStore.findCursorValueReader(
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
index a3f5b03..7c6a68e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
@@ -19,6 +19,7 @@
import androidx.room.Query
import androidx.room.SkipQueryVerification
import androidx.room.Transaction
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XAnnotationBox
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
@@ -250,10 +251,10 @@
val pojoMappings = mappings.filterIsInstance<PojoRowAdapter.PojoMapping>()
val pojoUnusedFields = pojoMappings
.filter { it.unusedFields.isNotEmpty() }
- .associate { it.pojo.typeName to it.unusedFields }
+ .associate { it.pojo.typeName.toJavaPoet() to it.unusedFields }
if (unusedColumns.isNotEmpty() || pojoUnusedFields.isNotEmpty()) {
val warningMsg = ProcessorErrors.cursorPojoMismatch(
- pojoTypeNames = pojoMappings.map { it.pojo.typeName },
+ pojoTypeNames = pojoMappings.map { it.pojo.typeName.toJavaPoet() },
unusedColumns = unusedColumns,
allColumns = columnNames,
pojoUnusedFields = pojoUnusedFields,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt
index 879a7b3..8d558de 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt
@@ -15,11 +15,12 @@
*/
package androidx.room.processor
-import androidx.room.ext.isEntityElement
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XAnnotationBox
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
+import androidx.room.ext.isEntityElement
import androidx.room.vo.Entity
import androidx.room.vo.Pojo
import androidx.room.vo.ShortcutEntity
@@ -138,7 +139,7 @@
context.logger.e(
it.element,
ProcessorErrors.cannotFindAsEntityField(
- targetEntity.typeName.toString()
+ targetEntity.typeName.toJavaPoet().toString()
)
)
@@ -156,7 +157,7 @@
context.logger.e(
executableElement,
ProcessorErrors.noColumnsInPartialEntity(
- partialEntityName = pojo.typeName.toString()
+ partialEntityName = pojo.typeName.toJavaPoet().toString()
)
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
index 1c17c65..1edbcda 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
@@ -16,11 +16,12 @@
package androidx.room.processor
-import androidx.room.parser.SQLTypeAffinity
-import androidx.room.parser.SqlParser
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
import androidx.room.ext.isNotNone
+import androidx.room.parser.SQLTypeAffinity
+import androidx.room.parser.SqlParser
import androidx.room.processor.EntityProcessor.Companion.createIndexName
import androidx.room.processor.EntityProcessor.Companion.extractForeignKeys
import androidx.room.processor.EntityProcessor.Companion.extractIndices
@@ -514,7 +515,7 @@
Warning.INDEX_FROM_EMBEDDED_ENTITY_IS_DROPPED,
embedded.field.element,
ProcessorErrors.droppedEmbeddedIndex(
- entityName = embedded.pojo.typeName.toString(),
+ entityName = embedded.pojo.typeName.toJavaPoet().toString(),
fieldPath = embedded.field.getPath(),
grandParent = element.qualifiedName
)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt
index ff259c2..3b442a4 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt
@@ -18,6 +18,7 @@
import androidx.room.OnConflictStrategy
import androidx.room.Update
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.vo.UpdateMethod
@@ -51,7 +52,7 @@
context.checker.check(
missingPrimaryKeys.isEmpty(), executableElement,
ProcessorErrors.missingPrimaryKeysInPartialEntityForUpdate(
- partialEntityName = pojo.typeName.toString(),
+ partialEntityName = pojo.typeName.toJavaPoet().toString(),
primaryKeyNames = missingPrimaryKeys.map { it.columnName }
)
)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/UpsertionMethodProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/UpsertionMethodProcessor.kt
index 4e07a9c..4098bb4 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/UpsertionMethodProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/UpsertionMethodProcessor.kt
@@ -17,6 +17,7 @@
package androidx.room.processor
import androidx.room.Upsert
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.vo.UpsertionMethod
@@ -55,7 +56,7 @@
entity.primaryKey.autoGenerateId || !missingPrimaryKeys,
executableElement,
ProcessorErrors.missingPrimaryKeysInPartialEntityForUpsert(
- partialEntityName = pojo.typeName.toString(),
+ partialEntityName = pojo.typeName.toJavaPoet().toString(),
primaryKeyNames = entity.primaryKey.fields.columnNames
)
)
@@ -70,7 +71,7 @@
missingRequiredFields.isEmpty(),
executableElement,
ProcessorErrors.missingRequiredColumnsInPartialEntity(
- partialEntityName = pojo.typeName.toString(),
+ partialEntityName = pojo.typeName.toJavaPoet().toString(),
missingColumnNames = missingRequiredFields.map { it.columnName }
)
)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt
index 0bf6717..c9ffebb 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt
@@ -28,7 +28,8 @@
class CodeGenScope(
val writer: TypeWriter
) {
- val builder by lazy { XCodeBlock.builder(writer.codeLanguage) }
+ val language = writer.codeLanguage
+ val builder by lazy { XCodeBlock.builder(language) }
private val tmpVarIndices = mutableMapOf<String, Int>()
companion object {
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/CursorQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/CursorQueryResultBinderProvider.kt
index fb889c4..009c521 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/CursorQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/CursorQueryResultBinderProvider.kt
@@ -16,8 +16,9 @@
package androidx.room.solver.binderprovider
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XType
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
import androidx.room.solver.QueryResultBinderProvider
@@ -35,5 +36,5 @@
}
override fun matches(declared: XType): Boolean =
- declared.typeArguments.isEmpty() && declared.typeName == AndroidTypeNames.CURSOR
+ declared.typeArguments.isEmpty() && declared.typeName == CURSOR.toJavaPoet()
}
\ No newline at end of file
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt
index 887fec8..903180c 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt
@@ -16,7 +16,8 @@
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.L
import androidx.room.ext.N
import androidx.room.ext.RoomTypeNames
@@ -61,7 +62,7 @@
builder.apply {
addStatement(
"final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
+ CURSOR.toJavaPoet(),
cursorVar,
RoomTypeNames.DB_UTIL,
dbField,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
index 844aa5d..74142bc 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
@@ -16,14 +16,16 @@
package androidx.room.solver.query.result
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.compiler.processing.XType
import androidx.room.ext.AndroidTypeNames
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.L
import androidx.room.ext.N
import androidx.room.ext.RoomCoroutinesTypeNames
import androidx.room.ext.RoomTypeNames
import androidx.room.ext.T
-import androidx.room.compiler.processing.XType
import androidx.room.solver.CodeGenScope
import com.squareup.javapoet.FieldSpec
import com.squareup.javapoet.MethodSpec
@@ -98,7 +100,7 @@
builder.apply {
addStatement(
"final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
+ CURSOR.toJavaPoet(),
cursorVar,
RoomTypeNames.DB_UTIL,
dbField,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt
index 38d5132..48fed6b 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt
@@ -16,7 +16,8 @@
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.L
import androidx.room.ext.N
import androidx.room.ext.T
@@ -40,7 +41,7 @@
transactionWrapper?.beginTransactionWithControlFlow()
val resultName = scope.getTmpVar("_tmpResult")
builder.addStatement(
- "final $T $L = $N.query($L)", AndroidTypeNames.CURSOR, resultName,
+ "final $T $L = $N.query($L)", CURSOR.toJavaPoet(), resultName,
dbField, roomSQLiteQueryVar
)
transactionWrapper?.commitTransaction()
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt
index 5b79e64..258ddf2 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt
@@ -16,7 +16,8 @@
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.L
import androidx.room.ext.N
@@ -88,7 +89,7 @@
)
scope.builder().addStatement(
"final $T $N = $T.wrapMappedColumns($N, $L, $L)",
- AndroidTypeNames.CURSOR,
+ CURSOR.toJavaPoet(),
cursorDelegateVarName,
RoomTypeNames.CURSOR_UTIL,
cursorVarName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt
index 89e143e..d9abfaf 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt
@@ -15,7 +15,8 @@
*/
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.L
import androidx.room.ext.N
import androidx.room.ext.RoomTypeNames
@@ -50,7 +51,7 @@
val cursorVar = scope.getTmpVar("_cursor")
addStatement(
"final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
+ CURSOR.toJavaPoet(),
cursorVar,
RoomTypeNames.DB_UTIL,
dbField,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt
index e88f895..5daba2a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt
@@ -16,7 +16,8 @@
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.L
import androidx.room.ext.N
@@ -75,7 +76,7 @@
addAnnotation(Override::class.java)
addModifiers(Modifier.PROTECTED)
returns(ParameterizedTypeName.get(CommonTypeNames.LIST, itemTypeName))
- val cursorParam = ParameterSpec.builder(AndroidTypeNames.CURSOR, "cursor")
+ val cursorParam = ParameterSpec.builder(CURSOR.toJavaPoet(), "cursor")
.build()
addParameter(cursorParam)
val resultVar = scope.getTmpVar("_result")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultimapQueryResultAdapter.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultimapQueryResultAdapter.kt
index fb94243..3b2c0f3 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultimapQueryResultAdapter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultimapQueryResultAdapter.kt
@@ -16,6 +16,7 @@
package androidx.room.solver.query.result
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XType
import androidx.room.ext.L
import androidx.room.ext.W
@@ -24,6 +25,9 @@
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
import androidx.room.processor.ProcessorErrors
+import androidx.room.processor.ProcessorErrors.AmbiguousColumnLocation.ENTITY
+import androidx.room.processor.ProcessorErrors.AmbiguousColumnLocation.MAP_INFO
+import androidx.room.processor.ProcessorErrors.AmbiguousColumnLocation.POJO
import androidx.room.solver.types.CursorValueReader
import androidx.room.vo.ColumnIndexVar
import androidx.room.vo.MapInfo
@@ -72,11 +76,11 @@
val ambiguousColumnName = it.usedColumns.first()
val (location, objectTypeName) = when (it) {
is SingleNamedColumnRowAdapter.SingleNamedColumnRowMapping ->
- ProcessorErrors.AmbiguousColumnLocation.MAP_INFO to null
+ MAP_INFO to null
is PojoRowAdapter.PojoMapping ->
- ProcessorErrors.AmbiguousColumnLocation.POJO to it.pojo.typeName
+ POJO to it.pojo.typeName.toJavaPoet()
is EntityRowAdapter.EntityMapping ->
- ProcessorErrors.AmbiguousColumnLocation.ENTITY to it.entity.typeName
+ ENTITY to it.entity.typeName.toJavaPoet()
else -> error("Unknown mapping type: $it")
}
context.logger.w(
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
index ffff340f..14b74ce 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
@@ -16,8 +16,18 @@
package androidx.room.solver.query.result
+import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.codegen.VisibilityModifier
+import androidx.room.compiler.codegen.XClassName
+import androidx.room.compiler.codegen.XFunSpec
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.XTypeSpec
+import androidx.room.compiler.codegen.addOriginatingElement
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XType
+import androidx.room.ext.AndroidTypeNames
import androidx.room.ext.L
+import androidx.room.ext.T
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
import androidx.room.processor.ProcessorErrors
@@ -29,6 +39,8 @@
import androidx.room.vo.Pojo
import androidx.room.vo.RelationCollector
import androidx.room.writer.FieldReadWriteWriter
+import androidx.room.writer.TypeWriter
+import kotlin.math.abs
/**
* Creates the entity from the given info.
@@ -36,9 +48,9 @@
* The info comes from the query processor so we know about the order of columns in the result etc.
*/
class PojoRowAdapter(
- context: Context,
+ private val context: Context,
private val info: QueryResultInfo?,
- query: ParsedQuery?,
+ private val query: ParsedQuery?,
val pojo: Pojo,
out: XType
) : QueryMappedRowAdapter(out) {
@@ -69,7 +81,7 @@
if (nonNulls.isNotEmpty()) {
context.logger.e(
ProcessorErrors.pojoMissingNonNull(
- pojoTypeName = pojo.typeName,
+ pojoTypeName = pojo.typeName.toJavaPoet(),
missingPojoFields = nonNulls.map { it.name },
allQueryColumns = info.columns.map { it.name }
)
@@ -134,7 +146,7 @@
}
override fun convert(outVarName: String, cursorVarName: String, scope: CodeGenScope) {
- scope.builder().apply {
+ fun doReadFromCursor(outVarName: String, scope: CodeGenScope) {
FieldReadWriteWriter.readFromCursor(
outVar = outVarName,
outPojo = pojo,
@@ -144,6 +156,52 @@
scope = scope
)
}
+ // TODO(b/127483380): Inline in code gen scope once Kotlin code gen progresses.
+ if (relationCollectors.isEmpty() && context.codeLanguage == CodeLanguage.KOTLIN) {
+ // The name of the class is based on the query, possible to be collisions, but good,
+ // enough for now.
+ val nameHash = abs(query?.original?.hashCode() ?: out.asTypeName().hashCode())
+ val className = XClassName.get("androidx.room.temp", "PojoRowAdapter_$nameHash")
+ object : TypeWriter(CodeLanguage.KOTLIN) {
+ override fun createTypeSpecBuilder(): XTypeSpec.Builder {
+ val readFunction = XFunSpec.builder(
+ CodeLanguage.KOTLIN,
+ "readFromCursor",
+ VisibilityModifier.PUBLIC
+ )
+ .returns(out.asTypeName())
+ .addParameter(AndroidTypeNames.CURSOR, cursorVarName)
+ .apply {
+ fieldsWithIndices.forEach {
+ addParameter(XTypeName.PRIMITIVE_INT, it.indexVar)
+ }
+ }
+ .addCode(
+ CodeGenScope(this).apply {
+ builder.addLocalVariable(outVarName, out.asTypeName())
+ doReadFromCursor(outVarName, this)
+ builder.addStatement("return %L", outVarName)
+ }.generate()
+ )
+ .build()
+ return XTypeSpec.classBuilder(codeLanguage, className)
+ .addOriginatingElement(pojo.element)
+ .addFunction(readFunction)
+ }
+ }.write(context.processingEnv)
+ scope.builder().apply {
+ addStatement("$L = new $T().readFromCursor($L, $L)",
+ outVarName,
+ className.toJavaPoet(),
+ cursorVarName,
+ fieldsWithIndices.joinToString { it.indexVar }
+ )
+ }
+ } else {
+ scope.builder().apply {
+ doReadFromCursor(outVarName, scope)
+ }
+ }
}
override fun getDefaultIndexAdapter() = indexAdapter
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt
index 6e92eea..9c8df06 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt
@@ -16,7 +16,8 @@
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.L
import androidx.room.ext.N
@@ -71,7 +72,7 @@
addAnnotation(Override::class.java)
addModifiers(Modifier.PROTECTED)
returns(ParameterizedTypeName.get(CommonTypeNames.LIST, itemTypeName))
- val cursorParam = ParameterSpec.builder(AndroidTypeNames.CURSOR, "cursor")
+ val cursorParam = ParameterSpec.builder(CURSOR.toJavaPoet(), "cursor")
.build()
addParameter(cursorParam)
val resultVar = scope.getTmpVar("_res")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
index 5d96bb9..919397e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -16,14 +16,15 @@
package androidx.room.solver.query.result
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.compiler.processing.XType
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.L
import androidx.room.ext.N
import androidx.room.ext.RoomTypeNames
import androidx.room.ext.S
import androidx.room.ext.T
-import androidx.room.compiler.processing.XType
import androidx.room.solver.CodeGenScope
import androidx.room.solver.RxType
import com.squareup.javapoet.FieldSpec
@@ -84,7 +85,7 @@
val cursorVar = scope.getTmpVar("_cursor")
addStatement(
"final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
+ CURSOR.toJavaPoet(),
cursorVar,
RoomTypeNames.DB_UTIL,
dbField,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt
index 9700977..4f4e610 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt
@@ -16,71 +16,77 @@
package androidx.room.solver.types
+import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_BYTE
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_CHAR
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_DOUBLE
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_FLOAT
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_INT
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_LONG
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_SHORT
import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XType
-import androidx.room.ext.L
-import androidx.room.ext.capitalize
import androidx.room.parser.SQLTypeAffinity
-import androidx.room.parser.SQLTypeAffinity.REAL
import androidx.room.solver.CodeGenScope
-import com.squareup.javapoet.TypeName.BYTE
-import com.squareup.javapoet.TypeName.CHAR
-import com.squareup.javapoet.TypeName.DOUBLE
-import com.squareup.javapoet.TypeName.FLOAT
-import com.squareup.javapoet.TypeName.INT
-import com.squareup.javapoet.TypeName.LONG
-import com.squareup.javapoet.TypeName.SHORT
-import java.util.Locale
/**
* Adapters for all primitives that has direct cursor mappings.
*/
-open class PrimitiveColumnTypeAdapter(
+class PrimitiveColumnTypeAdapter(
out: XType,
- val cursorGetter: String,
- val stmtSetter: String,
- typeAffinity: SQLTypeAffinity
+ typeAffinity: SQLTypeAffinity,
+ val primitive: Primitive,
) : ColumnTypeAdapter(out, typeAffinity) {
- val cast = if (cursorGetter == "get${out.typeName.toString().capitalize(Locale.US)}")
- ""
- else
- "(${out.typeName}) "
companion object {
+
+ enum class Primitive(
+ val typeName: XTypeName,
+ val cursorGetter: String,
+ val stmtSetter: String,
+ ) {
+ INT(PRIMITIVE_INT, "getInt", "bindLong"),
+ SHORT(PRIMITIVE_SHORT, "getShort", "bindLong"),
+ BYTE(PRIMITIVE_BYTE, "getShort", "bindLong"),
+ LONG(PRIMITIVE_LONG, "getLong", "bindLong"),
+ CHAR(PRIMITIVE_CHAR, "getInt", "bindLong"),
+ FLOAT(PRIMITIVE_FLOAT, "getFloat", "bindDouble"),
+ DOUBLE(PRIMITIVE_DOUBLE, "getDouble", "bindDouble"),
+ }
+
+ private fun getAffinity(primitive: Primitive) = when (primitive) {
+ Primitive.INT, Primitive.SHORT, Primitive.BYTE, Primitive.LONG, Primitive.CHAR ->
+ SQLTypeAffinity.INTEGER
+ Primitive.FLOAT, Primitive.DOUBLE ->
+ SQLTypeAffinity.REAL
+ }
+
fun createPrimitiveAdapters(
processingEnvironment: XProcessingEnv
): List<PrimitiveColumnTypeAdapter> {
- return listOf(
- Triple(INT, "getInt", "bindLong"),
- Triple(SHORT, "getShort", "bindLong"),
- Triple(BYTE, "getShort", "bindLong"),
- Triple(LONG, "getLong", "bindLong"),
- Triple(CHAR, "getInt", "bindLong"),
- Triple(FLOAT, "getFloat", "bindDouble"),
- Triple(DOUBLE, "getDouble", "bindDouble")
- ).map {
+ return Primitive.values().map {
PrimitiveColumnTypeAdapter(
- out = processingEnvironment.requireType(it.first),
- cursorGetter = it.second,
- stmtSetter = it.third,
- typeAffinity = when (it.first) {
- INT, SHORT, BYTE, LONG, CHAR -> SQLTypeAffinity.INTEGER
- FLOAT, DOUBLE -> REAL
- else -> throw IllegalArgumentException("invalid type")
- }
+ out = processingEnvironment.requireType(it.typeName),
+ typeAffinity = getAffinity(it),
+ primitive = it
)
}
}
}
+ private val cursorGetter = primitive.cursorGetter
+ private val stmtSetter = primitive.stmtSetter
+
override fun bindToStmt(
stmtName: String,
indexVarName: String,
valueVarName: String,
scope: CodeGenScope
) {
- scope.builder()
- .addStatement("$L.$L($L, $L)", stmtName, stmtSetter, indexVarName, valueVarName)
+ scope.builder
+ .addStatement("%L.%L(%L, %L)", stmtName, stmtSetter, indexVarName, valueVarName)
}
override fun readFromCursor(
@@ -89,10 +95,33 @@
indexVarName: String,
scope: CodeGenScope
) {
- scope.builder()
- .addStatement(
- "$L = $L$L.$L($L)", outVarName, cast, cursorVarName,
- cursorGetter, indexVarName
- )
+ scope.builder.addStatement(
+ "%L = %L",
+ outVarName,
+ XCodeBlock.of(
+ scope.language,
+ "%L.%L(%L)",
+ cursorVarName,
+ cursorGetter,
+ indexVarName
+ ).let {
+ // These primitives don't have an exact cursor getter.
+ val castFunction = when (primitive) {
+ Primitive.BYTE -> "toByte"
+ Primitive.CHAR -> "toChar"
+ else -> null
+ } ?: return@let it
+ when (it.language) {
+ // For Java a cast will suffice
+ CodeLanguage.JAVA -> {
+ XCodeBlock.ofCast(it.language, out.asTypeName(), it)
+ }
+ // For Kotlin a converter function is emitted
+ CodeLanguage.KOTLIN -> {
+ XCodeBlock.of(it.language, "%L.%L()", it, castFunction)
+ }
+ }
+ }
+ )
}
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/Constructor.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
index 566d845..8cba86e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
@@ -16,15 +16,13 @@
package androidx.room.vo
-import androidx.room.ext.L
-import androidx.room.ext.T
+import androidx.room.compiler.codegen.XCodeBlock
import androidx.room.compiler.processing.XExecutableElement
import androidx.room.compiler.processing.isConstructor
import androidx.room.compiler.processing.isMethod
-import com.squareup.javapoet.CodeBlock
/**
- * For each Entity / Pojo we process has a constructor. It might be the empty constructor or a
+ * Each Entity / Pojo we process has a constructor. It might be the empty constructor or a
* constructor with fields. It can also be a static factory method, such as in the case of an
* AutoValue Pojo.
*/
@@ -40,21 +38,28 @@
}
}
- fun writeConstructor(outVar: String, args: String, builder: CodeBlock.Builder) {
+ fun writeConstructor(outVar: String, args: String, builder: XCodeBlock.Builder) {
when {
element.isConstructor() -> {
builder.addStatement(
- "$L = new $T($L)", outVar,
- element.enclosingElement.className, args
+ "%L = %L",
+ outVar,
+ XCodeBlock.ofNewInstance(
+ builder.language,
+ element.enclosingElement.asClassName(),
+ args
+ )
)
}
element.isMethod() -> {
// TODO when we generate Kotlin code, we need to handle not having enclosing
// elements.
builder.addStatement(
- "$L = $T.$L($L)", outVar,
- element.enclosingElement.className,
- element.jvmName, args
+ "%L = %T.%L(%L)",
+ outVar,
+ element.enclosingElement.asClassName(),
+ element.jvmName,
+ args
)
}
else -> throw IllegalStateException("Invalid constructor kind ${element.kindName()}")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/EntityOrView.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/EntityOrView.kt
index acfe6a1..b52fa68 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/EntityOrView.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/EntityOrView.kt
@@ -16,7 +16,7 @@
package androidx.room.vo
-import com.squareup.javapoet.TypeName
+import androidx.room.compiler.codegen.XTypeName
/**
* Common interface between [Entity] and [DatabaseView].
@@ -28,5 +28,5 @@
*/
val tableName: String
- val typeName: TypeName
+ val typeName: XTypeName
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/Field.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/Field.kt
index fc84ff6..f2e9bf4 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/Field.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/Field.kt
@@ -16,6 +16,8 @@
package androidx.room.vo
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XFieldElement
import androidx.room.compiler.processing.XNullability
import androidx.room.compiler.processing.XType
@@ -50,9 +52,10 @@
lateinit var setter: FieldSetter
// binds the field into a statement
var statementBinder: StatementValueBinder? = null
+
// reads this field from a cursor column
var cursorValueReader: CursorValueReader? = null
- val typeName: TypeName by lazy { type.typeName }
+ val typeName: XTypeName by lazy { type.asTypeName() }
override fun getIdKey(): String {
return buildString {
@@ -99,7 +102,10 @@
result.add(name.substring(1).decapitalize(Locale.US))
}
- if (typeName == TypeName.BOOLEAN || typeName == TypeName.BOOLEAN.box()) {
+ if (
+ typeName.toJavaPoet() == TypeName.BOOLEAN ||
+ typeName.toJavaPoet() == TypeName.BOOLEAN.box()
+ ) {
if (name.length > 2 && name.startsWith("is") && name[2].isUpperCase()) {
result.add(name.substring(2).decapitalize(Locale.US))
}
@@ -113,7 +119,10 @@
val getterNameWithVariations by lazy {
nameWithVariations.map { "get${it.capitalize(Locale.US)}" } +
- if (typeName == TypeName.BOOLEAN || typeName == TypeName.BOOLEAN.box()) {
+ if (
+ typeName.toJavaPoet() == TypeName.BOOLEAN ||
+ typeName.toJavaPoet() == TypeName.BOOLEAN.box()
+ ) {
nameWithVariations.flatMap {
listOf("is${it.capitalize(Locale.US)}", "has${it.capitalize(Locale.US)}")
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldGetter.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldGetter.kt
index ae3ce9c..d3a040e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldGetter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldGetter.kt
@@ -16,20 +16,22 @@
package androidx.room.vo
-import androidx.room.ext.L
-import androidx.room.ext.T
+import androidx.room.compiler.codegen.XCodeBlock
import androidx.room.compiler.processing.XType
-import com.squareup.javapoet.CodeBlock
data class FieldGetter(val jvmName: String, val type: XType, val callType: CallType) {
- fun writeGet(ownerVar: String, outVar: String, builder: CodeBlock.Builder) {
+ fun writeGet(ownerVar: String, outVar: String, builder: XCodeBlock.Builder) {
val stmt = when (callType) {
- CallType.FIELD -> "final $T $L = $L.$L"
- CallType.METHOD -> "final $T $L = $L.$L()"
+ CallType.FIELD -> "%L.%L"
+ CallType.METHOD -> "%L.%L()"
CallType.CONSTRUCTOR -> null
}
- stmt?.let {
- builder.addStatement(stmt, type.typeName, outVar, ownerVar, jvmName)
+ if (stmt != null) {
+ builder.addLocalVariable(
+ name = outVar,
+ typeName = type.asTypeName(),
+ assignExpr = XCodeBlock.of(builder.language, stmt, ownerVar, jvmName)
+ )
}
}
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldSetter.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldSetter.kt
index 01a3ba3..a8086bc 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldSetter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/FieldSetter.kt
@@ -16,18 +16,17 @@
package androidx.room.vo
-import androidx.room.ext.L
+import androidx.room.compiler.codegen.XCodeBlock
import androidx.room.compiler.processing.XType
-import com.squareup.javapoet.CodeBlock
data class FieldSetter(val jvmName: String, val type: XType, val callType: CallType) {
- fun writeSet(ownerVar: String, inVar: String, builder: CodeBlock.Builder) {
+ fun writeSet(ownerVar: String, inVar: String, builder: XCodeBlock.Builder) {
val stmt = when (callType) {
- CallType.FIELD -> "$L.$L = $L"
- CallType.METHOD -> "$L.$L($L)"
+ CallType.FIELD -> "%L.%L = %L"
+ CallType.METHOD -> "%L.%L(%L)"
CallType.CONSTRUCTOR -> null
}
- stmt?.let {
+ if (stmt != null) {
builder.addStatement(stmt, ownerVar, jvmName, inVar)
}
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/Pojo.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/Pojo.kt
index b463a7b..25241e9 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/Pojo.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/Pojo.kt
@@ -16,11 +16,11 @@
package androidx.room.vo
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
import androidx.room.processor.DatabaseViewProcessor
import androidx.room.processor.EntityProcessor
-import com.squareup.javapoet.TypeName
/**
* A class is turned into a Pojo if it is used in a query response.
@@ -33,7 +33,7 @@
val relations: List<Relation>,
val constructor: Constructor? = null
) : HasFields {
- val typeName: TypeName by lazy { type.typeName }
+ val typeName: XTypeName by lazy { type.asTypeName() }
override val fields = Fields(fields)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
index c14b90a..00a4ccb 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
@@ -16,6 +16,7 @@
package androidx.room.vo
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XType
import androidx.room.ext.CollectionTypeNames
import androidx.room.ext.CommonTypeNames
@@ -44,8 +45,6 @@
import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeName
import java.nio.ByteBuffer
-import java.util.ArrayList
-import java.util.HashSet
import java.util.Locale
/**
@@ -402,8 +401,8 @@
// Gets the resulting relation type name. (i.e. the Pojo's @Relation field type name.)
private fun relationTypeFor(relation: Relation) =
- if (relation.field.typeName is ParameterizedTypeName) {
- val paramType = relation.field.typeName as ParameterizedTypeName
+ if (relation.field.typeName.toJavaPoet() is ParameterizedTypeName) {
+ val paramType = relation.field.typeName.toJavaPoet() as ParameterizedTypeName
val paramTypeName = if (paramType.rawType == CommonTypeNames.LIST) {
ParameterizedTypeName.get(
ClassName.get(ArrayList::class.java),
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/ShortcutEntity.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/ShortcutEntity.kt
index 01c6e60..a87b33f 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/ShortcutEntity.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/ShortcutEntity.kt
@@ -16,6 +16,8 @@
package androidx.room.vo
+import androidx.room.compiler.codegen.toJavaPoet
+
/**
* Represents a shortcut method parameter entity.
*/
@@ -24,7 +26,7 @@
private val partialEntity: Pojo? // the partial entity
) {
val tableName = entity.tableName
- val entityTypeName = entity.typeName
+ val entityTypeName = entity.typeName.toJavaPoet()
val primaryKey by lazy {
if (partialEntity == null) {
entity.primaryKey
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
index db75984..9898cf0 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
@@ -19,7 +19,6 @@
import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.codegen.VisibilityModifier
import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.apply
import androidx.room.compiler.codegen.XFunSpec
import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
import androidx.room.compiler.codegen.XTypeSpec
@@ -28,11 +27,9 @@
import androidx.room.compiler.processing.XTypeElement
import androidx.room.ext.RoomTypeNames
import androidx.room.ext.SupportDbTypeNames
-import androidx.room.ext.T
import androidx.room.migration.bundle.EntityBundle
import androidx.room.migration.bundle.FtsEntityBundle
import androidx.room.vo.AutoMigration
-import com.squareup.kotlinpoet.javapoet.toKClassName
/**
* Writes the implementation of migrations that were annotated with @AutoMigration.
@@ -63,14 +60,10 @@
name = "callback",
visibility = VisibilityModifier.PRIVATE,
initExpr = if (!autoMigration.isSpecProvided) {
- XCodeBlock.builder(codeLanguage).apply(
- javaCodeBuilder = {
- add("new $T()", autoMigration.specClassName)
- },
- kotlinCodeBuilder = {
- add("%T()", autoMigration.specClassName.toKClassName())
- }
- ).build()
+ XCodeBlock.ofNewInstance(
+ codeLanguage,
+ autoMigration.specClassName.toXClassName()
+ )
} else {
null
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
index 9b465ec..d5ac75a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
@@ -89,7 +89,7 @@
private fun shortcutEntityFieldNamePart(shortcutEntity: ShortcutEntity): String {
return if (shortcutEntity.isPartialEntity) {
- typeNameToFieldName(shortcutEntity.pojo.typeName) + "As" +
+ typeNameToFieldName(shortcutEntity.pojo.typeName.toJavaPoet()) + "As" +
typeNameToFieldName(shortcutEntity.entityTypeName)
} else {
typeNameToFieldName(shortcutEntity.entityTypeName)
@@ -635,11 +635,12 @@
) : SharedFieldSpec(
baseName = "insertionAdapterOf${shortcutEntityFieldNamePart(shortcutEntity)}",
type = ParameterizedTypeName.get(
- RoomTypeNames.INSERTION_ADAPTER, shortcutEntity.pojo.typeName
+ RoomTypeNames.INSERTION_ADAPTER, shortcutEntity.pojo.typeName.toJavaPoet()
)
) {
override fun getUniqueKey(): String {
- return "${shortcutEntity.pojo.typeName}-${shortcutEntity.entityTypeName}$onConflictText"
+ return "${shortcutEntity.pojo.typeName.toJavaPoet()}-" +
+ "${shortcutEntity.entityTypeName}$onConflictText"
}
override fun prepare(writer: TypeWriter, builder: FieldSpec.Builder) {
@@ -654,7 +655,7 @@
) : SharedFieldSpec(
baseName = "${methodPrefix}AdapterOf${shortcutEntityFieldNamePart(shortcutEntity)}",
type = ParameterizedTypeName.get(
- RoomTypeNames.DELETE_OR_UPDATE_ADAPTER, shortcutEntity.pojo.typeName
+ RoomTypeNames.DELETE_OR_UPDATE_ADAPTER, shortcutEntity.pojo.typeName.toJavaPoet()
)
) {
override fun prepare(writer: TypeWriter, builder: FieldSpec.Builder) {
@@ -662,7 +663,7 @@
}
override fun getUniqueKey(): String {
- return "${shortcutEntity.pojo.typeName}-${shortcutEntity.entityTypeName}" +
+ return "${shortcutEntity.pojo.typeName.toJavaPoet()}-${shortcutEntity.entityTypeName}" +
"$methodPrefix$onConflictText"
}
}
@@ -672,11 +673,11 @@
) : SharedFieldSpec(
baseName = "upsertionAdapterOf${shortcutEntityFieldNamePart(shortcutEntity)}",
type = ParameterizedTypeName.get(
- RoomTypeNames.UPSERTION_ADAPTER, shortcutEntity.pojo.typeName
+ RoomTypeNames.UPSERTION_ADAPTER, shortcutEntity.pojo.typeName.toJavaPoet()
)
) {
override fun getUniqueKey(): String {
- return "${shortcutEntity.pojo.typeName}-${shortcutEntity.entityTypeName}"
+ return "${shortcutEntity.pojo.typeName.toJavaPoet()}-${shortcutEntity.entityTypeName}"
}
override fun prepare(writer: TypeWriter, builder: FieldSpec.Builder) {
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt
index af86099..891711a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt
@@ -16,7 +16,8 @@
package androidx.room.writer
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.L
import androidx.room.ext.N
import androidx.room.ext.RoomTypeNames
@@ -35,7 +36,7 @@
import javax.lang.model.element.Modifier.PRIVATE
class EntityCursorConverterWriter(val entity: Entity) : TypeWriter.SharedMethodSpec(
- "entityCursorConverter_${entity.typeName.toString().stripNonJava()}"
+ "entityCursorConverter_${entity.typeName.toJavaPoet().toString().stripNonJava()}"
) {
override fun getUniqueKey(): String {
return "generic_entity_converter_of_${entity.element.qualifiedName}"
@@ -44,10 +45,10 @@
override fun prepare(methodName: String, writer: TypeWriter, builder: MethodSpec.Builder) {
builder.apply {
val cursorParam = ParameterSpec
- .builder(AndroidTypeNames.CURSOR, "cursor").build()
+ .builder(CURSOR.toJavaPoet(), "cursor").build()
addParameter(cursorParam)
addModifiers(PRIVATE)
- returns(entity.typeName)
+ returns(entity.typeName.toJavaPoet())
addCode(buildConvertMethodBody(writer, cursorParam))
}
}
@@ -56,7 +57,11 @@
val scope = CodeGenScope(writer)
val entityVar = scope.getTmpVar("_entity")
scope.builder().apply {
- scope.builder().addStatement("final $T $L", entity.typeName, entityVar)
+ scope.builder().addStatement(
+ "final $T $L",
+ entity.typeName.toJavaPoet(),
+ entityVar
+ )
val fieldsWithIndices = entity.fields.map {
val indexVar = scope.getTmpVar(
"_cursorIndexOf${it.name.stripNonJava().capitalize(Locale.US)}"
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt
index 4963ac1..5766ce6 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt
@@ -16,6 +16,7 @@
package androidx.room.writer
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.ext.L
import androidx.room.ext.RoomTypeNames
import androidx.room.ext.S
@@ -48,7 +49,7 @@
}
return EntityDeletionAdapterWriter(
tableName = entity.tableName,
- pojoTypeName = entity.pojo.typeName,
+ pojoTypeName = entity.pojo.typeName.toJavaPoet(),
fields = fieldsToUse
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt
index cd328f7..fc6e477 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt
@@ -16,6 +16,7 @@
package androidx.room.writer
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XNullability
import androidx.room.ext.L
import androidx.room.ext.RoomTypeNames
@@ -69,7 +70,12 @@
fun createAnonymous(typeWriter: TypeWriter, dbParam: String): TypeSpec {
@Suppress("RemoveSingleExpressionStringTemplate")
return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
- superclass(ParameterizedTypeName.get(RoomTypeNames.INSERTION_ADAPTER, pojo.typeName))
+ superclass(
+ ParameterizedTypeName.get(
+ RoomTypeNames.INSERTION_ADAPTER,
+ pojo.typeName.toJavaPoet()
+ )
+ )
addMethod(
MethodSpec.methodBuilder("createQuery").apply {
addAnnotation(Override::class.java)
@@ -111,7 +117,9 @@
).build()
)
val valueParam = "value"
- addParameter(ParameterSpec.builder(pojo.typeName, valueParam).build())
+ addParameter(
+ ParameterSpec.builder(pojo.typeName.toJavaPoet(), valueParam).build()
+ )
val mapped = FieldWithIndex.byOrder(pojo.fields)
FieldReadWriteWriter.bindToStatement(
ownerVar = valueParam,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt
index e6023e5..e085422 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt
@@ -16,6 +16,7 @@
package androidx.room.writer
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.ext.L
import androidx.room.ext.RoomTypeNames
import androidx.room.ext.S
@@ -56,7 +57,7 @@
superclass(
ParameterizedTypeName.get(
RoomTypeNames.DELETE_OR_UPDATE_ADAPTER,
- pojo.typeName
+ pojo.typeName.toJavaPoet()
)
)
addMethod(
@@ -97,7 +98,9 @@
).build()
)
val valueParam = "value"
- addParameter(ParameterSpec.builder(pojo.typeName, valueParam).build())
+ addParameter(
+ ParameterSpec.builder(pojo.typeName.toJavaPoet(), valueParam).build()
+ )
val mappedField = FieldWithIndex.byOrder(pojo.fields)
FieldReadWriteWriter.bindToStatement(
ownerVar = valueParam,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpsertionAdapterWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpsertionAdapterWriter.kt
index eab3b3e..ab9a46a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpsertionAdapterWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/EntityUpsertionAdapterWriter.kt
@@ -16,6 +16,7 @@
package androidx.room.writer
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.ext.L
import androidx.room.ext.RoomTypeNames
import androidx.room.ext.T
@@ -44,7 +45,7 @@
dbParam: String
): CodeBlock {
val upsertionAdapter = ParameterizedTypeName.get(
- RoomTypeNames.UPSERTION_ADAPTER, pojo.typeName
+ RoomTypeNames.UPSERTION_ADAPTER, pojo.typeName.toJavaPoet()
)
val insertionHelper = EntityInsertionAdapterWriter.create(entity, "")
.createAnonymous(typeWriter, dbParam)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
index 51719ba..bf053bb 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
@@ -16,8 +16,9 @@
package androidx.room.writer
-import androidx.room.ext.L
-import androidx.room.ext.T
+import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.ext.capitalize
import androidx.room.ext.defaultValue
import androidx.room.solver.CodeGenScope
@@ -28,7 +29,6 @@
import androidx.room.vo.FieldWithIndex
import androidx.room.vo.Pojo
import androidx.room.vo.RelationCollector
-import com.squareup.javapoet.TypeName
import java.util.Locale
/**
@@ -73,13 +73,10 @@
val allParents = getAllParents(fieldsWithIndices.map { it.field })
val rootNode = Node(rootVar, null)
rootNode.directFields = fieldsWithIndices.filter { it.field.parent == null }
- val parentNodes = allParents.associate {
- Pair(
- it,
- Node(
- varName = scope.getTmpVar("_tmp${it.field.name.capitalize(Locale.US)}"),
- fieldParent = it
- )
+ val parentNodes = allParents.associateWith {
+ Node(
+ varName = scope.getTmpVar("_tmp${it.field.name.capitalize(Locale.US)}"),
+ fieldParent = it
)
}
parentNodes.values.forEach { node ->
@@ -118,15 +115,15 @@
fieldParent.getter.writeGet(
ownerVar = node.parentNode!!.varName,
outVar = node.varName,
- builder = scope.builder()
+ builder = scope.builder
)
- scope.builder().apply {
- beginControlFlow("if($L != null)", node.varName).apply {
+ scope.builder.apply {
+ beginControlFlow("if (%L != null)", node.varName).apply {
bindWithDescendants()
}
nextControlFlow("else").apply {
node.allFields().forEach {
- addStatement("$L.bindNull($L)", stmtParamVar, it.indexVar)
+ addStatement("%L.bindNull(%L)", stmtParamVar, it.indexVar)
}
}
endControlFlow()
@@ -146,16 +143,20 @@
private fun construct(
outVar: String,
constructor: Constructor?,
- typeName: TypeName,
+ typeName: XTypeName,
localVariableNames: Map<String, FieldWithIndex>,
localEmbeddeds: List<Node>,
localRelations: Map<String, Field>,
scope: CodeGenScope
) {
if (constructor == null) {
- // best hope code generation
- scope.builder().apply {
- addStatement("$L = new $T()", outVar, typeName)
+ // Instantiate with default constructor, best hope for code generation
+ scope.builder.apply {
+ addStatement(
+ "%L = %L",
+ outVar,
+ XCodeBlock.ofNewInstance(scope.language, typeName)
+ )
}
return
}
@@ -173,7 +174,7 @@
}
}
val args = variableNames.joinToString(",") { it ?: "null" }
- constructor.writeConstructor(outVar, args, scope.builder())
+ constructor.writeConstructor(outVar, args, scope.builder)
}
/**
@@ -196,7 +197,7 @@
}.associateBy { fwi ->
FieldReadWriteWriter(fwi).readIntoTmpVar(
cursorVar,
- fwi.field.setter.type.typeName,
+ fwi.field.setter.type.asTypeName(),
scope
)
}
@@ -257,7 +258,7 @@
setter.writeSet(
ownerVar = node.varName,
inVar = varName,
- builder = scope.builder()
+ builder = scope.builder
)
}
// assign relation fields that were not part of the constructor
@@ -267,7 +268,7 @@
field.setter.writeSet(
ownerVar = node.varName,
inVar = varName,
- builder = scope.builder()
+ builder = scope.builder
)
}
}
@@ -277,9 +278,9 @@
readNode()
} else {
// always declare, we'll set below
- scope.builder().addStatement(
- "final $T $L", fieldParent.pojo.typeName,
- node.varName
+ scope.builder.addLocalVariable(
+ node.varName,
+ fieldParent.pojo.typeName
)
if (fieldParent.nonNull) {
readNode()
@@ -289,15 +290,15 @@
if (it.alwaysExists) {
"$cursorVar.isNull(${it.indexVar})"
} else {
- "( ${it.indexVar} == -1 || $cursorVar.isNull(${it.indexVar}))"
+ "(${it.indexVar} == -1 || $cursorVar.isNull(${it.indexVar}))"
}
}
- scope.builder().apply {
- beginControlFlow("if (! ($L))", allNullCheck).apply {
+ scope.builder.apply {
+ beginControlFlow("if (!(%L))", allNullCheck).apply {
readNode()
}
- nextControlFlow(" else ").apply {
- addStatement("$L = null", node.varName)
+ nextControlFlow("else").apply {
+ addStatement("%L = null", node.varName)
}
endControlFlow()
}
@@ -332,23 +333,21 @@
* @param scope The code generation scope
*/
private fun readFromCursor(ownerVar: String, cursorVar: String, scope: CodeGenScope) {
- fun toRead() {
+ fun doRead() {
field.cursorValueReader?.let { reader ->
- scope.builder().apply {
+ scope.builder.apply {
when (field.setter.callType) {
CallType.FIELD -> {
- reader.readFromCursor(
- "$ownerVar.${field.setter.jvmName}", cursorVar,
- indexVar, scope
- )
+ val outFieldName = "$ownerVar.${field.setter.jvmName}"
+ reader.readFromCursor(outFieldName, cursorVar, indexVar, scope)
}
CallType.METHOD -> {
val tmpField = scope.getTmpVar(
"_tmp${field.name.capitalize(Locale.US)}"
)
- addStatement("final $T $L", field.setter.type.typeName, tmpField)
+ addLocalVariable(tmpField, field.setter.type.asTypeName())
reader.readFromCursor(tmpField, cursorVar, indexVar, scope)
- addStatement("$L.$L($L)", ownerVar, field.setter.jvmName, tmpField)
+ addStatement("%L.%L(%L)", ownerVar, field.setter.jvmName, tmpField)
}
CallType.CONSTRUCTOR -> {
// no-op
@@ -358,11 +357,11 @@
}
}
if (alwaysExists) {
- toRead()
+ doRead()
} else {
- scope.builder().apply {
- beginControlFlow("if ($L != -1)", indexVar).apply {
- toRead()
+ scope.builder.apply {
+ beginControlFlow("if (%L != -1)", indexVar).apply {
+ doRead()
}
endControlFlow()
}
@@ -374,17 +373,17 @@
*/
fun readIntoTmpVar(
cursorVar: String,
- typeName: TypeName,
+ typeName: XTypeName,
scope: CodeGenScope
): String {
val tmpField = scope.getTmpVar("_tmp${field.name.capitalize(Locale.US)}")
- scope.builder().apply {
- addStatement("final $T $L", typeName, tmpField)
+ scope.builder.apply {
+ addLocalVariable(tmpField, typeName)
if (alwaysExists) {
field.cursorValueReader?.readFromCursor(tmpField, cursorVar, indexVar, scope)
} else {
- beginControlFlow("if ($L == -1)", indexVar).apply {
- addStatement("$L = $L", tmpField, typeName.defaultValue())
+ beginControlFlow("if (%L == -1)", indexVar).apply {
+ addStatement("%L = %L", tmpField, typeName.toJavaPoet().defaultValue())
}
nextControlFlow("else").apply {
field.cursorValueReader?.readFromCursor(tmpField, cursorVar, indexVar, scope)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt
index e7bd3a9..3d96052 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt
@@ -16,7 +16,8 @@
package androidx.room.writer
-import androidx.room.ext.AndroidTypeNames
+import androidx.room.compiler.codegen.toJavaPoet
+import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CollectionTypeNames
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.L
@@ -52,7 +53,7 @@
val relation = collector.relation
return "RelationCollectorMethodWriter" +
"-${collector.mapTypeName}" +
- "-${relation.entity.typeName}" +
+ "-${relation.entity.typeName.toJavaPoet()}" +
"-${relation.entityField.columnName}" +
"-${relation.pojoTypeName}" +
"-${relation.createLoadAllSql()}"
@@ -191,7 +192,7 @@
}
addStatement(
"final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
+ CURSOR.toJavaPoet(),
cursorVar,
RoomTypeNames.DB_UTIL,
DaoWriter.dbField,
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/DeleteOrUpdateShortcutMethodProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/DeleteOrUpdateShortcutMethodProcessorTest.kt
index 9991b4d..f5ea0af 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/DeleteOrUpdateShortcutMethodProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/DeleteOrUpdateShortcutMethodProcessorTest.kt
@@ -18,6 +18,7 @@
import COMMON
import androidx.room.Dao
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
@@ -37,10 +38,10 @@
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeName
+import kotlin.reflect.KClass
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
-import kotlin.reflect.KClass
/**
* Base test class for shortcut methods.
@@ -110,7 +111,10 @@
assertThat(param.pojoType?.typeName, `is`(USER_TYPE_NAME))
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["user"]?.isPartialEntity, `is`(false))
- assertThat(shortcut.entities["user"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["user"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
}
}
@@ -149,8 +153,14 @@
assertThat(it.pojoType?.typeName, `is`(USER_TYPE_NAME))
}
assertThat(shortcut.entities.size, `is`(2))
- assertThat(shortcut.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
- assertThat(shortcut.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["u1"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
+ assertThat(
+ shortcut.entities["u1"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
assertThat(
shortcut.parameters.map { it.name },
`is`(listOf("u1", "u2"))
@@ -190,7 +200,10 @@
)
assertThat(param.pojoType?.typeName, `is`(USER_TYPE_NAME))
assertThat(shortcut.entities.size, `is`(1))
- assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["users"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
}
}
}
@@ -213,7 +226,10 @@
)
)
assertThat(shortcut.entities.size, `is`(1))
- assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["users"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
}
}
@@ -238,7 +254,10 @@
)
)
assertThat(shortcut.entities.size, `is`(1))
- assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["users"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
}
}
@@ -263,7 +282,10 @@
)
)
assertThat(shortcut.entities.size, `is`(1))
- assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["users"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
}
}
@@ -289,7 +311,10 @@
)
)
assertThat(shortcut.entities.size, `is`(1))
- assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
+ assertThat(
+ shortcut.entities["users"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
}
}
@@ -324,8 +349,14 @@
)
assertThat(shortcut.parameters.map { it.name }, `is`(listOf("u1", "b1")))
assertThat(shortcut.entities.size, `is`(2))
- assertThat(shortcut.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
- assertThat(shortcut.entities["b1"]?.pojo?.typeName, `is`(BOOK_TYPE_NAME))
+ assertThat(
+ shortcut.entities["u1"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USER_TYPE_NAME)
+ )
+ assertThat(
+ shortcut.entities["b1"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(BOOK_TYPE_NAME)
+ )
}
}
}
@@ -421,7 +452,10 @@
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["username"]?.isPartialEntity, `is`(true))
assertThat(shortcut.entities["username"]?.entityTypeName, `is`(USER_TYPE_NAME))
- assertThat(shortcut.entities["username"]?.pojo?.typeName, `is`(USERNAME_TYPE_NAME))
+ assertThat(
+ shortcut.entities["username"]?.pojo?.let { it.typeName.toJavaPoet() },
+ `is`(USERNAME_TYPE_NAME)
+ )
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/InsertOrUpsertShortcutMethodProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/InsertOrUpsertShortcutMethodProcessorTest.kt
index 46b6fca..467a22f 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/InsertOrUpsertShortcutMethodProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/InsertOrUpsertShortcutMethodProcessorTest.kt
@@ -18,6 +18,7 @@
import COMMON
import androidx.room.Dao
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
@@ -34,12 +35,12 @@
import androidx.room.solver.shortcut.result.InsertOrUpsertMethodAdapter
import androidx.room.testing.context
import androidx.room.vo.InsertOrUpsertShortcutMethod
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.TypeName
-import kotlin.reflect.KClass
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ArrayTypeName
+import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
+import com.squareup.javapoet.TypeName
+import kotlin.reflect.KClass
import org.junit.Test
/**
@@ -137,7 +138,7 @@
assertThat(insertionUpsertion.entities["user"]?.isPartialEntity)
.isEqualTo(false)
- assertThat(insertionUpsertion.entities["user"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["user"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(ClassName.get("foo.bar", "User") as TypeName)
assertThat(insertionUpsertion.returnType.typeName)
@@ -162,10 +163,10 @@
assertThat(insertionUpsertion.entities.size)
.isEqualTo(2)
- assertThat(insertionUpsertion.entities["u1"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["u1"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
- assertThat(insertionUpsertion.entities["u2"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["u2"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.parameters.map { it.name })
@@ -200,7 +201,7 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(1)
- assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.returnType.typeName)
@@ -229,7 +230,7 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(1)
- assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.returnType.typeName)
@@ -258,7 +259,7 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(1)
- assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.returnType.typeName).isEqualTo(TypeName.VOID)
@@ -286,7 +287,7 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(1)
- assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.returnType.typeName).isEqualTo(TypeName.VOID)
@@ -314,7 +315,7 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(1)
- assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.returnType.typeName).isEqualTo(TypeName.VOID)
@@ -343,7 +344,7 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(1)
- assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["users"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
assertThat(insertionUpsertion.returnType.typeName).isEqualTo(TypeName.VOID)
@@ -371,10 +372,10 @@
assertThat(insertionUpsertion.entities.size).isEqualTo(2)
- assertThat(insertionUpsertion.entities["u1"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["u1"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USER_TYPE_NAME)
- assertThat(insertionUpsertion.entities["b1"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["b1"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(BOOK_TYPE_NAME)
}
}
@@ -593,7 +594,7 @@
assertThat(insertionUpsertion.entities["username"]?.entityTypeName)
.isEqualTo(USER_TYPE_NAME)
- assertThat(insertionUpsertion.entities["username"]?.pojo?.typeName)
+ assertThat(insertionUpsertion.entities["username"]?.pojo?.typeName?.toJavaPoet())
.isEqualTo(USERNAME_TYPE_NAME)
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
index 1df902e..f408fbe 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
@@ -18,6 +18,7 @@
import COMMON
import androidx.room.Embedded
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.XFieldElement
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
@@ -44,8 +45,8 @@
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.TypeName
import java.io.File
-import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.instanceOf
+import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.not
import org.hamcrest.CoreMatchers.notNullValue
import org.hamcrest.CoreMatchers.nullValue
@@ -212,7 +213,7 @@
assertThat(parent.prefix, `is`(""))
assertThat(parent.field.name, `is`("myPoint"))
assertThat(
- parent.pojo.typeName,
+ parent.pojo.typeName.toJavaPoet(),
`is`(ClassName.get("foo.bar.MyPojo", "Point") as TypeName)
)
}
@@ -315,7 +316,7 @@
)
val pointField = pojo.embeddedFields.first { it.field.name == "genericField" }
assertThat(
- pointField.pojo.typeName,
+ pointField.pojo.typeName.toJavaPoet(),
`is`(ClassName.get("foo.bar", "Point") as TypeName)
)
}
@@ -686,7 +687,7 @@
assertThat(pojo.relations.size, `is`(1))
val rel = pojo.relations.first()
assertThat(rel.projection, `is`(listOf("uid")))
- assertThat(rel.entity.typeName, `is`(COMMON.USER_TYPE_NAME as TypeName))
+ assertThat(rel.entity.typeName.toJavaPoet(), `is`(COMMON.USER_TYPE_NAME as TypeName))
}
}
@@ -704,7 +705,7 @@
assertThat(pojo.relations.size, `is`(1))
val rel = pojo.relations.first()
assertThat(rel.projection, `is`(listOf("name")))
- assertThat(rel.entity.typeName, `is`(COMMON.USER_TYPE_NAME as TypeName))
+ assertThat(rel.entity.typeName.toJavaPoet(), `is`(COMMON.USER_TYPE_NAME as TypeName))
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
index 235d729..42c6c57 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
@@ -17,6 +17,7 @@
package androidx.room.processor
import COMMON
+import androidx.room.compiler.codegen.toJavaPoet
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.runProcessorTest
@@ -34,8 +35,8 @@
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.TypeName
-import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.hasItems
+import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -2600,7 +2601,7 @@
)
val parsed = parser.process()
val field = parsed.primaryKey.fields.first()
- assertThat(field.typeName).isEqualTo(TypeName.LONG)
+ assertThat(field.typeName.toJavaPoet()).isEqualTo(TypeName.LONG)
}
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
index 939a336..4b649bf 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
@@ -57,7 +57,7 @@
arrayOf(
TypeName.BYTE,
"st.bindLong(6, inp);",
- "out = (byte) crs.getShort(9);"
+ "out = (byte) (crs.getShort(9));"
),
arrayOf(
TypeName.SHORT,
@@ -72,7 +72,7 @@
arrayOf(
TypeName.CHAR,
"st.bindLong(6, inp);",
- "out = (char) crs.getInt(9);"
+ "out = (char) (crs.getInt(9));"
),
arrayOf(
TypeName.FLOAT,
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/KotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/KotlinCodeGenTest.kt
new file mode 100644
index 0000000..0e920dd
--- /dev/null
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/KotlinCodeGenTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2022 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.writer
+
+import androidx.room.DatabaseProcessingStep
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.runKspTest
+import androidx.room.processor.Context
+import loadTestSource
+import org.junit.Test
+
+// Dany's Kotlin codegen test playground (and tests too)
+class KotlinCodeGenTest {
+
+ val databaseSrc = Source.kotlin(
+ "MyDatabase.kt",
+ """
+ import androidx.room.*
+
+ @Database(entities = [MyEntity::class], version = 1, exportSchema = false)
+ abstract class MyDatabase : RoomDatabase() {
+ abstract fun getDao(): MyDao
+ }
+ """.trimIndent()
+ )
+
+ @Test
+ fun pojoRowAdapter_primitives() {
+ val testName = object {}.javaClass.enclosingMethod!!.name
+ val src = Source.kotlin(
+ "MyDao.kt",
+ """
+ import androidx.room.*
+
+ @Dao
+ interface MyDao {
+ @Query("SELECT * FROM MyEntity")
+ fun getEntity(): MyEntity
+ }
+
+ @Entity
+ data class MyEntity(
+ @PrimaryKey
+ val int: Int,
+ val short: Short,
+ val byte: Byte,
+ val long: Long,
+ val char: Char,
+ val float: Float,
+ val double: Double,
+ )
+ """.trimIndent()
+ )
+ runTest(
+ sources = listOf(src, databaseSrc),
+ expectedFilePath = getTestGoldenPath(testName)
+ )
+ }
+
+ private fun getTestGoldenPath(testName: String): String {
+ return "kotlinCodeGen/$testName.kt"
+ }
+
+ private fun runTest(
+ sources: List<Source>,
+ expectedFilePath: String,
+ handler: (XTestInvocation) -> Unit = { }
+ ) {
+ runKspTest(
+ sources = sources,
+ options = mapOf(Context.BooleanProcessorOptions.GENERATE_KOTLIN.argName to "true"),
+ ) {
+ val databaseFqn = "androidx.room.Database"
+ DatabaseProcessingStep().process(
+ it.processingEnv,
+ mapOf(databaseFqn to it.roundEnv.getElementsAnnotatedWith(databaseFqn)),
+ it.roundEnv.isProcessingOver
+ )
+ it.assertCompilationResult {
+ this.generatedSource(
+ loadTestSource(
+ expectedFilePath,
+ "androidx.room.temp.PojoRowAdapter_1427165205"
+ )
+ )
+ this.hasNoWarnings()
+ }
+ handler.invoke(it)
+ }
+ }
+}
\ No newline at end of file
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/ComplexDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/ComplexDao.java
index 4436ebf..c9f0981c7 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/ComplexDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/ComplexDao.java
@@ -493,7 +493,7 @@
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final Info _tmpInfo;
- if (! (_cursor.isNull(_cursorIndexOfSerial) && _cursor.isNull(_cursorIndexOfCode))) {
+ if (!(_cursor.isNull(_cursorIndexOfSerial) && _cursor.isNull(_cursorIndexOfCode))) {
_tmpInfo = new Info();
_tmpInfo.serial = _cursor.getInt(_cursorIndexOfSerial);
if (_cursor.isNull(_cursorIndexOfCode)) {
@@ -501,7 +501,7 @@
} else {
_tmpInfo.code = _cursor.getString(_cursorIndexOfCode);
}
- } else {
+ } else {
_tmpInfo = null;
}
_item = new Child1(_tmpId,_tmpName,_tmpInfo);
@@ -537,7 +537,7 @@
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final Info _tmpInfo;
- if (! (_cursor.isNull(_cursorIndexOfSerial) && _cursor.isNull(_cursorIndexOfCode))) {
+ if (!(_cursor.isNull(_cursorIndexOfSerial) && _cursor.isNull(_cursorIndexOfCode))) {
_tmpInfo = new Info();
_tmpInfo.serial = _cursor.getInt(_cursorIndexOfSerial);
if (_cursor.isNull(_cursorIndexOfCode)) {
@@ -545,7 +545,7 @@
} else {
_tmpInfo.code = _cursor.getString(_cursorIndexOfCode);
}
- } else {
+ } else {
_tmpInfo = null;
}
_item = new Child2(_tmpId,_tmpName,_tmpInfo);
@@ -584,7 +584,7 @@
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final Info _tmpInfo;
- if (! (_cursor.isNull(_cursorIndexOfSerial) && _cursor.isNull(_cursorIndexOfCode))) {
+ if (!(_cursor.isNull(_cursorIndexOfSerial) && _cursor.isNull(_cursorIndexOfCode))) {
_tmpInfo = new Info();
_tmpInfo.serial = _cursor.getInt(_cursorIndexOfSerial);
if (_cursor.isNull(_cursorIndexOfCode)) {
@@ -592,7 +592,7 @@
} else {
_tmpInfo.code = _cursor.getString(_cursorIndexOfCode);
}
- } else {
+ } else {
_tmpInfo = null;
}
_item = new Child1(_tmpId,_tmpName,_tmpInfo);
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/pojoRowAdapter_primitives.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/pojoRowAdapter_primitives.kt
new file mode 100644
index 0000000..367cf89
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/pojoRowAdapter_primitives.kt
@@ -0,0 +1,46 @@
+package androidx.room.temp
+
+import MyEntity
+import android.database.Cursor
+import javax.`annotation`.processing.Generated
+import kotlin.Byte
+import kotlin.Char
+import kotlin.Double
+import kotlin.Float
+import kotlin.Int
+import kotlin.Long
+import kotlin.Short
+import kotlin.Suppress
+
+@Generated(value = ["androidx.room.RoomProcessor"])
+@Suppress(names = ["unchecked", "deprecation"])
+public class PojoRowAdapter_1427165205 {
+ public fun readFromCursor(
+ _cursor: Cursor,
+ _cursorIndexOfInt: Int,
+ _cursorIndexOfShort: Int,
+ _cursorIndexOfByte: Int,
+ _cursorIndexOfLong: Int,
+ _cursorIndexOfChar: Int,
+ _cursorIndexOfFloat: Int,
+ _cursorIndexOfDouble: Int,
+ ): MyEntity {
+ val _result: MyEntity
+ val _tmpInt: Int
+ _tmpInt = _cursor.getInt(_cursorIndexOfInt)
+ val _tmpShort: Short
+ _tmpShort = _cursor.getShort(_cursorIndexOfShort)
+ val _tmpByte: Byte
+ _tmpByte = _cursor.getShort(_cursorIndexOfByte).toByte()
+ val _tmpLong: Long
+ _tmpLong = _cursor.getLong(_cursorIndexOfLong)
+ val _tmpChar: Char
+ _tmpChar = _cursor.getInt(_cursorIndexOfChar).toChar()
+ val _tmpFloat: Float
+ _tmpFloat = _cursor.getFloat(_cursorIndexOfFloat)
+ val _tmpDouble: Double
+ _tmpDouble = _cursor.getDouble(_cursorIndexOfDouble)
+ _result = MyEntity(_tmpInt,_tmpShort,_tmpByte,_tmpLong,_tmpChar,_tmpFloat,_tmpDouble)
+ return _result
+ }
+}
\ No newline at end of file