diff --git a/.gitignore b/.gitignore index 5ad9e3195b..fdebf06a95 100644 --- a/.gitignore +++ b/.gitignore @@ -329,3 +329,11 @@ DerivedData/ # End of https://www.gitignore.io/api/c,git,c++,java,cmake,xcode,kotlin,android,intellij,visualstudiocode dynamic_libraries.properties + +**/.kotlin + +**/output + +packages/test-sync/mongodb-realm/ + +packages/m2-buildrepo diff --git a/CHANGELOG.md b/CHANGELOG.md index e3631ecee3..a8514c747d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,11 +98,12 @@ * Minimum Gradle version: 7.2. * Minimum Android Gradle Plugin version: 7.1.3. * Minimum Android SDK: 16. -* Minimum R8: 8.0.34. +* Minimum R8: 8.3.37. ### Internal * Updated to Realm Core 14.7.0 commit c280bdb17522323d5c30dc32a2b9efc9dc80ca3b. * Changed Kotlin compiler testing framework to https://github.com/zacsweers/kotlin-compile-testing +* Updated to Detekt 1.23.6. ## 1.16.0 (2024-05-01) diff --git a/benchmarks/androidApp/build.gradle.kts b/benchmarks/androidApp/build.gradle.kts index 9cb9b3ae58..2d3a387568 100644 --- a/benchmarks/androidApp/build.gradle.kts +++ b/benchmarks/androidApp/build.gradle.kts @@ -5,6 +5,8 @@ plugins { } android { + namespace = "io.realm.kotlin.benchmarks.android" + testNamespace = "io.realm.kotlin.benchmarks.android.test" compileSdk = Versions.Android.compileSdkVersion compileOptions { diff --git a/benchmarks/androidApp/src/androidTest/AndroidManifest.xml b/benchmarks/androidApp/src/androidTest/AndroidManifest.xml index 4ceb5c7961..092969f295 100644 --- a/benchmarks/androidApp/src/androidTest/AndroidManifest.xml +++ b/benchmarks/androidApp/src/androidTest/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> + xmlns:tools="http://schemas.android.com/tools" > , ) fun realm_sync_subscriptionset_insert_or_assign( - mutatableSubscriptionSet: RealmMutableSubscriptionSetPointer, + mutableSubscriptionSet: RealmMutableSubscriptionSetPointer, query: RealmQueryPointer, name: String? ): Pair diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt index 291cf24a23..5d7c871ca5 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt @@ -20,8 +20,4 @@ expect enum class CoreConnectionState { RLM_SYNC_CONNECTION_STATE_DISCONNECTED, RLM_SYNC_CONNECTION_STATE_CONNECTING, RLM_SYNC_CONNECTION_STATE_CONNECTED; - - companion object { - fun of(nativeValue: Int): CoreConnectionState - } } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index 6b223a1204..1eb7aa437e 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -41,10 +41,6 @@ expect enum class SyncConnectionErrorCode : CodeDescription { override val nativeValue: Int override val description: String? - - companion object { - internal fun of(nativeValue: Int): SyncConnectionErrorCode? - } } /** @@ -91,10 +87,6 @@ expect enum class SyncSessionErrorCode : CodeDescription { override val nativeValue: Int override val description: String? - - companion object { - internal fun of(nativeValue: Int): SyncSessionErrorCode? - } } /** @@ -130,10 +122,6 @@ expect enum class WebsocketErrorCode : CodeDescription { override val nativeValue: Int override val description: String? - - companion object { - fun of(nativeValue: Int): WebsocketErrorCode? - } } /** @@ -152,8 +140,4 @@ expect enum class WebsocketCallbackResult : CodeDescription { override val nativeValue: Int override val description: String? - - companion object { - fun of(nativeValue: Int): WebsocketCallbackResult? - } } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt index dd9ccc5e45..7eeb9804dd 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt @@ -25,8 +25,4 @@ expect enum class SyncSessionResyncMode { RLM_SYNC_SESSION_RESYNC_MODE_DISCARD_LOCAL, RLM_SYNC_SESSION_RESYNC_MODE_RECOVER, RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD; - - companion object { - fun fromInt(nativeValue: Int): SyncSessionResyncMode - } } diff --git a/packages/cinterop/src/jvm/jni/java_class_global_def.hpp b/packages/cinterop/src/jvm/jni/java_class_global_def.hpp index f3c32ab128..2c202ca1f6 100644 --- a/packages/cinterop/src/jvm/jni/java_class_global_def.hpp +++ b/packages/cinterop/src/jvm/jni/java_class_global_def.hpp @@ -70,6 +70,8 @@ class JavaClassGlobalDef { , m_io_realm_kotlin_internal_interop_sync_websocket_transport(env, "io/realm/kotlin/internal/interop/sync/WebSocketTransport", false) , m_io_realm_kotlin_internal_interop_sync_websocket_client(env, "io/realm/kotlin/internal/interop/sync/WebSocketClient", false) , m_io_realm_kotlin_internal_interop_notification_callback(env, "io/realm/kotlin/internal/interop/NotificationCallback", false) + , m_io_realm_kotlin_internal_interop_sync_connection_state(env, "io/realm/kotlin/internal/interop/sync/CoreConnectionState", false) + { } @@ -100,6 +102,7 @@ class JavaClassGlobalDef { jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_websocket_transport; jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_websocket_client; jni_util::JavaClass m_io_realm_kotlin_internal_interop_notification_callback; + jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_connection_state; inline static std::unique_ptr& instance() { @@ -170,6 +173,11 @@ class JavaClassGlobalDef { return instance()->m_io_realm_kotlin_internal_interop_sync_app_error; } + inline static const jni_util::JavaClass& connection_state() + { + return instance()->m_io_realm_kotlin_internal_interop_sync_connection_state; + } + inline static const jni_util::JavaClass& log_callback() { return instance()->m_io_realm_kotlin_internal_interop_log_callback; diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 45055933be..facb5d5814 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -1373,6 +1373,7 @@ actual object RealmInterop { CoreLogLevel.valueFromPriority(realmc.realm_get_log_level_category(category).toShort()) actual fun realm_get_category_names(): List { + @Suppress("UNCHECKED_CAST") val names: Array = realmc.realm_get_log_category_names() as Array return names.asList() } @@ -2092,22 +2093,23 @@ actual object RealmInterop { } actual fun realm_sync_subscriptionset_insert_or_assign( - mutatableSubscriptionSet: RealmMutableSubscriptionSetPointer, + mutableSubscriptionSet: RealmMutableSubscriptionSetPointer, query: RealmQueryPointer, name: String? ): Pair { val outIndex = longArrayOf(1) val outInserted = BooleanArray(1) realmc.realm_sync_subscription_set_insert_or_assign_query( - mutatableSubscriptionSet.cptr(), + mutableSubscriptionSet.cptr(), query.cptr(), name, outIndex, outInserted ) + @Suppress("UNCHECKED_CAST") return Pair( realm_sync_subscription_at( - mutatableSubscriptionSet as RealmSubscriptionSetPointer, + mutableSubscriptionSet as RealmSubscriptionSetPointer, outIndex[0] ), outInserted[0] diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt index 8f04ec3eb2..bb9bd00a16 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@file:Suppress("NOTHING_TO_INLINE") package io.realm.kotlin.internal.interop diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt index 72331fd1db..a3977c5aa9 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@file:Suppress("NOTHING_TO_INLINE") package io.realm.kotlin.internal.interop diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt index 8199f74352..bac74a88e6 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt @@ -16,17 +16,17 @@ package io.realm.kotlin.internal.interop.sync -import io.realm.kotlin.internal.interop.NativeEnumerated import io.realm.kotlin.internal.interop.realm_sync_connection_state_e -actual enum class CoreConnectionState(override val nativeValue: Int) : NativeEnumerated { +actual enum class CoreConnectionState(val value: Int) { RLM_SYNC_CONNECTION_STATE_DISCONNECTED(realm_sync_connection_state_e.RLM_SYNC_CONNECTION_STATE_DISCONNECTED), RLM_SYNC_CONNECTION_STATE_CONNECTING(realm_sync_connection_state_e.RLM_SYNC_CONNECTION_STATE_CONNECTING), RLM_SYNC_CONNECTION_STATE_CONNECTED(realm_sync_connection_state_e.RLM_SYNC_CONNECTION_STATE_CONNECTED); - actual companion object { - actual fun of(nativeValue: Int): CoreConnectionState = - values().find { it.nativeValue == nativeValue } - ?: error("Unknown connection state: $nativeValue") + companion object { + @JvmStatic + fun of(value: Int): CoreConnectionState = + entries.find { it.value == value } + ?: error("Unknown connection state: $value") } } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt index f86bf847f6..4120e446b5 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt @@ -27,13 +27,8 @@ actual enum class CoreSyncSessionState(override val nativeValue: Int) : NativeEn RLM_SYNC_SESSION_STATE_PAUSED(realm_sync_session_state_e.RLM_SYNC_SESSION_STATE_PAUSED); companion object { - fun of(state: Int): CoreSyncSessionState { - for (value in values()) { - if (value.nativeValue == state) { - return value - } - } - error("Unknown sync session state: $state") - } + fun of(state: Int): CoreSyncSessionState = + entries.find { it.nativeValue == state } + ?: error("Unknown sync session state: $state") } } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index 103fec4534..2b4f74131e 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -42,9 +42,9 @@ actual enum class SyncConnectionErrorCode( RLM_SYNC_ERR_CONNECTION_SWITCH_TO_FLX_SYNC("SwitchToFlxSync", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_FLX_SYNC), RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS("SwitchToPbs", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS); - actual companion object { - internal actual fun of(nativeValue: Int): SyncConnectionErrorCode? = - values().firstOrNull { value -> + companion object { + internal fun of(nativeValue: Int): SyncConnectionErrorCode? = + entries.firstOrNull { value -> value.nativeValue == nativeValue } } @@ -91,9 +91,9 @@ actual enum class SyncSessionErrorCode( RLM_SYNC_ERR_SESSION_BAD_SCHEMA_VERSION("BadSchemaVersion", realm_sync_errno_session_e.RLM_SYNC_ERR_SESSION_BAD_SCHEMA_VERSION), RLM_SYNC_ERR_SESSION_SCHEMA_VERSION_CHANGED("SchemaVersionChanged", realm_sync_errno_session_e.RLM_SYNC_ERR_SESSION_SCHEMA_VERSION_CHANGED); - actual companion object { - internal actual fun of(nativeValue: Int): SyncSessionErrorCode? = - values().firstOrNull { value -> + companion object { + internal fun of(nativeValue: Int): SyncSessionErrorCode? = + entries.firstOrNull { value -> value.nativeValue == nativeValue } } @@ -131,9 +131,9 @@ actual enum class WebsocketErrorCode( RLM_ERR_WEBSOCKET_RETRY_ERROR("RetryError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RETRY_ERROR), RLM_ERR_WEBSOCKET_FATAL_ERROR("FatalError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_FATAL_ERROR); - actual companion object { - actual fun of(nativeValue: Int): WebsocketErrorCode? = - values().firstOrNull { value -> + companion object { + fun of(nativeValue: Int): WebsocketErrorCode? = + entries.firstOrNull { value -> value.nativeValue == nativeValue } } @@ -174,9 +174,9 @@ actual enum class WebsocketCallbackResult(actual override val description: Strin realm_sync_socket_callback_result_e.RLM_ERR_SYNC_SOCKET_INVALID_ARGUMENT ); - actual companion object { - actual fun of(nativeValue: Int): WebsocketCallbackResult? = - values().firstOrNull { value -> + companion object { + fun of(nativeValue: Int): WebsocketCallbackResult? = + entries.firstOrNull { value -> value.nativeValue == nativeValue } } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt index 8c26c8271b..77186f4cde 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt @@ -25,9 +25,9 @@ actual enum class SyncSessionResyncMode(override val nativeValue: Int) : NativeE RLM_SYNC_SESSION_RESYNC_MODE_RECOVER(realm_sync_session_resync_mode_e.RLM_SYNC_SESSION_RESYNC_MODE_RECOVER), RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD(realm_sync_session_resync_mode_e.RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD); - actual companion object { - actual fun fromInt(nativeValue: Int): SyncSessionResyncMode { - for (value in SyncSessionResyncMode.values()) { + companion object { + fun of(nativeValue: Int): SyncSessionResyncMode { + for (value in entries) { if (value.nativeValue == nativeValue) { return value } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/CoreLogLevel.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/CoreLogLevel.kt index 199770d3ad..dca0ba68ff 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/CoreLogLevel.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/CoreLogLevel.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2021 Realm Inc. + * + * 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 io.realm.kotlin.internal.interop actual enum class CoreLogLevel(private val internalPriority: Int) { diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 6f32c608f2..da0ae06505 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -15,7 +15,6 @@ */ // TODO https://github.com/realm/realm-kotlin/issues/889 @file:Suppress("TooGenericExceptionThrown", "TooGenericExceptionCaught") -@file:OptIn(ExperimentalForeignApi::class) package io.realm.kotlin.internal.interop @@ -55,7 +54,6 @@ import kotlinx.cinterop.CPointerVar import kotlinx.cinterop.CPointerVarOf import kotlinx.cinterop.CValue import kotlinx.cinterop.CVariable -import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.LongVar import kotlinx.cinterop.MemScope import kotlinx.cinterop.StableRef @@ -124,7 +122,6 @@ import realm_wrapper.realm_results_t import realm_wrapper.realm_scheduler_t import realm_wrapper.realm_set_t import realm_wrapper.realm_string_t -import realm_wrapper.realm_sync_session_resync_mode import realm_wrapper.realm_sync_session_state_e import realm_wrapper.realm_sync_session_stop_policy_e import realm_wrapper.realm_sync_socket_post_callback_t @@ -140,11 +137,11 @@ import realm_wrapper.realm_value_type import realm_wrapper.realm_version_id_t import realm_wrapper.realm_work_queue_t import kotlin.collections.set -import kotlin.native.internal.createCleaner +import kotlin.experimental.ExperimentalNativeApi +import kotlin.native.ref.createCleaner -@SharedImmutable actual val INVALID_CLASS_KEY: ClassKey by lazy { ClassKey(realm_wrapper.RLM_INVALID_CLASS_KEY.toLong()) } -@SharedImmutable + actual val INVALID_PROPERTY_KEY: PropertyKey by lazy { PropertyKey(realm_wrapper.RLM_INVALID_PROPERTY_KEY) } private fun throwOnError() { @@ -208,7 +205,7 @@ class CPointerWrapper(ptr: CPointer?, managed: Boolean val ptr: CPointer? = _ptr.ptr - @OptIn(ExperimentalStdlibApi::class) + @OptIn(ExperimentalNativeApi::class) val cleaner = if (managed) { createCleaner(_ptr) { it.release() @@ -223,7 +220,9 @@ class CPointerWrapper(ptr: CPointer?, managed: Boolean } // Convenience type cast +@Suppress("NOTHING_TO_INLINE") inline fun NativePointer.cptr(): CPointer { + @Suppress("UNCHECKED_CAST") return (this as CPointerWrapper).ptr as CPointer } @@ -270,7 +269,6 @@ fun String.toRString(memScope: MemScope) = cValue { set(memScope, this@toRString) } -@OptIn(ExperimentalForeignApi::class) @Suppress("LargeClass", "FunctionNaming") actual object RealmInterop { @@ -411,6 +409,7 @@ actual object RealmInterop { actual fun realm_config_set_encryption_key(config: RealmConfigurationPointer, encryptionKey: ByteArray) { memScoped { val encryptionKeyPointer = encryptionKey.refTo(0).getPointer(memScope) + @Suppress("UNCHECKED_CAST") realm_wrapper.realm_config_set_encryption_key( config.cptr(), encryptionKeyPointer as CPointer, @@ -424,7 +423,7 @@ actual object RealmInterop { val encryptionKey = ByteArray(ENCRYPTION_KEY_LENGTH) val encryptionKeyPointer = encryptionKey.refTo(0).getPointer(memScope) - val keyLength = realm_wrapper.realm_config_get_encryption_key( + @Suppress("UNCHECKED_CAST") val keyLength = realm_wrapper.realm_config_get_encryption_key( config.cptr(), encryptionKeyPointer as CPointer ) @@ -2550,7 +2549,7 @@ actual object RealmInterop { ) { realm_wrapper.realm_app_config_set_metadata_mode( appConfig.cptr(), - realm_wrapper.realm_sync_client_metadata_mode.byValue(metadataMode.metadataValue.toUInt()) + metadataMode.metadataValue ) } @@ -2560,6 +2559,7 @@ actual object RealmInterop { ) { memScoped { val encryptionKeyPointer = encryptionKey.refTo(0).getPointer(memScope) + @Suppress("UNCHECKED_CAST") realm_wrapper.realm_app_config_set_metadata_encryption_key( appConfig.cptr(), encryptionKeyPointer as CPointer @@ -2673,7 +2673,7 @@ actual object RealmInterop { ) { realm_wrapper.realm_sync_config_set_resync_mode( syncConfig.cptr(), - realm_sync_session_resync_mode.byValue(resyncMode.nativeValue) + resyncMode.value ) } @@ -2780,7 +2780,7 @@ actual object RealmInterop { actual fun realm_sync_connection_state(syncSession: RealmSyncSessionPointer): CoreConnectionState = CoreConnectionState.of( - realm_wrapper.realm_sync_session_get_connection_state(syncSession.cptr()).value.toInt() + realm_wrapper.realm_sync_session_get_connection_state(syncSession.cptr()) ) actual fun realm_sync_session_pause(syncSession: RealmSyncSessionPointer) { @@ -2839,7 +2839,7 @@ actual object RealmInterop { syncSession.cptr(), staticCFunction { userData, oldState, newState -> safeUserData(userData).run { - onChange(oldState.value.toInt(), newState.value.toInt()) + onChange(CoreConnectionState.of(oldState), CoreConnectionState.of(newState)) } }, StableRef.create(callback).asCPointer(), @@ -3458,7 +3458,7 @@ actual object RealmInterop { } actual fun realm_sync_subscriptionset_insert_or_assign( - mutatableSubscriptionSet: RealmMutableSubscriptionSetPointer, + mutableSubscriptionSet: RealmMutableSubscriptionSetPointer, query: RealmQueryPointer, name: String? ): Pair { @@ -3466,15 +3466,16 @@ actual object RealmInterop { val outIndex = alloc() val outInserted = alloc() realm_wrapper.realm_sync_subscription_set_insert_or_assign_query( - mutatableSubscriptionSet.cptr(), + mutableSubscriptionSet.cptr(), query.cptr(), name, outIndex.ptr, outInserted.ptr ) + @Suppress("UNCHECKED_CAST") return Pair( realm_sync_subscription_at( - mutatableSubscriptionSet as RealmSubscriptionSetPointer, + mutableSubscriptionSet as RealmSubscriptionSetPointer, outIndex.value.toLong() ), outInserted.value @@ -3814,6 +3815,7 @@ private inline fun disposeUserData(userdata: COpaquePointer?) // Development debugging methods // TODO Consider consolidating into platform abstract methods!? // private inline fun printlntid(s: String) = printlnWithTid(s) +@Suppress("NOTHING_TO_INLINE") private inline fun printlntid(s: String) = Unit private fun printlnWithTid(s: String) { @@ -3825,7 +3827,6 @@ private fun printlnWithTid(s: String) { private fun tid(): ULong { memScoped { - initRuntimeIfNeeded() val tidVar = alloc() pthread_threadid_np(null, tidVar.ptr).ensureUnixCallResult("pthread_threadid_np") return tidVar.value @@ -3833,6 +3834,8 @@ private fun tid(): ULong { } private fun getUnixError() = strerror(posix_errno())!!.toKString() + +@Suppress("NOTHING_TO_INLINE") private inline fun Int.ensureUnixCallResult(s: String): Int { if (this != 0) { throw Error("$s ${getUnixError()}") diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt index 799d7670cf..efbbc58f64 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValue.kt @@ -37,18 +37,33 @@ actual class RealmValueList(actual val size: Int, val head: CPointer byteArray.usePinned { @@ -60,6 +75,7 @@ actual value class RealmValue actual constructor( } } + @Suppress("NOTHING_TO_INLINE") actual inline fun getUUIDBytes(): ByteArray = memScoped { UByteArray(UUID_BYTES_SIZE).let { byteArray -> byteArray.usePinned { @@ -71,13 +87,16 @@ actual value class RealmValue actual constructor( } } + @Suppress("NOTHING_TO_INLINE") actual inline fun getDecimal128Array(): ULongArray { val w = value.decimal128.w return ulongArrayOf(w[0], w[1]) } + @Suppress("NOTHING_TO_INLINE") actual inline fun getLink(): Link = value.asLink() + @Suppress("NOTHING_TO_INLINE") actual inline fun isNull(): Boolean = value.type == ValueType.RLM_TYPE_NULL.nativeValue override fun toString(): String { diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt index eaef3fb7f3..8e8a384bed 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmValueAllocator.kt @@ -42,8 +42,12 @@ class NativeMemAllocator : MemTrackingAllocator { val scope = Arena() + @Suppress("NOTHING_TO_INLINE") override inline fun allocRealmValueT(): RealmValueT = scope.alloc() - override inline fun allocRealmValueList(count: Int): RealmValueList = RealmValueList(count, scope.allocArray(count)) + + @Suppress("NOTHING_TO_INLINE") + override inline fun allocRealmValueList(count: Int): RealmValueList = + RealmValueList(count, scope.allocArray(count)) override fun nullTransport(): RealmValue = createTransport(null, realm_value_type.RLM_TYPE_NULL) @@ -136,6 +140,7 @@ class NativeMemAllocator : MemTrackingAllocator { is_list = true this.arg = arg.arguments.head } + is RealmQuerySingleArgument -> { nb_args = 1U is_list = false @@ -154,7 +159,7 @@ class NativeMemAllocator : MemTrackingAllocator { private inline fun createTransport( value: T?, type: realm_value_type, - block: (RealmValueT.(value: T) -> Unit) = {} + block: (RealmValueT.(value: T) -> Unit) = {}, ): RealmValue { val struct: realm_value_t = allocRealmValueT() struct.type = when (value) { @@ -170,12 +175,14 @@ class NativeMemAllocator : MemTrackingAllocator { * We always need to track and free native resources in K/N so all allocators return a * [MemTrackingAllocator]. */ +@Suppress("NOTHING_TO_INLINE") actual inline fun realmValueAllocator(): MemAllocator = NativeMemAllocator() /** * We always need to track and free native resources in K/N so all allocators return a * [MemTrackingAllocator]. */ +@Suppress("NOTHING_TO_INLINE") actual inline fun trackingRealmValueAllocator(): MemTrackingAllocator = NativeMemAllocator() /** diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/SynchronizableObjectDarwin.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/SynchronizableObjectDarwin.kt index 45a7dba42d..e8cf53bbc6 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/SynchronizableObjectDarwin.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/SynchronizableObjectDarwin.kt @@ -25,13 +25,14 @@ import realm_wrapper.native_pthread_mutex_destroy import realm_wrapper.native_pthread_mutex_lock import realm_wrapper.native_pthread_mutex_t import realm_wrapper.native_pthread_mutex_unlock -import kotlin.native.internal.createCleaner +import kotlin.experimental.ExperimentalNativeApi +import kotlin.native.ref.createCleaner // Inspired by https://github.com/ktorio/ktor/blob/1.2.x/ktor-utils/posix/src/io/ktor/util/LockNative.kt actual class SynchronizableObject { private val mutex = nativeHeap.alloc() - @OptIn(ExperimentalStdlibApi::class) + @OptIn(ExperimentalNativeApi::class) private val cleaner = createCleaner(mutex) { capturedMutex -> native_pthread_mutex_destroy(capturedMutex.ptr) nativeHeap.free(capturedMutex) diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt index 5f29a97181..3a8b43cbfb 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreConnectionState.kt @@ -16,18 +16,17 @@ package io.realm.kotlin.internal.interop.sync -import io.realm.kotlin.internal.interop.NativeEnumerated import realm_wrapper.realm_sync_connection_state -actual enum class CoreConnectionState(override val nativeValue: UInt) : NativeEnumerated { - RLM_SYNC_CONNECTION_STATE_DISCONNECTED(realm_sync_connection_state.RLM_SYNC_CONNECTION_STATE_DISCONNECTED.value), - RLM_SYNC_CONNECTION_STATE_CONNECTING(realm_sync_connection_state.RLM_SYNC_CONNECTION_STATE_CONNECTING.value), - RLM_SYNC_CONNECTION_STATE_CONNECTED(realm_sync_connection_state.RLM_SYNC_CONNECTION_STATE_CONNECTED.value), +actual enum class CoreConnectionState(val value: realm_sync_connection_state) { + RLM_SYNC_CONNECTION_STATE_DISCONNECTED(realm_sync_connection_state.RLM_SYNC_CONNECTION_STATE_DISCONNECTED), + RLM_SYNC_CONNECTION_STATE_CONNECTING(realm_sync_connection_state.RLM_SYNC_CONNECTION_STATE_CONNECTING), + RLM_SYNC_CONNECTION_STATE_CONNECTED(realm_sync_connection_state.RLM_SYNC_CONNECTION_STATE_CONNECTED), ; - actual companion object { - actual fun of(nativeValue: Int): CoreConnectionState = - values().find { it.nativeValue == nativeValue.toUInt() } + companion object { + fun of(nativeValue: realm_sync_connection_state): CoreConnectionState = + entries.find { it.value == nativeValue } ?: error("Unknown property type: $nativeValue") } } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt index 5e8bdabe27..a266928c58 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/CoreSyncSessionState.kt @@ -30,7 +30,7 @@ actual enum class CoreSyncSessionState( companion object { fun of(state: realm_sync_session_state_e): CoreSyncSessionState { - for (value in values()) { + for (value in entries) { if (value.nativeValue == state) { return value } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/MetadataMode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/MetadataMode.kt index 96ebfa4af8..9cab4fb912 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/MetadataMode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/MetadataMode.kt @@ -18,8 +18,8 @@ package io.realm.kotlin.internal.interop.sync import realm_wrapper.realm_sync_client_metadata_mode_e -actual enum class MetadataMode(val metadataValue: Int) { - RLM_SYNC_CLIENT_METADATA_MODE_DISABLED(realm_sync_client_metadata_mode_e.RLM_SYNC_CLIENT_METADATA_MODE_DISABLED.value.toInt()), - RLM_SYNC_CLIENT_METADATA_MODE_PLAINTEXT(realm_sync_client_metadata_mode_e.RLM_SYNC_CLIENT_METADATA_MODE_PLAINTEXT.value.toInt()), - RLM_SYNC_CLIENT_METADATA_MODE_ENCRYPTED(realm_sync_client_metadata_mode_e.RLM_SYNC_CLIENT_METADATA_MODE_ENCRYPTED.value.toInt()) +actual enum class MetadataMode(val metadataValue: realm_sync_client_metadata_mode_e) { + RLM_SYNC_CLIENT_METADATA_MODE_DISABLED(realm_sync_client_metadata_mode_e.RLM_SYNC_CLIENT_METADATA_MODE_DISABLED), + RLM_SYNC_CLIENT_METADATA_MODE_PLAINTEXT(realm_sync_client_metadata_mode_e.RLM_SYNC_CLIENT_METADATA_MODE_PLAINTEXT), + RLM_SYNC_CLIENT_METADATA_MODE_ENCRYPTED(realm_sync_client_metadata_mode_e.RLM_SYNC_CLIENT_METADATA_MODE_ENCRYPTED) } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index ca5daf217b..1a42c622c8 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -42,13 +42,6 @@ actual enum class SyncConnectionErrorCode( RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS("SwitchToPbs", realm_sync_errno_connection.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS); actual override val nativeValue: Int = errorCode.value.toInt() - - actual companion object { - internal actual fun of(nativeValue: Int): SyncConnectionErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } } actual enum class SyncSessionErrorCode( @@ -93,13 +86,6 @@ actual enum class SyncSessionErrorCode( RLM_SYNC_ERR_SESSION_SCHEMA_VERSION_CHANGED("SchemaVersionChanged", realm_sync_errno_session.RLM_SYNC_ERR_SESSION_SCHEMA_VERSION_CHANGED); actual override val nativeValue: Int = errorCode.value.toInt() - - actual companion object { - internal actual fun of(nativeValue: Int): SyncSessionErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } } actual enum class WebsocketErrorCode( @@ -135,13 +121,6 @@ actual enum class WebsocketErrorCode( actual override val nativeValue: Int = errorCode.value.toInt() val asNativeEnum: realm_web_socket_errno = errorCode - - actual companion object { - actual fun of(nativeValue: Int): WebsocketErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } } actual enum class WebsocketCallbackResult( @@ -184,11 +163,4 @@ actual enum class WebsocketCallbackResult( actual override val nativeValue: Int = nativeError.value.toInt() val asNativeEnum: realm_sync_socket_callback_result = nativeError - - actual companion object { - actual fun of(nativeValue: Int): WebsocketCallbackResult? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt index 8c1b8941b2..15ee968e73 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncSessionResyncMode.kt @@ -16,23 +16,23 @@ package io.realm.kotlin.internal.interop.sync -import io.realm.kotlin.internal.interop.NativeEnumerated import realm_wrapper.realm_sync_session_resync_mode +import realm_wrapper.realm_sync_session_resync_mode_e -actual enum class SyncSessionResyncMode(override val nativeValue: UInt) : NativeEnumerated { - RLM_SYNC_SESSION_RESYNC_MODE_MANUAL(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_MANUAL.value), - RLM_SYNC_SESSION_RESYNC_MODE_DISCARD_LOCAL(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_DISCARD_LOCAL.value), - RLM_SYNC_SESSION_RESYNC_MODE_RECOVER(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_RECOVER.value), - RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD.value); +actual enum class SyncSessionResyncMode(val value: realm_sync_session_resync_mode_e) { + RLM_SYNC_SESSION_RESYNC_MODE_MANUAL(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_MANUAL), + RLM_SYNC_SESSION_RESYNC_MODE_DISCARD_LOCAL(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_DISCARD_LOCAL), + RLM_SYNC_SESSION_RESYNC_MODE_RECOVER(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_RECOVER), + RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD(realm_sync_session_resync_mode.RLM_SYNC_SESSION_RESYNC_MODE_RECOVER_OR_DISCARD); - actual companion object { - actual fun fromInt(nativeValue: Int): SyncSessionResyncMode { - for (value in SyncSessionResyncMode.values()) { - if (value.nativeValue.toInt() == nativeValue) { - return value + companion object { + fun of(mode: realm_sync_session_resync_mode_e): SyncSessionResyncMode { + for (entry in entries) { + if (entry.value.value == mode.value) { + return entry } } - error("Unknown session resync mode: $nativeValue") + error("Unknown session resync mode: $mode") } } } diff --git a/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt b/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt index f7e0af80b6..3f95f67edf 100644 --- a/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt +++ b/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt @@ -47,6 +47,8 @@ import kotlinx.cinterop.readBytes import kotlinx.cinterop.toKString import kotlinx.cinterop.useContents import kotlinx.cinterop.value +import platform.Foundation.NSFileManager +import platform.Foundation.temporaryDirectory import realm_wrapper.RLM_CLASS_NORMAL import realm_wrapper.RLM_COLLECTION_TYPE_NONE import realm_wrapper.RLM_PROPERTY_NORMAL @@ -70,7 +72,8 @@ import realm_wrapper.realm_schema_t import realm_wrapper.realm_schema_validate import realm_wrapper.realm_string_t import realm_wrapper.realm_t -import kotlin.native.internal.GC +import kotlin.native.runtime.GC +import kotlin.native.runtime.NativeRuntimeApi import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -81,7 +84,10 @@ import kotlin.test.assertTrue // Direct tests of the 'cinterop' low level C-API wrapper for Darwin platforms. // These test are not thought as being exhaustive, but is more to provide a playground for // experiments and maybe more relevant for reproduction of C-API issues. +@OptIn(NativeRuntimeApi::class) class CinteropTest { + private val tmpDir = NSFileManager.defaultManager.temporaryDirectory().path!! + /** * Tests whether our autorelease pointer wrapper releases native memory. * @@ -152,9 +158,9 @@ class CinteropTest { SchemaValidationMode.RLM_SCHEMA_VALIDATION_BASIC.nativeValue.toULong() ) ) - + val path = "$tmpDir/c_api_test.realm" val config = realm_config_new() - realm_config_set_path(config, "c_api_test.realm") + realm_config_set_path(config, path) realm_config_set_schema(config, realmSchemaNew) realm_config_set_schema_mode(config, realm_schema_mode_e.RLM_SCHEMA_MODE_AUTOMATIC) realm_config_set_schema_version(config, 1UL) @@ -209,8 +215,7 @@ class CinteropTest { memScoped { val nativeConfig = RealmInterop.realm_config_new() - - RealmInterop.realm_config_set_path(nativeConfig, "default.realm") + RealmInterop.realm_config_set_path(nativeConfig, "$tmpDir/default.realm") RealmInterop.realm_config_set_schema(nativeConfig, schema) RealmInterop.realm_config_set_schema_mode( nativeConfig, diff --git a/packages/gradle-plugin/build.gradle.kts b/packages/gradle-plugin/build.gradle.kts index 673c3ab092..9e083baa80 100644 --- a/packages/gradle-plugin/build.gradle.kts +++ b/packages/gradle-plugin/build.gradle.kts @@ -101,7 +101,7 @@ sourceSets { } // Task to generate gradle plugin runtime constants for SDK and core versions -tasks.create("versionConstants") { +val versionConstants: Task = tasks.create("versionConstants") { val coreDependenciesFile = layout.projectDirectory.file( listOf("..", "external", "core", "dependencies.yml").joinToString(File.separator) ) @@ -128,4 +128,8 @@ tasks.create("versionConstants") { } } -tasks.getByName("compileKotlin").dependsOn("versionConstants") +tasks.getByName("compileKotlin").dependsOn(versionConstants) +tasks.getByName("sourcesJar").dependsOn(versionConstants) +afterEvaluate { + tasks.getByName("publishPluginJar").dependsOn(versionConstants) +} diff --git a/packages/gradle.properties b/packages/gradle.properties index dbcb870063..63e45d7e03 100644 --- a/packages/gradle.properties +++ b/packages/gradle.properties @@ -94,3 +94,4 @@ syncTestLoginPassword=password # syncTestLoginPublicApiKey=replace-with-value # synctestLoginPrivateApiKey=replace-with-value # syncTestClusterName=replace-with-value +android.disableAutomaticComponentCreation=true diff --git a/packages/jni-swig-stub/build.gradle.kts b/packages/jni-swig-stub/build.gradle.kts index 7662f9c2e7..8d7325558c 100644 --- a/packages/jni-swig-stub/build.gradle.kts +++ b/packages/jni-swig-stub/build.gradle.kts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import org.gradle.api.tasks.compile.JavaCompile plugins { id("java-library") @@ -25,14 +26,18 @@ val generatedSourceRoot = "$buildDir/generated/sources" java { withSourcesJar() + withJavadocJar() sourceSets { main { - this.java.srcDir("$generatedSourceRoot/java") + java.srcDir("$generatedSourceRoot/java") } } + + sourceCompatibility = Versions.sourceCompatibilityVersion + targetCompatibility = Versions.targetCompatibilityVersion } -tasks.create("realmWrapperJvm") { +val realmWrapperJvm: Task = tasks.create("realmWrapperJvm") { doLast { // If task is actually triggered (not up to date) then we should clean up the old stuff delete(fileTree(generatedSourceRoot)) @@ -49,10 +54,16 @@ tasks.create("realmWrapperJvm") { outputs.dir("$generatedSourceRoot/jni") } -tasks.named("compileJava") { - dependsOn("realmWrapperJvm") +tasks.named("javadoc") { + enabled = false } +tasks.withType(JavaCompile::class) { + dependsOn(realmWrapperJvm) +} + +tasks.getByName("sourcesJar").dependsOn(realmWrapperJvm) + realmPublish { pom { name = "JNI Swig Stubs" @@ -62,13 +73,6 @@ realmPublish { } } -java { - withSourcesJar() - withJavadocJar() - sourceCompatibility = Versions.sourceCompatibilityVersion - targetCompatibility = Versions.targetCompatibilityVersion -} - publishing { publications { register(mavenPublicationName) { diff --git a/packages/jni-swig-stub/realm.i b/packages/jni-swig-stub/realm.i index 8028cd1651..96593c782c 100644 --- a/packages/jni-swig-stub/realm.i +++ b/packages/jni-swig-stub/realm.i @@ -37,6 +37,7 @@ using namespace realm::jni_util; // (calling SoLoader directly will create a circular dependency with `jvmMain`) try { Class classToLoad = Class.forName("io.realm.kotlin.jvm.SoLoader"); + @SuppressWarnings("deprecation") Object instance = classToLoad.newInstance(); java.lang.reflect.Method loadMethod = classToLoad.getDeclaredMethod("load"); loadMethod.invoke(instance); @@ -59,6 +60,13 @@ std::string rlm_stdstr(realm_string_t val) } %} +%typemap(javafinalize) SWIGTYPE %{ +@SuppressWarnings({"deprecation", "removal"}) +protected void finalize() { + delete(); +} +%} + // This sets up a type map for all methods with the argument pattern of: // realm_void_user_completion_func_t, void* userdata, realm_free_userdata_func_t // This will make Swig wrap methods taking this argument pattern into: diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp index c62c0757b2..a112cf6d1a 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp @@ -396,6 +396,17 @@ jobject convert_to_jvm_app_error(JNIEnv* env, const realm_app_error_t* error) { return env->PopLocalFrame(result); } +jobject core_connection_state(JNIEnv* env, realm_sync_connection_state_e state) { + static JavaMethod connection_state_constructor(env, + JavaClassGlobalDef::connection_state(), + "of", + "(I)Lio/realm/kotlin/internal/interop/sync/CoreConnectionState;", + true); + env->PushLocalFrame(1); + auto result = env->CallStaticObjectMethod(JavaClassGlobalDef::connection_state(), connection_state_constructor, jint(state)); + jni_check_exception(env); + return env->PopLocalFrame(result); +} void app_complete_void_callback(void *userdata, const realm_app_error_t *error) { auto env = get_env(true); @@ -1258,10 +1269,13 @@ void realm_sync_session_connection_state_change_callback(void *userdata, realm_sync_connection_state_e old_state, realm_sync_connection_state_e new_state) { auto env = get_env(true); - static JavaMethod java_callback_method(env, JavaClassGlobalDef::connection_state_change_callback(), "onChange", "(II)V"); + static JavaMethod java_callback_method(env, JavaClassGlobalDef::connection_state_change_callback(), "onChange", "(Lio/realm/kotlin/internal/interop/sync/CoreConnectionState;Lio/realm/kotlin/internal/interop/sync/CoreConnectionState;)V"); + + jobject jold_state = core_connection_state(env, old_state); + jobject jnew_state = core_connection_state(env, new_state); jni_check_exception(env); - env->CallVoidMethod(static_cast(userdata), java_callback_method, jint(old_state), jint(new_state)); + env->CallVoidMethod(static_cast(userdata), java_callback_method, jold_state, jnew_state); jni_check_exception(env); } diff --git a/packages/library-base/build.gradle.kts b/packages/library-base/build.gradle.kts index 124e3cb7f7..f45b9dec9a 100644 --- a/packages/library-base/build.gradle.kts +++ b/packages/library-base/build.gradle.kts @@ -1,3 +1,7 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile + /* * Copyright 2020 Realm Inc. * @@ -35,15 +39,17 @@ project.extensions.configure(kotlinx.atomicfu.plugin.gradle.AtomicFUPluginExtens } // Common Kotlin configuration +@Suppress("UNUSED_VARIABLE") kotlin { jvm() - androidTarget("android") { + androidTarget { // Changing this will also requires an update to the publishCIPackages task // in /packages/build.gradle.kts publishLibraryVariants("release") } - ios() + iosX64() iosSimulatorArm64() + iosArm64() macosX64() macosArm64() @@ -118,25 +124,31 @@ kotlin { // Using a custom name module for internal methods to avoid default name mangling in Kotlin compiler which uses the module // name and build type variant as a suffix, this default behaviour can cause mismatch at runtime https://github.com/realm/realm-kotlin/issues/621 -tasks.withType().configureEach { - kotlinOptions { - freeCompilerArgs += listOf("-module-name", "io.realm.kotlin.library") +tasks.withType().configureEach { + compilerOptions.moduleName.set("io.realm.kotlin.library") +} + +tasks.withType>().configureEach { + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") } } -tasks.withType().all { - kotlinOptions { - freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") + +tasks.withType().configureEach { + compilerOptions { + freeCompilerArgs.add("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") } } // Android configuration android { - compileSdkVersion(Versions.Android.compileSdkVersion) + namespace = "io.realm.kotlin" + compileSdk = Versions.Android.compileSdkVersion buildToolsVersion = Versions.Android.buildToolsVersion defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) + minSdk = Versions.Android.minSdk + targetSdk = Versions.Android.targetSdk testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" sourceSets { @@ -191,6 +203,7 @@ tasks.withType().configureEach { } jdkVersion.set(8) } + @Suppress("UNUSED_VARIABLE") val commonMain by getting { includes.from( "overview.md", diff --git a/packages/library-base/gradle.properties b/packages/library-base/gradle.properties new file mode 100644 index 0000000000..63de1180aa --- /dev/null +++ b/packages/library-base/gradle.properties @@ -0,0 +1,16 @@ +# +# Copyright 2024 Realm Inc. +# +# 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. +# +kotlin.mpp.applyDefaultHierarchyTemplate=false diff --git a/packages/library-base/proguard-rules-consumer-common.pro b/packages/library-base/proguard-rules-consumer-common.pro index 9fc9815bde..aed375ecbb 100644 --- a/packages/library-base/proguard-rules-consumer-common.pro +++ b/packages/library-base/proguard-rules-consumer-common.pro @@ -52,6 +52,10 @@ # TODO OPTIMIZE Only keep actually required symbols *; } +-keep class io.realm.kotlin.internal.interop.sync.CoreConnectionState { + # TODO OPTIMIZE Only keep actually required symbols + *; +} -keep class io.realm.kotlin.internal.interop.sync.SyncError { # TODO OPTIMIZE Only keep actually required symbols *; diff --git a/packages/library-base/src/androidMain/AndroidManifest.xml b/packages/library-base/src/androidMain/AndroidManifest.xml index 1069c422a1..bd87c63b69 100644 --- a/packages/library-base/src/androidMain/AndroidManifest.xml +++ b/packages/library-base/src/androidMain/AndroidManifest.xml @@ -16,6 +16,5 @@ --> + xmlns:tools="http://schemas.android.com/tools"> diff --git a/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/LogCatLogger.kt b/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/LogCatLogger.kt index dc6129d2ab..f5c274033a 100644 --- a/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/LogCatLogger.kt +++ b/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/LogCatLogger.kt @@ -46,7 +46,7 @@ internal class LogCatLogger( val logMessage: String = prepareLogMessage( throwable = throwable, message = messageWithCategory(category, message), - args = *args + args = args ) // Short circuit if message can fit into a single line in LogCat diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmDictionaryExt.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmDictionaryExt.kt index b3d48fa629..942f4c6adf 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmDictionaryExt.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmDictionaryExt.kt @@ -88,6 +88,8 @@ public fun realmDictionaryEntryOf(entry: Map.Entry): RealmDiction * @returns an in-memory copy of all input objects. * @throws IllegalArgumentException if depth < 0 or, or the list is not valid to copy. */ + +@Suppress("NOTHING_TO_INLINE") public inline fun RealmDictionary.copyFromRealm( depth: UInt = UInt.MAX_VALUE ): Map { diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmSetExt.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmSetExt.kt index 6f34237352..69029c4094 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmSetExt.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/ext/RealmSetExt.kt @@ -46,6 +46,8 @@ public fun realmSetOf(vararg elements: T): RealmSet = * @returns an in-memory copy of all input objects. * @throws IllegalArgumentException if depth < 0 or, or the list is not valid to copy. */ + +@Suppress("NOTHING_TO_INLINE") public inline fun RealmSet.copyFromRealm( depth: UInt = UInt.MAX_VALUE ): Set { diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ContextLogger.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ContextLogger.kt index 4b4231a8fa..9441372de2 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ContextLogger.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ContextLogger.kt @@ -90,12 +90,14 @@ public class ContextLogger(public val context: String? = null) { } } + @Suppress("NOTHING_TO_INLINE") private inline fun doLog(level: LogLevel, throwable: Throwable?) { checkPriority(level) { RealmLog.doLog(SdkLogCategory, level, throwable, null) } } + @Suppress("NOTHING_TO_INLINE") private inline fun doLog( level: LogLevel, throwable: Throwable?, diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/Converters.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/Converters.kt index 84ca1eb9e1..db62d1cb01 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/Converters.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/Converters.kt @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@file:Suppress("NOTHING_TO_INLINE", "OVERRIDE_BY_INLINE") package io.realm.kotlin.internal @@ -42,7 +43,6 @@ import io.realm.kotlin.types.geo.GeoCircle import io.realm.kotlin.types.geo.GeoPolygon import org.mongodb.kbson.BsonObjectId import org.mongodb.kbson.Decimal128 -import kotlin.native.concurrent.SharedImmutable import kotlin.reflect.KClass // This file contains all code for converting public API values into values passed to the C-API. @@ -144,6 +144,7 @@ internal inline fun realmValueToRealmAny( ?.clazz ?: throw IllegalArgumentException("The object class is not present in the current schema - are you using an outdated schema version?") val realmObject = realmValueToRealmObject(realmValue, clazz, mediator, owner) + @Suppress("UNCHECKED_CAST") RealmAny.create(realmObject!! as RealmObject, clazz as KClass) } } @@ -217,6 +218,7 @@ internal abstract class CompositeConverter : } // RealmValueConverter with default pass-through public-to-storage-type implementation +@Suppress("UNCHECKED_CAST") internal abstract class PassThroughPublicConverter : CompositeConverter() { override fun fromPublic(value: T?): T? = passthrough(value) as T? override fun toPublic(value: T?): T? = passthrough(value) as T? @@ -338,7 +340,6 @@ internal object Decimal128Converter : PassThroughPublicConverter() { decimal128Transport(value) } -@SharedImmutable internal val primitiveTypeConverters: Map, RealmValueConverter<*>> = mapOf, RealmValueConverter<*>>( Byte::class to ByteConverter, @@ -365,6 +366,7 @@ internal object RealmValueArgumentConverter { fun MemTrackingAllocator.kAnyToPrimaryKeyRealmValue(value: Any?): RealmValue { return value?.let { value -> primitiveTypeConverters[value::class]?.let { converter -> + @Suppress("UNCHECKED_CAST") with(converter as RealmValueConverter) { publicToRealmValue(value) } @@ -383,6 +385,7 @@ internal object RealmValueArgumentConverter { realmAnyToRealmValueWithoutImport(value) else -> { primitiveTypeConverters[value::class]?.let { converter -> + @Suppress("UNCHECKED_CAST") with(converter as RealmValueConverter) { publicToRealmValue(value) } @@ -579,6 +582,7 @@ internal inline fun realmObjectToRealmReferenceOrError( } // Returns a converter fixed to convert objects of the given type in the context of the given mediator/realm +@Suppress("UNCHECKED_CAST") internal fun converter( clazz: KClass ): RealmValueConverter = primitiveTypeConverters.getValue(clazz) as RealmValueConverter diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/KeyPathFlowable.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/KeyPathFlowable.kt index ecf54903fb..055ec93ef5 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/KeyPathFlowable.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/KeyPathFlowable.kt @@ -29,5 +29,5 @@ import kotlinx.coroutines.flow.Flow */ internal interface KeyPathFlowable { - fun asFlow(keyPaths: List? = null): Flow + fun asFlow(keyPaths: List?): Flow } diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ObjectBoundRealmResults.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ObjectBoundRealmResults.kt index 93d501ae9a..d13e08a979 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ObjectBoundRealmResults.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ObjectBoundRealmResults.kt @@ -81,4 +81,4 @@ internal class ObjectBoundRealmResults( internal fun Flow.bind( reference: RealmObjectReference ): Flow = - this.terminateWhen(reference.asFlow()) { it is DeletedObject } + this.terminateWhen(reference.asFlow(null)) { it is DeletedObject } diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt index a1c1b820b0..6868b8097e 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt @@ -91,10 +91,11 @@ internal class RealmAnyImpl constructor( val getValue = getValue(RealmAny.Type.OBJECT) return clazz.cast(getValue) } - + @Suppress("UNCHECKED_CAST") override fun asList(): RealmList = getValue(RealmAny.Type.LIST) as RealmList + @Suppress("UNCHECKED_CAST") override fun asDictionary(): RealmDictionary = getValue(RealmAny.Type.DICTIONARY) as RealmDictionary diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmInstantImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmInstantImpl.kt index cdc7d7fabe..11993b64a3 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmInstantImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmInstantImpl.kt @@ -45,6 +45,8 @@ public fun Duration.toRealmInstant(): RealmInstant { internal fun RealmInstant.restrictToMillisPrecision() = toDuration().inWholeMilliseconds.milliseconds.toRealmInstant() - +@Suppress("NOTHING_TO_INLINE") public inline fun RealmInstant.asBsonDateTime(): BsonDateTime = BsonDateTime(toDuration().inWholeMilliseconds) + +@Suppress("NOTHING_TO_INLINE") public inline fun BsonDateTime.asRealmInstant(): RealmInstant = value.milliseconds.toRealmInstant() diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmListInternal.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmListInternal.kt index 2e2669c955..fcb76e19e6 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmListInternal.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmListInternal.kt @@ -326,7 +326,6 @@ internal class PrimitiveListOperator( } } - @Suppress("UNCHECKED_CAST") override fun set( index: Int, element: E, @@ -375,18 +374,15 @@ internal class RealmAnyListOperator( val issueDynamicMutableObject: Boolean ) : ListOperator { - @Suppress("UNCHECKED_CAST") - override fun get(index: Int): RealmAny? { - return getterScope { - val transport = realm_list_get(nativePointer, index.toLong()) - return realmValueToRealmAny( - transport, null, mediator, realmReference, - issueDynamicObject, - issueDynamicMutableObject, - { RealmInterop.realm_list_get_list(nativePointer, index.toLong()) }, - { RealmInterop.realm_list_get_dictionary(nativePointer, index.toLong()) } - ) - } + override fun get(index: Int): RealmAny? = getterScope { + val transport = realm_list_get(nativePointer, index.toLong()) + return realmValueToRealmAny( + transport, null, mediator, realmReference, + issueDynamicObject, + issueDynamicMutableObject, + { RealmInterop.realm_list_get_list(nativePointer, index.toLong()) }, + { RealmInterop.realm_list_get_dictionary(nativePointer, index.toLong()) } + ) } override fun indexOf(element: RealmAny?): Int { @@ -443,7 +439,6 @@ internal class RealmAnyListOperator( } } - @Suppress("UNCHECKED_CAST") override fun set( index: Int, element: RealmAny?, @@ -548,7 +543,6 @@ internal class RealmObjectListOperator( } } - @Suppress("UNCHECKED_CAST") override fun set( index: Int, element: E, @@ -608,7 +602,6 @@ internal class EmbeddedRealmObjectListOperator( RealmObjectHelper.assign(newObj, element, updatePolicy, cache) } - @Suppress("UNCHECKED_CAST") override fun set( index: Int, element: E, diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmMapInternal.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmMapInternal.kt index 65160db22c..495d9b1edd 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmMapInternal.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmMapInternal.kt @@ -344,6 +344,7 @@ internal open class PrimitiveMapOperator constructor( override fun getValue(resultsPointer: RealmResultsPointer, index: Int): V? { return getterScope { + @Suppress("UNCHECKED_CAST") with(realmValueConverter) { val transport = realm_results_get(resultsPointer, index.toLong()) realmValueToPublic(transport) diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectHelper.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectHelper.kt index 1b210bf165..f21e85de1d 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectHelper.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectHelper.kt @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@file:Suppress("NOTHING_TO_INLINE") package io.realm.kotlin.internal @@ -76,7 +77,7 @@ import kotlin.reflect.KProperty1 * * Inlining would anyway yield the same result as generating it. */ -@Suppress("LargeClass") +@Suppress("LargeClass", "UNCHECKED_CAST") internal object RealmObjectHelper { // --------------------------------------------------------------------- @@ -873,7 +874,7 @@ internal object RealmObjectHelper { @Suppress("UNCHECKED_CAST") val members = - companion.`io_realm_kotlin_fields` as Map> + companion.io_realm_kotlin_fields as Map> members.map { it.key to it.value.get(source) } } properties.map { @@ -1195,7 +1196,7 @@ internal object RealmObjectHelper { operator.putAll(value as RealmDictionary<*>, updatePolicy, cache) } } - else -> IllegalStateException("Unknown type: ${propertyMetadata.collectionType}") + else -> throw IllegalStateException("Unknown type: ${propertyMetadata.collectionType}") } } @@ -1306,7 +1307,7 @@ internal object RealmObjectHelper { ( realmStorageType == RealmStorageType.OBJECT && value !is BaseRealmObject ) || - (realmStorageType != RealmStorageType.OBJECT && value!!::class.realmStorageType() != kClass) + (realmStorageType != RealmStorageType.OBJECT && value::class.realmStorageType() != kClass) ) ) ) diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectReference.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectReference.kt index aca06a8157..b92d0d0a59 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectReference.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectReference.kt @@ -78,6 +78,7 @@ public class RealmObjectReference( objectPointer = pointer ) + @Suppress("unchecked_cast") override fun freeze( frozenRealm: RealmReference ): RealmObjectReference? { @@ -93,6 +94,7 @@ public class RealmObjectReference( return thaw(liveRealm, type) } + @Suppress("unchecked_cast") public fun thaw( liveRealm: RealmReference, clazz: KClass @@ -149,14 +151,10 @@ public class RealmObjectReference( objectPointer.let { RealmInterop.realm_object_delete(it) } } - override fun isValid(): Boolean { - val ptr = objectPointer - return if (ptr != null) { + override fun isValid(): Boolean = + objectPointer.let { ptr -> !ptr.isReleased() && RealmInterop.realm_object_is_valid(ptr) - } else { - false } - } internal fun checkValid() { if (!this.isValid()) { diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectUtil.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectUtil.kt index ea4b858a9b..4e86a39423 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectUtil.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmObjectUtil.kt @@ -34,7 +34,7 @@ internal fun RealmObjectInternal.manage( type: KClass, objectPointer: RealmObjectPointer ): T { - this.`io_realm_kotlin_objectReference` = RealmObjectReference( + this.io_realm_kotlin_objectReference = RealmObjectReference( type = type, owner = realm, mediator = mediator, @@ -45,7 +45,7 @@ internal fun RealmObjectInternal.manage( RealmInterop.realm_object_get_table(objectPointer) ).name } else { - realmObjectCompanionOrThrow(type).`io_realm_kotlin_className` + realmObjectCompanionOrThrow(type).io_realm_kotlin_className } ) @@ -106,6 +106,7 @@ internal fun RealmObjectReference.toRealmObject(): T = /** * Returns the [RealmObjectCompanion] associated with a given [BaseRealmObject]'s [KClass]. */ +@Suppress("NOTHING_TO_INLINE") internal inline fun KClass<*>.realmObjectCompanionOrNull(): RealmObjectCompanion? { @Suppress("invisible_reference", "invisible_member") return realmObjectCompanionOrNull(this) @@ -125,7 +126,8 @@ internal inline fun KClass.realmObjectCompanion * This will be `null` for unmanaged objects. */ internal val T.realmObjectReference: RealmObjectReference? - get() = (this as RealmObjectInternal).`io_realm_kotlin_objectReference` as RealmObjectReference? + @Suppress("UNCHECKED_CAST") + get() = (this as RealmObjectInternal).io_realm_kotlin_objectReference as RealmObjectReference? /** * If the Realm Object is managed it calls the specified function block and returns its result, @@ -184,6 +186,7 @@ internal fun createDetachedCopy( cache: ManagedToUnmanagedObjectCache, ): T { val id = realmObject.getIdentifier() + @Suppress("UNCHECKED_CAST") val result: BaseRealmObject = cache[id] as T? ?: run { val unmanagedObject = mediator.companionOf(realmObject::class).`io_realm_kotlin_newInstance`() as BaseRealmObject cache[id] = unmanagedObject @@ -201,5 +204,6 @@ internal fun createDetachedCopy( if (closeAfterCopy) { realmObject.realmObjectReference!!.objectPointer.release() } + @Suppress("UNCHECKED_CAST") return result as T } diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUUIDImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUUIDImpl.kt index 17c630915b..9f7158c01d 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUUIDImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUUIDImpl.kt @@ -103,6 +103,8 @@ public class RealmUUIDImpl : RealmUUID { } } } - +@Suppress("NOTHING_TO_INLINE") public inline fun RealmUUID.asBsonBinary(): BsonBinary = BsonBinary(BsonBinarySubType.UUID_STANDARD, bytes) + +@Suppress("NOTHING_TO_INLINE") public inline fun BsonBinary.asRealmUUID(): RealmUUID = RealmUUID.from(data) diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUtils.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUtils.kt index eea159ef51..16f7df2bf9 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUtils.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmUtils.kt @@ -91,7 +91,7 @@ internal fun checkRealmClosed(realm: RealmReference) { } internal fun create(mediator: Mediator, realm: LiveRealmReference, type: KClass): T = - create(mediator, realm, type, realmObjectCompanionOrThrow(type).`io_realm_kotlin_className`) + create(mediator, realm, type, realmObjectCompanionOrThrow(type).io_realm_kotlin_className) internal fun create( mediator: Mediator, @@ -153,6 +153,7 @@ internal fun copyToRealm( throw IllegalArgumentException("Cannot copy an invalid managed object to Realm.") } + @Suppress("UNCHECKED_CAST") return cache[element] as T? ?: element.runIfManaged { if (owner == realmReference) { element @@ -161,7 +162,7 @@ internal fun copyToRealm( } } ?: run { // Create a new object if it wasn't managed - var className: String? + val className: String? var hasPrimaryKey: Boolean = false var primaryKey: Any? = null if (element is DynamicUnmanagedRealmObject) { @@ -179,7 +180,7 @@ internal fun copyToRealm( primaryKey = primaryKeyName?.let { val properties = element.properties if (properties.containsKey(primaryKeyName)) { - properties.get(primaryKeyName) + properties[primaryKeyName] } else { throw IllegalArgumentException("Cannot create object of type '$className' without primary key property '$primaryKeyName'") } @@ -190,7 +191,7 @@ internal fun copyToRealm( if (companion.io_realm_kotlin_classKind == RealmClassKind.EMBEDDED) { throw IllegalArgumentException("Cannot create embedded object without a parent") } - companion.`io_realm_kotlin_primaryKey`?.let { + companion.io_realm_kotlin_primaryKey?.let { hasPrimaryKey = true primaryKey = (it as KProperty1).get(element) } @@ -219,7 +220,7 @@ internal fun copyToRealm( cache[element] = target assign(target, element, updatePolicy, cache) target - } as T + } } /** @@ -241,6 +242,7 @@ public fun TypedRealmObject.getRealm(): T? { if (!this.isManaged()) { return null } + @Suppress("UNCHECKED_CAST") return if (this is RealmObjectInternal) { val objRef: RealmObjectReference = io_realm_kotlin_objectReference!! objRef.owner.owner as T @@ -252,6 +254,7 @@ public fun RealmList<*>.getRealm(): T? { return when (this) { is UnmanagedRealmList -> null is ManagedRealmList -> { + @Suppress("UNCHECKED_CAST") return this.operator.realmReference.owner as T } else -> { @@ -263,6 +266,7 @@ public fun RealmSet<*>.getRealm(): T? { return when (this) { is UnmanagedRealmSet -> null is ManagedRealmSet -> { + @Suppress("UNCHECKED_CAST") return this.operator.realmReference.owner as T } else -> { @@ -274,6 +278,7 @@ public fun RealmDictionary<*>.getRealm(): T? { return when (this) { is UnmanagedRealmDictionary -> null is ManagedRealmDictionary -> { + @Suppress("UNCHECKED_CAST") return this.operator.realmReference.owner as T } else -> { @@ -283,6 +288,7 @@ public fun RealmDictionary<*>.getRealm(): T? { } public fun RealmResults<*>.getRealm(): T { if (this is RealmResultsImpl) { + @Suppress("UNCHECKED_CAST") return this.realm.owner as T } else { throw IllegalStateException("Unsupported results type: $this::class") @@ -291,6 +297,7 @@ public fun RealmResults<*>.getRealm(): T { public fun RealmQuery<*>.getRealm(): T { if (this is ObjectQuery) { + @Suppress("UNCHECKED_CAST") return this.realmReference.owner as T } else { throw IllegalStateException("Unsupported query type: $this::class") diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicMutableRealmObjectImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicMutableRealmObjectImpl.kt index da3665c088..ad8d6088eb 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicMutableRealmObjectImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicMutableRealmObjectImpl.kt @@ -57,7 +57,10 @@ internal class DynamicMutableRealmObjectImpl : DynamicMutableRealmObject, Dynami clazz, nullable = false, issueDynamicMutableObject = true - ).let { it as RealmList } + ).let { + @Suppress("unchecked_cast") + it as RealmList + } } override fun getNullableValueList(propertyName: String, clazz: KClass): RealmList { @@ -81,7 +84,10 @@ internal class DynamicMutableRealmObjectImpl : DynamicMutableRealmObject, Dynami clazz, nullable = false, issueDynamicMutableObject = true - ).let { it as RealmSet } + ).let { + @Suppress("unchecked_cast") + it as RealmSet + } } override fun getNullableValueSet(propertyName: String, clazz: KClass): RealmSet { @@ -100,7 +106,7 @@ internal class DynamicMutableRealmObjectImpl : DynamicMutableRealmObject, Dynami override fun getValueDictionary( propertyName: String, - clazz: KClass + clazz: KClass, ): RealmDictionary { return RealmObjectHelper.dynamicGetDictionary( `io_realm_kotlin_objectReference`!!, @@ -108,7 +114,10 @@ internal class DynamicMutableRealmObjectImpl : DynamicMutableRealmObject, Dynami clazz, nullable = false, issueDynamicMutableObject = true - ).let { it as RealmDictionary } + ).let { + @Suppress("unchecked_cast") + it as RealmDictionary + } } override fun getNullableValueDictionary( diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicRealmObjectImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicRealmObjectImpl.kt index a38dca01fe..5179fb4298 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicRealmObjectImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicRealmObjectImpl.kt @@ -34,15 +34,26 @@ public open class DynamicRealmObjectImpl : DynamicRealmObject, RealmObjectIntern // This should never be null after initialization of a dynamic object, but we currently cannot // represent that in the type system as we one some code paths construct the Kotlin object // before having the realm object reference - override var `io_realm_kotlin_objectReference`: RealmObjectReference? = null + override var `io_realm_kotlin_objectReference`: RealmObjectReference? = + null override fun getValue(propertyName: String, clazz: KClass): T { // dynamicGetSingle checks nullability of property, so null pointer check raises appropriate NPE - return RealmObjectHelper.dynamicGet(this.`io_realm_kotlin_objectReference`!!, propertyName, clazz, false)!! + return RealmObjectHelper.dynamicGet( + obj = this.`io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = false + )!! } override fun getNullableValue(propertyName: String, clazz: KClass): T? { - return RealmObjectHelper.dynamicGet(`io_realm_kotlin_objectReference`!!, propertyName, clazz, true) + return RealmObjectHelper.dynamicGet( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = true + ) } override fun getObject(propertyName: String): DynamicRealmObject? { @@ -50,12 +61,28 @@ public open class DynamicRealmObjectImpl : DynamicRealmObject, RealmObjectIntern } override fun getValueList(propertyName: String, clazz: KClass): RealmList { - return RealmObjectHelper.dynamicGetList(`io_realm_kotlin_objectReference`!!, propertyName, clazz, false) - .let { it as RealmList } + return RealmObjectHelper.dynamicGetList( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = false + ) + .let { + @Suppress("unchecked_cast") + it as RealmList + } } - override fun getNullableValueList(propertyName: String, clazz: KClass): RealmList { - return RealmObjectHelper.dynamicGetList(`io_realm_kotlin_objectReference`!!, propertyName, clazz, true) + override fun getNullableValueList( + propertyName: String, + clazz: KClass, + ): RealmList { + return RealmObjectHelper.dynamicGetList( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = true + ) } override fun getObjectList(propertyName: String): RealmList { @@ -63,12 +90,28 @@ public open class DynamicRealmObjectImpl : DynamicRealmObject, RealmObjectIntern } override fun getValueSet(propertyName: String, clazz: KClass): RealmSet { - return RealmObjectHelper.dynamicGetSet(`io_realm_kotlin_objectReference`!!, propertyName, clazz, false) - .let { it as RealmSet } + return RealmObjectHelper.dynamicGetSet( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = false + ) + .let { + @Suppress("unchecked_cast") + it as RealmSet + } } - override fun getNullableValueSet(propertyName: String, clazz: KClass): RealmSet { - return RealmObjectHelper.dynamicGetSet(`io_realm_kotlin_objectReference`!!, propertyName, clazz, true) + override fun getNullableValueSet( + propertyName: String, + clazz: KClass, + ): RealmSet { + return RealmObjectHelper.dynamicGetSet( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = true + ) } override fun getObjectSet(propertyName: String): RealmSet { @@ -77,17 +120,30 @@ public open class DynamicRealmObjectImpl : DynamicRealmObject, RealmObjectIntern override fun getValueDictionary( propertyName: String, - clazz: KClass + clazz: KClass, ): RealmDictionary { - return RealmObjectHelper.dynamicGetDictionary(`io_realm_kotlin_objectReference`!!, propertyName, clazz, false) - .let { it as RealmDictionary } + return RealmObjectHelper.dynamicGetDictionary( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = false + ) + .let { + @Suppress("unchecked_cast") + it as RealmDictionary + } } override fun getNullableValueDictionary( propertyName: String, - clazz: KClass + clazz: KClass, ): RealmDictionary { - return RealmObjectHelper.dynamicGetDictionary(`io_realm_kotlin_objectReference`!!, propertyName, clazz, true) + return RealmObjectHelper.dynamicGetDictionary( + obj = `io_realm_kotlin_objectReference`!!, + propertyName = propertyName, + clazz = clazz, + nullable = true + ) } override fun getObjectDictionary(propertyName: String): RealmDictionary { @@ -95,6 +151,9 @@ public open class DynamicRealmObjectImpl : DynamicRealmObject, RealmObjectIntern } override fun getBacklinks(propertyName: String): RealmResults { - return RealmObjectHelper.dynamicGetBacklinks(`io_realm_kotlin_objectReference`!!, propertyName) + return RealmObjectHelper.dynamicGetBacklinks( + `io_realm_kotlin_objectReference`!!, + propertyName + ) } } diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicUnmanagedRealmObject.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicUnmanagedRealmObject.kt index 1eb16172ce..99f7947433 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicUnmanagedRealmObject.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/dynamic/DynamicUnmanagedRealmObject.kt @@ -1,3 +1,5 @@ +@file:Suppress("UNCHECKED_CAST") + package io.realm.kotlin.internal.dynamic import io.realm.kotlin.dynamic.DynamicMutableRealmObject diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/CoroutineUtils.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/CoroutineUtils.kt index 270198220c..258b908930 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/CoroutineUtils.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/CoroutineUtils.kt @@ -1,7 +1,10 @@ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.internal.platform import kotlinx.coroutines.CloseableCoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/ScalarQuery.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/ScalarQuery.kt index 2c7911e5bc..673a5e5a79 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/ScalarQuery.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/ScalarQuery.kt @@ -129,7 +129,7 @@ internal class MinMaxQuery constructor( private val queryType: AggregatorQueryType ) : BaseScalarQuery(realmReference, queryPointer, mediator, classKey, clazz), TypeBoundQuery, RealmScalarNullableQuery { - @Suppress("ExplicitItLambdaParameter") + @Suppress("ExplicitItLambdaParameter", "UNCHECKED_CAST") override val converter: (RealmValue) -> T? = when (propertyMetadata.type) { PropertyType.RLM_PROPERTY_TYPE_INT -> { it -> IntConverter.fromRealmValue(it)?.let { coerceLong(propertyMetadata.name, it, type) } as T? } PropertyType.RLM_PROPERTY_TYPE_FLOAT -> { it -> FloatConverter.fromRealmValue(it)?.let { coerceFloat(propertyMetadata.name, it, type) } as T? } @@ -182,7 +182,7 @@ internal class MinMaxQuery constructor( transport, null, mediator, realmReference, false, false, ) as T? else -> converter(transport) - } as T? + } } } @@ -201,7 +201,7 @@ internal class SumQuery constructor( private val type: KClass ) : BaseScalarQuery(realmReference, queryPointer, mediator, classKey, clazz), TypeBoundQuery, RealmScalarQuery { - @Suppress("ExplicitItLambdaParameter") + @Suppress("ExplicitItLambdaParameter", "unchecked_cast") override val converter: (RealmValue) -> T? = when (propertyMetadata.type) { PropertyType.RLM_PROPERTY_TYPE_INT -> { it -> IntConverter.fromRealmValue(it)?.let { coerceLong(propertyMetadata.name, it, type) } as T? } PropertyType.RLM_PROPERTY_TYPE_FLOAT -> { it -> DoubleConverter.fromRealmValue(it)?.let { coerceDouble(propertyMetadata.name, it, type) } as T? } diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/SingleQuery.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/SingleQuery.kt index 3db3de2c10..977de67d88 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/SingleQuery.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/SingleQuery.kt @@ -20,6 +20,7 @@ import io.realm.kotlin.notifications.internal.DeletedObjectImpl import io.realm.kotlin.notifications.internal.PendingObjectImpl import io.realm.kotlin.query.RealmSingleQuery import io.realm.kotlin.types.BaseRealmObject +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.flatMapLatest @@ -56,6 +57,7 @@ internal class SingleQuery constructor( * new head if any. * If there is an update, we ignore it, as the object flow would automatically emit the event. */ + @OptIn(ExperimentalCoroutinesApi::class) override fun asFlow(keyPaths: List?): Flow> { var oldHead: E? = null val keyPathInfo = keyPaths?.let { diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Channel.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Channel.kt index 4278ebcac5..70ef790127 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Channel.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Channel.kt @@ -23,6 +23,7 @@ import kotlinx.coroutines.channels.ChannelResult import kotlinx.coroutines.channels.ProducerScope // Conventional try-with-resource wrapper for channels +@Suppress("NOTHING_TO_INLINE") public inline fun , R> T.use(block: (channel: T) -> R): R { try { return block(this) @@ -32,10 +33,12 @@ public inline fun , R> T.use(block: (channel: T) -> R): R { } // Public to be accessible from sync progress listeners +@Suppress("NOTHING_TO_INLINE") public inline fun ProducerScope.trySendWithBufferOverflowCheck(value: T) { trySend(value).checkForBufferOverFlow()?.let { cancel(it) } } +@Suppress("NOTHING_TO_INLINE") public inline fun ChannelResult.checkForBufferOverFlow(): CancellationException? = if (!isClosed && isFailure) { CancellationException( diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Flow.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Flow.kt index 382d622ceb..2285c7ff55 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Flow.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/util/Flow.kt @@ -15,6 +15,7 @@ */ package io.realm.kotlin.internal.util +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow @@ -25,6 +26,7 @@ import kotlinx.coroutines.selects.whileSelect * Flow wrapper that will terminate the flow once the [completionFlow] emits an element that * satisfies the [completionPredicate]. */ +@OptIn(ExperimentalCoroutinesApi::class) internal fun Flow.terminateWhen( completionFlow: Flow, completionPredicate: (S) -> Boolean diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/log/RealmLog.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/log/RealmLog.kt index 5b066e57b0..04e76bf587 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/log/RealmLog.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/log/RealmLog.kt @@ -174,6 +174,7 @@ public object RealmLog { /** * Log a message. */ + @Suppress("NOTHING_TO_INLINE") internal inline fun doLog( category: LogCategory, level: LogLevel, @@ -186,7 +187,7 @@ public object RealmLog { level = level, throwable = throwable, message = message, - args = *args + args = args ) } diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/types/MutableRealmInt.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/types/MutableRealmInt.kt index 44760062a8..faa3783b3f 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/types/MutableRealmInt.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/types/MutableRealmInt.kt @@ -167,6 +167,10 @@ public abstract class MutableRealmInt : Comparable, Number() { override fun toByte(): Byte = get().toByte() + @Deprecated( + "Direct conversion to Char is deprecated. Use toInt().toChar() or Char constructor instead.\nSee https://youtrack.jetbrains.com/issue/KT-46465 for details about the migration", + replaceWith = ReplaceWith("this.toInt().toChar()") + ) override fun toChar(): Char = get().toInt().toChar() override fun toDouble(): Double = get().toDouble() diff --git a/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/CoroutineUtilsSharedJvm.kt b/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/CoroutineUtilsSharedJvm.kt index 5a47b93231..ac74b48745 100644 --- a/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/CoroutineUtilsSharedJvm.kt +++ b/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/CoroutineUtilsSharedJvm.kt @@ -1,7 +1,10 @@ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.internal.platform import kotlinx.coroutines.CloseableCoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.asCoroutineDispatcher import java.util.concurrent.Executors import kotlin.coroutines.CoroutineContext diff --git a/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/StdOutLogger.kt b/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/StdOutLogger.kt index a4179f4345..1998e1e027 100644 --- a/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/StdOutLogger.kt +++ b/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/StdOutLogger.kt @@ -42,7 +42,7 @@ internal class StdOutLogger( val logMessage: String = prepareLogMessage( throwable = throwable, message = messageWithCategory(category, message), - args = *args + args = args ) val timestamp: String = getTimestamp() println("$timestamp ${level.name}: [$tag] $logMessage") @@ -55,7 +55,7 @@ internal class StdOutLogger( * * We cannot use `DateFormatter` as it isn't thread-safe. */ - @Suppress("NewApi") + @Suppress("NewApi", "NOTHING_TO_INLINE") private inline fun getTimestamp(): String { return TIMESTAMP_FORMATTER.format(Instant.now().atZone(ZoneId.systemDefault())) } diff --git a/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/NSLogLogger.kt b/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/NSLogLogger.kt index 4b01fed2ca..6caa94aef5 100644 --- a/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/NSLogLogger.kt +++ b/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/NSLogLogger.kt @@ -42,7 +42,7 @@ internal class NSLogLogger( val logMessage: String = prepareLogMessage( throwable = throwable, message = messageWithCategory(category, message), - args = *args, + args = args, ) NSLog("%s: [%s] %s", level.name, tag, logMessage) @@ -107,5 +107,6 @@ internal class NSLogLogger( // TODO `throwable.stackTraceToString()` have a memory leak. See https://youtrack.jetbrains.com/issue/KT-46291. // So use a slimmed down version until it has been fixed. + @Suppress("NOTHING_TO_INLINE") private inline fun dumpStackTrace(throwable: Throwable): String = throwable.toString() } diff --git a/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt b/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt index 87ad3abf97..a1c269ebb4 100644 --- a/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt +++ b/packages/library-base/src/nativeDarwin/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2021 Realm Inc. + * + * 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 io.realm.kotlin.internal.platform import io.realm.kotlin.internal.RealmInstantImpl @@ -5,6 +20,7 @@ import io.realm.kotlin.internal.interop.SyncConnectionParams import io.realm.kotlin.internal.util.Exceptions import io.realm.kotlin.log.RealmLogger import io.realm.kotlin.types.RealmInstant +import kotlinx.cinterop.BetaInteropApi import kotlinx.cinterop.BooleanVar import kotlinx.cinterop.ObjCObjectVar import kotlinx.cinterop.ULongVar @@ -126,6 +142,7 @@ public actual fun returnType(field: KMutableProperty1 return field.returnType } +@OptIn(BetaInteropApi::class) private fun preparePath(directoryPath: String, dir: NSURL) { val fm = NSFileManager.defaultManager memScoped { diff --git a/packages/library-base/src/nativeMacos/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt b/packages/library-base/src/nativeMacos/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt index 563382605b..9b5ba128b3 100644 --- a/packages/library-base/src/nativeMacos/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt +++ b/packages/library-base/src/nativeMacos/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2021 Realm Inc. + * + * 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 io.realm.kotlin.internal.platform import kotlinx.cinterop.alloc diff --git a/packages/library-sync/build.gradle.kts b/packages/library-sync/build.gradle.kts index 3860ab158a..9b0410eca7 100644 --- a/packages/library-sync/build.gradle.kts +++ b/packages/library-sync/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + /* * Copyright 2020 Realm Inc. * @@ -33,9 +36,10 @@ project.extensions.configure(kotlinx.atomicfu.plugin.gradle.AtomicFUPluginExtens } // Common Kotlin configuration +@Suppress("UNUSED_VARIABLE") kotlin { jvm() - androidTarget("android") { + androidTarget { // Changing this will also requires an update to the publishCIPackages task // in /packages/build.gradle.kts publishLibraryVariants("release") @@ -116,20 +120,25 @@ kotlin { // Using a custom name module for internal methods to avoid default name mangling in Kotlin compiler which uses the module // name and build type variant as a suffix, this default behaviour can cause mismatch at runtime https://github.com/realm/realm-kotlin/issues/621 -tasks.withType().configureEach { - kotlinOptions { - freeCompilerArgs = listOf("-module-name", "io.realm.kotlin.library") +tasks.withType>().configureEach { + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") } } +tasks.withType().configureEach { + compilerOptions.moduleName.set("io.realm.kotlin.library") +} + // Android configuration android { - compileSdkVersion(Versions.Android.compileSdkVersion) + namespace = "io.realm.kotlin.mongodb" + compileSdk = Versions.Android.compileSdkVersion buildToolsVersion = Versions.Android.buildToolsVersion defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) + minSdk = Versions.Android.minSdk + targetSdk = Versions.Android.targetSdk testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" sourceSets { diff --git a/packages/library-sync/gradle.properties b/packages/library-sync/gradle.properties new file mode 100644 index 0000000000..63de1180aa --- /dev/null +++ b/packages/library-sync/gradle.properties @@ -0,0 +1,16 @@ +# +# Copyright 2024 Realm Inc. +# +# 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. +# +kotlin.mpp.applyDefaultHierarchyTemplate=false diff --git a/packages/library-sync/src/androidMain/AndroidManifest.xml b/packages/library-sync/src/androidMain/AndroidManifest.xml index 34c98bc70e..a01e9d54ca 100644 --- a/packages/library-sync/src/androidMain/AndroidManifest.xml +++ b/packages/library-sync/src/androidMain/AndroidManifest.xml @@ -16,8 +16,7 @@ --> + xmlns:tools="http://schemas.android.com/tools"> diff --git a/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt b/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt index 2217071573..49b07d01d7 100644 --- a/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt +++ b/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt @@ -24,7 +24,6 @@ import android.net.ConnectivityManager import android.net.ConnectivityManager.NetworkCallback import android.net.Network import android.net.NetworkCapabilities -import android.net.NetworkInfo import android.net.NetworkRequest import android.os.Build import androidx.startup.Initializer @@ -43,7 +42,7 @@ internal class RealmSyncInitializer : Initializer { @Suppress("DEPRECATION") // Should only be called below API 21 fun isConnected(cm: ConnectivityManager?): Boolean { return cm?.let { - val networkInfo: NetworkInfo? = cm.activeNetworkInfo + val networkInfo: android.net.NetworkInfo? = cm.activeNetworkInfo networkInfo != null && networkInfo.isConnectedOrConnecting || isEmulator() } ?: true } diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/ext/UserExt.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/ext/UserExt.kt index 72384cff01..5846b130dc 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/ext/UserExt.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/ext/UserExt.kt @@ -32,6 +32,7 @@ import org.mongodb.kbson.serialization.EJson * * @return The profile for this user. */ +@Suppress("NOTHING_TO_INLINE") public inline fun User.profileAsBsonDocument(): BsonDocument = (this as UserImpl).profileInternal { ejson -> Bson(ejson) as BsonDocument @@ -45,6 +46,7 @@ public inline fun User.profileAsBsonDocument(): BsonDocument = * * @return The custom user data associated with the user. */ +@Suppress("NOTHING_TO_INLINE") public inline fun User.customDataAsBsonDocument(): BsonDocument? = (this as UserImpl).customDataInternal { ejson -> Bson(ejson) as BsonDocument diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MongoCollectionImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MongoCollectionImpl.kt index a8af3b37a5..f88504e6d2 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MongoCollectionImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MongoCollectionImpl.kt @@ -232,6 +232,7 @@ internal inline fun MongoCollectionImpl<*>.decodeFromBsonValue(bsonV @PublishedApi internal inline fun MongoCollectionImpl<*>.decodeFromBsonValueList(bsonValues: List): List { return if (R::class == BsonValue::class) { + @Suppress("UNCHECKED_CAST") bsonValues as List } else { bsonValues.map { eJson.decodeFromBsonValue(it) } diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt index 4d6395dd1d..9fcfdc8a1b 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt @@ -142,11 +142,11 @@ internal open class SyncSessionImpl( token.value = NotificationToken( RealmInterop.realm_sync_session_register_connection_state_change_callback( nativePointer - ) { oldState: Int, newState: Int -> + ) { oldState: CoreConnectionState, newState: CoreConnectionState -> trySendWithBufferOverflowCheck( ConnectionStateChange( - connectionStateFrom(CoreConnectionState.of(oldState)), - connectionStateFrom(CoreConnectionState.of(newState)) + connectionStateFrom(oldState), + connectionStateFrom(newState) ) ) } diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncedRealmContext.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncedRealmContext.kt index 95c505b1f3..5cde72de64 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncedRealmContext.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncedRealmContext.kt @@ -94,6 +94,7 @@ private fun initSyncContextIfNeeded(realm: T): SyncedRealmContex // Kotlin Native. val syncContext = (realm as RealmImpl).syncContext return if (syncContext.value != null) { + @Suppress("UNCHECKED_CAST") syncContext.value!! as SyncedRealmContext } else { // Worst case, two SyncedRealmContext will be created and one of them will thrown @@ -101,6 +102,7 @@ private fun initSyncContextIfNeeded(realm: T): SyncedRealmContex // some point, it start having too much state, we can consider making `lazy` properties // inside the class to defer the construction cost. syncContext.compareAndSet(null, SyncedRealmContext(realm)) + @Suppress("UNCHECKED_CAST") syncContext.value!! as SyncedRealmContext } } diff --git a/packages/plugin-compiler/build.gradle.kts b/packages/plugin-compiler/build.gradle.kts index 7ed67284cc..e3059adea5 100644 --- a/packages/plugin-compiler/build.gradle.kts +++ b/packages/plugin-compiler/build.gradle.kts @@ -23,11 +23,15 @@ plugins { val mavenPublicationName = "compilerPlugin" dependencies { + kapt("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") + annotationProcessor("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") compileOnly("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") // Added to prevent warnings about inconsistent versions // w: Runtime JAR files in the classpath should have the same version. These files were found in the classpath: // w: Consider providing an explicit dependency on kotlin-reflect 1.4 to prevent strange errors implementation(kotlin("reflect")) + kapt(Deps.autoService) + annotationProcessor(Deps.autoService) compileOnly(Deps.autoService) kapt(Deps.autoServiceAnnotation) @@ -42,9 +46,7 @@ dependencies { } tasks.withType { - kotlinOptions { - freeCompilerArgs = listOf("-Xjvm-default=all-compatibility") - } + compilerOptions.freeCompilerArgs.add("-Xjvm-default=all-compatibility") } realmPublish { diff --git a/packages/plugin-compiler/gradle.properties b/packages/plugin-compiler/gradle.properties new file mode 100644 index 0000000000..63de1180aa --- /dev/null +++ b/packages/plugin-compiler/gradle.properties @@ -0,0 +1,16 @@ +# +# Copyright 2024 Realm Inc. +# +# 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. +# +kotlin.mpp.applyDefaultHierarchyTemplate=false diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/AccessorModifierIrGeneration.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/AccessorModifierIrGeneration.kt index 5db24b72c2..9b0d917c01 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/AccessorModifierIrGeneration.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/AccessorModifierIrGeneration.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(UnsafeDuringIrConstructionAPI::class) + package io.realm.kotlin.compiler import io.realm.kotlin.compiler.ClassIds.ASYMMETRIC_OBJECT_INTERFACE @@ -82,6 +84,7 @@ import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrDeclarationReference +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeArgument diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index d2da55690b..2fe6836975 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(UnsafeDuringIrConstructionAPI::class, UnsafeDuringIrConstructionAPI::class) + package io.realm.kotlin.compiler import io.realm.kotlin.compiler.ClassIds.ASYMMETRIC_OBJECT_INTERFACE @@ -89,6 +91,7 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeArgument @@ -150,6 +153,7 @@ val anyRealmObjectInterfacesFqNames = realmObjectInterfaceFqNames + realmEmbedde fun IrType.classIdOrFail(): ClassId = getClass()?.classId ?: error("Can't get classId of ${render()}") +@Suppress("NOTHING_TO_INLINE") inline fun PsiElement.hasInterface(interfaces: Set): Boolean { var hasRealmObjectAsSuperType = false this.acceptChildren(object : PsiElementVisitor() { @@ -177,6 +181,8 @@ inline fun PsiElement.hasInterface(interfaces: Set): Boolean { return hasRealmObjectAsSuperType } + +@Suppress("NOTHING_TO_INLINE") inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set): Boolean { // Using PSI to find super types to avoid cyclic reference (see https://github.com/realm/realm-kotlin/issues/339) return this.findPsi()?.hasInterface(interfaces) ?: false @@ -309,6 +315,7 @@ internal fun IrPluginContext.lookupConstructorInClass( internal fun IrClass.lookupCompanionDeclaration( name: Name ): T { + @Suppress("UNCHECKED_CAST") return this.companionObject()?.declarations?.first { it is IrDeclarationWithName && it.name == name } as T diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt index 996c947463..71b741a572 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt @@ -1,3 +1,5 @@ +@file:OptIn(UnsafeDuringIrConstructionAPI::class) + package io.realm.kotlin.compiler import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext @@ -8,6 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.name.Name diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt index 2ee010aafc..c01a74dbcd 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(UnsafeDuringIrConstructionAPI::class) + package io.realm.kotlin.compiler import io.realm.kotlin.compiler.ClassIds.MODEL_OBJECT_ANNOTATION @@ -32,6 +34,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.starProjectedType import org.jetbrains.kotlin.ir.util.companionObject diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticCompanionExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticCompanionExtension.kt index f72760985b..bacc16f120 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticCompanionExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticCompanionExtension.kt @@ -106,16 +106,17 @@ class RealmModelSyntheticCompanionExtension : SyntheticResolveExtension { companionClass.source ).apply { initialize( - null, - companionClass.thisAsReceiverParameter, - emptyList(), - emptyList(), + /* extensionReceiverParameter = */ null, + /* dispatchReceiverParameter = */ companionClass.thisAsReceiverParameter, + /* contextReceiverParameters = */ emptyList(), + /* typeParameters = */ emptyList(), + /* unsubstitutedValueParameters = */ emptyList(), // FIXME Howto resolve types from "runtime" module. Should be // `io.realm.kotlin.internal.Table`, but doesn't seem to break as long as the actual // implementation return type can be cast to this return type - realmObjectClass.builtIns.anyType, - Modality.OPEN, - DescriptorVisibilities.PUBLIC + /* unsubstitutedReturnType = */ realmObjectClass.builtIns.anyType, + /* modality = */ Modality.OPEN, + /* visibility = */ DescriptorVisibilities.PUBLIC ) } } @@ -133,13 +134,14 @@ class RealmModelSyntheticCompanionExtension : SyntheticResolveExtension { companionClass.source ).apply { initialize( - null, - companionClass.thisAsReceiverParameter, - emptyList(), - emptyList(), - realmObjectClass.builtIns.anyType, - Modality.OPEN, - DescriptorVisibilities.PUBLIC + /* extensionReceiverParameter = */ null, + /* dispatchReceiverParameter = */ companionClass.thisAsReceiverParameter, + /* contextReceiverParameters = */ emptyList(), + /* typeParameters = */ emptyList(), + /* unsubstitutedValueParameters = */ emptyList(), + /* unsubstitutedReturnType = */ realmObjectClass.builtIns.anyType, + /* modality = */ Modality.OPEN, + /* visibility = */ DescriptorVisibilities.PUBLIC ) } } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt index b689042620..0ce7399497 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(UnsafeDuringIrConstructionAPI::class) + package io.realm.kotlin.compiler import io.realm.kotlin.compiler.ClassIds.CLASS_INFO @@ -90,6 +92,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrPropertyReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classFqName diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt index dd9f77fd65..0218a50d72 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.com.intellij.mock.MockProject import org.jetbrains.kotlin.com.intellij.openapi.extensions.LoadingOrder -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter @@ -47,13 +46,14 @@ import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension * The [RealmObjectCompanion] holds static information about the schema (members, primary key, etc.) * and utility methods for constructing objects, etc. */ -@AutoService(ComponentRegistrar::class) +@Suppress("deprecation") +@AutoService(org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar::class) @OptIn(ExperimentalCompilerApi::class) // TODO ComponentRegistrar is deprecated. Should be migrated to CompilerPluginRegistrar to support // indicating whether plugin is k2-compatible, etc. See these issues for more context: // - https://youtrack.jetbrains.com/issue/KT-52665/Deprecate-ComponentRegistrar // - https://youtrack.jetbrains.com/issue/KT-55300 -class Registrar : ComponentRegistrar { +class Registrar : org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar { override fun registerProjectComponents( project: MockProject, configuration: CompilerConfiguration diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt index 28d3443ea7..c85173b3f1 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(UnsafeDuringIrConstructionAPI::class) + package io.realm.kotlin.compiler import io.realm.kotlin.compiler.ClassIds.APP_CONFIGURATION_BUILDER @@ -35,6 +37,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.util.companionObject import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid diff --git a/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt b/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt index 3280f61993..29ac0c46fc 100644 --- a/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt +++ b/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt @@ -38,7 +38,6 @@ import io.realm.kotlin.internal.schema.SchemaMetadata import io.realm.kotlin.types.BaseRealmObject import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.TypedRealmObject -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.junit.Test import java.io.File @@ -127,7 +126,7 @@ class GenerationExtensionTest { assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode) val kClazz = result.classLoader.loadClass("sample.input.Sample") - val sampleModel = kClazz.newInstance()!! + val sampleModel = kClazz.getDeclaredConstructor().newInstance()!! assertTrue(sampleModel is RealmObject) assertTrue(sampleModel is RealmObjectInternal) @@ -337,7 +336,7 @@ class GenerationExtensionTest { assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode) val kClazz = result.classLoader.loadClass("sample.input.Sample") - val sampleModel = kClazz.newInstance()!! + val sampleModel = kClazz.getDeclaredConstructor().newInstance()!! val nameProperty = sampleModel::class.members.find { it.name == "stringField" } ?: fail("Couldn't find property name of class Sample") assertTrue(nameProperty is KMutableProperty<*>) @@ -384,9 +383,10 @@ class GenerationExtensionTest { inputs.assertGeneratedIR() } + @Suppress("deprecation") private fun compile( inputs: Files, - plugins: List = listOf(Registrar()), + plugins: List = listOf(Registrar()), options: List = emptyList(), ): JvmCompilationResult { return KotlinCompilation().apply { diff --git a/packages/settings.gradle.kts b/packages/settings.gradle.kts index 511d23763d..6ea6605fde 100644 --- a/packages/settings.gradle.kts +++ b/packages/settings.gradle.kts @@ -24,6 +24,7 @@ dependencyResolutionManagement { getPropertyValue("testRepository")?.let { maven("file://${rootDir.absolutePath}/$it") } +// maven("https://oss.sonatype.org/content/repositories/snapshots") } } fun getPropertyValue(propertyName: String): String? { diff --git a/packages/test-base/build.gradle.kts b/packages/test-base/build.gradle.kts index 5651ba1111..3fc4722ce4 100644 --- a/packages/test-base/build.gradle.kts +++ b/packages/test-base/build.gradle.kts @@ -16,6 +16,9 @@ */ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithSimulatorTests +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile +import kotlin.math.min plugins { id("org.jetbrains.kotlin.multiplatform") @@ -69,6 +72,7 @@ configurations.all { } // Common Kotlin configuration +@Suppress("UNUSED_VARIABLE") kotlin { sourceSets { val commonMain by getting { @@ -100,6 +104,7 @@ kotlin { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.coroutines}") + implementation(kotlin("reflect")) } } } @@ -107,12 +112,13 @@ kotlin { // Android configuration android { - compileSdkVersion(Versions.Android.compileSdkVersion) + namespace = "io.realm.testapp" + compileSdk = Versions.Android.compileSdkVersion buildToolsVersion = Versions.Android.buildToolsVersion defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) + minSdk = Versions.Android.minSdk + targetSdk = Versions.Android.targetSdk multiDexEnabled = true testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -153,13 +159,13 @@ android { // Remove overlapping resources after adding "org.jetbrains.kotlinx:kotlinx-coroutines-test" to // avoid errors like "More than one file was found with OS independent path 'META-INF/AL2.0'." packagingOptions { - exclude("META-INF/AL2.0") - exclude("META-INF/LGPL2.1") + resources.excludes.add("META-INF/AL2.0") + resources.excludes.add("META-INF/LGPL2.1") } } - +@Suppress("UNUSED_VARIABLE") kotlin { - android("android") + androidTarget() sourceSets { val commonTest by getting val androidMain by getting { @@ -217,7 +223,7 @@ kotlin { } } } - +@Suppress("UNUSED_VARIABLE") kotlin { jvm() sourceSets { @@ -236,7 +242,7 @@ kotlin { } } } - +@Suppress("UNUSED_VARIABLE") kotlin { if (HOST_OS == OperatingSystem.MACOS_ARM64) { iosSimulatorArm64("ios") @@ -271,9 +277,15 @@ kotlin { } } -tasks.withType().all { - kotlinOptions { - freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") +tasks.withType>().configureEach { + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } +} + +tasks.withType().configureEach { + compilerOptions { + freeCompilerArgs.add("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") } } diff --git a/packages/test-base/gradle.properties b/packages/test-base/gradle.properties new file mode 100644 index 0000000000..63de1180aa --- /dev/null +++ b/packages/test-base/gradle.properties @@ -0,0 +1,16 @@ +# +# Copyright 2024 Realm Inc. +# +# 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. +# +kotlin.mpp.applyDefaultHierarchyTemplate=false diff --git a/packages/test-base/src/androidMain/AndroidManifest.xml b/packages/test-base/src/androidMain/AndroidManifest.xml index b024a2db1a..9cb277137c 100644 --- a/packages/test-base/src/androidMain/AndroidManifest.xml +++ b/packages/test-base/src/androidMain/AndroidManifest.xml @@ -15,8 +15,7 @@ ~ limitations under the License. --> - + diff --git a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/primarykey/PrimaryKey.kt b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/primarykey/PrimaryKey.kt index f1aa4df3f4..3022741bec 100644 --- a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/primarykey/PrimaryKey.kt +++ b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/primarykey/PrimaryKey.kt @@ -39,12 +39,12 @@ class PrimaryKeyByteNullable : RealmObject { class PrimaryKeyChar : RealmObject { @PrimaryKey - var primaryKey: Char = Random.nextULong().toByte().toChar() + var primaryKey: Char = Random.nextULong().toInt().toChar() } class PrimaryKeyCharNullable : RealmObject { @PrimaryKey - var primaryKey: Char? = Random.nextULong().toByte().toChar() + var primaryKey: Char? = Random.nextULong().toInt().toChar() } class PrimaryKeyShort : RealmObject { diff --git a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt index cbf3a8bb2c..07f07f59b9 100644 --- a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt +++ b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt @@ -16,9 +16,7 @@ package io.realm.kotlin.test.platform -import kotlinx.coroutines.CoroutineScope - -expect class RunLoopThread : CoroutineScope { +expect class RunLoopThread { fun run(block: RunLoopThread.() -> Unit) diff --git a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/util/Utils.kt b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/util/Utils.kt index 34134cb6a4..e267ba80d7 100644 --- a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/util/Utils.kt +++ b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/test/util/Utils.kt @@ -98,6 +98,7 @@ fun Instant.toRealmInstant(): RealmInstant { * Channel implementation specifically suited for tests. Its size is unlimited, but will fail * the test if canceled while still containing unconsumed elements. */ +@Suppress("NOTHING_TO_INLINE") inline fun TestChannel( capacity: Int = Channel.UNLIMITED, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, @@ -114,6 +115,7 @@ inline fun TestChannel( * Helper method that will use `trySend` to send a message to a Channel and throw * an error if `trySend` returns false */ +@Suppress("NOTHING_TO_INLINE") inline fun Channel.trySendOrFail(value: T) { val result: ChannelResult = this.trySend(value) if (result.isFailure) { diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/CopyFromRealmTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/CopyFromRealmTests.kt index 178e6515b0..6bcf6a0efe 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/CopyFromRealmTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/CopyFromRealmTests.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -@file:Suppress("invisible_reference", "invisible_member") +@file:Suppress("invisible_reference", "invisible_member", "unchecked_cast") package io.realm.kotlin.test.common import io.realm.kotlin.Realm @@ -760,10 +760,10 @@ class CopyFromRealmTests { intField = 3 } - val managedSample1 = realm.writeBlocking { + val managedSample1: Sample = realm.writeBlocking { copyToRealm(sample) } - val managedSample2 = realm.writeBlocking { + val managedSample2: Sample = realm.writeBlocking { findLatest(managedSample1)!!.apply { intField = 42 } @@ -772,7 +772,7 @@ class CopyFromRealmTests { val o2p = (managedSample2 as RealmObjectInternal).io_realm_kotlin_objectReference!!.objectPointer assertFalse(RealmInterop.realm_equals(o1p, o2p)) - val unmanagedObjects = realm.copyFromRealm(listOf(managedSample1, managedSample2)) + val unmanagedObjects = realm.copyFromRealm(listOf(managedSample1, managedSample2)) assertEquals(2, unmanagedObjects.size) val unmanagedSample1 = unmanagedObjects.first() val unmanagedSample2 = unmanagedObjects.last() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/MutableRealmTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/MutableRealmTests.kt index efecc14bfd..5893c2c2aa 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/MutableRealmTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/MutableRealmTests.kt @@ -43,11 +43,11 @@ import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith +import kotlin.test.assertIs import kotlin.test.assertNotEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertSame -import kotlin.test.assertTrue import kotlin.test.fail @Suppress("LargeClass") @@ -469,7 +469,7 @@ class MutableRealmTests { @Test fun writeReturningUnmanaged() { - assertTrue(realm.writeBlocking { Parent() } is Parent) + assertIs(realm.writeBlocking { Parent() }) } @Test diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt index c9bd4a159d..0be48546b2 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@file:Suppress("unchecked_cast") +@file:OptIn(ExperimentalCoroutinesApi::class) package io.realm.kotlin.test.common @@ -56,6 +58,7 @@ import io.realm.kotlin.types.RealmSet import io.realm.kotlin.types.RealmUUID import io.realm.kotlin.types.annotations.FullText import io.realm.kotlin.types.annotations.PersistedName +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/ReadMeTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/ReadMeTests.kt index 2b3d1a912f..3ce0c5482f 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/ReadMeTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/ReadMeTests.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.test.common import io.realm.kotlin.Realm @@ -43,6 +45,7 @@ import io.realm.kotlin.types.RealmList import io.realm.kotlin.types.RealmObject import kotlinx.coroutines.CloseableCoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.cancel import kotlin.test.AfterTest diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmConfigurationTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmConfigurationTests.kt index e45b2c5c67..887fec0f16 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmConfigurationTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmConfigurationTests.kt @@ -1,4 +1,6 @@ @file:Suppress("invisible_member", "invisible_reference") +@file:OptIn(ExperimentalCoroutinesApi::class) + /* * Copyright 2021 Realm Inc. * @@ -34,6 +36,8 @@ import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.platform.platformFileSystem import io.realm.kotlin.test.util.use import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.newSingleThreadContext import okio.Path.Companion.toPath import kotlin.random.Random @@ -265,17 +269,18 @@ class RealmConfigurationTests { @Test fun notificationDispatcherRealmConfigurationDefault() { val configuration = RealmConfiguration.create(schema = setOf(Sample::class)) - assertTrue((configuration as InternalConfiguration).notificationDispatcherFactory is CoroutineDispatcherFactory) + assertIs((configuration as InternalConfiguration).notificationDispatcherFactory) } @Test fun notificationDispatcherRealmConfigurationBuilderDefault() { val configuration = RealmConfiguration.Builder(schema = setOf(Sample::class)).build() - assertTrue((configuration as InternalConfiguration).notificationDispatcherFactory is CoroutineDispatcherFactory) + assertIs((configuration as InternalConfiguration).notificationDispatcherFactory) } @Test @Suppress("invisible_member") + @DelicateCoroutinesApi fun notificationDispatcherRealmConfigurationBuilder() { val dispatcher = newSingleThreadContext("ConfigurationTest") val configuration = RealmConfiguration.Builder(schema = setOf(Sample::class)) @@ -286,17 +291,18 @@ class RealmConfigurationTests { @Test fun writeDispatcherRealmConfigurationDefault() { val configuration = RealmConfiguration.create(schema = setOf(Sample::class)) - assertTrue((configuration as InternalConfiguration).writeDispatcherFactory.create().dispatcher is CoroutineDispatcher) + assertIs((configuration as InternalConfiguration).writeDispatcherFactory.create().dispatcher) } @Test fun writeDispatcherRealmConfigurationBuilderDefault() { val configuration = RealmConfiguration.Builder(schema = setOf(Sample::class)).build() - assertTrue((configuration as InternalConfiguration).writeDispatcherFactory.create().dispatcher is CoroutineDispatcher) + assertIs((configuration as InternalConfiguration).writeDispatcherFactory.create().dispatcher) } @Test @Suppress("invisible_member") + @DelicateCoroutinesApi fun writeDispatcherRealmConfigurationBuilder() { val dispatcher = newSingleThreadContext("ConfigurationTest") val configuration = @@ -307,6 +313,7 @@ class RealmConfigurationTests { @Test @Suppress("invisible_member") + @DelicateCoroutinesApi fun writesExecutesOnWriteDispatcher() { val dispatcher = newSingleThreadContext("ConfigurationTest") val configuration = diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmDictionaryTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmDictionaryTests.kt index 476616dc9f..c14837b3a8 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmDictionaryTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmDictionaryTests.kt @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@file:Suppress("unchecked_cast") package io.realm.kotlin.test.common diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmListTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmListTests.kt index d4580e747a..a4f9cf1355 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmListTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmListTests.kt @@ -711,6 +711,7 @@ class RealmListTests : EmbeddedObjectCollectionQueryTests { private val managedTesters: List> by lazy { descriptors.map { val elementType = it.elementType + @Suppress("UNCHECKED_CAST") when (val classifier = elementType.classifier) { RealmObject::class -> RealmObjectListTester( realm = realm, diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmObjectTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmObjectTests.kt index 09cf50fec8..b669bc516b 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmObjectTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmObjectTests.kt @@ -319,6 +319,7 @@ class RealmObjectTests : RealmStateTest { // FIXME RealmObject doesn't actually implement RealmState yet @Ignore + @Test override fun isClosed() { TODO("Not yet implemented") } diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSetTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSetTests.kt index 52329bb57c..eadeb1f72e 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSetTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSetTests.kt @@ -72,6 +72,7 @@ class RealmSetTests : CollectionQueryTests { private lateinit var tmpDir: String private lateinit var realm: Realm + @Suppress("UNCHECKED_CAST") private val managedTesters: List> by lazy { descriptors.map { val elementType = it.elementType @@ -797,6 +798,7 @@ internal abstract class ManagedSetTester( realm.writeBlocking { val set = typeSafetyManager.createContainerAndGetCollection(this) val element = if (classifier == RealmObject::class) { + @Suppress("UNCHECKED_CAST") copyToRealm(dataSet[0] as RealmObject) as T } else { dataSet[0] diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmTests.kt index 6265dc6938..6e01a6f7ef 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmTests.kt @@ -35,6 +35,8 @@ import io.realm.kotlin.test.platform.platformFileSystem import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.test.util.use +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.async import kotlinx.coroutines.cancelAndJoin @@ -398,8 +400,10 @@ class RealmTests { assertEquals(1, realm.query().find().size) } + @OptIn(ExperimentalCoroutinesApi::class) @Test @Suppress("invisible_member") + @DelicateCoroutinesApi fun writesOnFrozenRealm() { val dispatcher = newSingleThreadContext("background") runBlocking { diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SerializationTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SerializationTests.kt index 0d02750309..8bf8b69926 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SerializationTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SerializationTests.kt @@ -314,18 +314,12 @@ class SerializationTests { RealmAny.Type.TIMESTAMP -> SerializableSample().apply { nullableRealmAnyField = RealmAny.create(timestampField) } - RealmAny.Type.OBJECT -> SerializableSample().apply { + RealmAny.Type.OBJECT_ID -> SerializableSample().apply { nullableRealmAnyField = RealmAny.create(bsonObjectIdField) } RealmAny.Type.UUID -> SerializableSample().apply { nullableRealmAnyField = RealmAny.create(uuidField) } - RealmAny.Type.OBJECT_ID -> SerializableSample().apply { - SerializableSample().let { - nullableObject = it - nullableRealmAnyField = RealmAny.create(it) - } - } RealmAny.Type.OBJECT -> SerializableSample().apply { SerializableSample().let { nullableObject = it diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/VersionTrackingTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/VersionTrackingTests.kt index a33fa06d16..b0a8bbcaa5 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/VersionTrackingTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/VersionTrackingTests.kt @@ -34,6 +34,7 @@ import io.realm.kotlin.notifications.ResultsChange import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.flow.launchIn @@ -135,6 +136,7 @@ class VersionTrackingTests { } } + @OptIn(DelicateCoroutinesApi::class) @Test fun realmAsFlow_doesNotTrackVersions() = runBlocking { realm.activeVersions().run { diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/dynamic/DynamicMutableRealmObjectTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/dynamic/DynamicMutableRealmObjectTests.kt index 6fcfc90c19..f07fd73009 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/dynamic/DynamicMutableRealmObjectTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/dynamic/DynamicMutableRealmObjectTests.kt @@ -587,6 +587,7 @@ class DynamicMutableRealmObjectTests { clazz ) assertEquals(1, valueList.size) + @Suppress("UNCHECKED_CAST") assertEquals(value, valueList[0] as T) } diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt index 3cf096dfa2..7a58b2f8ac 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt @@ -28,6 +28,7 @@ import io.realm.kotlin.test.common.utils.RealmEntityNotificationTests import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.delay @@ -269,6 +270,7 @@ class BacklinksNotificationsTests : RealmEntityNotificationTests { assertIs>(resultsChange) assertEquals(0, resultsChange.list.size) } + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(c1.isEmpty) observer2.cancel() c1.close() @@ -445,15 +447,11 @@ class BacklinksNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is UpdatedResults -> { - assertEquals(0, resultsChange.insertions.size) - assertEquals(1, resultsChange.changes.size) - assertEquals(0, resultsChange.deletions.size) - assertEquals(2, resultsChange.list.first().objectBacklinks.size) - } - else -> fail("Unexpected change: $resultsChange") - } + + assertEquals(0, resultsChange.insertions.size) + assertEquals(1, resultsChange.changes.size) + assertEquals(0, resultsChange.deletions.size) + assertEquals(2, resultsChange.list.first().objectBacklinks.size) } observer.cancel() c.close() @@ -489,18 +487,14 @@ class BacklinksNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is UpdatedResults -> { - assertEquals(0, resultsChange.insertions.size) - assertEquals(1, resultsChange.changes.size) - assertEquals(0, resultsChange.deletions.size) - assertEquals(1, resultsChange.list.first().objectBacklinks.size) - // This starts at 42, if the first write triggers a change event, it will - // catch it here. - assertEquals(resultsChange.list.first().objectBacklinks.first().intField, 1) - } - else -> fail("Unexpected change: $resultsChange") - } + + assertEquals(0, resultsChange.insertions.size) + assertEquals(1, resultsChange.changes.size) + assertEquals(0, resultsChange.deletions.size) + assertEquals(1, resultsChange.list.first().objectBacklinks.size) + // This starts at 42, if the first write triggers a change event, it will + // catch it here. + assertEquals(resultsChange.list.first().objectBacklinks.first().intField, 1) } observer.cancel() c.close() @@ -556,14 +550,7 @@ class BacklinksNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is ResultsChange<*> -> { - // Default value is 42, so if this event is triggered by the first write - // this assert will fail - assertEquals(1, resultsChange.list.first().intField) - } - else -> fail("Unexpected change: $resultsChange") - } + assertEquals(1, resultsChange.list.first().intField) } observer.cancel() c.close() @@ -618,15 +605,10 @@ class BacklinksNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is ResultsChange<*> -> { - assertEquals(0, resultsChange.insertions.size) - assertEquals(1, resultsChange.changes.size) - assertEquals(0, resultsChange.deletions.size) - assertEquals(1, resultsChange.list.first().objectBacklinks.size) - } - else -> fail("Unexpected change: $resultsChange") - } + assertEquals(0, resultsChange.insertions.size) + assertEquals(1, resultsChange.changes.size) + assertEquals(0, resultsChange.deletions.size) + assertEquals(1, resultsChange.list.first().objectBacklinks.size) } observer.cancel() c.close() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedDictionaryNotificationTest.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedDictionaryNotificationTest.kt index f5b8fa593d..0b25592dd4 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedDictionaryNotificationTest.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedDictionaryNotificationTest.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.test.common.notifications import io.realm.kotlin.Realm @@ -32,6 +34,7 @@ import io.realm.kotlin.test.common.utils.FlowableTests import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.types.RealmAny +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -262,6 +265,7 @@ class RealmAnyNestedDictionaryNotificationTest : FlowableTests, DeletableEntityN TODO("Not yet implemented") } + @Test @Ignore override fun closeRealmInsideFlowThrows() { TODO("Not yet implemented") diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedListNotificationTest.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedListNotificationTest.kt index 99113c3f08..fab126948e 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedListNotificationTest.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmAnyNestedListNotificationTest.kt @@ -34,6 +34,7 @@ import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.test.util.trySendOrFail import io.realm.kotlin.types.RealmAny +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -168,6 +169,7 @@ class RealmAnyNestedListNotificationTest : FlowableTests, DeletableEntityNotific } // Check channel 1 didn't receive the update + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(channel1.isEmpty) // But channel 2 did assertEquals(2, channel2.receiveOrFail().list.size) @@ -251,6 +253,7 @@ class RealmAnyNestedListNotificationTest : FlowableTests, DeletableEntityNotific TODO("Not yet implemented") } + @Test @Ignore override fun closeRealmInsideFlowThrows() { TODO("Not yet implemented") diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmDictionaryNotificationsTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmDictionaryNotificationsTests.kt index cd9fe302fc..240f0a1327 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmDictionaryNotificationsTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmDictionaryNotificationsTests.kt @@ -32,6 +32,7 @@ import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.types.RealmDictionary +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -395,6 +396,7 @@ class RealmDictionaryNotificationsTests : RealmEntityNotificationTests { // Check channel 1 didn't receive the update assertEquals(NULLABLE_DICTIONARY_OBJECT_VALUES.size + 1, channel2.receiveOrFail().map.size) + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(channel1.isEmpty) observer2.cancel() @@ -461,16 +463,11 @@ class RealmDictionaryNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { mapChange -> assertIs>(mapChange) - when (mapChange) { - is UpdatedMap -> { - assertEquals(1, mapChange.changes.size) - assertEquals("1", mapChange.changes.first()) - // This starts as Realm, so if the first write triggers a change event, it will - // catch it here. - assertEquals("Foo", mapChange.map["1"]!!.stringField) - } - else -> fail("Unexpected change: $mapChange") - } + assertEquals(1, mapChange.changes.size) + assertEquals("1", mapChange.changes.first()) + // This starts as Realm, so if the first write triggers a change event, it will + // catch it here. + assertEquals("Foo", mapChange.map["1"]!!.stringField) } observer.cancel() c.close() @@ -586,16 +583,12 @@ class RealmDictionaryNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { mapChange -> assertIs>(mapChange) - when (mapChange) { - is MapChange -> { - // Core will only report something changed to the top-level property. - assertEquals(1, mapChange.changes.size) - // Default value is Realm, so if this event is triggered by the first write - // this assert will fail - assertEquals("Parent change", mapChange.map.values.first()!!.stringField) - } - else -> fail("Unexpected change: $mapChange") - } + + // Core will only report something changed to the top-level property. + assertEquals(1, mapChange.changes.size) + // Default value is Realm, so if this event is triggered by the first write + // this assert will fail + assertEquals("Parent change", mapChange.map.values.first()!!.stringField) } observer.cancel() c.close() @@ -664,13 +657,9 @@ class RealmDictionaryNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { mapChange -> assertIs>(mapChange) - when (mapChange) { - is MapChange -> { - // Core will only report something changed to the top-level property. - assertEquals(1, mapChange.changes.size) - } - else -> fail("Unexpected change: $mapChange") - } + + // Core will only report something changed to the top-level property. + assertEquals(1, mapChange.changes.size) } observer.cancel() c.close() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmListNotificationsTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmListNotificationsTests.kt index da7e69c462..4385b7671e 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmListNotificationsTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmListNotificationsTests.kt @@ -39,6 +39,7 @@ import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.test.util.trySendOrFail import io.realm.kotlin.types.RealmAny import io.realm.kotlin.types.RealmList +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -354,6 +355,7 @@ class RealmListNotificationsTests : RealmEntityNotificationTests { // Check channel 1 didn't receive the update assertEquals(OBJECT_VALUES.size + 1, channel2.receiveOrFail().list.size) + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(channel1.isEmpty) observer2.cancel() @@ -506,15 +508,11 @@ class RealmListNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { listChange -> assertIs>(listChange) - when (listChange) { - is UpdatedList -> { - assertEquals(1, listChange.changes.size) - // This starts as Realm, so if the first write triggers a change event, it will - // catch it here. - assertEquals("Foo", listChange.list.first().stringField) - } - else -> fail("Unexpected change: $listChange") - } + + assertEquals(1, listChange.changes.size) + // This starts as Realm, so if the first write triggers a change event, it will + // catch it here. + assertEquals("Foo", listChange.list.first().stringField) } observer.cancel() c.close() @@ -555,12 +553,8 @@ class RealmListNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { listChange -> assertIs>(listChange) - when (listChange) { - is UpdatedList -> { - assertEquals(1, listChange.changes.size) - } - else -> fail("Unexpected change: $listChange") - } + + assertEquals(1, listChange.changes.size) } observer.cancel() c.close() @@ -625,16 +619,12 @@ class RealmListNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { listChange -> assertIs>(listChange) - when (listChange) { - is ListChange -> { - // Core will only report something changed to the top-level property. - assertEquals(1, listChange.changes.size) - // Default value is -1, so if this event is triggered by the first write - // this assert will fail - assertEquals(1, listChange.list.first().id) - } - else -> fail("Unexpected change: $listChange") - } + + // Core will only report something changed to the top-level property. + assertEquals(1, listChange.changes.size) + // Default value is -1, so if this event is triggered by the first write + // this assert will fail + assertEquals(1, listChange.list.first().id) } observer.cancel() c.close() @@ -698,13 +688,9 @@ class RealmListNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { listChange -> assertIs>(listChange) - when (listChange) { - is ListChange -> { - // Core will only report something changed to the top-level property. - assertEquals(1, listChange.changes.size) - } - else -> fail("Unexpected change: $listChange") - } + + // Core will only report something changed to the top-level property. + assertEquals(1, listChange.changes.size) } observer.cancel() c.close() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmObjectNotificationsTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmObjectNotificationsTests.kt index 4375f90beb..dc15abbee3 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmObjectNotificationsTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmObjectNotificationsTests.kt @@ -29,6 +29,7 @@ import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.test.util.update +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -198,6 +199,7 @@ class RealmObjectNotificationsTests : RealmEntityNotificationTests { assertIs>(objectChange) assertEquals("Baz", objectChange.obj.stringField) } + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(c1.isEmpty) observer2.cancel() c1.close() @@ -324,14 +326,10 @@ class RealmObjectNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { objectChange -> assertIs>(objectChange) - when (objectChange) { - is UpdatedObject -> { - assertEquals(1, objectChange.changedFields.size) - assertEquals("stringField", objectChange.changedFields.first()) - assertEquals("Bar", objectChange.obj.stringField) - } - else -> fail("Unexpected change: $objectChange") - } + + assertEquals(1, objectChange.changedFields.size) + assertEquals("stringField", objectChange.changedFields.first()) + assertEquals("Bar", objectChange.obj.stringField) } observer.cancel() c.close() @@ -366,15 +364,11 @@ class RealmObjectNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { objectChange -> assertIs>(objectChange) - when (objectChange) { - is UpdatedObject -> { - // Core will only report something changed to the top-level property. - assertEquals(1, objectChange.changedFields.size) - assertEquals("nullableObject", objectChange.changedFields.first()) - assertEquals("Bar", objectChange.obj.nullableObject!!.stringField) - } - else -> fail("Unexpected change: $objectChange") - } + + // Core will only report something changed to the top-level property. + assertEquals(1, objectChange.changedFields.size) + assertEquals("nullableObject", objectChange.changedFields.first()) + assertEquals("Bar", objectChange.obj.nullableObject!!.stringField) } observer.cancel() c.close() @@ -422,14 +416,10 @@ class RealmObjectNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { objectChange -> assertIs>(objectChange) - when (objectChange) { - is UpdatedObject -> { - // Default value is Realm, so if this event is triggered by the first write - // this assert will fail - assertEquals("Parent change", objectChange.obj.stringField) - } - else -> fail("Unexpected change: $objectChange") - } + + // Default value is Realm, so if this event is triggered by the first write + // this assert will fail + assertEquals("Parent change", objectChange.obj.stringField) } observer.cancel() c.close() @@ -476,15 +466,11 @@ class RealmObjectNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { objectChange -> assertIs>(objectChange) - when (objectChange) { - is UpdatedObject -> { - // Core will only report something changed to the top-level property. - assertEquals(1, objectChange.changedFields.size) - assertEquals("nullableObject", objectChange.changedFields.first()) - assertEquals("Bar", objectChange.obj.nullableObject!!.nullableObject!!.nullableObject!!.nullableObject!!.nullableObject!!.stringField) - } - else -> fail("Unexpected change: $objectChange") - } + + // Core will only report something changed to the top-level property. + assertEquals(1, objectChange.changedFields.size) + assertEquals("nullableObject", objectChange.changedFields.first()) + assertEquals("Bar", objectChange.obj.nullableObject!!.nullableObject!!.nullableObject!!.nullableObject!!.nullableObject!!.stringField) } observer.cancel() c.close() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmResultsNotificationsTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmResultsNotificationsTests.kt index 906d7b49e8..a58958ea6c 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmResultsNotificationsTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmResultsNotificationsTests.kt @@ -38,6 +38,7 @@ import io.realm.kotlin.test.common.utils.assertIsChangeSet import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.filterNot @@ -319,6 +320,7 @@ class RealmResultsNotificationsTests : FlowableTests, KeyPathFlowableTests { assertIs>(resultsChange) assertEquals(2, resultsChange.list.size) } + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(c1.isEmpty) observer2.cancel() c1.close() @@ -413,12 +415,7 @@ class RealmResultsNotificationsTests : FlowableTests, KeyPathFlowableTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is UpdatedResults -> { - assertEquals(1, resultsChange.changes.size) - } - else -> fail("Unexpected change: $resultsChange") - } + assertEquals(1, resultsChange.changes.size) } observer.cancel() c.close() @@ -455,12 +452,7 @@ class RealmResultsNotificationsTests : FlowableTests, KeyPathFlowableTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is UpdatedResults -> { - assertEquals(1, resultsChange.changes.size) - } - else -> fail("Unexpected change: $resultsChange") - } + assertEquals(1, resultsChange.changes.size) } observer.cancel() c.close() @@ -510,16 +502,11 @@ class RealmResultsNotificationsTests : FlowableTests, KeyPathFlowableTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is ResultsChange<*> -> { - // Core will only report something changed to the top-level property. - assertEquals(1, resultsChange.changes.size) - // Default value is 42, so if this event is triggered by the first write - // this assert will fail - assertEquals(1, resultsChange.list.first().intField) - } - else -> fail("Unexpected change: $resultsChange") - } + // Core will only report something changed to the top-level property. + assertEquals(1, resultsChange.changes.size) + // Default value is 42, so if this event is triggered by the first write + // this assert will fail + assertEquals(1, resultsChange.list.first().intField) } observer.cancel() c.close() @@ -569,13 +556,8 @@ class RealmResultsNotificationsTests : FlowableTests, KeyPathFlowableTests { } c.receiveOrFail().let { resultsChange -> assertIs>(resultsChange) - when (resultsChange) { - is ResultsChange<*> -> { - // Core will only report something changed to the top-level property. - assertEquals(1, resultsChange.changes.size) - } - else -> fail("Unexpected change: $resultsChange") - } + // Core will only report something changed to the top-level property. + assertEquals(1, resultsChange.changes.size) } observer.cancel() c.close() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmSetNotificationsTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmSetNotificationsTests.kt index 3117be3da2..43e777a3b8 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmSetNotificationsTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmSetNotificationsTests.kt @@ -32,6 +32,7 @@ import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.types.RealmSet +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -226,6 +227,7 @@ class RealmSetNotificationsTests : RealmEntityNotificationTests { // Check channel 1 didn't receive the update assertEquals(SET_OBJECT_VALUES.size + 1, channel2.receiveOrFail().set.size) + @OptIn(ExperimentalCoroutinesApi::class) assertTrue(channel1.isEmpty) observer2.cancel() @@ -376,14 +378,9 @@ class RealmSetNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { setChange -> assertIs>(setChange) - when (setChange) { - is UpdatedSet -> { - assertEquals(0, setChange.deletions) - assertEquals(0, setChange.insertions) - assertNotNull(setChange.set.firstOrNull { it.stringField == "Foo" }) - } - else -> fail("Unexpected change: $setChange") - } + assertEquals(0, setChange.deletions) + assertEquals(0, setChange.insertions) + assertNotNull(setChange.set.firstOrNull { it.stringField == "Foo" }) } observer.cancel() c.close() @@ -424,14 +421,9 @@ class RealmSetNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { setChange -> assertIs>(setChange) - when (setChange) { - is UpdatedSet -> { - assertEquals(0, setChange.insertions) - assertEquals(0, setChange.deletions) - assertEquals("Bar", setChange.set.first().objectSetField.first().stringField) - } - else -> fail("Unexpected change: $setChange") - } + assertEquals(0, setChange.insertions) + assertEquals(0, setChange.deletions) + assertEquals("Bar", setChange.set.first().objectSetField.first().stringField) } observer.cancel() c.close() @@ -497,17 +489,12 @@ class RealmSetNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { setChange -> assertIs>(setChange) - when (setChange) { - is SetChange -> { - // Core will only report something changed to the top-level property. - assertEquals(0, setChange.insertions) - assertEquals(0, setChange.deletions) - // Default value is Realm, so if this event is triggered by the first write - // this assert will fail - assertEquals("Bar", setChange.set.first().stringField) - } - else -> fail("Unexpected change: $setChange") - } + // Core will only report something changed to the top-level property. + assertEquals(0, setChange.insertions) + assertEquals(0, setChange.deletions) + // Default value is Realm, so if this event is triggered by the first write + // this assert will fail + assertEquals("Bar", setChange.set.first().stringField) } observer.cancel() c.close() @@ -571,24 +558,19 @@ class RealmSetNotificationsTests : RealmEntityNotificationTests { } c.receiveOrFail().let { setChange -> assertIs>(setChange) - when (setChange) { - is SetChange -> { - // Core will only report something changed to the top-level property. - assertEquals(0, setChange.insertions) - assertEquals(0, setChange.deletions) - assertEquals( - "Bar", - setChange.set.first() - .objectSetField.first() - .objectSetField.first() - .objectSetField.first() - .objectSetField.first() - .objectSetField.first() - .stringField - ) - } - else -> fail("Unexpected change: $setChange") - } + // Core will only report something changed to the top-level property. + assertEquals(0, setChange.insertions) + assertEquals(0, setChange.deletions) + assertEquals( + "Bar", + setChange.set.first() + .objectSetField.first() + .objectSetField.first() + .objectSetField.first() + .objectSetField.first() + .objectSetField.first() + .stringField + ) } observer.cancel() c.close() diff --git a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt index 09874438cc..498ba62df6 100644 --- a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt +++ b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt @@ -83,6 +83,8 @@ actual object PlatformUtils { allocGarbage(0) Thread.sleep(100) System.gc() + // runFinalization is deprecated, could we invoke our finalizers manually? + @Suppress("deprecation") System.runFinalization() } Thread.sleep(5000) // 5 seconds to give the GC some time to process diff --git a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt index 178817903e..05ca42e215 100644 --- a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt +++ b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt @@ -32,6 +32,7 @@ object Compiler { KotlinCompilation().apply { sources = listOf(source) messageOutputStream = System.out + @Suppress("deprecation") componentRegistrars = plugins inheritClassPath = true kotlincArguments = listOf("-Xjvm-default=all-compatibility") diff --git a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/jvm/RealmTests.kt b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/jvm/RealmTests.kt index bba733d103..def22b97a2 100644 --- a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/jvm/RealmTests.kt +++ b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/jvm/RealmTests.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.test.jvm import io.realm.kotlin.Realm @@ -26,6 +28,7 @@ import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.test.util.use import kotlinx.coroutines.CloseableCoroutineDispatcher +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first diff --git a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/Dispatcher.kt b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/Dispatcher.kt index eb2de517d2..bc8c0b24ea 100644 --- a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/Dispatcher.kt +++ b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/Dispatcher.kt @@ -19,6 +19,7 @@ package io.realm.kotlin.test.platform import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Delay +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.Runnable import platform.darwin.DISPATCH_TIME_NOW @@ -38,6 +39,7 @@ internal class NsQueueDispatcher(private val dispatchQueue: dispatch_queue_t) : dispatch_async(dispatchQueue) { block.run() } } + @OptIn(ExperimentalCoroutinesApi::class) override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation) { val queue = dispatch_get_main_queue() diff --git a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt index 87cd82b932..d92ec1d549 100644 --- a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt +++ b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt @@ -30,7 +30,8 @@ import platform.posix.S_IRWXU import platform.posix.nanosleep import platform.posix.pthread_threadid_np import platform.posix.timespec -import kotlin.native.internal.GC +import kotlin.native.runtime.GC +import kotlin.native.runtime.NativeRuntimeApi import kotlin.time.Duration actual object PlatformUtils { @@ -67,6 +68,7 @@ actual object PlatformUtils { } } + @OptIn(NativeRuntimeApi::class) actual fun triggerGC() { GC.collect() } diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt index 7fe01117be..3a2a3dbbe3 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.test.darwin import io.realm.kotlin.internal.platform.singleThreadDispatcher @@ -24,6 +26,7 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.newSingleThreadContext diff --git a/packages/test-sync/build.gradle.kts b/packages/test-sync/build.gradle.kts index 67f7c2d414..8bf974864c 100644 --- a/packages/test-sync/build.gradle.kts +++ b/packages/test-sync/build.gradle.kts @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithSimulatorTests import com.codingfeline.buildkonfig.compiler.FieldSpec.Type +import kotlin.math.min plugins { id("org.jetbrains.kotlin.multiplatform") @@ -72,6 +73,7 @@ configurations.all { } // Common Kotlin configuration +@Suppress("UNUSED_VARIABLE") kotlin { sourceSets { val commonMain by getting { @@ -127,14 +129,15 @@ kotlin { // Android configuration android { - compileSdkVersion(Versions.Android.compileSdkVersion) + namespace = "io.realm.sync.testapp" + compileSdk = Versions.Android.compileSdkVersion buildToolsVersion = Versions.Android.buildToolsVersion testBuildType = (properties["testBuildType"] ?: "debug") as String defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) + minSdk = Versions.Android.minSdk + targetSdk = Versions.Android.targetSdk testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled = true @@ -166,13 +169,13 @@ android { // Remove overlapping resources after adding "org.jetbrains.kotlinx:kotlinx-coroutines-test" to // avoid errors like "More than one file was found with OS independent path 'META-INF/AL2.0'." packagingOptions { - exclude("META-INF/AL2.0") - exclude("META-INF/LGPL2.1") + resources.excludes.add("META-INF/AL2.0") + resources.excludes.add("META-INF/LGPL2.1") } } - +@Suppress("UNUSED_VARIABLE") kotlin { - android("android") + androidTarget() sourceSets { val androidMain by getting { dependencies { @@ -227,7 +230,7 @@ kotlin { } } } - +@Suppress("UNUSED_VARIABLE") kotlin { jvm() sourceSets { @@ -247,6 +250,7 @@ kotlin { } } } +@Suppress("UNUSED_VARIABLE") kotlin { if (HOST_OS == OperatingSystem.MACOS_ARM64) { iosSimulatorArm64("ios") diff --git a/packages/test-sync/gradle.properties b/packages/test-sync/gradle.properties new file mode 100644 index 0000000000..63de1180aa --- /dev/null +++ b/packages/test-sync/gradle.properties @@ -0,0 +1,16 @@ +# +# Copyright 2024 Realm Inc. +# +# 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. +# +kotlin.mpp.applyDefaultHierarchyTemplate=false diff --git a/packages/test-sync/proguard-rules-test.pro b/packages/test-sync/proguard-rules-test.pro index 5719606b10..cbdb79e7e5 100644 --- a/packages/test-sync/proguard-rules-test.pro +++ b/packages/test-sync/proguard-rules-test.pro @@ -33,3 +33,11 @@ -keep class org.mongodb.kbson.serialization.* { *; } + +-dontwarn androidx.annotation.experimental.Experimental$Level +-dontwarn androidx.annotation.experimental.Experimental +-dontwarn java.lang.management.ManagementFactory +-dontwarn java.lang.management.RuntimeMXBean +-dontwarn org.slf4j.impl.StaticLoggerBinder +-dontwarn org.slf4j.impl.StaticMDCBinder +-dontwarn org.slf4j.impl.StaticMarkerBinder diff --git a/packages/test-sync/src/androidMain/AndroidManifest.xml b/packages/test-sync/src/androidMain/AndroidManifest.xml index ff9d65c6a1..e467cc8dad 100644 --- a/packages/test-sync/src/androidMain/AndroidManifest.xml +++ b/packages/test-sync/src/androidMain/AndroidManifest.xml @@ -15,8 +15,7 @@ ~ limitations under the License. --> - + diff --git a/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/TestApp.kt b/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/TestApp.kt index 4af35452e4..9dc98af5b9 100644 --- a/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/TestApp.kt +++ b/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/TestApp.kt @@ -44,6 +44,7 @@ import io.realm.kotlin.test.util.TestHelper import io.realm.kotlin.test.util.use import kotlinx.coroutines.CloseableCoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.ExperimentalCoroutinesApi import org.mongodb.kbson.ExperimentalKBsonSerializerApi import org.mongodb.kbson.serialization.EJson @@ -91,7 +92,7 @@ open class TestApp private constructor( * @param debug enable trace of command server and rest api calls in the test app. **/ @Suppress("LongParameterList") - @OptIn(ExperimentalKBsonSerializerApi::class) + @OptIn(ExperimentalKBsonSerializerApi::class, ExperimentalCoroutinesApi::class) constructor( testId: String?, appName: String = TEST_APP_PARTITION, @@ -175,6 +176,7 @@ open class TestApp private constructor( // Tearing down the SyncSession still relies on the the event loop (powered by the coroutines) of the platform networking // to post Function Handler, so we need to close it after we close the App + @OptIn(ExperimentalCoroutinesApi::class) if (dispatcher is CloseableCoroutineDispatcher) { dispatcher.close() } diff --git a/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/util/KtorTestMethods.kt b/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/util/KtorTestMethods.kt deleted file mode 100644 index e0d7e37cb6..0000000000 --- a/packages/test-sync/src/commonMain/kotlin/io/realm/kotlin/test/mongodb/util/KtorTestMethods.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2022 Realm Inc. - * - * 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 io.realm.kotlin.test.mongodb.util - -import io.ktor.http.HttpMethod -import kotlin.native.concurrent.SharedImmutable - -// Sits here because [SharedImmutable] annotation is only available in common. -@SharedImmutable -val TEST_METHODS = listOf( - HttpMethod.Get, - HttpMethod.Post, - HttpMethod.Patch, - HttpMethod.Put, - HttpMethod.Delete, -) diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppConfigurationTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppConfigurationTests.kt index 530ceb7ced..c0c23ef492 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppConfigurationTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppConfigurationTests.kt @@ -479,6 +479,7 @@ class AppConfigurationTests { assertNotEquals(config, otherConfig) } + @Test @Ignore // TODO fun dispatcher() { } diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppTests.kt index 06ae7fc104..ee9a0e90bc 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/AppTests.kt @@ -18,7 +18,6 @@ package io.realm.kotlin.test.mongodb.common import io.realm.kotlin.Realm import io.realm.kotlin.RealmConfiguration -import io.realm.kotlin.internal.platform.appFilesDirectory import io.realm.kotlin.internal.platform.fileExists import io.realm.kotlin.internal.platform.runBlocking import io.realm.kotlin.log.LogLevel @@ -43,6 +42,7 @@ import io.realm.kotlin.test.mongodb.asTestApp import io.realm.kotlin.test.mongodb.common.utils.assertFailsWithMessage import io.realm.kotlin.test.mongodb.createUserAndLogIn import io.realm.kotlin.test.mongodb.use +import io.realm.kotlin.test.platform.PlatformUtils import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.TestHelper import io.realm.kotlin.test.util.TestHelper.randomEmail @@ -376,6 +376,8 @@ class AppTests { @Test fun encryptedMetadataRealm() { + val tempDir = PlatformUtils.createTempDir() + // Create new test app with a random encryption key val key = TestHelper.getRandomKey() TestApp( @@ -384,7 +386,7 @@ class AppTests { builder = { it .encryptionKey(key) - .syncRootDirectory("${appFilesDirectory()}/foo") + .syncRootDirectory("$tempDir/foo") } ).use { app -> // Create Realm in order to create the sync metadata Realm @@ -413,6 +415,8 @@ class AppTests { @Test fun encryptedMetadataRealm_openWithWrongKeyThrows() { + val tempDir = PlatformUtils.createTempDir() + // Create new test app with a random encryption key val correctKey = TestHelper.getRandomKey() TestApp( @@ -421,7 +425,7 @@ class AppTests { builder = { it .encryptionKey(correctKey) - .syncRootDirectory("${appFilesDirectory()}/foo") + .syncRootDirectory("$tempDir/foo") } ).use { app -> // Create Realm in order to create the sync metadata Realm @@ -452,6 +456,8 @@ class AppTests { @Test fun encryptedMetadataRealm_openWithoutKeyThrows() { + val tempDir = PlatformUtils.createTempDir() + // Create new test app with a random encryption key TestApp( "encryptedMetadataRealm_openWithoutKeyThrows", @@ -459,7 +465,7 @@ class AppTests { builder = { it .encryptionKey(TestHelper.getRandomKey()) - .syncRootDirectory("${appFilesDirectory()}/foo") + .syncRootDirectory("$tempDir/foo") } ).use { app -> // Create Realm in order to create the sync metadata Realm diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SubscriptionExtensionsTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SubscriptionExtensionsTests.kt index c254d30efd..45cf941a6f 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SubscriptionExtensionsTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SubscriptionExtensionsTests.kt @@ -14,12 +14,15 @@ * limitations under the License. */ +@file:OptIn(ExperimentalFlexibleSyncApi::class) + package io.realm.kotlin.test.mongodb.common import io.realm.kotlin.Realm import io.realm.kotlin.entities.sync.flx.FlexParentObject import io.realm.kotlin.ext.query import io.realm.kotlin.internal.platform.runBlocking +import io.realm.kotlin.mongodb.annotations.ExperimentalFlexibleSyncApi import io.realm.kotlin.mongodb.ext.subscribe import io.realm.kotlin.mongodb.subscriptions import io.realm.kotlin.mongodb.sync.Subscription diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/KtorNetworkTransportTest.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/KtorNetworkTransportTest.kt index 20195dd79d..fcef828d8f 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/KtorNetworkTransportTest.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/KtorNetworkTransportTest.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.realm.kotlin.test.mongodb.common.internal import io.ktor.http.HttpMethod @@ -29,17 +31,25 @@ import io.realm.kotlin.test.mongodb.util.AppServicesClient import io.realm.kotlin.test.mongodb.util.BaasApp import io.realm.kotlin.test.mongodb.util.KtorTestAppInitializer.initialize import io.realm.kotlin.test.mongodb.util.Service -import io.realm.kotlin.test.mongodb.util.TEST_METHODS import io.realm.kotlin.test.util.TestChannel import io.realm.kotlin.test.util.receiveOrFail import io.realm.kotlin.test.util.trySendOrFail import kotlinx.coroutines.CloseableCoroutineDispatcher +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals +val TEST_METHODS = listOf( + HttpMethod.Get, + HttpMethod.Post, + HttpMethod.Patch, + HttpMethod.Put, + HttpMethod.Delete, +) + internal class KtorNetworkTransportTest { private lateinit var transport: KtorNetworkTransport private lateinit var endpoint: String