@@ -73,7 +73,6 @@ import org.jetbrains.kotlin.ir.builders.irGet
7373import org.jetbrains.kotlin.ir.builders.irGetObject
7474import org.jetbrains.kotlin.ir.builders.irIfNull
7575import org.jetbrains.kotlin.ir.builders.irLetS
76- import org.jetbrains.kotlin.ir.builders.irNull
7776import org.jetbrains.kotlin.ir.builders.irReturn
7877import org.jetbrains.kotlin.ir.builders.irString
7978import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -109,6 +108,8 @@ import org.jetbrains.kotlin.ir.types.isShort
109108import org.jetbrains.kotlin.ir.types.isString
110109import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
111110import org.jetbrains.kotlin.ir.types.makeNotNull
111+ import org.jetbrains.kotlin.ir.types.superTypes
112+ import org.jetbrains.kotlin.ir.types.typeOrNull
112113import org.jetbrains.kotlin.ir.util.classId
113114import org.jetbrains.kotlin.ir.util.defaultType
114115import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -123,7 +124,7 @@ import org.jetbrains.kotlin.types.KotlinType
123124import org.jetbrains.kotlin.types.StarProjectionImpl
124125import org.jetbrains.kotlin.types.isNullable
125126import org.jetbrains.kotlin.types.typeUtil.supertypes
126- import java.lang .IllegalStateException
127+ import kotlin .IllegalStateException
127128import kotlin.collections.set
128129
129130/* *
@@ -413,7 +414,6 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
413414 fromRealmValue = longToChar,
414415 toPublic = null ,
415416 setFunction = setValue,
416- // fromPublic = charToLong,
417417 fromPublic = { _, value ->
418418 irCall(callee = charToLong).apply {
419419 putValueArgument(0 , value)
@@ -436,7 +436,6 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
436436 fromRealmValue = longToShort,
437437 toPublic = null ,
438438 setFunction = setValue,
439- // fromPublic = shortToLong,
440439 fromPublic = { _, value ->
441440 irCall(callee = shortToLong).apply {
442441 putValueArgument(0 , value)
@@ -459,7 +458,6 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
459458 fromRealmValue = longToInt,
460459 toPublic = null ,
461460 setFunction = setValue,
462- // fromPublic = intToLong,
463461 fromPublic = { _, value ->
464462 irCall(callee = intToLong).apply {
465463 putValueArgument(0 , value)
@@ -736,77 +734,86 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
736734 declaration.hasAnnotation(TYPE_ADAPTER_ANNOTATION ) -> {
737735 logDebug(" Object property named ${declaration.name} is an adapted type." )
738736
739- // TODO check nullability
737+ val adapterClassReference =
738+ declaration.getAnnotation(TYPE_ADAPTER_ANNOTATION .asSingleFqName())
739+ .getValueArgument(0 )!! as IrClassReference
740+ val adapterClass: IrClass = adapterClassReference.classType.getClass()!!
740741
742+ // TODO find correct super type adapter type, might be multiple ones
743+ val (realmType: IrTypeArgument , userType) =
744+ (adapterClassReference.symbol.superTypes().first() as IrSimpleType )
745+ .arguments
746+ .let { arguments ->
747+ arguments[0 ] to arguments[1 ]
748+ }
749+
750+ // TODO check nullability
741751 // 1. Extract what is the actual schema property
742752 // TODO extract the type from the annotation, by now hardcoded one
743- val schemaProperty = SchemaProperty (
744- propertyType = PropertyType .RLM_PROPERTY_TYPE_TIMESTAMP ,
745- declaration = declaration,
746- collectionType = CollectionType .NONE
747- )
748- fields[name] = schemaProperty
749- // 2. Modify the accessor to use the type adapter. The type adapter might or
750- // not be provided (singleton vs class)
751-
752- val adapterClassReference = declaration.getAnnotation(TYPE_ADAPTER_ANNOTATION .asSingleFqName()).getValueArgument(0 )!! as IrClassReference
753- val adapterClass: IrClass = adapterClassReference.classType.getClass()!!
754753
755- // check kind (object / class)
756- when (adapterClass.kind) {
757- ClassKind .CLASS -> {
758- modifyAccessor(
759- property = schemaProperty,
760- getFunction = getInstant,
761- fromRealmValue = null ,
762- toPublic = {objReference, realmValue ->
763- irCall(callee = providedAdapterFromRealm).apply {
764- // pass the class from the annotation
765- putValueArgument(0 , objReference)
766- putValueArgument(1 , adapterClassReference)
767- putValueArgument(2 , realmValue)
768- }
769- },
770- setFunction = setValue,
771- fromPublic = { objReference, publicValue ->
772- irCall(callee = providedAdapterToRealm).apply {
773- // pass the class from the annotation
774- putValueArgument(0 , objReference)
775- putValueArgument(1 , adapterClassReference)
776- putValueArgument(2 , publicValue)
777- }
778- },
779- toRealmValue = null
780- )
781- }
782- ClassKind .OBJECT -> {
783- val fromRealm = adapterClass.lookupFunction(REALM_TYPE_ADAPTER_FROM_REALM )
784- val toRealm = adapterClass.lookupFunction(REALM_TYPE_ADAPTER_TO_REALM )
785-
786- modifyAccessor(
787- property = schemaProperty,
788- getFunction = getInstant,
789- fromRealmValue = null ,
790- toPublic = { _, realmValue ->
791- irCall(callee = fromRealm).apply {
792- putValueArgument(0 , realmValue)
793- dispatchReceiver = irGetObject(adapterClass.symbol)
794- }
795- },
796- setFunction = setValue,
797- fromPublic = { _, publicValue ->
798- irCall(callee = toRealm).apply {
799- putValueArgument(0 , publicValue)
800- dispatchReceiver = irGetObject(adapterClass.symbol)
801- }
802- },
803- toRealmValue = null
804- )
754+ val schemaProperty =
755+ retrieveSchemaProperty(declaration, realmType.typeOrNull!! )
756+
757+ if (schemaProperty!= null ) {
758+ fields[name] = schemaProperty!!
759+ // 2. Modify the accessor to use the type adapter. The type adapter might or
760+ // not be provided (singleton vs class)
761+
762+ // check kind (object / class)
763+ when (adapterClass.kind) {
764+ ClassKind .CLASS -> {
765+ modifyAccessor(
766+ property = schemaProperty,
767+ getFunction = getInstant,
768+ fromRealmValue = null ,
769+ toPublic = {objReference, realmValue ->
770+ irCall(callee = providedAdapterFromRealm).apply {
771+ // pass the class from the annotation
772+ putValueArgument(0 , objReference)
773+ putValueArgument(1 , adapterClassReference)
774+ putValueArgument(2 , realmValue)
775+ }
776+ },
777+ setFunction = setValue,
778+ fromPublic = { objReference, publicValue ->
779+ irCall(callee = providedAdapterToRealm).apply {
780+ // pass the class from the annotation
781+ putValueArgument(0 , objReference)
782+ putValueArgument(1 , adapterClassReference)
783+ putValueArgument(2 , publicValue)
784+ }
785+ },
786+ toRealmValue = null
787+ )
788+ }
789+ ClassKind .OBJECT -> {
790+ val fromRealm = adapterClass.lookupFunction(REALM_TYPE_ADAPTER_FROM_REALM )
791+ val toRealm = adapterClass.lookupFunction(REALM_TYPE_ADAPTER_TO_REALM )
792+
793+ modifyAccessor(
794+ property = schemaProperty,
795+ getFunction = getInstant,
796+ fromRealmValue = null ,
797+ toPublic = { _, realmValue ->
798+ irCall(callee = fromRealm).apply {
799+ putValueArgument(0 , realmValue)
800+ dispatchReceiver = irGetObject(adapterClass.symbol)
801+ }
802+ },
803+ setFunction = setValue,
804+ fromPublic = { _, publicValue ->
805+ irCall(callee = toRealm).apply {
806+ putValueArgument(0 , publicValue)
807+ dispatchReceiver = irGetObject(adapterClass.symbol)
808+ }
809+ },
810+ toRealmValue = null
811+ )
812+ }
813+ else -> throw IllegalStateException (" Unsupported type" )
805814 }
806- else -> throw IllegalStateException (" Unsupported type" )
807815 }
808816 }
809-
810817 else -> {
811818 logError(" Realm does not support persisting properties of this type. Mark the field with `@Ignore` to suppress this error." , declaration.locationOf())
812819 }
@@ -817,6 +824,74 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
817824 })
818825 }
819826
827+ private fun retrieveSchemaProperty (property : IrProperty , type : IrType ): SchemaProperty ? =
828+ when {
829+ type.isLong() -> SchemaProperty (
830+ propertyType = PropertyType .RLM_PROPERTY_TYPE_INT ,
831+ declaration = property,
832+ collectionType = CollectionType .NONE
833+ )
834+ type.isBoolean() -> SchemaProperty (
835+ propertyType = PropertyType .RLM_PROPERTY_TYPE_BOOL ,
836+ declaration = property,
837+ collectionType = CollectionType .NONE
838+ )
839+ type.isString() -> SchemaProperty (
840+ propertyType = PropertyType .RLM_PROPERTY_TYPE_STRING ,
841+ declaration = property,
842+ collectionType = CollectionType .NONE
843+ )
844+ type.isByteArray() -> SchemaProperty (
845+ propertyType = PropertyType .RLM_PROPERTY_TYPE_BINARY ,
846+ declaration = property,
847+ collectionType = CollectionType .NONE
848+ )
849+ type.isRealmAny() -> SchemaProperty (
850+ propertyType = PropertyType .RLM_PROPERTY_TYPE_MIXED ,
851+ declaration = property,
852+ collectionType = CollectionType .NONE
853+ )
854+ type.isRealmInstant() -> SchemaProperty (
855+ propertyType = PropertyType .RLM_PROPERTY_TYPE_TIMESTAMP ,
856+ declaration = property,
857+ collectionType = CollectionType .NONE
858+ )
859+ type.isFloat() -> SchemaProperty (
860+ propertyType = PropertyType .RLM_PROPERTY_TYPE_FLOAT ,
861+ declaration = property,
862+ collectionType = CollectionType .NONE
863+ )
864+ type.isDouble() -> SchemaProperty (
865+ propertyType = PropertyType .RLM_PROPERTY_TYPE_DOUBLE ,
866+ declaration = property,
867+ collectionType = CollectionType .NONE
868+ )
869+ // type.isLinkingObject() ->PropertyType.RLM_PROPERTY_TYPE_OBJECT // TODO should be supported (I think so)
870+ // type.isRealmInstant() ->PropertyType.RLM_PROPERTY_TYPE_LINKING_OBJECTS // TODO should be supported (Unsure write some API)
871+ type.isDecimal128() -> SchemaProperty (
872+ propertyType = PropertyType .RLM_PROPERTY_TYPE_DECIMAL128 ,
873+ declaration = property,
874+ collectionType = CollectionType .NONE
875+ )
876+ type.isObjectId() -> SchemaProperty (
877+ propertyType = PropertyType .RLM_PROPERTY_TYPE_OBJECT_ID ,
878+ declaration = property,
879+ collectionType = CollectionType .NONE
880+ )
881+ type.isRealmUUID() -> SchemaProperty (
882+ propertyType = PropertyType .RLM_PROPERTY_TYPE_UUID ,
883+ declaration = property,
884+ collectionType = CollectionType .NONE
885+ )
886+ else -> {
887+ logError(
888+ " Invalid type parameter, only Realm types are supported" , // TODO find a better error message
889+ property.locationOf()
890+ )
891+ null
892+ }
893+ }
894+
820895 private fun processCollectionField (
821896 collectionType : CollectionType ,
822897 fields : MutableMap <String , SchemaProperty >,
0 commit comments