I am trying to use Room for Kotlin Multiplatform (version 2.7.1) with ksp version 2.1.21-2.0.1.
How can I use the experimental type kotlin.time.Instant in my models?
The annotation processor apparently creates implementations without experimental annotations. This yields the error This declaration needs opt-in. Its usage must be marked with '@kotlin.time.ExperimentalTime' or '@OptIn(kotlin.time.ExperimentalTime::class)'.
I tried adding @OptIn(ExperimentalTime::class) to the member, the constructor and the data class itself, but none of those approaches seem to work. The compiler still gives the error. The compiler apparently also gives the error for accessing the type convertors even though they are annotated with @OptIn(ExperimentalTime::class) and not generated by the annotation processor. I tried putting @OptIn everywhere I can think of, but the error still persists..
Consider the following code:
@OptIn(ExperimentalTime::class)
@Database(
version = 1,
entities = [
RoomEntityModel::class,
],
)
@TypeConverters(RoomDataConverters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun getRoomEntityDao(): RoomEntityModelDao
}
class RoomDataConverters {
@OptIn(ExperimentalTime::class)
@TypeConverter
fun nullableInstantToString(value: Instant?) = value?.let { instantToString(it) }
@OptIn(ExperimentalTime::class)
@TypeConverter
fun instantToString(value: Instant) = value.toString()
@OptIn(ExperimentalTime::class)
@TypeConverter
fun nullableStringToInstant(value: String?) = value?.let { stringToInstant(it) }
@OptIn(ExperimentalTime::class)
@TypeConverter
fun stringToInstant(value: String) = Instant.parse(value)
}
@OptIn(ExperimentalTime::class)
@Dao
interface RoomEntityModelDao : BinanceKlineModelDao {
@OptIn(ExperimentalTime::class)
@Insert
suspend fun insert(vararg models: RoomEntityModel)
}
@OptIn(kotlin.time.ExperimentalTime::class)
@androidx.room.Entity("RoomEntityModel")
data class RoomEntityModel @OptIn(kotlin.time.ExperimentalTime::class) constructor(
@androidx.room.PrimaryKey
@androidx.room.ColumnInfo("instant")
@OptIn(kotlin.time.ExperimentalTime::class)
val instant: kotlin.time.Instant,
)
This results in the following implementation for RoomEntityModelDao
package REDACTED.`data`
import androidx.room.EntityInsertAdapter
import androidx.room.RoomDatabase
import androidx.room.util.performSuspending
import androidx.sqlite.SQLiteStatement
import REDACTED.`data`.local.database.RoomDataConverters
import javax.`annotation`.processing.Generated
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.collections.List
import kotlin.reflect.KClass
@Generated(value = ["androidx.room.RoomProcessor"])
@Suppress(names = ["UNCHECKED_CAST", "DEPRECATION", "REDUNDANT_PROJECTION", "REMOVAL"])
public class RoomEntityModelDao_Impl(
__db: RoomDatabase,
) : RoomEntityModelDao {
private val __db: RoomDatabase
private val __insertAdapterOfRoomEntityModel: EntityInsertAdapter<RoomEntityModel>
private val __roomDataConverters: RoomDataConverters = RoomDataConverters()
init {
this.__db = __db
this.__insertAdapterOfRoomEntityModel = object : EntityInsertAdapter<RoomEntityModel>() {
protected override fun createQuery(): String =
"INSERT OR ABORT INTO `RoomEntityModel` (`instant`) VALUES (?)"
protected override fun bind(statement: SQLiteStatement, entity: RoomEntityModel) {
val _tmp: String = __roomDataConverters.instantToString(entity.instant)
statement.bindText(1, _tmp)
}
}
}
public override suspend fun insert(vararg models: RoomEntityModel): Unit = performSuspending(__db,
false, true) { _connection ->
__insertAdapterOfRoomEntityModel.insert(_connection, models)
}
public companion object {
public fun getRequiredConverters(): List<KClass<*>> = emptyList()
}
}
And gives the errors
e: file:///REDACTED/generated/ksp/jvm/jvmMain/kotlin/REDACTED/data/RoomEntityModelDao_Impl.kt:32:49 This declaration needs opt-in. Its usage must be marked with '@kotlin.time.ExperimentalTime' or '@OptIn(kotlin.time.ExperimentalTime::class)'
e: file:///REDACTED/generated/ksp/jvm/jvmMain/kotlin/REDACTED/data/RoomEntityModelDao_Impl.kt:32:72 This declaration needs opt-in. Its usage must be marked with '@kotlin.time.ExperimentalTime' or '@OptIn(kotlin.time.ExperimentalTime::class)'
I had the same problem, but with Room for Android instead of KMP.
Instead of creating wrapper classes, a cleaner solution is to opt-in to ExperimentalTime for the entire module (as suggested in this IssueTracker conversation).
To do this, add the following line to your module(app)-level build.gradle.kts file (I'm using Kotlin syntax):
// ...
android {
// ...
kotlin.compilerOptions.optIn.add("kotlin.time.ExperimentalTime") // <- add this line
// ...
The following links may be helpful for adapting these configuration changes for KMP:
https://kotlinlang.org/docs/opt-in-requirements.html#opt-in-a-module
https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-dsl-reference.html#compiler-options
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With