Skip to content

Commit

Permalink
Remove asymmetric objects
Browse files Browse the repository at this point in the history
  • Loading branch information
clementetb committed Sep 17, 2024
1 parent 5e6c12c commit f93b9e8
Show file tree
Hide file tree
Showing 17 changed files with 15 additions and 196 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ data class ClassInfo(
) {

val isEmbedded = flags and ClassFlags.RLM_CLASS_EMBEDDED != 0
val isAsymmetric = flags and ClassFlags.RLM_CLASS_ASYMMETRIC != 0

companion object {
// Convenience wrapper to ease maintaining compiler plugin
Expand All @@ -38,11 +37,9 @@ data class ClassInfo(
primaryKey: String?,
numProperties: Long,
isEmbedded: Boolean = false,
isAsymmetric: Boolean = false
): ClassInfo {
val flags: Int = when {
isEmbedded -> ClassFlags.RLM_CLASS_EMBEDDED
isAsymmetric -> ClassFlags.RLM_CLASS_ASYMMETRIC
else -> ClassFlags.RLM_CLASS_NORMAL
}
return ClassInfo(name, primaryKey ?: SCHEMA_NO_VALUE, numProperties, 0, flags = flags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ expect enum class SchemaMode {
expect object ClassFlags {
val RLM_CLASS_NORMAL: Int
val RLM_CLASS_EMBEDDED: Int
val RLM_CLASS_ASYMMETRIC: Int
}

expect enum class PropertyType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ package io.realm.kotlin.internal.interop
actual object ClassFlags {
actual val RLM_CLASS_NORMAL = realm_class_flags_e.RLM_CLASS_NORMAL
actual val RLM_CLASS_EMBEDDED = realm_class_flags_e.RLM_CLASS_EMBEDDED
actual val RLM_CLASS_ASYMMETRIC = realm_class_flags_e.RLM_CLASS_ASYMMETRIC
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ actual enum class SchemaMode(override val nativeValue: realm_schema_mode) : Nati
actual object ClassFlags {
actual val RLM_CLASS_NORMAL = realm_wrapper.RLM_CLASS_NORMAL.toInt()
actual val RLM_CLASS_EMBEDDED = realm_wrapper.RLM_CLASS_EMBEDDED.toInt()
actual val RLM_CLASS_ASYMMETRIC = realm_wrapper.RLM_CLASS_ASYMMETRIC.toInt()
}

actual enum class PropertyType(override val nativeValue: UInt) : NativeEnumerated {
Expand Down
76 changes: 1 addition & 75 deletions packages/library-base/proguard-rules-consumer-common.pro
Original file line number Diff line number Diff line change
Expand Up @@ -35,51 +35,15 @@
-keep class io.realm.kotlin.internal.interop.JVMScheduler {
*;
}
# Interop, sync-specific classes
-keep class io.realm.kotlin.internal.interop.sync.NetworkTransport {
# TODO OPTIMIZE Only keep actually required symbols
*;
}
-keep class io.realm.kotlin.internal.interop.sync.Response {
# TODO OPTIMIZE Only keep actually required symbols
*;
}

-keep class io.realm.kotlin.internal.interop.LongPointerWrapper {
# TODO OPTIMIZE Only keep actually required symbols
*;
}
-keep class io.realm.kotlin.internal.interop.sync.AppError {
# 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
*;
}
-keep class io.realm.kotlin.internal.interop.LogCallback {
# TODO OPTIMIZE Only keep actually required symbols
*;
}
-keep class io.realm.kotlin.internal.interop.SyncErrorCallback {
# TODO OPTIMIZE Only keep actually required symbols
*;
}
-keep class io.realm.kotlin.internal.interop.sync.JVMSyncSessionTransferCompletionCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.ResponseCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.ResponseCallbackImpl {
*;
}
-keep class io.realm.kotlin.internal.interop.AppCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.CompactOnLaunchCallback {
*;
}
Expand All @@ -89,36 +53,12 @@
-keep class io.realm.kotlin.internal.interop.DataInitializationCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.SubscriptionSetCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.SyncBeforeClientResetHandler {
*;
}
-keep class io.realm.kotlin.internal.interop.SyncAfterClientResetHandler {
*;
}
-keep class io.realm.kotlin.internal.interop.AsyncOpenCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.NativePointer {
*;
}
-keep class io.realm.kotlin.internal.interop.ProgressCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.ApiKeyWrapper {
*;
}
-keep class io.realm.kotlin.internal.interop.ConnectionStateChangeCallback {
*;
}
-keep class io.realm.kotlin.internal.interop.SyncThreadObserver {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.CoreCompensatingWriteInfo {
*;
}
# Preserve Function<X> methods as they back various functional interfaces called from JNI
-keep class kotlin.jvm.functions.Function* {
*;
Expand All @@ -127,20 +67,6 @@
*;
}

# Platform networking callback
-keep class io.realm.kotlin.internal.interop.sync.WebSocketTransport {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.CancellableTimer {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.WebSocketClient {
*;
}
-keep class io.realm.kotlin.internal.interop.sync.WebSocketObserver {
*;
}

# Un-comment for debugging
#-printconfiguration /tmp/full-r8-config.txt
#-keepattributes LineNumberTable,SourceFile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ internal interface InternalMutableRealm : MutableRealm {
}

override fun deleteAll() {
schema().classes.filter {
it.kind != RealmClassKind.ASYMMETRIC
}.forEach {
schema().classes.forEach {
val clazz: KClass<out TypedRealmObject>? = realmReference.schemaMetadata[it.name]?.clazz
if (clazz != null) {
delete(clazz)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public open class DynamicMutableRealmImpl(
query: String,
vararg args: Any?
): RealmQuery<DynamicMutableRealmObject> {
checkAsymmetric(className, "Queries on asymmetric objects are not allowed: $className")
return ObjectQuery(
realmReference,
realmReference.schemaMetadata.getOrThrow(className).classKey,
Expand All @@ -76,7 +75,6 @@ public open class DynamicMutableRealmImpl(
obj: DynamicRealmObject,
updatePolicy: UpdatePolicy
): DynamicMutableRealmObject {
checkAsymmetric(obj.type, "Asymmetric Realm objects can only be added using the `insert()` method.")
return io.realm.kotlin.internal.copyToRealm(configuration.mediator, realmReference, obj, updatePolicy, mutableMapOf()) as DynamicMutableRealmObject
}

Expand All @@ -102,22 +100,13 @@ public open class DynamicMutableRealmImpl(
}

override fun delete(className: String) {
checkAsymmetric(className, "Asymmetric Realm objects cannot be deleted manually: $className")
delete(query(className).find())
}

private fun checkAsymmetric(className: String, errorMessage: String) {
if (realmReference.owner.schema()[className]?.kind == RealmClassKind.ASYMMETRIC) {
throw IllegalArgumentException(errorMessage)
}
}

override fun deleteAll() {
schema().let { schema: RealmSchema ->
for (schemaClass: RealmClass in schema.classes) {
if (schema[schemaClass.name]?.kind != RealmClassKind.ASYMMETRIC) {
delete(schemaClass.name)
}
delete(schemaClass.name)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ internal open class DynamicRealmImpl(
query: String,
vararg args: Any?
): RealmQuery<DynamicRealmObject> {
if (realmReference.owner.schema()[className]?.kind == RealmClassKind.ASYMMETRIC) {
throw IllegalArgumentException("Queries on asymmetric objects are not allowed: $className")
}
return ObjectQuery(
realmReference,
realmReference.schemaMetadata.getOrThrow(className).classKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public data class RealmClassImpl(
override val kind: RealmClassKind
get() = when {
cinteropClass.isEmbedded -> RealmClassKind.EMBEDDED
cinteropClass.isAsymmetric -> RealmClassKind.ASYMMETRIC
else -> RealmClassKind.STANDARD
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,4 @@ public enum class RealmClassKind {
* See [io.realm.kotlin.types.EmbeddedRealmObject] for more details.
*/
EMBEDDED,
/**
* Asymmetric Realm objects extend the [io.realm.kotlin.types.mongodb.AsymmetricRealmObject] interface.
*
* These kind of classes can only be used in a synced realm and are "write-only", i.e. once
* you written an asymmetric object to a Realm, it is no longer possible access or query them.
*
* See [io.realm.kotlin.types.mongodb.AsymmetricRealmObject] for more details.
*/
ASYMMETRIC
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

package io.realm.kotlin.compiler

import io.realm.kotlin.compiler.ClassIds.ASYMMETRIC_OBJECT_INTERFACE
import io.realm.kotlin.compiler.ClassIds.EMBEDDED_OBJECT_INTERFACE
import io.realm.kotlin.compiler.ClassIds.IGNORE_ANNOTATION
import io.realm.kotlin.compiler.ClassIds.KBSON_DECIMAL128
Expand Down Expand Up @@ -223,11 +222,6 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
objectReferenceProperty = irClass.lookupProperty(OBJECT_REFERENCE)
objectReferenceType = objectReferenceProperty.backingField!!.type

// Attempt to find the interface for asymmetric objects.
// The class will normally only be on the classpath for library-sync builds, not
// library-base builds.
val asymmetricRealmObjectInterface: IrClass? = pluginContext.referenceClass(ASYMMETRIC_OBJECT_INTERFACE)?.owner

irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
@Suppress("LongMethod")
override fun visitProperty(declaration: IrProperty): IrStatement {
Expand Down Expand Up @@ -646,19 +640,6 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
toRealmValue = null
)
}
asymmetricRealmObjectInterface != null && propertyType.isSubtypeOfClass(asymmetricRealmObjectInterface.symbol) -> {
// Asymmetric objects must be top-level objects, so any link to one
// should be illegal. This will be detected later when creating the
// schema methods. So for now, just add the field to the list of schema
// properties, but do not modify the accessor.
logDebug("Object property named ${declaration.name} is ${if (nullable) "" else "not "}nullable")
val schemaProperty = SchemaProperty(
propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT,
declaration = declaration,
collectionType = CollectionType.NONE
)
fields[name] = schemaProperty
}
propertyType.isSubtypeOfClass(realmObjectInterface) -> {
logDebug("Object property named ${declaration.name} is ${if (nullable) "" else "not "}nullable")
val schemaProperty = SchemaProperty(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ internal object Names {

val REALM_OBJECT: Name = Name.identifier("RealmObject")
val EMBEDDED_REALM_OBJECT: Name = Name.identifier("EmbeddedRealmObject")
val ASYMMETRIC_REALM_OBJECT: Name = Name.identifier("AsymmetricRealmObject")

val REALM_OBJECT_COMPANION_CLASS_MEMBER: Name =
Name.identifier("${REALM_SYNTHETIC_PROPERTY_PREFIX}class")
Expand Down Expand Up @@ -116,7 +115,6 @@ object ClassIds {
val REALM_OBJECT_INTERFACE = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmObject"))
val TYPED_REALM_OBJECT_INTERFACE = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("TypedRealmObject"))
val EMBEDDED_OBJECT_INTERFACE = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("EmbeddedRealmObject"))
val ASYMMETRIC_OBJECT_INTERFACE = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("AsymmetricRealmObject"))

val CLASS_APP_CONFIGURATION = ClassId(FqNames.PACKAGE_MONGODB, Name.identifier("AppConfiguration"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@

package io.realm.kotlin.compiler

import io.realm.kotlin.compiler.ClassIds.ASYMMETRIC_OBJECT_INTERFACE
import io.realm.kotlin.compiler.ClassIds.BASE_REALM_OBJECT_INTERFACE
import io.realm.kotlin.compiler.ClassIds.EMBEDDED_OBJECT_INTERFACE
import io.realm.kotlin.compiler.ClassIds.KOTLIN_COLLECTIONS_LISTOF
import io.realm.kotlin.compiler.ClassIds.PERSISTED_NAME_ANNOTATION
import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_INTERFACE
import io.realm.kotlin.compiler.FqNames.PACKAGE_TYPES
import io.realm.kotlin.compiler.Names.ASYMMETRIC_REALM_OBJECT
import io.realm.kotlin.compiler.Names.EMBEDDED_REALM_OBJECT
import io.realm.kotlin.compiler.Names.REALM_OBJECT
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
Expand Down Expand Up @@ -147,8 +145,7 @@ val ClassDescriptor.isRealmObjectCompanion

val realmObjectInterfaceFqNames = setOf(REALM_OBJECT_INTERFACE)
val realmEmbeddedObjectInterfaceFqNames = setOf(EMBEDDED_OBJECT_INTERFACE)
val realmAsymmetricObjectInterfaceFqNames = setOf(ASYMMETRIC_OBJECT_INTERFACE)
val anyRealmObjectInterfacesFqNames = realmObjectInterfaceFqNames + realmEmbeddedObjectInterfaceFqNames + realmAsymmetricObjectInterfaceFqNames
val anyRealmObjectInterfacesFqNames = realmObjectInterfaceFqNames + realmEmbeddedObjectInterfaceFqNames

fun IrType.classIdOrFail(): ClassId = getClass()?.classId ?: error("Can't get classId of ${render()}")

Expand Down Expand Up @@ -194,16 +191,15 @@ inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set<String>): Boolean {
// `RealmObject` (Kotlin, interface).
val realmObjectPsiNames = setOf("RealmObject", "io.realm.kotlin.types.RealmObject")
val embeddedRealmObjectPsiNames = setOf("EmbeddedRealmObject", "io.realm.kotlin.types.EmbeddedRealmObject")
val asymmetricRealmObjectPsiNames = setOf("AsymmetricRealmObject", "io.realm.kotlin.types.AsymmetricRealmObject")
val realmJavaObjectPsiNames = setOf("io.realm.RealmObject()", "RealmObject()")
val ClassDescriptor.isRealmObject: Boolean
get() = this.hasInterfacePsi(realmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames)
val ClassDescriptor.isEmbeddedRealmObject: Boolean
get() = this.hasInterfacePsi(embeddedRealmObjectPsiNames)
val ClassDescriptor.isBaseRealmObject: Boolean
get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames + asymmetricRealmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames)
get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames)

val realmObjectTypes: Set<Name> = setOf(REALM_OBJECT, EMBEDDED_REALM_OBJECT, ASYMMETRIC_REALM_OBJECT)
val realmObjectTypes: Set<Name> = setOf(REALM_OBJECT, EMBEDDED_REALM_OBJECT)
val realmObjectClassIds = realmObjectTypes.map { name -> ClassId(PACKAGE_TYPES, name) }

// This is the K2 equivalent of our PSI hack to determine if a symbol has a RealmObject base class.
Expand Down Expand Up @@ -251,18 +247,12 @@ val IrClass.isRealmObject
val IrClass.isEmbeddedRealmObject: Boolean
get() = superTypes.any { it.classId == EMBEDDED_OBJECT_INTERFACE }

val IrClass.isAsymmetricRealmObject: Boolean
get() = superTypes.any { it.classId == ASYMMETRIC_OBJECT_INTERFACE }

val IrType.classId: ClassId?
get() = this.getClass()?.classId

val IrType.isEmbeddedRealmObject: Boolean
get() = superTypes().any { it.classId == EMBEDDED_OBJECT_INTERFACE }

val IrType.isAsymmetricRealmObject: Boolean
get() = superTypes().any { it.classId == ASYMMETRIC_OBJECT_INTERFACE }

internal fun IrFunctionBuilder.at(startOffset: Int, endOffset: Int) = also {
this.startOffset = startOffset
this.endOffset = endOffset
Expand Down
Loading

0 comments on commit f93b9e8

Please sign in to comment.