Generate actual modifier in Room database constructor when the initialize function is overridden.
Bug: 359631627
Test: DatabaseObjectConstructorWriterKotlinCodeGenTest
Change-Id: If4cd1227d018d8bf7dd65ddbc5056e9d59c2c772
diff --git a/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/BaseAutoMigrationTest.kt b/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/BaseAutoMigrationTest.kt
index 1e9bc88..4e33f4f 100644
--- a/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/BaseAutoMigrationTest.kt
+++ b/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/BaseAutoMigrationTest.kt
@@ -166,4 +166,6 @@
}
expect object BaseAutoMigrationTest_AutoMigrationDatabaseConstructor :
- RoomDatabaseConstructor<AutoMigrationDatabase>
+ RoomDatabaseConstructor<AutoMigrationDatabase> {
+ override fun initialize(): AutoMigrationDatabase
+}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt b/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
index a07fca5..0f00fc6 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
@@ -146,10 +146,10 @@
)
.write(context.processingEnv)
}
- if (db.constructorObjectElement != null) {
+ if (db.constructorObject != null) {
DatabaseObjectConstructorWriter(
database = db,
- constructorObjectElement = db.constructorObjectElement
+ constructorObject = db.constructorObject
)
.write(context.processingEnv)
}
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 b49a6c2..6cf7930 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
@@ -34,6 +34,7 @@
import androidx.room.vo.Dao
import androidx.room.vo.DaoMethod
import androidx.room.vo.Database
+import androidx.room.vo.DatabaseConstructor
import androidx.room.vo.DatabaseView
import androidx.room.vo.Entity
import androidx.room.vo.FtsEntity
@@ -135,7 +136,7 @@
errorMsg = ProcessorErrors.INVALID_DATABASE_VERSION
)
- val constructorObjectElement = processConstructorObject(element)
+ val constructorObject = processConstructorObject(element)
val database =
Database(
@@ -148,7 +149,7 @@
exportSchema = dbAnnotation.value.exportSchema,
enableForeignKeys = hasForeignKeys,
overrideClearAllTables = hasClearAllTables,
- constructorObjectElement = constructorObjectElement
+ constructorObject = constructorObject
)
database.autoMigrations = processAutoMigrations(element, database.bundle)
return database
@@ -543,7 +544,7 @@
return result
}
- private fun processConstructorObject(element: XTypeElement): XTypeElement? {
+ private fun processConstructorObject(element: XTypeElement): DatabaseConstructor? {
val annotation = element.getAnnotation(androidx.room.ConstructedBy::class)
if (annotation == null) {
// If no @ConstructedBy is present then validate target is JVM (including Android)
@@ -604,6 +605,16 @@
return null
}
- return typeElement
+ val initializeExecutableElement =
+ context.processingEnv
+ .requireTypeElement(RoomTypeNames.ROOM_DB_CONSTRUCTOR)
+ .getDeclaredMethods()
+ .single()
+ val isInitOverridden =
+ typeElement.getDeclaredMethods().any {
+ it.overrides(initializeExecutableElement, typeElement)
+ }
+
+ return DatabaseConstructor(typeElement, isInitOverridden)
}
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/Database.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/Database.kt
index aaab5ca..15f95d4 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/Database.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/Database.kt
@@ -40,7 +40,7 @@
val exportSchema: Boolean,
val enableForeignKeys: Boolean,
val overrideClearAllTables: Boolean,
- val constructorObjectElement: XTypeElement?
+ val constructorObject: DatabaseConstructor?
) {
// This variable will be set once auto-migrations are processed given the DatabaseBundle from
// this object. This is necessary for tracking the versions involved in the auto-migration.
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/DatabaseConstructor.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/DatabaseConstructor.kt
new file mode 100644
index 0000000..f3ae2ae
--- /dev/null
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/DatabaseConstructor.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 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.vo
+
+import androidx.room.compiler.processing.XTypeElement
+
+/** Represents the declared [androidx.room.ConstructedBy] referenced object. */
+data class DatabaseConstructor(val element: XTypeElement, val overridesInitialize: Boolean)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseObjectConstructorWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseObjectConstructorWriter.kt
index 09c9c47..7289096 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseObjectConstructorWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseObjectConstructorWriter.kt
@@ -18,10 +18,10 @@
import androidx.room.compiler.codegen.toKotlinPoet
import androidx.room.compiler.processing.XProcessingEnv
-import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.addOriginatingElement
import androidx.room.ext.RoomTypeNames.ROOM_DB_CONSTRUCTOR
import androidx.room.vo.Database
+import androidx.room.vo.DatabaseConstructor
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
@@ -30,19 +30,19 @@
class DatabaseObjectConstructorWriter(
private val database: Database,
- private val constructorObjectElement: XTypeElement
+ private val constructorObject: DatabaseConstructor
) {
fun write(processingEnv: XProcessingEnv) {
val databaseClassName = database.typeName.toKotlinPoet()
- val objectClassName = constructorObjectElement.asClassName().toKotlinPoet()
+ val objectClassName = constructorObject.element.asClassName().toKotlinPoet()
val typeSpec =
TypeSpec.objectBuilder(objectClassName)
.apply {
addOriginatingElement(database.element)
addModifiers(KModifier.ACTUAL)
- if (constructorObjectElement.isInternal()) {
+ if (constructorObject.element.isInternal()) {
addModifiers(KModifier.INTERNAL)
- } else if (constructorObjectElement.isPublic()) {
+ } else if (constructorObject.element.isPublic()) {
addModifiers(KModifier.PUBLIC)
}
addSuperinterface(
@@ -50,9 +50,14 @@
)
addFunction(
FunSpec.builder("initialize")
- .addModifiers(KModifier.OVERRIDE)
- .returns(databaseClassName)
- .addStatement("return %L()", database.implTypeName.toKotlinPoet())
+ .apply {
+ if (constructorObject.overridesInitialize) {
+ addModifiers(KModifier.ACTUAL)
+ }
+ addModifiers(KModifier.OVERRIDE)
+ returns(databaseClassName)
+ addStatement("return %L()", database.implTypeName.toKotlinPoet())
+ }
.build()
)
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
index 0cc8204..421fb25 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
@@ -404,7 +404,7 @@
exportSchema = false,
enableForeignKeys = false,
overrideClearAllTables = true,
- constructorObjectElement = null,
+ constructorObject = null,
)
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt
index 46f81e2..536bc08 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt
@@ -72,7 +72,7 @@
exportSchema = false,
enableForeignKeys = false,
overrideClearAllTables = true,
- constructorObjectElement = null,
+ constructorObject = null,
)
val expectedLegacyHash =
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseObjectConstructorWriterKotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseObjectConstructorWriterKotlinCodeGenTest.kt
index bd893d3..3a6c7f7 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseObjectConstructorWriterKotlinCodeGenTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseObjectConstructorWriterKotlinCodeGenTest.kt
@@ -93,6 +93,26 @@
)
}
+ @Test
+ fun actualDatabaseConstructor_overridesInitialize() {
+ val ctorSrc =
+ Source.kotlin(
+ "MyDatabaseCtor.kt",
+ """
+ import androidx.room.*
+
+ expect object MyDatabaseCtor : RoomDatabaseConstructor<MyDatabase> {
+ override fun initialize(): MyDatabase
+ }
+ """
+ .trimIndent()
+ )
+ runTest(
+ sources = listOf(databaseSrc, ctorSrc),
+ expectedFilePath = getTestGoldenPath(testName.methodName)
+ )
+ }
+
private fun getTestGoldenPath(testName: String): String {
return "kotlinCodeGen/$testName.kt"
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/actualDatabaseConstructor_overridesInitialize.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/actualDatabaseConstructor_overridesInitialize.kt
new file mode 100644
index 0000000..599f927d
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/actualDatabaseConstructor_overridesInitialize.kt
@@ -0,0 +1,5 @@
+import androidx.room.RoomDatabaseConstructor
+
+public actual object MyDatabaseCtor : RoomDatabaseConstructor<MyDatabase> {
+ actual override fun initialize(): MyDatabase = MyDatabase_Impl()
+}
\ No newline at end of file