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 ba1b9fa899..7d32340d16 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 @@ -389,6 +389,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_INT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty @@ -400,6 +401,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { // the managed object to which the fields belongs. modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getMutableInt, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -418,12 +420,14 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { } val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_MIXED, + type = propertyType, declaration = declaration, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getRealmAny, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -438,11 +442,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_BINARY, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getByteArray, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -456,11 +462,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_STRING, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getString, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -474,11 +482,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_INT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getLong, fromRealmValue = longToByte, toPublic = null, @@ -496,11 +506,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_INT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getLong, fromRealmValue = longToChar, toPublic = typeAdapterMethodReferences?.toPublic, @@ -518,11 +530,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_INT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getLong, fromRealmValue = longToShort, toPublic = typeAdapterMethodReferences?.toPublic, @@ -540,11 +554,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_INT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getLong, fromRealmValue = longToInt, toPublic = typeAdapterMethodReferences?.toPublic, @@ -562,11 +578,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_INT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getLong, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -580,11 +598,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_BOOL, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getBoolean, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -598,11 +618,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_FLOAT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getFloat, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -616,11 +638,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_DOUBLE, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getDouble, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -634,11 +658,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_DECIMAL128, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getDecimal128, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -677,6 +703,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { fields[name] = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_LINKING_OBJECTS, declaration = declaration, + type = propertyType, collectionType = CollectionType.LIST, coreGenericTypes = listOf( CoreType( @@ -692,11 +719,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_TIMESTAMP, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getInstant, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -710,11 +739,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT_ID, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getObjectId, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -728,11 +759,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { var schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT_ID, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getObjectId, fromRealmValue = objectIdToRealmObjectId, toPublic = typeAdapterMethodReferences?.toPublic, @@ -746,11 +779,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_UUID, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getUUID, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -761,26 +796,28 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { } propertyType.isRealmList() -> { logDebug("RealmList property named ${declaration.name} is ${if (nullable) "" else "not "}nullable") - processCollectionField(CollectionType.LIST, fields, name, declaration, typeAdapterMethodReferences) + processCollectionField(CollectionType.LIST, fields, name, declaration, propertyType, typeAdapterMethodReferences) } propertyType.isRealmSet() -> { logDebug("RealmSet property named ${declaration.name} is ${if (nullable) "" else "not "}nullable") - processCollectionField(CollectionType.SET, fields, name, declaration, typeAdapterMethodReferences) + processCollectionField(CollectionType.SET, fields, name, declaration, propertyType, typeAdapterMethodReferences) } propertyType.isRealmDictionary() -> { logDebug("RealmDictionary property named ${declaration.name} is ${if (nullable) "" else "not "}nullable") - processCollectionField(CollectionType.DICTIONARY, fields, name, declaration, typeAdapterMethodReferences) + processCollectionField(CollectionType.DICTIONARY, fields, name, declaration, propertyType, typeAdapterMethodReferences) } propertyType.isSubtypeOfClass(embeddedRealmObjectInterface) -> { logDebug("Object property named ${declaration.name} is embedded and ${if (nullable) "" else "not "}nullable") val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty modifyAccessor( - schemaProperty, + property = schemaProperty, + type = propertyType, getFunction = getObject, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -798,6 +835,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty @@ -807,6 +845,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT, declaration = declaration, + type = propertyType, collectionType = CollectionType.NONE ) fields[name] = schemaProperty @@ -814,6 +853,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { // conversion so bypass any converters in accessors modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = getObject, fromRealmValue = null, toPublic = typeAdapterMethodReferences?.toPublic, @@ -837,6 +877,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { fields: MutableMap, name: String, declaration: IrProperty, + propertyType: IrType, typeAdapterMethodReferences: TypeAdapterMethodReferences?, ) { val type: KotlinType = @@ -862,6 +903,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { val schemaProperty = SchemaProperty( propertyType = genericPropertyType, declaration = declaration, + type = propertyType, collectionType = collectionType, coreGenericTypes = listOf(coreGenericTypes) ) @@ -881,6 +923,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { // getCollection/setCollection gets/sets raw collections so it bypasses any converters in accessors modifyAccessor( property = schemaProperty, + type = propertyType, getFunction = when (collectionType) { CollectionType.LIST -> getList CollectionType.SET -> getSet @@ -906,6 +949,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { @Suppress("LongParameterList", "LongMethod", "ComplexMethod") private fun modifyAccessor( property: SchemaProperty, + type: IrType, getFunction: IrSimpleFunction, fromRealmValue: IrSimpleFunction? = null, toPublic: (IrBuilderWithScope.(IrGetValue, IrFunctionAccessExpression)->IrDeclarationReference)? = null, @@ -914,12 +958,13 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { toRealmValue: IrSimpleFunction? = null, collectionType: CollectionType = CollectionType.NONE ) { + // TODO check this backing field if required val backingField = property.declaration.backingField!! val type: IrType? = when (collectionType) { - CollectionType.NONE -> backingField.type + CollectionType.NONE -> type CollectionType.LIST, CollectionType.SET, - CollectionType.DICTIONARY -> getCollectionElementType(backingField.type) + CollectionType.DICTIONARY -> getCollectionElementType(type) } val getter = property.declaration.getter val setter = property.declaration.setter 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 3eb1ae88de..9f9dc3a9ad 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 @@ -410,6 +410,7 @@ private const val NO_ALIAS = "" data class SchemaProperty( val propertyType: PropertyType, val declaration: IrProperty, + val type: IrType, val collectionType: CollectionType = CollectionType.NONE, val coreGenericTypes: List? = null, ) { 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 db43326fcf..d6752b6057 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 @@ -536,29 +536,29 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi ?: fatalError("Property without backing field or type.") // Nullability applies to the generic type in collections val nullable = if (value.collectionType == CollectionType.NONE) { - backingField.type.isNullable() + value.type.isNullable() } else { value.coreGenericTypes?.get(0)?.nullable ?: fatalError("Missing generic type while processing a collection field.") } val primaryKey = backingField.hasAnnotation(PRIMARY_KEY_ANNOTATION) - if (primaryKey && validPrimaryKeyTypes.find { it.classFqName == backingField.type.classFqName } == null) { + if (primaryKey && validPrimaryKeyTypes.find { it.classFqName == value.type.classFqName } == null) { logError( - "Primary key ${property.name} is of type ${backingField.type.classId?.shortClassName} but must be of type ${validPrimaryKeyTypes.map { it.classId?.shortClassName }}", + "Primary key ${property.name} is of type ${value.type.classId?.shortClassName} but must be of type ${validPrimaryKeyTypes.map { it.classId?.shortClassName }}", property.locationOf() ) } val isIndexed = backingField.hasAnnotation(INDEX_ANNOTATION) - if (isIndexed && indexableTypes.find { it.classFqName == backingField.type.classFqName } == null) { + if (isIndexed && indexableTypes.find { it.classFqName == value.type.classFqName } == null) { logError( - "Indexed key ${property.name} is of type ${backingField.type.classId?.shortClassName} but must be of type ${indexableTypes.map { it.classId?.shortClassName }}", + "Indexed key ${property.name} is of type ${value.type.classId?.shortClassName} but must be of type ${indexableTypes.map { it.classId?.shortClassName }}", property.locationOf() ) } val isFullTextIndexed = backingField.hasAnnotation(FULLTEXT_ANNOTATION) - if (isFullTextIndexed && fullTextIndexableTypes.find { it.classFqName == backingField.type.classFqName } == null) { + if (isFullTextIndexed && fullTextIndexableTypes.find { it.classFqName == value.type.classFqName } == null) { logError( - "Full-text key ${property.name} is of type ${backingField.type.classId?.shortClassName} but must be of type ${fullTextIndexableTypes.map { it.classId?.shortClassName }}", + "Full-text key ${property.name} is of type ${value.type.classId?.shortClassName} but must be of type ${fullTextIndexableTypes.map { it.classId?.shortClassName }}", property.locationOf() ) } @@ -598,13 +598,13 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi // Collections of type RealmObject require the type parameter be retrieved from the generic argument when (value.collectionType) { CollectionType.NONE -> { - backingField.type + value.type } CollectionType.LIST, CollectionType.SET, CollectionType.DICTIONARY -> { - getCollectionElementType(backingField.type) - ?: error("Could not get collection type from ${backingField.type}") + getCollectionElementType(value.type) + ?: error("Could not get collection type from ${value.type}") } } } @@ -655,12 +655,12 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi // Collections of type RealmObject require the type parameter be retrieved from the generic argument when (collectionTypeSymbol) { PROPERTY_COLLECTION_TYPE_NONE -> - backingField.type + value.type PROPERTY_COLLECTION_TYPE_LIST, PROPERTY_COLLECTION_TYPE_SET, PROPERTY_COLLECTION_TYPE_DICTIONARY -> - getCollectionElementType(backingField.type) - ?: error("Could not get collection type from ${backingField.type}") + getCollectionElementType(value.type) + ?: error("Could not get collection type from ${value.type}") else -> error("Unsupported collection type '$collectionTypeSymbol' for field ${entry.key}") } diff --git a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/TypeAdaptersTests.kt b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/TypeAdaptersTests.kt index 921ba8cc17..fb1bab87ca 100644 --- a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/TypeAdaptersTests.kt +++ b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/TypeAdaptersTests.kt @@ -138,26 +138,35 @@ class TypeAdaptersTests { BsonObjectId::class to "BsonObjectId()", RealmUUID::class to "RealmUUID.random()", ByteArray::class to "byteArrayOf(42)", - MutableRealmInt::class to "MutableRealmInt.create(42)" + MutableRealmInt::class to "MutableRealmInt.create(42)", + RealmObject::class to "TestObject2()" ) allFieldTypes .filterNot { type -> // TODO tidy list unsupported types in TypeDescriptor - type.elementType.classifier == RealmObject::class || type.elementType.classifier == Byte::class || +// type.elementType.classifier == RealmObject::class || type.elementType.classifier == Char::class || type.elementType.classifier == Short::class || type.elementType.classifier == Int::class || type.elementType.classifier == MutableRealmInt::class } + .filterNot { + it.collectionType == CollectionType.RLM_COLLECTION_TYPE_NONE +//// }.filter { +//// it.elementType.classifier == RealmObject::class + } .forEach { type -> val elementType = type.elementType val default = if (!elementType.nullable) defaults[elementType.classifier] ?: error("unmapped default") else null - val kotlinLiteral = type.toKotlinLiteral() - + val kotlinLiteral = if(type.elementType.classifier == RealmObject::class) { + type.toKotlinLiteral().replace("RealmObject", "TestObject2") + } else { + type.toKotlinLiteral() + } println(kotlinLiteral) val result = compileFromSource( @@ -183,6 +192,10 @@ class TypeAdaptersTests { class NonRealmType + class TestObject2: RealmObject { + var name: String = "" + } + class TestObject : RealmObject { @TypeAdapter(adapter = ValidRealmTypeAdapter::class) var userType: UserType = UserType()