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:
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
+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