Skip to content

Commit

Permalink
Remove all descriptor based APIs from the compiler plugin. Moving it …
Browse files Browse the repository at this point in the history
…a bit closer to K2 support.
  • Loading branch information
Christian Melchior committed Aug 7, 2023
1 parent 273fd31 commit 3edc468
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ 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
Expand All @@ -78,14 +77,15 @@ 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
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
Expand All @@ -100,16 +100,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.js.descriptorUtils.getKotlinTypeFqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
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
Expand All @@ -120,7 +120,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)
Expand Down Expand Up @@ -546,7 +545,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().getKotlinTypeFqName(true)}'.",
declaration.locationOf()
)
}
Expand Down Expand Up @@ -715,7 +714,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.",
Expand Down Expand Up @@ -960,80 +959,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
}

Expand All @@ -1043,8 +1042,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)
Expand Down Expand Up @@ -1101,10 +1100,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.getKotlinTypeFqName(true)
}'",
declaration.locationOf()
)
null
Expand Down Expand Up @@ -1160,12 +1160,12 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
supertypes: Collection<KotlinType>,
objectType: RealmObjectType = RealmObjectType.EITHER
): Boolean = supertypes.any {
val objectFqNames = when (objectType) {
val objectFqNames: Set<ClassId> = when (objectType) {
RealmObjectType.OBJECT -> realmObjectInterfaceFqNames
RealmObjectType.EMBEDDED -> realmEmbeddedObjectInterfaceFqNames
RealmObjectType.EITHER -> realmObjectInterfaceFqNames + realmEmbeddedObjectInterfaceFqNames
}
it.constructor.declarationDescriptor?.fqNameSafe in objectFqNames
it.constructor.declarationDescriptor?.classId in objectFqNames
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ internal object FqNames {
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 = FqName("io.realm.kotlin.types.BaseRealmObject")
val REALM_OBJECT_INTERFACE = FqName("io.realm.kotlin.types.RealmObject")
val BASE_REALM_OBJECT_INTERFACE = ClassId(FqName("io.realm.kotlin.types"), FqName("BaseRealmObject"), false)
val REALM_OBJECT_INTERFACE = ClassId(FqName("io.realm.kotlin.types"), FqName("RealmObject"), false)
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 EMBEDDED_OBJECT_INTERFACE = ClassId(FqName("io.realm.kotlin.types"), FqName("EmbeddedRealmObject"), false)
val ASYMMETRIC_OBJECT_INTERFACE = ClassId(FqName("io.realm.kotlin.types"), FqName("AsymmetricRealmObject"), false)

// External visible interface of Realm objects
val KOTLIN_COLLECTIONS_SET = FqName("kotlin.collections.Set")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:OptIn(FirIncompatiblePluginAPI::class)

package io.realm.kotlin.compiler

Expand Down Expand Up @@ -82,13 +81,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
Expand All @@ -97,6 +95,7 @@ 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.ClassId
Expand Down Expand Up @@ -134,6 +133,8 @@ val realmEmbeddedObjectInterfaceFqNames = setOf(FqNames.EMBEDDED_OBJECT_INTERFAC
val realmAsymmetricObjectInterfaceFqNames = setOf(FqNames.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<String>): Boolean {
// Using PSI to find super types to avoid cyclic reference (see https://github.com/realm/realm-kotlin/issues/339)
var hasRealmObjectAsSuperType = false
Expand Down Expand Up @@ -184,22 +185,25 @@ fun IrMutableAnnotationContainer.hasAnnotation(annotation: FqName): Boolean {
}

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
Expand Down Expand Up @@ -240,11 +244,13 @@ internal fun IrPluginContext.lookupClassOrThrow(name: ClassId): IrClass {
?: fatalError("Cannot find ${name.asString()} on platform $platform.")
}

@OptIn(FirIncompatiblePluginAPI::class)
internal fun IrPluginContext.lookupClassOrThrow(name: FqName): IrClass {
return referenceClass(name)?.owner
?: fatalError("Cannot find ${name.asString()} on platform $platform.")
}

@OptIn(FirIncompatiblePluginAPI::class)
internal fun IrPluginContext.lookupConstructorInClass(
fqName: FqName,
filter: (ctor: IrConstructorSymbol) -> Boolean = { true }
Expand Down Expand Up @@ -384,6 +390,7 @@ internal fun <T : IrExpression> buildOf(
}
}

@OptIn(FirIncompatiblePluginAPI::class)
internal fun <T : IrExpression> buildSetOf(
context: IrPluginContext,
startOffset: Int,
Expand All @@ -400,6 +407,7 @@ internal fun <T : IrExpression> buildSetOf(
return buildOf(context, startOffset, endOffset, setOf, setIrClass, elementType, args)
}

@OptIn(FirIncompatiblePluginAPI::class)
internal fun <T : IrExpression> buildListOf(
context: IrPluginContext,
startOffset: Int,
Expand Down
Loading

0 comments on commit 3edc468

Please sign in to comment.