Remove old JVM backend implementation of Parcelize

There's no way for the end user to use this implementation anymore,
since old JVM backend cannot be enabled, and nothing else from Kotlin
depends on it.
This commit is contained in:
Alexander Udalov
2023-03-06 16:26:46 +01:00
parent f4b4922a13
commit 163a052f98
21 changed files with 18 additions and 1324 deletions
@@ -2,7 +2,8 @@
* Copyright 2010-2022 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
@@ -2,7 +2,8 @@
* Copyright 2010-2022 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.common.ir.addExtensionReceiver
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.psiElement
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.isJvmInterface
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -1,144 +0,0 @@
/*
* Copyright 2010-2022 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.parcelize
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.codegen.AbstractClassBuilder
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
import org.jetbrains.kotlin.codegen.DelegatingClassBuilder
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.RecordComponentVisitor
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class ParcelizeClinitClassBuilderInterceptorExtension : ClassBuilderInterceptorExtension {
override fun interceptClassBuilderFactory(
interceptedFactory: ClassBuilderFactory,
bindingContext: BindingContext,
diagnostics: DiagnosticSink
): ClassBuilderFactory {
return ParcelableClinitClassBuilderFactory(interceptedFactory, bindingContext)
}
private inner class ParcelableClinitClassBuilderFactory(
private val delegateFactory: ClassBuilderFactory,
val bindingContext: BindingContext
) : ClassBuilderFactory {
override fun newClassBuilder(origin: JvmDeclarationOrigin): ClassBuilder {
return AndroidOnDestroyCollectorClassBuilder(origin, delegateFactory.newClassBuilder(origin), bindingContext)
}
override fun getClassBuilderMode() = delegateFactory.classBuilderMode
override fun asText(builder: ClassBuilder?): String? {
return delegateFactory.asText((builder as AndroidOnDestroyCollectorClassBuilder).delegateClassBuilder)
}
override fun asBytes(builder: ClassBuilder?): ByteArray? {
return delegateFactory.asBytes((builder as AndroidOnDestroyCollectorClassBuilder).delegateClassBuilder)
}
override fun close() {
delegateFactory.close()
}
}
private class AndroidOnDestroyCollectorClassBuilder(
val declarationOrigin: JvmDeclarationOrigin,
val delegateClassBuilder: ClassBuilder,
val bindingContext: BindingContext
) : DelegatingClassBuilder() {
private var currentClass: KtClassOrObject? = null
private var currentClassName: String? = null
private var isClinitGenerated = false
override fun getDelegate() = delegateClassBuilder
override fun defineClass(
origin: PsiElement?,
version: Int,
access: Int,
name: String,
signature: String?,
superName: String,
interfaces: Array<out String>
) {
currentClass = origin as? KtClassOrObject
currentClassName = name
isClinitGenerated = false
super.defineClass(origin, version, access, name, signature, superName, interfaces)
}
override fun done(generateSmapCopyToAnnotation: Boolean) {
if (!isClinitGenerated && currentClass != null && currentClassName != null) {
val descriptor = bindingContext[BindingContext.CLASS, currentClass]
if (descriptor != null && declarationOrigin.descriptor == descriptor && descriptor.isParcelize) {
val baseVisitor = super.newMethod(JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC, "<clinit>", "()V", null, null)
val visitor = ClinitAwareMethodVisitor(currentClassName!!, baseVisitor)
visitor.visitCode()
visitor.visitInsn(Opcodes.RETURN)
visitor.visitEnd()
}
}
super.done(generateSmapCopyToAnnotation)
}
override fun newMethod(
origin: JvmDeclarationOrigin,
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
if (name == "<clinit>" && currentClass != null && currentClassName != null) {
isClinitGenerated = true
val descriptor = bindingContext[BindingContext.CLASS, currentClass]
if (descriptor != null && declarationOrigin.descriptor == descriptor && descriptor.isParcelize) {
return ClinitAwareMethodVisitor(
currentClassName!!,
super.newMethod(origin, access, name, desc, signature, exceptions)
)
}
}
return super.newMethod(origin, access, name, desc, signature, exceptions)
}
override fun newRecordComponent(name: String, desc: String, signature: String?): RecordComponentVisitor {
return AbstractClassBuilder.EMPTY_RECORD_VISITOR
}
}
private class ClinitAwareMethodVisitor(val parcelableName: String, mv: MethodVisitor) : MethodVisitor(Opcodes.API_VERSION, mv) {
override fun visitInsn(opcode: Int) {
if (opcode == Opcodes.RETURN) {
val iv = InstructionAdapter(this)
val creatorName = "$parcelableName\$Creator"
val creatorType = Type.getObjectType(creatorName)
iv.anew(creatorType)
iv.dup()
iv.invokespecial(creatorName, "<init>", "()V", false)
iv.putstatic(parcelableName, "CREATOR", "Landroid/os/Parcelable\$Creator;")
}
super.visitInsn(opcode)
}
}
}
@@ -1,426 +0,0 @@
/*
* Copyright 2010-2022 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.parcelize
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy.CodegenBased
import org.jetbrains.kotlin.codegen.context.ClassContext
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.ParcelizeNames.NEW_ARRAY_NAME
import org.jetbrains.kotlin.parcelize.ParcelizeResolveExtension.Companion.createMethod
import org.jetbrains.kotlin.parcelize.ParcelizeSyntheticComponent.ComponentKind.*
import org.jetbrains.kotlin.parcelize.serializers.*
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase.Companion.FILE_DESCRIPTOR_FQNAME
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
open class ParcelizeCodegenExtension : ParcelizeExtensionBase, ExpressionCodegenExtension {
open fun isAvailable(element: PsiElement): Boolean {
return true
}
override val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean
get() = true
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
val declaration = codegen.myClass as? PsiElement ?: return
if (!isAvailable(declaration)) {
return
}
val parcelableClass = codegen.descriptor
if (!parcelableClass.isParcelizeClassDescriptor) {
return
}
val propertiesToSerialize = getPropertiesToSerialize(codegen, parcelableClass)
val parcelerObject = parcelableClass.companionObjectDescriptor?.takeIf {
TypeUtils.getAllSupertypes(it.defaultType).any { supertype -> supertype.isParceler }
}
with(parcelableClass) {
if (hasSyntheticDescribeContents()) {
writeDescribeContentsFunction(codegen, propertiesToSerialize)
}
if (hasSyntheticWriteToParcel()) {
writeWriteToParcel(codegen, propertiesToSerialize, PARCEL_TYPE, parcelerObject)
}
if (!hasCreatorField()) {
writeCreatorAccessField(codegen, parcelableClass)
}
}
if (codegen.state.classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
val parcelClassType = ParcelizeResolveExtension.resolveParcelClassType(parcelableClass.module)
?: error("Can't resolve 'android.os.Parcel' class")
val parcelableCreatorClassType = ParcelizeResolveExtension.resolveParcelableCreatorClassType(parcelableClass.module)
?: error("Can't resolve 'android.os.Parcelable.Creator' class")
writeCreatorClass(
codegen,
parcelableClass, parcelClassType, parcelableCreatorClassType,
PARCEL_TYPE, parcelerObject, propertiesToSerialize
)
}
}
private fun getCompanionClassType(containerAsmType: Type, parcelerObject: ClassDescriptor): Pair<Type, String> {
val shortName = parcelerObject.name
return Pair(Type.getObjectType(containerAsmType.internalName + "\$$shortName"), shortName.asString())
}
private fun ClassDescriptor.writeWriteToParcel(
codegen: ImplementationBodyCodegen,
properties: List<PropertyToSerialize>,
parcelAsmType: Type,
parcelerObject: ClassDescriptor?
): Unit? {
val containerAsmType = codegen.typeMapper.mapType(this.defaultType)
return findFunction(WRITE_TO_PARCEL)?.write(codegen) {
if (parcelerObject != null) {
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
v.getstatic(containerAsmType.internalName, companionFieldName, companionAsmType.descriptor)
v.load(0, containerAsmType)
v.load(1, PARCEL_TYPE)
v.load(2, Type.INT_TYPE)
v.invokevirtual(
companionAsmType.internalName, "write",
"(${containerAsmType.descriptor}${PARCEL_TYPE.descriptor}I)V", false
)
} else {
val frameMap = FrameMap().apply {
enterTemp(containerAsmType)
enterTemp(PARCEL_TYPE)
enterTemp(Type.INT_TYPE)
}
val globalContext = ParcelSerializer.ParcelSerializerContext(codegen.typeMapper, containerAsmType, emptyList(), frameMap)
if (properties.isEmpty()) {
val entityType = this@writeWriteToParcel.defaultType
val asmType = codegen.state.typeMapper.mapType(entityType)
val serializer = if (this@writeWriteToParcel.kind == ClassKind.CLASS) {
NullAwareParcelSerializerWrapper(ZeroParameterClassSerializer(asmType, entityType))
} else {
ParcelSerializer.get(entityType, asmType, globalContext, strict = true)
}
v.load(1, parcelAsmType)
v.load(0, containerAsmType)
serializer.writeValue(v)
} else {
for ((fieldName, type, parcelers) in properties) {
val asmType = codegen.typeMapper.mapType(type)
v.load(1, parcelAsmType)
v.load(0, containerAsmType)
v.getfield(containerAsmType.internalName, fieldName, asmType.descriptor)
val serializer = ParcelSerializer.get(type, asmType, globalContext.copy(typeParcelers = parcelers))
serializer.writeValue(v)
}
}
}
v.areturn(Type.VOID_TYPE)
}
}
private fun ClassDescriptor.writeDescribeContentsFunction(
codegen: ImplementationBodyCodegen,
propertiesToSerialize: List<PropertyToSerialize>
): Unit? {
val hasFileDescriptorAnywhere = propertiesToSerialize.any { it.type.containsFileDescriptor() }
return findFunction(DESCRIBE_CONTENTS)?.write(codegen) {
v.aconst(if (hasFileDescriptorAnywhere) 1 /* CONTENTS_FILE_DESCRIPTOR */ else 0)
v.areturn(Type.INT_TYPE)
}
}
private fun KotlinType.containsFileDescriptor(): Boolean {
val declarationDescriptor = this.constructor.declarationDescriptor
if (declarationDescriptor != null) {
if (declarationDescriptor.fqNameSafe == FILE_DESCRIPTOR_FQNAME) {
return true
}
}
return this.arguments.any { it.type.containsFileDescriptor() }
}
data class PropertyToSerialize(val name: String, val type: KotlinType, val parcelers: List<TypeParcelerMapping>)
private fun getPropertiesToSerialize(
codegen: ImplementationBodyCodegen,
parcelableClass: ClassDescriptor
): List<PropertyToSerialize> {
if (parcelableClass.kind != ClassKind.CLASS) {
return emptyList()
}
val constructor = parcelableClass.constructors.firstOrNull { it.isPrimary } ?: return emptyList()
val propertiesToSerialize = constructor.valueParameters.mapNotNull { param ->
codegen.bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, param]
}
val classParcelers = getTypeParcelers(parcelableClass.annotations)
return propertiesToSerialize.map {
PropertyToSerialize(it.name.asString(), it.type, classParcelers + getTypeParcelers(it.annotations))
}
}
private fun writeCreateFromParcel(
codegen: ImplementationBodyCodegen,
parcelableClass: ClassDescriptor,
parcelableCreatorClassType: KotlinType,
creatorClass: ClassDescriptorImpl,
parcelClassType: KotlinType,
parcelAsmType: Type,
parcelerObject: ClassDescriptor?,
properties: List<PropertyToSerialize>
) {
val containerAsmType = codegen.typeMapper.mapType(parcelableClass)
val creatorAsmType = codegen.typeMapper.mapType(creatorClass)
val overriddenFunction = parcelableCreatorClassType.findFunction(CREATE_FROM_PARCEL)
?: error("Can't resolve 'android.os.Parcelable.Creator.${CREATE_FROM_PARCEL.methodName}' method")
createMethod(
creatorClass, CREATE_FROM_PARCEL, Modality.FINAL,
parcelableClass.defaultType.replaceArgumentsWithStarProjections(), "in" to parcelClassType
).write(codegen, overriddenFunction) {
if (parcelerObject != null) {
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
v.getstatic(containerAsmType.internalName, companionFieldName, companionAsmType.descriptor)
v.load(1, PARCEL_TYPE)
v.invokevirtual(companionAsmType.internalName, "create", "(${PARCEL_TYPE.descriptor})$containerAsmType", false)
} else {
v.anew(containerAsmType)
v.dup()
val asmConstructorParameters = StringBuilder()
val frameMap = FrameMap().apply {
enterTemp(creatorAsmType)
enterTemp(PARCEL_TYPE)
}
val globalContext = ParcelSerializer.ParcelSerializerContext(codegen.typeMapper, containerAsmType, emptyList(), frameMap)
if (properties.isEmpty()) {
val entityType = parcelableClass.defaultType
val asmType = codegen.state.typeMapper.mapType(entityType)
val serializer = if (parcelableClass.kind == ClassKind.CLASS) {
NullAwareParcelSerializerWrapper(ZeroParameterClassSerializer(asmType, entityType))
} else {
ParcelSerializer.get(entityType, asmType, globalContext, strict = true)
}
v.load(1, parcelAsmType)
serializer.readValue(v)
} else {
for ((_, type, parcelers) in properties) {
val asmType = codegen.typeMapper.mapType(type)
asmConstructorParameters.append(asmType.descriptor)
val serializer = ParcelSerializer.get(type, asmType, globalContext.copy(typeParcelers = parcelers))
v.load(1, parcelAsmType)
serializer.readValue(v)
}
v.invokespecial(containerAsmType.internalName, "<init>", "($asmConstructorParameters)V", false)
}
}
v.areturn(containerAsmType)
}
}
private fun writeCreatorAccessField(codegen: ImplementationBodyCodegen, parcelableClass: ClassDescriptor) {
val creatorType = Type.getObjectType("android/os/Parcelable\$Creator")
val parcelableType = codegen.typeMapper.mapType(parcelableClass)
val fieldSignature = "L${creatorType.internalName}<${parcelableType.descriptor}>;"
codegen.v.newField(
JvmDeclarationOrigin.NO_ORIGIN,
ACC_STATIC or ACC_PUBLIC or ACC_FINAL,
"CREATOR",
creatorType.descriptor,
fieldSignature,
null
)
}
private fun writeCreatorClass(
codegen: ImplementationBodyCodegen,
parcelableClass: ClassDescriptor,
parcelClassType: KotlinType,
parcelableCreatorClassType: KotlinType,
parcelAsmType: Type,
parcelerObject: ClassDescriptor?,
properties: List<PropertyToSerialize>
) {
val containerAsmType = codegen.typeMapper.mapType(parcelableClass.defaultType)
val creatorAsmType = Type.getObjectType(containerAsmType.internalName + "\$Creator")
val creatorClass = ClassDescriptorImpl(
parcelableClass, Name.identifier("Creator"), Modality.FINAL, ClassKind.CLASS, listOf(parcelableCreatorClassType),
parcelableClass.source, false, LockBasedStorageManager.NO_LOCKS
)
creatorClass.initialize(
MemberScope.Empty, emptySet(),
DescriptorFactory.createPrimaryConstructorForObject(creatorClass, creatorClass.source)
)
val classBuilderForCreator = codegen.state.factory.newVisitor(
JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, null, creatorClass),
Type.getObjectType(creatorAsmType.internalName),
codegen.myClass.containingKtFile
)
val classContextForCreator = ClassContext(
codegen.typeMapper, creatorClass, OwnerKind.IMPLEMENTATION, codegen.context.parentContext, null
)
val codegenForCreator = ImplementationBodyCodegen(
codegen.myClass, classContextForCreator, classBuilderForCreator, codegen.state, codegen.parentCodegen, false
)
val classSignature = "Ljava/lang/Object;Landroid/os/Parcelable\$Creator<${containerAsmType.descriptor}>;"
classBuilderForCreator.defineClass(
null, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
creatorAsmType.internalName, classSignature, "java/lang/Object",
arrayOf("android/os/Parcelable\$Creator")
)
codegen.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC)
codegenForCreator.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC)
writeSyntheticClassMetadata(classBuilderForCreator, codegen.state, InlineUtil.isInPublicInlineScope(parcelableClass))
writeCreatorConstructor(codegenForCreator, creatorClass, creatorAsmType)
writeNewArrayMethod(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelerObject)
writeCreateFromParcel(
codegenForCreator,
parcelableClass, parcelableCreatorClassType, creatorClass, parcelClassType,
parcelAsmType, parcelerObject, properties
)
classBuilderForCreator.done(codegen.state.generateSmapCopyToAnnotation)
}
private fun writeCreatorConstructor(codegen: ImplementationBodyCodegen, creatorClass: ClassDescriptor, creatorAsmType: Type) {
DescriptorFactory.createPrimaryConstructorForObject(creatorClass, creatorClass.source)
.apply {
returnType = creatorClass.defaultType
}.write(codegen) {
v.load(0, creatorAsmType)
v.invokespecial("java/lang/Object", "<init>", "()V", false)
v.areturn(Type.VOID_TYPE)
}
}
private fun writeNewArrayMethod(
codegen: ImplementationBodyCodegen,
parcelableClass: ClassDescriptor,
parcelableCreatorClassType: KotlinType,
creatorClass: ClassDescriptorImpl,
parcelerObject: ClassDescriptor?
) {
val builtIns = parcelableClass.builtIns
val parcelableAsmType = codegen.typeMapper.mapType(parcelableClass)
val overriddenFunction = parcelableCreatorClassType.findFunction(NEW_ARRAY)
?: error("Can't resolve 'android.os.Parcelable.Creator.${NEW_ARRAY.methodName}' method")
createMethod(
creatorClass, NEW_ARRAY, Modality.FINAL,
builtIns.getArrayType(Variance.INVARIANT, parcelableClass.defaultType.replaceArgumentsWithStarProjections()),
"size" to builtIns.intType
).write(codegen, overriddenFunction) {
if (parcelerObject != null) {
val newArrayMethod = parcelerObject.unsubstitutedMemberScope
.getContributedFunctions(NEW_ARRAY_NAME, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
.firstOrNull {
it.typeParameters.isEmpty()
&& it.kind == CallableMemberDescriptor.Kind.DECLARATION
&& (it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type))
&& !((it.containingDeclaration as? ClassDescriptor)?.defaultType?.isParceler ?: true)
}
if (newArrayMethod != null) {
val containerAsmType = codegen.typeMapper.mapType(parcelableClass.defaultType)
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
v.getstatic(containerAsmType.internalName, companionFieldName, companionAsmType.descriptor)
v.load(1, Type.INT_TYPE)
v.invokevirtual(companionAsmType.internalName, "newArray", "(I)[$parcelableAsmType", false)
v.areturn(Type.getType("[$parcelableAsmType"))
return@write
}
}
v.load(1, Type.INT_TYPE)
v.newarray(parcelableAsmType)
v.areturn(Type.getType("[$parcelableAsmType"))
}
}
private fun FunctionDescriptor.write(
codegen: ImplementationBodyCodegen,
overriddenDescriptor: FunctionDescriptor? = null,
code: ExpressionCodegen.() -> Unit
) {
val declarationOrigin = JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, null, this)
if (overriddenDescriptor != null) {
this.overriddenDescriptors = listOf(overriddenDescriptor)
}
codegen.functionCodegen.generateMethod(declarationOrigin, this, object : CodegenBased(codegen.state) {
override fun doGenerateBody(e: ExpressionCodegen, signature: JvmMethodSignature) = with(e) {
e.code()
}
})
}
private fun KotlinType.findFunction(componentKind: ParcelizeSyntheticComponent.ComponentKind): SimpleFunctionDescriptor? {
return memberScope
.getContributedFunctions(Name.identifier(componentKind.methodName), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
.firstOrNull()
}
}
@@ -8,8 +8,6 @@ package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.parcelize.ir.AndroidSymbols
import org.jetbrains.kotlin.parcelize.ir.ParcelizeFirIrTransformer
class ParcelizeFirIrGeneratorExtension : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.descriptors.Modality
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.util.companionObject
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELER_FQN
import org.jetbrains.kotlin.parcelize.ParcelizeSyntheticComponent
import org.jetbrains.kotlin.parcelize.fir.ParcelizePluginKey
class ParcelizeFirIrTransformer(
@@ -8,8 +8,6 @@ package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.parcelize.ir.AndroidSymbols
import org.jetbrains.kotlin.parcelize.ir.ParcelizeIrTransformer
class ParcelizeIrGeneratorExtension : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
@@ -17,4 +15,3 @@ class ParcelizeIrGeneratorExtension : IrGenerationExtension {
ParcelizeIrTransformer(pluginContext, androidSymbols).transform(moduleFragment)
}
}
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.descriptors.Modality
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.parcelize.ParcelizeNames.FLAGS_NAME
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELABLE_FQN
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELER_FQN
import org.jetbrains.kotlin.parcelize.ParcelizeNames.WRITE_TO_PARCEL_NAME
import org.jetbrains.kotlin.parcelize.ParcelizeSyntheticComponent
@OptIn(ObsoleteDescriptorBasedAPI::class)
class ParcelizeIrTransformer(
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
@@ -3,7 +3,7 @@
* 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.parcelize.ir
package org.jetbrains.kotlin.parcelize
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities