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