Parcelize: Fix metadata and remap synthetic descriptor stubs

This commit is contained in:
Steven Schäfer
2020-05-04 16:18:08 +02:00
committed by Alexander Udalov
parent 779133e71e
commit d62b353ab5
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.android.parcel.ir
import org.jetbrains.kotlin.android.parcel.ANDROID_PARCELABLE_CLASS_FQNAME import org.jetbrains.kotlin.android.parcel.ANDROID_PARCELABLE_CLASS_FQNAME
import org.jetbrains.kotlin.android.parcel.PARCELER_FQNAME import org.jetbrains.kotlin.android.parcel.PARCELER_FQNAME
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent
import org.jetbrains.kotlin.android.parcel.serializers.ParcelableExtensionBase import org.jetbrains.kotlin.android.parcel.serializers.ParcelableExtensionBase
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
@@ -18,13 +19,17 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -36,9 +41,26 @@ class ParcelableIrTransformer(private val context: CommonBackendContext, private
private val deferredOperations = mutableListOf<() -> Unit>() private val deferredOperations = mutableListOf<() -> Unit>()
private fun defer(block: () -> Unit) = deferredOperations.add(block) private fun defer(block: () -> Unit) = deferredOperations.add(block)
private val symbolMap = mutableMapOf<IrFunctionSymbol, IrFunctionSymbol>()
fun transform(moduleFragment: IrModuleFragment) { fun transform(moduleFragment: IrModuleFragment) {
moduleFragment.accept(this, null) moduleFragment.accept(this, null)
deferredOperations.forEach { it() } deferredOperations.forEach { it() }
// Remap broken stubs, which psi2ir generates for the synthetic descriptors coming from the ParcelizeResolveExtension.
moduleFragment.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
val remappedSymbol = symbolMap[expression.symbol]
?: return super.visitCall(expression)
return IrCallImpl(
expression.startOffset, expression.endOffset, expression.type, remappedSymbol,
expression.typeArgumentsCount, expression.valueArgumentsCount, expression.origin,
expression.superQualifierSymbol
).apply {
copyTypeAndValueArgumentsFrom(expression)
}
}
})
} }
override fun visitElement(element: IrElement) = element.acceptChildren(this, null) override fun visitElement(element: IrElement) = element.acceptChildren(this, null)
@@ -56,7 +78,7 @@ class ParcelableIrTransformer(private val context: CommonBackendContext, private
} }
if (declaration.descriptor.hasSyntheticDescribeContents()) { if (declaration.descriptor.hasSyntheticDescribeContents()) {
declaration.addOverride( val describeContents = declaration.addOverride(
ANDROID_PARCELABLE_CLASS_FQNAME, ANDROID_PARCELABLE_CLASS_FQNAME,
"describeContents", "describeContents",
context.irBuiltIns.intType, context.irBuiltIns.intType,
@@ -66,11 +88,22 @@ class ParcelableIrTransformer(private val context: CommonBackendContext, private
body = context.createIrBuilder(symbol).run { body = context.createIrBuilder(symbol).run {
irExprBody(irInt(flags)) irExprBody(irInt(flags))
} }
(this as IrFunctionImpl).metadata = MetadataSource.Function(
declaration.descriptor.findFunction(ParcelableSyntheticComponent.ComponentKind.DESCRIBE_CONTENTS)!!
)
}
declaration.functions.find {
it.descriptor.safeAs<ParcelableSyntheticComponent>()?.componentKind == ParcelableSyntheticComponent.ComponentKind.DESCRIBE_CONTENTS
}?.let { stub ->
symbolMap[stub.symbol] = describeContents.symbol
declaration.declarations.remove(stub)
} }
} }
if (declaration.descriptor.hasSyntheticWriteToParcel()) { if (declaration.descriptor.hasSyntheticWriteToParcel()) {
declaration.addOverride( val writeToParcel = declaration.addOverride(
ANDROID_PARCELABLE_CLASS_FQNAME, ANDROID_PARCELABLE_CLASS_FQNAME,
"writeToParcel", "writeToParcel",
context.irBuiltIns.unitType, context.irBuiltIns.unitType,
@@ -110,6 +143,17 @@ class ParcelableIrTransformer(private val context: CommonBackendContext, private
} }
} }
} }
(this as IrFunctionImpl).metadata = MetadataSource.Function(
declaration.descriptor.findFunction(ParcelableSyntheticComponent.ComponentKind.WRITE_TO_PARCEL)!!
)
}
declaration.functions.find {
it.descriptor.safeAs<ParcelableSyntheticComponent>()?.componentKind == ParcelableSyntheticComponent.ComponentKind.WRITE_TO_PARCEL
}?.let { stub ->
symbolMap[stub.symbol] = writeToParcel.symbol
declaration.declarations.remove(stub)
} }
} }