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 428929dace..ddf3f025f8 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 @@ -13,28 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:OptIn(FirIncompatiblePluginAPI::class) package io.realm.kotlin.compiler -import io.realm.kotlin.compiler.FqNames.ASYMMETRIC_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.EMBEDDED_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.IGNORE_ANNOTATION -import io.realm.kotlin.compiler.FqNames.KBSON_DECIMAL128 -import io.realm.kotlin.compiler.FqNames.KBSON_OBJECT_ID -import io.realm.kotlin.compiler.FqNames.REALM_ANY -import io.realm.kotlin.compiler.FqNames.REALM_BACKLINKS -import io.realm.kotlin.compiler.FqNames.REALM_DICTIONARY -import io.realm.kotlin.compiler.FqNames.REALM_EMBEDDED_BACKLINKS -import io.realm.kotlin.compiler.FqNames.REALM_INSTANT -import io.realm.kotlin.compiler.FqNames.REALM_LIST -import io.realm.kotlin.compiler.FqNames.REALM_MUTABLE_INTEGER -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_HELPER -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_ID -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.REALM_SET -import io.realm.kotlin.compiler.FqNames.REALM_UUID -import io.realm.kotlin.compiler.FqNames.TRANSIENT_ANNOTATION +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 +import io.realm.kotlin.compiler.ClassIds.KBSON_OBJECT_ID +import io.realm.kotlin.compiler.ClassIds.REALM_ANY +import io.realm.kotlin.compiler.ClassIds.REALM_BACKLINKS +import io.realm.kotlin.compiler.ClassIds.REALM_DICTIONARY +import io.realm.kotlin.compiler.ClassIds.REALM_EMBEDDED_BACKLINKS +import io.realm.kotlin.compiler.ClassIds.REALM_INSTANT +import io.realm.kotlin.compiler.ClassIds.REALM_LIST +import io.realm.kotlin.compiler.ClassIds.REALM_MUTABLE_INTEGER +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_HELPER +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_ID +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_INTERFACE +import io.realm.kotlin.compiler.ClassIds.REALM_SET +import io.realm.kotlin.compiler.ClassIds.REALM_UUID +import io.realm.kotlin.compiler.ClassIds.TRANSIENT_ANNOTATION import io.realm.kotlin.compiler.Names.OBJECT_REFERENCE import io.realm.kotlin.compiler.Names.REALM_ACCESSOR_HELPER_GET_BOOLEAN import io.realm.kotlin.compiler.Names.REALM_ACCESSOR_HELPER_GET_BYTE_ARRAY @@ -59,10 +58,8 @@ import io.realm.kotlin.compiler.Names.REALM_OBJECT_HELPER_SET_LIST import io.realm.kotlin.compiler.Names.REALM_OBJECT_HELPER_SET_OBJECT import io.realm.kotlin.compiler.Names.REALM_OBJECT_HELPER_SET_SET import io.realm.kotlin.compiler.Names.REALM_SYNTHETIC_PROPERTY_PREFIX -import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.builders.IrBlockBuilder import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.builders.irBlockBody @@ -78,6 +75,8 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrValueParameter +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.expressions.IrStatementOrigin @@ -85,7 +84,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeArgument -import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.impl.IrAbstractSimpleType import org.jetbrains.kotlin.ir.types.isBoolean import org.jetbrains.kotlin.ir.types.isByte @@ -100,16 +98,16 @@ import org.jetbrains.kotlin.ir.types.isShort import org.jetbrains.kotlin.ir.types.isString import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.types.makeNotNull -import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.ir.util.defaultType -import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.classId -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.StarProjectionImpl import org.jetbrains.kotlin.types.isNullable @@ -120,7 +118,6 @@ import kotlin.collections.set * Modifies the IR tree to transform getter/setter to call the C-Interop layer to retrieve read the managed values from the Realm * It also collect the schema information while processing the class properties. */ -@OptIn(ObsoleteDescriptorBasedAPI::class) class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { private val realmObjectHelper: IrClass = pluginContext.lookupClassOrThrow(REALM_OBJECT_HELPER) @@ -192,25 +189,25 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { // Top level SDK->Core converters private val byteToLong: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.byteToLong")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("byteToLong"))).first().owner private val charToLong: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.charToLong")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("charToLong"))).first().owner private val shortToLong: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.shortToLong")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("shortToLong"))).first().owner private val intToLong: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.intToLong")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("intToLong"))).first().owner // Top level Core->SDK converters private val longToByte: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.longToByte")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("longToByte"))).first().owner private val longToChar: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.longToChar")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("longToChar"))).first().owner private val longToShort: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.longToShort")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("longToShort"))).first().owner private val longToInt: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.longToInt")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("longToInt"))).first().owner private val objectIdToRealmObjectId: IrSimpleFunction = - pluginContext.referenceFunctions(FqName("io.realm.kotlin.internal.objectIdToRealmObjectId")).first().owner + pluginContext.referenceFunctions(CallableId(FqName("io.realm.kotlin.internal"), Name.identifier("objectIdToRealmObjectId"))).first().owner private lateinit var objectReferenceProperty: IrProperty private lateinit var objectReferenceType: IrType @@ -546,7 +543,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { if (!(isValidTargetType || isValidGenericType)) { val targetPropertyName = getLinkingObjectPropertyName(declaration.backingField!!) logError( - "Error in backlinks field '${declaration.name}' - target property '$targetPropertyName' does not reference '${sourceType.toKotlinType()}'.", + "Error in backlinks field '${declaration.name}' - target property '$targetPropertyName' does not reference '${sourceType.toIrBasedKotlinType().getKotlinTypeFqNameCompat(true)}'.", declaration.locationOf() ) } @@ -715,7 +712,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { name: String, declaration: IrProperty ) { - val type = declaration.symbol.descriptor.type + val type: KotlinType = declaration.symbol.owner.toIrBasedDescriptor().type if (type.arguments[0] is StarProjectionImpl) { logError( "Error in field ${declaration.name} - ${collectionType.description} cannot use a '*' projection.", @@ -960,80 +957,80 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { } private fun IrType.isRealmList(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmListClassId = realmListClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmListClassId: ClassId? = realmListClass.classId return propertyClassId == realmListClassId } private fun IrType.isRealmSet(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmSetClassId = realmSetClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmSetClassId: ClassId? = realmSetClass.classId return propertyClassId == realmSetClassId } private fun IrType.isRealmDictionary(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmDictionaryClassId = realmDictionaryClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmDictionaryClassId: ClassId? = realmDictionaryClass.classId return propertyClassId == realmDictionaryClassId } private fun IrType.isRealmInstant(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmInstantClassId = realmInstantClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmInstantClassId: ClassId? = realmInstantClass.classId return propertyClassId == realmInstantClassId } private fun IrType.isLinkingObject(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmBacklinksClassId: ClassId? = realmBacklinksClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmBacklinksClassId: ClassId? = realmBacklinksClass.classId return propertyClassId == realmBacklinksClassId } private fun IrType.isEmbeddedLinkingObject(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmEmbeddedBacklinksClassId: ClassId? = realmEmbeddedBacklinksClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmEmbeddedBacklinksClassId: ClassId? = realmEmbeddedBacklinksClass.classId return propertyClassId == realmEmbeddedBacklinksClassId } private fun IrType.isDecimal128(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val objectIdClassId = decimal128Class.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val objectIdClassId: ClassId? = decimal128Class.classId return propertyClassId == objectIdClassId } private fun IrType.isObjectId(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val objectIdClassId = objectIdClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val objectIdClassId: ClassId? = objectIdClass.classId return propertyClassId == objectIdClassId } private fun IrType.isRealmObjectId(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val objectIdClassId = realmObjectIdClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val objectIdClassId: ClassId? = realmObjectIdClass.classId return propertyClassId == objectIdClassId } private fun IrType.hasSameClassId(other: IrType): Boolean { - val classId = this.classifierOrFail.descriptor.classId - val otherClassId = other.classifierOrFail.descriptor.classId - return classId == otherClassId + val propertyClassId: ClassId = this.classIdOrFail() + val otherClassId = other.classIdOrFail() + return propertyClassId == otherClassId } private fun IrType.isRealmUUID(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val realmUUIDClassId = realmUUIDClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val realmUUIDClassId: ClassId? = realmUUIDClass.classId return propertyClassId == realmUUIDClassId } fun IrType.isMutableRealmInteger(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val mutableRealmIntegerClassId = mutableRealmIntegerClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val mutableRealmIntegerClassId: ClassId? = mutableRealmIntegerClass.classId return propertyClassId == mutableRealmIntegerClassId } fun IrType.isRealmAny(): Boolean { - val propertyClassId = this.classifierOrFail.descriptor.classId - val mutableRealmIntegerClassId = realmAnyClass.descriptor.classId + val propertyClassId: ClassId = this.classIdOrFail() + val mutableRealmIntegerClassId: ClassId? = realmAnyClass.classId return propertyClassId == mutableRealmIntegerClassId } @@ -1043,8 +1040,8 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { declaration: IrProperty ): CoreType? { // Check first if the generic is a subclass of RealmObject - val descriptorType = declaration.symbol.descriptor.type - val collectionGenericType = descriptorType.arguments[0].type + val descriptorType: KotlinType = declaration.toIrBasedDescriptor().type + val collectionGenericType: KotlinType = descriptorType.arguments[0].type val supertypes = collectionGenericType.constructor.supertypes val isEmbedded = inheritsFromRealmObject(supertypes, RealmObjectType.EMBEDDED) @@ -1101,10 +1098,11 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { } // Otherwise just return the matching core type present in the declaration - val genericPropertyType = getPropertyTypeFromKotlinType(collectionGenericType) + val genericPropertyType: PropertyType? = getPropertyTypeFromKotlinType(collectionGenericType) return if (genericPropertyType == null) { logError( - "Unsupported type for ${collectionType.description}: '$collectionGenericType'", + "Unsupported type for ${collectionType.description}: '${collectionGenericType.getKotlinTypeFqNameCompat(true) + }'", declaration.locationOf() ) null @@ -1160,12 +1158,12 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) { supertypes: Collection, objectType: RealmObjectType = RealmObjectType.EITHER ): Boolean = supertypes.any { - val objectFqNames = when (objectType) { + val objectFqNames: Set = when (objectType) { RealmObjectType.OBJECT -> realmObjectInterfaceFqNames RealmObjectType.EMBEDDED -> realmEmbeddedObjectInterfaceFqNames RealmObjectType.EITHER -> realmObjectInterfaceFqNames + realmEmbeddedObjectInterfaceFqNames } - it.constructor.declarationDescriptor?.fqNameSafe in objectFqNames + it.constructor.declarationDescriptor?.classId in objectFqNames } } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt index 27111250af..c4d1a87176 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt @@ -16,9 +16,9 @@ package io.realm.kotlin.compiler -import io.realm.kotlin.compiler.FqNames.CLASS_APP_CONFIGURATION import io.realm.kotlin.compiler.FqNames.PACKAGE_MONGODB import io.realm.kotlin.compiler.FqNames.PACKAGE_MONGODB_INTERNAL +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -86,69 +86,79 @@ internal object Names { } internal object FqNames { + val PACKAGE_ANNOTATIONS = FqName("io.realm.kotlin.types.annotations") + val PACKAGE_KBSON = FqName("org.mongodb.kbson") + val PACKAGE_KOTLIN_COLLECTIONS = FqName("kotlin.collections") + val PACKAGE_KOTLIN_REFLECT = FqName("kotlin.reflect") + val PACKAGE_TYPES = FqName("io.realm.kotlin.types") + val PACKAGE_REALM_INTEROP = FqName("io.realm.kotlin.internal.interop") + val PACKAGE_REALM_INTERNAL = FqName("io.realm.kotlin.internal") + val PACKAGE_MONGODB = FqName("io.realm.kotlin.mongodb") + val PACKAGE_MONGODB_INTERNAL = FqName("io.realm.kotlin.mongodb.internal") +} + +object ClassIds { + // TODO we can replace with RealmObject::class.java.canonicalName if we make the runtime_api available as a compile time only dependency for the compiler-plugin val REALM_NATIVE_POINTER = FqName("io.realm.kotlin.internal.interop.NativePointer") - val REALM_OBJECT_INTERNAL_INTERFACE = FqName("io.realm.kotlin.internal.RealmObjectInternal") + val REALM_OBJECT_INTERNAL_INTERFACE = ClassId(FqNames.PACKAGE_REALM_INTERNAL, Name.identifier("RealmObjectInternal")) + + val REALM_MODEL_COMPANION = ClassId(FqNames.PACKAGE_REALM_INTERNAL, Name.identifier("RealmObjectCompanion")) + val REALM_OBJECT_HELPER = ClassId(FqNames.PACKAGE_REALM_INTERNAL, Name.identifier("RealmObjectHelper")) + val REALM_CLASS_IMPL = ClassId(FqName("io.realm.kotlin.internal.schema"), Name.identifier("RealmClassImpl")) + val OBJECT_REFERENCE_CLASS = ClassId(FqNames.PACKAGE_REALM_INTERNAL, Name.identifier("RealmObjectReference")) - val REALM_MODEL_COMPANION = FqName("io.realm.kotlin.internal.RealmObjectCompanion") - val REALM_OBJECT_HELPER = FqName("io.realm.kotlin.internal.RealmObjectHelper") - val REALM_CLASS_IMPL = FqName("io.realm.kotlin.internal.schema.RealmClassImpl") - val OBJECT_REFERENCE_CLASS = FqName("io.realm.kotlin.internal.RealmObjectReference") + val BASE_REALM_OBJECT_INTERFACE = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("BaseRealmObject")) + 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 BASE_REALM_OBJECT_INTERFACE = FqName("io.realm.kotlin.types.BaseRealmObject") - val REALM_OBJECT_INTERFACE = FqName("io.realm.kotlin.types.RealmObject") - val TYPED_REALM_OBJECT_INTERFACE = FqName("io.realm.kotlin.types.TypedRealmObject") - val EMBEDDED_OBJECT_INTERFACE = FqName("io.realm.kotlin.types.EmbeddedRealmObject") - val ASYMMETRIC_OBJECT_INTERFACE = FqName("io.realm.kotlin.types.AsymmetricRealmObject") + val CLASS_APP_CONFIGURATION = ClassId(FqNames.PACKAGE_MONGODB, Name.identifier("AppConfiguration")) // External visible interface of Realm objects - val KOTLIN_COLLECTIONS_SET = FqName("kotlin.collections.Set") - val KOTLIN_COLLECTIONS_LIST = FqName("kotlin.collections.List") - val KOTLIN_COLLECTIONS_LISTOF = FqName("kotlin.collections.listOf") - val KOTLIN_COLLECTIONS_MAP = FqName("kotlin.collections.Map") - val KOTLIN_COLLECTIONS_MAPOF = FqName("kotlin.collections.mapOf") - val KOTLIN_REFLECT_KMUTABLEPROPERTY1 = FqName("kotlin.reflect.KMutableProperty1") - val KOTLIN_REFLECT_KPROPERTY1 = FqName("kotlin.reflect.KProperty1") - val KOTLIN_PAIR = FqName("kotlin.Pair") + val KOTLIN_COLLECTIONS_SET = ClassId(FqNames.PACKAGE_KOTLIN_COLLECTIONS, Name.identifier("Set")) + val KOTLIN_COLLECTIONS_LIST = ClassId(FqNames.PACKAGE_KOTLIN_COLLECTIONS, Name.identifier("List")) + val KOTLIN_COLLECTIONS_LISTOF = CallableId(FqNames.PACKAGE_KOTLIN_COLLECTIONS, Name.identifier("listOf")) + val KOTLIN_COLLECTIONS_MAP = ClassId(FqNames.PACKAGE_KOTLIN_COLLECTIONS, Name.identifier("Map")) + val KOTLIN_COLLECTIONS_MAPOF = CallableId(FqNames.PACKAGE_KOTLIN_COLLECTIONS, Name.identifier("mapOf")) + val KOTLIN_REFLECT_KMUTABLEPROPERTY1 = ClassId(FqNames.PACKAGE_KOTLIN_REFLECT, Name.identifier("KMutableProperty1")) + val KOTLIN_REFLECT_KPROPERTY1 = ClassId(FqNames.PACKAGE_KOTLIN_REFLECT, Name.identifier("KProperty1")) + val KOTLIN_PAIR = ClassId(FqName("kotlin"), Name.identifier("Pair")) // Schema related types - val CLASS_INFO = FqName("io.realm.kotlin.internal.interop.ClassInfo") - val PROPERTY_INFO = FqName("io.realm.kotlin.internal.interop.PropertyInfo") - val PROPERTY_TYPE = FqName("io.realm.kotlin.internal.interop.PropertyType") - val COLLECTION_TYPE = FqName("io.realm.kotlin.internal.interop.CollectionType") - val PRIMARY_KEY_ANNOTATION = FqName("io.realm.kotlin.types.annotations.PrimaryKey") - val INDEX_ANNOTATION = FqName("io.realm.kotlin.types.annotations.Index") - val FULLTEXT_ANNOTATION = FqName("io.realm.kotlin.types.annotations.FullText") - val IGNORE_ANNOTATION = FqName("io.realm.kotlin.types.annotations.Ignore") - val PERSISTED_NAME_ANNOTATION = FqName("io.realm.kotlin.types.annotations.PersistedName") - val TRANSIENT_ANNOTATION = FqName("kotlin.jvm.Transient") - val MODEL_OBJECT_ANNOTATION = FqName("io.realm.kotlin.internal.platform.ModelObject") - val PROPERTY_INFO_CREATE = FqName("io.realm.kotlin.internal.schema.createPropertyInfo") - val CLASS_KIND_TYPE = FqName("io.realm.kotlin.schema.RealmClassKind") + val CLASS_INFO = ClassId(FqNames.PACKAGE_REALM_INTEROP, Name.identifier("ClassInfo")) + val PROPERTY_INFO = ClassId(FqNames.PACKAGE_REALM_INTEROP, Name.identifier("PropertyInfo")) + val PROPERTY_TYPE = ClassId(FqNames.PACKAGE_REALM_INTEROP, Name.identifier("PropertyType")) + val COLLECTION_TYPE = ClassId(FqNames.PACKAGE_REALM_INTEROP, Name.identifier("CollectionType")) + val PRIMARY_KEY_ANNOTATION = ClassId(FqNames.PACKAGE_ANNOTATIONS, Name.identifier("PrimaryKey")) + val INDEX_ANNOTATION = ClassId(FqNames.PACKAGE_ANNOTATIONS, Name.identifier("Index")) + val FULLTEXT_ANNOTATION = ClassId(FqNames.PACKAGE_ANNOTATIONS, Name.identifier("FullText")) + val IGNORE_ANNOTATION = ClassId(FqNames.PACKAGE_ANNOTATIONS, Name.identifier("Ignore")) + val PERSISTED_NAME_ANNOTATION = ClassId(FqNames.PACKAGE_ANNOTATIONS, Name.identifier("PersistedName")) + val TRANSIENT_ANNOTATION = ClassId(FqName("kotlin.jvm"), Name.identifier("Transient")) + val MODEL_OBJECT_ANNOTATION = ClassId(FqName("io.realm.kotlin.internal.platform"), Name.identifier("ModelObject")) + val PROPERTY_INFO_CREATE = CallableId(FqName("io.realm.kotlin.internal.schema"), Name.identifier("createPropertyInfo")) + val CLASS_KIND_TYPE = ClassId(FqName("io.realm.kotlin.schema"), Name.identifier("RealmClassKind")) // Realm data types - val REALM_LIST = FqName("io.realm.kotlin.types.RealmList") - val REALM_SET = FqName("io.realm.kotlin.types.RealmSet") - val REALM_DICTIONARY = FqName("io.realm.kotlin.types.RealmDictionary") - val REALM_INSTANT = FqName("io.realm.kotlin.types.RealmInstant") - val REALM_BACKLINKS = FqName("io.realm.kotlin.types.BacklinksDelegate") - val REALM_EMBEDDED_BACKLINKS = FqName("io.realm.kotlin.types.EmbeddedBacklinksDelegate") - val REALM_OBJECT_ID = FqName("io.realm.kotlin.types.ObjectId") - val KBSON_OBJECT_ID = FqName("org.mongodb.kbson.BsonObjectId") - val KBSON_DECIMAL128 = FqName("org.mongodb.kbson.BsonDecimal128") - val REALM_UUID = FqName("io.realm.kotlin.types.RealmUUID") - val REALM_MUTABLE_INTEGER = FqName("io.realm.kotlin.types.MutableRealmInt") - val REALM_ANY = FqName("io.realm.kotlin.types.RealmAny") - - val PACKAGE_MONGODB = FqName("io.realm.kotlin.mongodb") - val PACKAGE_MONGODB_INTERNAL = FqName("io.realm.kotlin.mongodb.internal") - val CLASS_APP_CONFIGURATION = FqName("io.realm.kotlin.mongodb.AppConfiguration") -} - -object ClassIds { + val REALM_LIST = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmList")) + val REALM_SET = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmSet")) + val REALM_DICTIONARY = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmDictionary")) + val REALM_INSTANT = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmInstant")) + val REALM_BACKLINKS = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("BacklinksDelegate")) + val REALM_EMBEDDED_BACKLINKS = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("EmbeddedBacklinksDelegate")) + val REALM_OBJECT_ID = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("ObjectId")) + val KBSON_OBJECT_ID = ClassId(FqNames.PACKAGE_KBSON, Name.identifier("BsonObjectId")) + val KBSON_DECIMAL128 = ClassId(FqNames.PACKAGE_KBSON, Name.identifier("BsonDecimal128")) + val REALM_UUID = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmUUID")) + val REALM_MUTABLE_INTEGER = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("MutableRealmInt")) + val REALM_ANY = ClassId(FqNames.PACKAGE_TYPES, Name.identifier("RealmAny")) + + // Sync types val APP = ClassId(PACKAGE_MONGODB, Name.identifier("App")) val APP_IMPL = ClassId(PACKAGE_MONGODB_INTERNAL, Name.identifier("AppImpl")) val APP_CONFIGURATION = ClassId(PACKAGE_MONGODB, Name.identifier("AppConfiguration")) val APP_CONFIGURATION_IMPL = ClassId(PACKAGE_MONGODB_INTERNAL, Name.identifier("AppConfigurationImpl")) - val APP_CONFIGURATION_BUILDER = ClassId(CLASS_APP_CONFIGURATION, Name.identifier("Builder")) + val APP_CONFIGURATION_BUILDER = ClassId(FqName("io.realm.kotlin.mongodb.AppConfiguration"), FqName("Builder"), true) } 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 49d337ae5d..936b0741b6 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 @@ -13,25 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:OptIn(FirIncompatiblePluginAPI::class) package io.realm.kotlin.compiler -import io.realm.kotlin.compiler.FqNames.ASYMMETRIC_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.BASE_REALM_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.EMBEDDED_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.KOTLIN_COLLECTIONS_LISTOF -import io.realm.kotlin.compiler.FqNames.PERSISTED_NAME_ANNOTATION -import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI +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 org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocationWithRange import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation +import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtil import org.jetbrains.kotlin.com.intellij.psi.PsiElement import org.jetbrains.kotlin.com.intellij.psi.PsiElementVisitor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder import org.jetbrains.kotlin.ir.builders.IrBlockBuilder @@ -49,6 +50,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.builders.irBlockBody import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin @@ -82,13 +84,12 @@ import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeArgument -import org.jetbrains.kotlin.ir.types.classFqName +import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.impl.IrAbstractSimpleType -import org.jetbrains.kotlin.ir.types.impl.IrErrorClassImpl.superTypes import org.jetbrains.kotlin.ir.types.impl.IrTypeBase import org.jetbrains.kotlin.ir.types.makeNullable -import org.jetbrains.kotlin.ir.types.superTypes import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.ir.util.companionObject import org.jetbrains.kotlin.ir.util.copyTo import org.jetbrains.kotlin.ir.util.file @@ -97,12 +98,16 @@ import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.isVararg import org.jetbrains.kotlin.ir.util.properties +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.superTypes import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SUPER_TYPE_LIST +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.types.KotlinType import java.lang.reflect.Field import java.util.function.Predicate @@ -129,11 +134,13 @@ fun IrPluginContext.blockBody( val ClassDescriptor.isRealmObjectCompanion get() = isCompanionObject && (containingDeclaration as ClassDescriptor).isBaseRealmObject -val realmObjectInterfaceFqNames = setOf(FqNames.REALM_OBJECT_INTERFACE) -val realmEmbeddedObjectInterfaceFqNames = setOf(FqNames.EMBEDDED_OBJECT_INTERFACE) -val realmAsymmetricObjectInterfaceFqNames = setOf(FqNames.ASYMMETRIC_OBJECT_INTERFACE) +val realmObjectInterfaceFqNames = setOf(REALM_OBJECT_INTERFACE) +val realmEmbeddedObjectInterfaceFqNames = setOf(EMBEDDED_OBJECT_INTERFACE) +val realmAsymmetricObjectInterfaceFqNames = setOf(ASYMMETRIC_OBJECT_INTERFACE) val anyRealmObjectInterfacesFqNames = realmObjectInterfaceFqNames + realmEmbeddedObjectInterfaceFqNames + realmAsymmetricObjectInterfaceFqNames +fun IrType.classIdOrFail(): ClassId = getClass()?.classId ?: error("Can't get classId of ${render()}") + 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) var hasRealmObjectAsSuperType = false @@ -179,27 +186,37 @@ val ClassDescriptor.isEmbeddedRealmObject: Boolean val ClassDescriptor.isBaseRealmObject: Boolean get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames + asymmetricRealmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames) +// JetBrains already have a method `fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol)` +// It is unclear exactly what the difference is and how to get a ClassSymbol from a ClassId, +// so for now just work around it. +fun IrAnnotationContainer?.hasAnnotation(annotation: ClassId): Boolean { + return this?.hasAnnotation(annotation.asSingleFqName()) ?: false +} + fun IrMutableAnnotationContainer.hasAnnotation(annotation: FqName): Boolean { return annotations.hasAnnotation(annotation) } val IrClass.isBaseRealmObject - get() = superTypes.any { it.classFqName in anyRealmObjectInterfacesFqNames } + get() = superTypes.any { it.classId in anyRealmObjectInterfacesFqNames } val IrClass.isRealmObject - get() = superTypes.any { it.classFqName == BASE_REALM_OBJECT_INTERFACE } + get() = superTypes.any { it.classId == BASE_REALM_OBJECT_INTERFACE } val IrClass.isEmbeddedRealmObject: Boolean - get() = superTypes.any { it.classFqName == EMBEDDED_OBJECT_INTERFACE } + get() = superTypes.any { it.classId == EMBEDDED_OBJECT_INTERFACE } val IrClass.isAsymmetricRealmObject: Boolean - get() = superTypes.any { it.classFqName == ASYMMETRIC_OBJECT_INTERFACE } + get() = superTypes.any { it.classId == ASYMMETRIC_OBJECT_INTERFACE } + +val IrType.classId: ClassId? + get() = this.getClass()?.classId val IrType.isEmbeddedRealmObject: Boolean - get() = superTypes().any { it.classFqName == EMBEDDED_OBJECT_INTERFACE } + get() = superTypes().any { it.classId == EMBEDDED_OBJECT_INTERFACE } val IrType.isAsymmetricRealmObject: Boolean - get() = superTypes().any { it.classFqName == ASYMMETRIC_OBJECT_INTERFACE } + get() = superTypes().any { it.classId == ASYMMETRIC_OBJECT_INTERFACE } internal fun IrFunctionBuilder.at(startOffset: Int, endOffset: Int) = also { this.startOffset = startOffset @@ -227,10 +244,10 @@ internal fun IrClass.lookupProperty(name: Name): IrProperty { } internal fun IrPluginContext.lookupFunctionInClass( - fqName: FqName, + clazz: ClassId, function: String ): IrSimpleFunction { - return lookupClassOrThrow(fqName).functions.first { + return lookupClassOrThrow(clazz).functions.first { it.name == Name.identifier(function) } } @@ -240,16 +257,11 @@ internal fun IrPluginContext.lookupClassOrThrow(name: ClassId): IrClass { ?: fatalError("Cannot find ${name.asString()} on platform $platform.") } -internal fun IrPluginContext.lookupClassOrThrow(name: FqName): IrClass { - return referenceClass(name)?.owner - ?: fatalError("Cannot find ${name.asString()} on platform $platform.") -} - internal fun IrPluginContext.lookupConstructorInClass( - fqName: FqName, + clazz: ClassId, filter: (ctor: IrConstructorSymbol) -> Boolean = { true } ): IrConstructorSymbol { - return referenceConstructors(fqName).first { + return referenceConstructors(clazz).first { filter(it) } } @@ -263,6 +275,28 @@ internal fun IrClass.lookupCompanionDeclaration( ?: fatalError("Cannot find companion method ${name.asString()} on ${this.name}") } +// Copy of `KotlinType.getKotlinTypeFqName` from Kotlin 1.8.21. This method needs to be backported +// as it is not available in Kotlin 1.8.0. +internal fun KotlinType.getKotlinTypeFqNameCompat(printTypeArguments: Boolean): String { + val declaration = requireNotNull(constructor.declarationDescriptor) { + "declarationDescriptor is null for constructor = $constructor with ${constructor.javaClass}" + } + if (declaration is TypeParameterDescriptor) { + return StringUtil.join(declaration.upperBounds, { type -> type.getKotlinTypeFqNameCompat(printTypeArguments) }, "&") + } + + val typeArguments = arguments + val typeArgumentsAsString = if (printTypeArguments && !typeArguments.isEmpty()) { + val joinedTypeArguments = StringUtil.join(typeArguments, { projection -> projection.type.getKotlinTypeFqNameCompat(false) }, ", ") + + "<$joinedTypeArguments>" + } else { + "" + } + + return DescriptorUtils.getFqName(declaration).asString() + typeArgumentsAsString +} + object SchemaCollector { val properties = mutableMapOf>() } @@ -344,7 +378,7 @@ data class SchemaProperty( companion object { fun getPersistedName(declaration: IrProperty): String { @Suppress("UNCHECKED_CAST") - return (declaration.getAnnotation(PERSISTED_NAME_ANNOTATION).getValueArgument(0)!! as IrConstImpl).value + return (declaration.getAnnotation(PERSISTED_NAME_ANNOTATION.asSingleFqName()).getValueArgument(0)!! as IrConstImpl).value } } } @@ -391,12 +425,12 @@ internal fun buildSetOf( elementType: IrType, args: List ): IrExpression { - val setOf = context.referenceFunctions(FqName("kotlin.collections.setOf")) + val setOf = context.referenceFunctions(CallableId(FqName("kotlin.collections"), Name.identifier("setOf"))) .first { val parameters = it.owner.valueParameters parameters.size == 1 && parameters.first().isVararg } - val setIrClass: IrClass = context.lookupClassOrThrow(FqNames.KOTLIN_COLLECTIONS_SET) + val setIrClass: IrClass = context.lookupClassOrThrow(ClassIds.KOTLIN_COLLECTIONS_SET) return buildOf(context, startOffset, endOffset, setOf, setIrClass, elementType, args) } @@ -412,7 +446,7 @@ internal fun buildListOf( val parameters = it.owner.valueParameters parameters.size == 1 && parameters.first().isVararg } - val listIrClass: IrClass = context.lookupClassOrThrow(FqNames.KOTLIN_COLLECTIONS_LIST) + val listIrClass: IrClass = context.lookupClassOrThrow(ClassIds.KOTLIN_COLLECTIONS_LIST) return buildOf(context, startOffset, endOffset, listOf, listIrClass, elementType, args) } @@ -602,7 +636,7 @@ fun getLinkingObjectPropertyName(backingField: IrField): String { fun getSchemaClassName(clazz: IrClass): String { return if (clazz.hasAnnotation(PERSISTED_NAME_ANNOTATION)) { @Suppress("UNCHECKED_CAST") - return (clazz.getAnnotation(PERSISTED_NAME_ANNOTATION).getValueArgument(0)!! as IrConstImpl).value + return (clazz.getAnnotation(PERSISTED_NAME_ANNOTATION.asSingleFqName()).getValueArgument(0)!! as IrConstImpl).value } else { clazz.name.identifier } 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 9529a5124b..4e590cf6ab 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 @@ -16,9 +16,9 @@ package io.realm.kotlin.compiler -import io.realm.kotlin.compiler.FqNames.MODEL_OBJECT_ANNOTATION -import io.realm.kotlin.compiler.FqNames.REALM_MODEL_COMPANION -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_INTERNAL_INTERFACE +import io.realm.kotlin.compiler.ClassIds.MODEL_OBJECT_ANNOTATION +import io.realm.kotlin.compiler.ClassIds.REALM_MODEL_COMPANION +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_INTERNAL_INTERFACE import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext 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 868fe782a9..db43326fcf 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 @@ -13,32 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:OptIn(FirIncompatiblePluginAPI::class) package io.realm.kotlin.compiler -import io.realm.kotlin.compiler.FqNames.CLASS_INFO -import io.realm.kotlin.compiler.FqNames.CLASS_KIND_TYPE -import io.realm.kotlin.compiler.FqNames.COLLECTION_TYPE -import io.realm.kotlin.compiler.FqNames.FULLTEXT_ANNOTATION -import io.realm.kotlin.compiler.FqNames.INDEX_ANNOTATION -import io.realm.kotlin.compiler.FqNames.KBSON_OBJECT_ID -import io.realm.kotlin.compiler.FqNames.KOTLIN_COLLECTIONS_MAP -import io.realm.kotlin.compiler.FqNames.KOTLIN_COLLECTIONS_MAPOF -import io.realm.kotlin.compiler.FqNames.KOTLIN_PAIR -import io.realm.kotlin.compiler.FqNames.OBJECT_REFERENCE_CLASS -import io.realm.kotlin.compiler.FqNames.PRIMARY_KEY_ANNOTATION -import io.realm.kotlin.compiler.FqNames.PROPERTY_INFO -import io.realm.kotlin.compiler.FqNames.PROPERTY_INFO_CREATE -import io.realm.kotlin.compiler.FqNames.PROPERTY_TYPE -import io.realm.kotlin.compiler.FqNames.REALM_ANY -import io.realm.kotlin.compiler.FqNames.REALM_INSTANT -import io.realm.kotlin.compiler.FqNames.REALM_MODEL_COMPANION -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_ID -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_INTERFACE -import io.realm.kotlin.compiler.FqNames.REALM_OBJECT_INTERNAL_INTERFACE -import io.realm.kotlin.compiler.FqNames.REALM_UUID -import io.realm.kotlin.compiler.FqNames.TYPED_REALM_OBJECT_INTERFACE +import io.realm.kotlin.compiler.ClassIds.CLASS_INFO +import io.realm.kotlin.compiler.ClassIds.CLASS_KIND_TYPE +import io.realm.kotlin.compiler.ClassIds.COLLECTION_TYPE +import io.realm.kotlin.compiler.ClassIds.FULLTEXT_ANNOTATION +import io.realm.kotlin.compiler.ClassIds.INDEX_ANNOTATION +import io.realm.kotlin.compiler.ClassIds.KBSON_OBJECT_ID +import io.realm.kotlin.compiler.ClassIds.KOTLIN_COLLECTIONS_MAP +import io.realm.kotlin.compiler.ClassIds.KOTLIN_COLLECTIONS_MAPOF +import io.realm.kotlin.compiler.ClassIds.KOTLIN_PAIR +import io.realm.kotlin.compiler.ClassIds.OBJECT_REFERENCE_CLASS +import io.realm.kotlin.compiler.ClassIds.PRIMARY_KEY_ANNOTATION +import io.realm.kotlin.compiler.ClassIds.PROPERTY_INFO +import io.realm.kotlin.compiler.ClassIds.PROPERTY_INFO_CREATE +import io.realm.kotlin.compiler.ClassIds.PROPERTY_TYPE +import io.realm.kotlin.compiler.ClassIds.REALM_ANY +import io.realm.kotlin.compiler.ClassIds.REALM_INSTANT +import io.realm.kotlin.compiler.ClassIds.REALM_MODEL_COMPANION +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_ID +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_INTERFACE +import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_INTERNAL_INTERFACE +import io.realm.kotlin.compiler.ClassIds.REALM_UUID +import io.realm.kotlin.compiler.ClassIds.TYPED_REALM_OBJECT_INTERFACE import io.realm.kotlin.compiler.Names.CLASS_INFO_CREATE import io.realm.kotlin.compiler.Names.OBJECT_REFERENCE import io.realm.kotlin.compiler.Names.PROPERTY_COLLECTION_TYPE_DICTIONARY @@ -55,13 +54,11 @@ import io.realm.kotlin.compiler.Names.REALM_OBJECT_COMPANION_NEW_INSTANCE_METHOD import io.realm.kotlin.compiler.Names.REALM_OBJECT_COMPANION_PRIMARY_KEY_MEMBER import io.realm.kotlin.compiler.Names.REALM_OBJECT_COMPANION_SCHEMA_METHOD import io.realm.kotlin.compiler.Names.SET -import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.at import org.jetbrains.kotlin.ir.builders.declarations.addGetter @@ -96,7 +93,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrPropertyReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.classFqName import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.isNullable import org.jetbrains.kotlin.ir.types.makeNullable @@ -156,10 +153,10 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi private val realmAnyType: IrType = pluginContext.lookupClassOrThrow(REALM_ANY).defaultType private val kMutableProperty1Class: IrClass = - pluginContext.lookupClassOrThrow(FqNames.KOTLIN_REFLECT_KMUTABLEPROPERTY1) + pluginContext.lookupClassOrThrow(ClassIds.KOTLIN_REFLECT_KMUTABLEPROPERTY1) private val kProperty1Class: IrClass = - pluginContext.lookupClassOrThrow(FqNames.KOTLIN_REFLECT_KPROPERTY1) + pluginContext.lookupClassOrThrow(ClassIds.KOTLIN_REFLECT_KPROPERTY1) private val mapClass: IrClass = pluginContext.lookupClassOrThrow(KOTLIN_COLLECTIONS_MAP) private val pairClass: IrClass = pluginContext.lookupClassOrThrow(KOTLIN_PAIR) @@ -191,8 +188,8 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi realmObjectMutablePropertyType ) - val realmClassImpl = pluginContext.lookupClassOrThrow(FqNames.REALM_CLASS_IMPL) - private val realmClassCtor = pluginContext.lookupConstructorInClass(FqNames.REALM_CLASS_IMPL) { + val realmClassImpl = pluginContext.lookupClassOrThrow(ClassIds.REALM_CLASS_IMPL) + private val realmClassCtor = pluginContext.lookupConstructorInClass(ClassIds.REALM_CLASS_IMPL) { it.owner.valueParameters.size == 2 } @@ -207,7 +204,7 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi objectIdType, realmObjectIdType, realmUUIDType - ).map { it.classifierOrFail } + ) } private val indexableTypes = with(pluginContext.irBuiltIns) { setOf( @@ -223,12 +220,12 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi realmObjectIdType, realmUUIDType, realmAnyType - ).map { it.classifierOrFail } + ) } private val fullTextIndexableTypes = with(pluginContext.irBuiltIns) { setOf( stringType - ).map { it.classifierOrFail } + ) } /** @@ -424,7 +421,6 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi // Generate body for the synthetic schema method defined inside the Companion instance previously declared via `RealmModelSyntheticCompanionExtension` // TODO OPTIMIZE should be a one time only constructed object - @OptIn(ObsoleteDescriptorBasedAPI::class) @Suppress("LongMethod", "ComplexMethod") fun addSchemaMethodBody(irClass: IrClass) { val companionObject = irClass.companionObject() as? IrClass @@ -545,25 +541,24 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi value.coreGenericTypes?.get(0)?.nullable ?: fatalError("Missing generic type while processing a collection field.") } - val primaryKey = backingField.hasAnnotation(PRIMARY_KEY_ANNOTATION) - if (primaryKey && backingField.type.classifierOrFail !in validPrimaryKeyTypes) { + if (primaryKey && validPrimaryKeyTypes.find { it.classFqName == backingField.type.classFqName } == null) { logError( - "Primary key ${property.name} is of type ${backingField.type.classifierOrFail.owner.symbol.descriptor.name} but must be of type ${validPrimaryKeyTypes.map { it.owner.symbol.descriptor.name }}", + "Primary key ${property.name} is of type ${backingField.type.classId?.shortClassName} but must be of type ${validPrimaryKeyTypes.map { it.classId?.shortClassName }}", property.locationOf() ) } val isIndexed = backingField.hasAnnotation(INDEX_ANNOTATION) - if (isIndexed && backingField.type.classifierOrFail !in indexableTypes) { + if (isIndexed && indexableTypes.find { it.classFqName == backingField.type.classFqName } == null) { logError( - "Indexed key ${property.name} is of type ${backingField.type.classifierOrFail.owner.symbol.descriptor.name} but must be of type ${indexableTypes.map { it.owner.symbol.descriptor.name }}", + "Indexed key ${property.name} is of type ${backingField.type.classId?.shortClassName} but must be of type ${indexableTypes.map { it.classId?.shortClassName }}", property.locationOf() ) } val isFullTextIndexed = backingField.hasAnnotation(FULLTEXT_ANNOTATION) - if (isFullTextIndexed && backingField.type.classifierOrFail !in fullTextIndexableTypes) { + if (isFullTextIndexed && fullTextIndexableTypes.find { it.classFqName == backingField.type.classFqName } == null) { logError( - "Full-text key ${property.name} is of type ${backingField.type.classifierOrFail.owner.symbol.descriptor.name} but must be of type ${fullTextIndexableTypes.map { it.owner.symbol.descriptor.name }}", + "Full-text key ${property.name} is of type ${backingField.type.classId?.shortClassName} but must be of type ${fullTextIndexableTypes.map { it.classId?.shortClassName }}", property.locationOf() ) } 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 c6ae6d6455..12c088f671 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 @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.runOnFilePostfix -import org.jetbrains.kotlin.ir.backend.js.utils.valueArguments import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer import org.jetbrains.kotlin.ir.declarations.IrFile @@ -130,7 +129,7 @@ private class SyncLowering(private val pluginContext: IrPluginContext, private v val transformer = object : IrElementTransformerVoid() { override fun visitCall(expression: IrCall): IrExpression { - replacements.get(expression.symbol)?.let { (target, dispatchReceiverFunction) -> + replacements[expression.symbol]?.let { (target, dispatchReceiverFunction) -> return IrCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, @@ -142,7 +141,8 @@ private class SyncLowering(private val pluginContext: IrPluginContext, private v superQualifierSymbol = null ).apply { dispatchReceiver = dispatchReceiverFunction(expression) - expression.valueArguments.forEachIndexed { index, irExpression -> + val valueArguments = List(expression.valueArgumentsCount) { expression.getValueArgument(it) } + valueArguments.forEachIndexed { index, irExpression -> putValueArgument(index, irExpression,) } putValueArgument( diff --git a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/CollectionTests.kt b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/CollectionTests.kt index 23266602ff..a58fdaf774 100644 --- a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/CollectionTests.kt +++ b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/CollectionTests.kt @@ -114,7 +114,7 @@ abstract class CollectionTests( ) ) assertEquals(KotlinCompilation.ExitCode.COMPILATION_ERROR, result.exitCode) - assertTrue(result.messages.contains("Unsupported type for ${collectionType.description}: 'A'")) + assertTrue(result.messages.contains("Unsupported type for ${collectionType.description}: 'A'"), result.messages) } // ------------------------------------------------