Directly search in IrClass for declarations to fill bodies with plugin
because some other compiler plugins (Compose) copy/rewrite IR declarations completely, and in the end, functions that are present in the final IR tree do not have bodies. Correctly create IrProperty and IrField when they were absent from the descriptors (in case for private serializer properties) Do not use symbol table because 'declare' API is not available in plugins. Fixes https://github.com/JetBrains/compose-jb/issues/46
This commit is contained in:
+4
-2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.common
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberToGenerate
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
|
||||
@@ -69,12 +70,13 @@ abstract class SerializerCodegen(
|
||||
serializerDescriptor::checkSerializableClassPropertyResult
|
||||
) { true }
|
||||
|
||||
val localSerializersFieldsDescriptors: List<PropertyDescriptor> = findLocalSerializersFieldDescriptors()
|
||||
lateinit var localSerializersFieldsDescriptors: List<Pair<PropertyDescriptor, IrProperty>>
|
||||
protected set
|
||||
|
||||
// Can be false if user specified inheritance from KSerializer explicitly
|
||||
protected val isGeneratedSerializer = serializerDescriptor.typeConstructor.supertypes.any(::isGeneratedKSerializer)
|
||||
|
||||
private fun findLocalSerializersFieldDescriptors(): List<PropertyDescriptor> {
|
||||
protected fun findLocalSerializersFieldDescriptors(): List<PropertyDescriptor> {
|
||||
val count = serializableDescriptor.declaredTypeParameters.size
|
||||
if (count == 0) return emptyList()
|
||||
val propNames = (0 until count).map { "${SerialEntityNames.typeArgPrefix}$it" }
|
||||
|
||||
+42
-47
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
@@ -42,10 +41,12 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
interface IrBuilderExtension {
|
||||
val compilerContext: SerializationPluginContext
|
||||
|
||||
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
||||
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
||||
}
|
||||
|
||||
fun IrClass.contributeFunction(descriptor: FunctionDescriptor, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) {
|
||||
val functionSymbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor)
|
||||
assert(functionSymbol.isBound)
|
||||
val f: IrSimpleFunction = functionSymbol.owner
|
||||
val f: IrSimpleFunction = searchForDeclaration(descriptor) ?: compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner
|
||||
// TODO: default parameters
|
||||
f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(
|
||||
this.startOffset,
|
||||
@@ -59,11 +60,7 @@ interface IrBuilderExtension {
|
||||
overwriteValueParameters: Boolean = false,
|
||||
bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit
|
||||
) {
|
||||
val ctorSymbol = compilerContext.symbolTable.referenceConstructor(descriptor)
|
||||
assert(ctorSymbol.isBound)
|
||||
|
||||
val c = ctorSymbol.owner
|
||||
|
||||
val c: IrConstructor = searchForDeclaration(descriptor) ?: compilerContext.symbolTable.referenceConstructor(descriptor).owner
|
||||
c.body = DeclarationIrBuilder(compilerContext, c.symbol, this.startOffset, this.endOffset).irBlockBody(
|
||||
this.startOffset,
|
||||
this.endOffset
|
||||
@@ -94,7 +91,7 @@ interface IrBuilderExtension {
|
||||
irInvoke(
|
||||
dispatchReceiver,
|
||||
callee,
|
||||
*valueArguments.toTypedArray(),
|
||||
args = valueArguments.toTypedArray(),
|
||||
typeHint = returnTypeHint
|
||||
).also { call -> typeArguments.forEachIndexed(call::putTypeArgument) }
|
||||
|
||||
@@ -226,16 +223,12 @@ interface IrBuilderExtension {
|
||||
fun generateSimplePropertyWithBackingField(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
propertyParent: IrClass,
|
||||
declare: Boolean,
|
||||
fieldName: Name = propertyDescriptor.name,
|
||||
): IrProperty {
|
||||
val irPropertySymbol = compilerContext.symbolTable.referenceProperty(propertyDescriptor)
|
||||
assert(irPropertySymbol.isBound || declare)
|
||||
|
||||
if (!irPropertySymbol.isBound) {
|
||||
val irProperty = propertyParent.searchForDeclaration<IrProperty>(propertyDescriptor) ?: run {
|
||||
with(propertyDescriptor) {
|
||||
propertyParent.factory.createProperty(
|
||||
propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irPropertySymbol,
|
||||
propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrPropertySymbolImpl(propertyDescriptor),
|
||||
name, visibility, modality, isVar, isConst, isLateInit, isDelegated, isExternal
|
||||
).also {
|
||||
it.parent = propertyParent
|
||||
@@ -243,50 +236,54 @@ interface IrBuilderExtension {
|
||||
}
|
||||
}
|
||||
}
|
||||
val irProperty = irPropertySymbol.owner
|
||||
|
||||
irProperty.backingField = generatePropertyBackingField(propertyDescriptor, irProperty, fieldName).apply {
|
||||
parent = propertyParent
|
||||
correspondingPropertySymbol = irPropertySymbol
|
||||
}
|
||||
propertyParent.generatePropertyBackingFieldIfNeeded(propertyDescriptor, irProperty, fieldName)
|
||||
val fieldSymbol = irProperty.backingField!!.symbol
|
||||
irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(irProperty, it, fieldSymbol, declare) }
|
||||
?.apply { parent = propertyParent }
|
||||
irProperty.setter = propertyDescriptor.setter?.let { generatePropertyAccessor(irProperty, it, fieldSymbol, declare) }
|
||||
?.apply { parent = propertyParent }
|
||||
irProperty.getter = propertyDescriptor.getter?.let {
|
||||
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = true)
|
||||
}?.apply { parent = propertyParent }
|
||||
irProperty.setter = propertyDescriptor.setter?.let {
|
||||
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = false)
|
||||
}?.apply { parent = propertyParent }
|
||||
return irProperty
|
||||
}
|
||||
|
||||
private fun generatePropertyBackingField(
|
||||
descriptor: PropertyDescriptor,
|
||||
private fun IrClass.generatePropertyBackingFieldIfNeeded(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
originProperty: IrProperty,
|
||||
name: Name,
|
||||
): IrField {
|
||||
val fieldSymbol = compilerContext.symbolTable.referenceField(descriptor)
|
||||
if (fieldSymbol.isBound) return fieldSymbol.owner
|
||||
) {
|
||||
if (originProperty.backingField != null) return
|
||||
|
||||
return with(descriptor) {
|
||||
val field = with(propertyDescriptor) {
|
||||
// TODO: type parameters
|
||||
originProperty.factory.createField(
|
||||
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, fieldSymbol, name, type.toIrType(),
|
||||
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(),
|
||||
visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null
|
||||
)
|
||||
}
|
||||
field.apply {
|
||||
parent = this@generatePropertyBackingFieldIfNeeded
|
||||
correspondingPropertySymbol = originProperty.symbol
|
||||
}
|
||||
|
||||
originProperty.backingField = field
|
||||
}
|
||||
|
||||
private fun generatePropertyAccessor(
|
||||
private fun IrClass.generatePropertyAccessor(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
property: IrProperty,
|
||||
descriptor: PropertyAccessorDescriptor,
|
||||
fieldSymbol: IrFieldSymbol,
|
||||
declare: Boolean
|
||||
isGetter: Boolean,
|
||||
): IrSimpleFunction {
|
||||
val symbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor)
|
||||
assert(symbol.isBound || declare)
|
||||
|
||||
if (!symbol.isBound) {
|
||||
val irAccessor: IrSimpleFunction = when (isGetter) {
|
||||
true -> searchForDeclaration<IrProperty>(propertyDescriptor)?.getter
|
||||
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
|
||||
} ?: run {
|
||||
with(descriptor) {
|
||||
property.factory.createFunction(
|
||||
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, symbol,
|
||||
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
|
||||
name, visibility, modality, returnType!!.toIrType(),
|
||||
isInline, isExternal, isTailrec, isSuspend, isOperator, isInfix, isExpect
|
||||
)
|
||||
@@ -298,11 +295,9 @@ interface IrBuilderExtension {
|
||||
}
|
||||
}
|
||||
|
||||
val irAccessor = symbol.owner
|
||||
irAccessor.body = when (descriptor) {
|
||||
is PropertyGetterDescriptor -> generateDefaultGetterBody(descriptor, irAccessor)
|
||||
is PropertySetterDescriptor -> generateDefaultSetterBody(descriptor, irAccessor)
|
||||
else -> throw AssertionError("Should be getter or setter: $descriptor")
|
||||
irAccessor.body = when (isGetter) {
|
||||
true -> generateDefaultGetterBody(descriptor as PropertyGetterDescriptor, irAccessor)
|
||||
false -> generateDefaultSetterBody(descriptor as PropertySetterDescriptor, irAccessor)
|
||||
}
|
||||
|
||||
return irAccessor
|
||||
@@ -557,8 +552,8 @@ interface IrBuilderExtension {
|
||||
kType,
|
||||
genericIndex
|
||||
) { it, _ ->
|
||||
val prop = enclosingGenerator.localSerializersFieldsDescriptors[it]
|
||||
irGetField(irGet(dispatchReceiverParameter), compilerContext.symbolTable.referenceField(prop).owner)
|
||||
val (prop, ir) = enclosingGenerator.localSerializersFieldsDescriptors[it]
|
||||
irGetField(irGet(dispatchReceiverParameter), ir.backingField!!)
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.serializerInstance(
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ class SerialInfoImplJvmIrGenerator(
|
||||
ctor.body = ctorBody
|
||||
|
||||
for (property in properties) {
|
||||
generateSimplePropertyWithBackingField(property.descriptor, irClass, true, Name.identifier("_" + property.name.asString()))
|
||||
generateSimplePropertyWithBackingField(property.descriptor, irClass, Name.identifier("_" + property.name.asString()))
|
||||
|
||||
val getter = property.getter!!
|
||||
getter.origin = SERIALIZABLE_SYNTHETIC_ORIGIN
|
||||
|
||||
+7
-7
@@ -65,11 +65,11 @@ open class SerializerIrGenerator(
|
||||
|
||||
// how to (auto)create backing field and getter/setter?
|
||||
compilerContext.symbolTable.withReferenceScope(irClass.descriptor) {
|
||||
prop = generateSimplePropertyWithBackingField(desc, irClass, false)
|
||||
prop = generateSimplePropertyWithBackingField(desc, irClass)
|
||||
|
||||
// TODO: Do not use descriptors here
|
||||
localSerializersFieldsDescriptors.forEach {
|
||||
generateSimplePropertyWithBackingField(it, irClass, true)
|
||||
localSerializersFieldsDescriptors = findLocalSerializersFieldDescriptors().map { it ->
|
||||
it to generateSimplePropertyWithBackingField(it, irClass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,11 +195,11 @@ open class SerializerIrGenerator(
|
||||
// store type arguments serializers in fields
|
||||
val thisAsReceiverParameter = irClass.thisReceiver!!
|
||||
ctor.valueParameters.forEachIndexed { index, param ->
|
||||
val localSerial = compilerContext.symbolTable.referenceField(localSerializersFieldsDescriptors[index])
|
||||
val localSerial = localSerializersFieldsDescriptors[index].second.backingField!!
|
||||
+irSetField(generateReceiverExpressionForFieldAccess(
|
||||
thisAsReceiverParameter.symbol,
|
||||
localSerializersFieldsDescriptors[index]
|
||||
), localSerial.owner, irGet(param))
|
||||
localSerializersFieldsDescriptors[index].first
|
||||
), localSerial, irGet(param))
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ open class SerializerIrGenerator(
|
||||
val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ ->
|
||||
irGetField(
|
||||
irGet(irFun.dispatchReceiverParameter!!),
|
||||
compilerContext.symbolTable.referenceField(localSerializersFieldsDescriptors[idx]).owner
|
||||
localSerializersFieldsDescriptors[idx].second.backingField!!
|
||||
)
|
||||
}
|
||||
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type
|
||||
|
||||
Reference in New Issue
Block a user