Remove module-wide ObsoleteDescriptorApi opt-in
and remove access to .descriptor whenever possible
This commit is contained in:
@@ -60,7 +60,6 @@ sourceSets {
|
|||||||
|
|
||||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
freeCompilerArgs += "-opt-in=org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI"
|
|
||||||
freeCompilerArgs += "-opt-in=org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi"
|
freeCompilerArgs += "-opt-in=org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-12
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
|||||||
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.isSealed
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
@@ -39,19 +38,26 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
|
||||||
abstract class BaseIrGenerator(private val currentClass: IrClass, final override val compilerContext: SerializationPluginContext): IrBuilderWithPluginContext {
|
abstract class BaseIrGenerator(private val currentClass: IrClass, final override val compilerContext: SerializationPluginContext) :
|
||||||
|
IrBuilderWithPluginContext {
|
||||||
|
|
||||||
private val throwMissedFieldExceptionFunc
|
private val throwMissedFieldExceptionFunc = compilerContext.referenceFunctions(
|
||||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
CallableId(
|
||||||
|
SerializationPackages.internalPackageFqName,
|
||||||
|
SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME
|
||||||
|
)
|
||||||
|
).singleOrNull()
|
||||||
|
|
||||||
private val throwMissedFieldExceptionArrayFunc
|
private val throwMissedFieldExceptionArrayFunc = compilerContext.referenceFunctions(
|
||||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
CallableId(
|
||||||
|
SerializationPackages.internalPackageFqName,
|
||||||
|
SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME
|
||||||
|
)
|
||||||
|
).singleOrNull()
|
||||||
|
|
||||||
private val enumSerializerFactoryFunc
|
private val enumSerializerFactoryFunc = compilerContext.enumSerializerFactoryFunc
|
||||||
= compilerContext.enumSerializerFactoryFunc
|
|
||||||
|
|
||||||
private val markedEnumSerializerFactoryFunc
|
private val markedEnumSerializerFactoryFunc = compilerContext.markedEnumSerializerFactoryFunc
|
||||||
= compilerContext.markedEnumSerializerFactoryFunc
|
|
||||||
|
|
||||||
fun useFieldMissingOptimization(): Boolean {
|
fun useFieldMissingOptimization(): Boolean {
|
||||||
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
||||||
@@ -250,7 +256,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
|||||||
genericGetter
|
genericGetter
|
||||||
)
|
)
|
||||||
val (functionToCall, args: List<IrExpression>) = if (innerSerial != null) whenHaveSerializer(innerSerial, sti) else whenDoNot(sti)
|
val (functionToCall, args: List<IrExpression>) = if (innerSerial != null) whenHaveSerializer(innerSerial, sti) else whenDoNot(sti)
|
||||||
val typeArgs = if (functionToCall.descriptor.typeParameters.isNotEmpty()) listOf(property.type) else listOf()
|
val typeArgs = if (functionToCall.owner.typeParameters.isNotEmpty()) listOf(property.type) else listOf()
|
||||||
return irInvoke(encoder, functionToCall, typeArguments = typeArgs, valueArguments = args, returnTypeHint = returnTypeHint)
|
return irInvoke(encoder, functionToCall, typeArguments = typeArgs, valueArguments = args, returnTypeHint = returnTypeHint)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +273,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
|||||||
|
|
||||||
val adjustedArgs: List<IrExpression> =
|
val adjustedArgs: List<IrExpression> =
|
||||||
// if typeArgs.size == args.size then the serializer is custom - we need to use the actual serializers from the arguments
|
// if typeArgs.size == args.size then the serializer is custom - we need to use the actual serializers from the arguments
|
||||||
if ((typeArgs.size != args.size) && (baseClass.descriptor.isSealed() || baseClass.descriptor.modality == Modality.ABSTRACT)) {
|
if ((typeArgs.size != args.size) && (baseClass.modality == Modality.SEALED || baseClass.modality == Modality.ABSTRACT)) {
|
||||||
val serializer = findStandardKotlinTypeSerializer(compilerContext, context.irBuiltIns.unitType)!!
|
val serializer = findStandardKotlinTypeSerializer(compilerContext, context.irBuiltIns.unitType)!!
|
||||||
// workaround for sealed and abstract classes - the `serializer` function expects non-null serializers, but does not use them, so serializers of any type can be passed
|
// workaround for sealed and abstract classes - the `serializer` function expects non-null serializers, but does not use them, so serializers of any type can be passed
|
||||||
List(baseClass.typeParameters.size) { irGetObject(serializer) }
|
List(baseClass.typeParameters.size) { irGetObject(serializer) }
|
||||||
|
|||||||
+2
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
import org.jetbrains.kotlin.ir.builders.irGetField
|
import org.jetbrains.kotlin.ir.builders.irGetField
|
||||||
@@ -78,6 +79,7 @@ fun IrBuilderWithScope.createPropertyByParamReplacer(
|
|||||||
Creates an initializer adapter function that can replace IR expressions of getting constructor parameter value by some other expression.
|
Creates an initializer adapter function that can replace IR expressions of getting constructor parameter value by some other expression.
|
||||||
Also adapter may replace IR expression of getting `this` value by another expression.
|
Also adapter may replace IR expression of getting `this` value by another expression.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
fun createInitializerAdapter(
|
fun createInitializerAdapter(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
paramGetReplacer: (ValueParameterDescriptor) -> IrExpression?,
|
paramGetReplacer: (ValueParameterDescriptor) -> IrExpression?,
|
||||||
|
|||||||
+9
-14
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
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.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -27,16 +28,12 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
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.platform.jvm.isJvm
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.hasSerializableOrMetaAnnotation
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInheritableSerialInfoAnnotation
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isSerialInfoAnnotation
|
|
||||||
|
|
||||||
|
|
||||||
interface IrBuilderWithPluginContext {
|
interface IrBuilderWithPluginContext {
|
||||||
@@ -134,7 +131,7 @@ interface IrBuilderWithPluginContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.contributeAnonymousInitializer(bodyGen: IrBlockBodyBuilder.() -> Unit) {
|
fun IrClass.contributeAnonymousInitializer(bodyGen: IrBlockBodyBuilder.() -> Unit) {
|
||||||
val symbol = IrAnonymousInitializerSymbolImpl(descriptor)
|
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
|
||||||
factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
||||||
it.parent = this
|
it.parent = this
|
||||||
declarations.add(it)
|
declarations.add(it)
|
||||||
@@ -256,9 +253,6 @@ interface IrBuilderWithPluginContext {
|
|||||||
result
|
result
|
||||||
)
|
)
|
||||||
|
|
||||||
@FirIncompatiblePluginAPI
|
|
||||||
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.setProperty(receiver: IrExpression, property: IrProperty, value: IrExpression): IrExpression {
|
fun IrBuilderWithScope.setProperty(receiver: IrExpression, property: IrProperty, value: IrExpression): IrExpression {
|
||||||
return if (property.setter != null)
|
return if (property.setter != null)
|
||||||
irSet(property.setter!!.returnType, receiver, property.setter!!.symbol, value)
|
irSet(property.setter!!.returnType, receiver, property.setter!!.symbol, value)
|
||||||
@@ -269,7 +263,7 @@ interface IrBuilderWithPluginContext {
|
|||||||
fun IrBuilderWithScope.generateAnySuperConstructorCall(toBuilder: IrBlockBodyBuilder) {
|
fun IrBuilderWithScope.generateAnySuperConstructorCall(toBuilder: IrBlockBodyBuilder) {
|
||||||
val anyConstructor = compilerContext.irBuiltIns.anyClass.owner.declarations.single { it is IrConstructor } as IrConstructor
|
val anyConstructor = compilerContext.irBuiltIns.anyClass.owner.declarations.single { it is IrConstructor } as IrConstructor
|
||||||
with(toBuilder) {
|
with(toBuilder) {
|
||||||
+IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
compilerContext.irBuiltIns.unitType,
|
compilerContext.irBuiltIns.unitType,
|
||||||
anyConstructor.symbol
|
anyConstructor.symbol
|
||||||
@@ -348,14 +342,14 @@ interface IrBuilderWithPluginContext {
|
|||||||
createClassReference(classSymbol.starProjectedType, startOffset, endOffset)
|
createClassReference(classSymbol.starProjectedType, startOffset, endOffset)
|
||||||
|
|
||||||
fun collectSerialInfoAnnotations(irClass: IrClass): List<IrConstructorCall> {
|
fun collectSerialInfoAnnotations(irClass: IrClass): List<IrConstructorCall> {
|
||||||
if (!(irClass.isInterface || irClass.descriptor.hasSerializableOrMetaAnnotation)) return emptyList()
|
if (!(irClass.isInterface || irClass.hasSerializableOrMetaAnnotation())) return emptyList()
|
||||||
val annotationByFq: MutableMap<FqName, IrConstructorCall> =
|
val annotationByFq: MutableMap<FqName, IrConstructorCall> =
|
||||||
irClass.annotations.associateBy { it.symbol.owner.parentAsClass.descriptor.fqNameSafe }.toMutableMap()
|
irClass.annotations.associateBy { it.symbol.owner.parentAsClass.fqNameWhenAvailable!! }.toMutableMap()
|
||||||
for (clazz in irClass.getAllSuperclasses()) {
|
for (clazz in irClass.getAllSuperclasses()) {
|
||||||
val annotations = clazz.annotations
|
val annotations = clazz.annotations
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
val descriptor = it.symbol.owner.parentAsClass.descriptor
|
val parent = it.symbol.owner.parentAsClass
|
||||||
if (descriptor.isInheritableSerialInfoAnnotation) descriptor.fqNameSafe to it else null
|
if (parent.isInheritableSerialInfoAnnotation) parent.fqNameWhenAvailable!! to it else null
|
||||||
}
|
}
|
||||||
annotations.forEach { (fqname, call) ->
|
annotations.forEach { (fqname, call) ->
|
||||||
if (fqname !in annotationByFq) {
|
if (fqname !in annotationByFq) {
|
||||||
@@ -371,7 +365,7 @@ interface IrBuilderWithPluginContext {
|
|||||||
fun IrBuilderWithScope.copyAnnotationsFrom(annotations: List<IrConstructorCall>): List<IrExpression> =
|
fun IrBuilderWithScope.copyAnnotationsFrom(annotations: List<IrConstructorCall>): List<IrExpression> =
|
||||||
annotations.mapNotNull { annotationCall ->
|
annotations.mapNotNull { annotationCall ->
|
||||||
val annotationClass = annotationCall.symbol.owner.parentAsClass
|
val annotationClass = annotationCall.symbol.owner.parentAsClass
|
||||||
if (!annotationClass.descriptor.isSerialInfoAnnotation) return@mapNotNull null
|
if (!annotationClass.isSerialInfoAnnotation) return@mapNotNull null
|
||||||
|
|
||||||
if (compilerContext.platform.isJvm()) {
|
if (compilerContext.platform.isJvm()) {
|
||||||
val implClass = compilerContext.serialInfoImplJvmIrGenerator.getImplClass(annotationClass)
|
val implClass = compilerContext.serialInfoImplJvmIrGenerator.getImplClass(annotationClass)
|
||||||
@@ -389,6 +383,7 @@ interface IrBuilderWithPluginContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
fun IrBuilderWithScope.wrapperClassReference(classType: IrType): IrClassReference {
|
fun IrBuilderWithScope.wrapperClassReference(classType: IrType): IrClassReference {
|
||||||
if (compilerContext.platform.isJvm()) {
|
if (compilerContext.platform.isJvm()) {
|
||||||
// "Byte::class" -> "java.lang.Byte::class"
|
// "Byte::class" -> "java.lang.Byte::class"
|
||||||
|
|||||||
+32
-6
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
@@ -23,11 +24,11 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
|||||||
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.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.platform.js.isJs
|
||||||
|
import org.jetbrains.kotlin.platform.konan.isNative
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.fir.SerializationPluginKey
|
import org.jetbrains.kotlinx.serialization.compiler.fir.SerializationPluginKey
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
|
||||||
|
|
||||||
internal fun IrType.isKSerializer(): Boolean {
|
internal fun IrType.isKSerializer(): Boolean {
|
||||||
val simpleType = this as? IrSimpleType ?: return false
|
val simpleType = this as? IrSimpleType ?: return false
|
||||||
@@ -89,7 +90,7 @@ private fun IrClass.checkSerializableOrMetaAnnotationArgs(mustDoNotHaveArgs: Boo
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return annotations
|
return annotations
|
||||||
.map { it.annotationClass.annotations }
|
.map { it.constructedClass.annotations }
|
||||||
.any { it.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName) }
|
.any { it.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +99,9 @@ internal val IrClass.isSerialInfoAnnotation: Boolean
|
|||||||
|| annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName)
|
|| annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName)
|
||||||
|| annotations.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName)
|
|| annotations.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName)
|
||||||
|
|
||||||
|
internal val IrClass.isInheritableSerialInfoAnnotation: Boolean
|
||||||
|
get() = annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName)
|
||||||
|
|
||||||
internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationPluginContext): Boolean
|
internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationPluginContext): Boolean
|
||||||
= (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
= (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
||||||
|| isEnumWithLegacyGeneratedSerializer(context)
|
|| isEnumWithLegacyGeneratedSerializer(context)
|
||||||
@@ -142,6 +146,7 @@ fun IrClass.getSuperClassNotAny(): IrClass? {
|
|||||||
return if (parentClass.defaultType.isAny()) null else parentClass
|
return if (parentClass.defaultType.isAny()) null else parentClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
internal fun IrDeclaration.isFromPlugin(): Boolean =
|
internal fun IrDeclaration.isFromPlugin(): Boolean =
|
||||||
this.origin == IrDeclarationOrigin.GeneratedByPlugin(SerializationPluginKey) || (this.descriptor as? CallableMemberDescriptor)?.kind == CallableMemberDescriptor.Kind.SYNTHESIZED // old FE doesn't specify origin
|
this.origin == IrDeclarationOrigin.GeneratedByPlugin(SerializationPluginKey) || (this.descriptor as? CallableMemberDescriptor)?.kind == CallableMemberDescriptor.Kind.SYNTHESIZED // old FE doesn't specify origin
|
||||||
|
|
||||||
@@ -165,14 +170,35 @@ fun IrClass.findSerializableSyntheticConstructor(): IrConstructorSymbol? {
|
|||||||
return declarations.filterIsInstance<IrConstructor>().singleOrNull { it.isSerializationCtor() }?.symbol
|
return declarations.filterIsInstance<IrConstructor>().singleOrNull { it.isSerializationCtor() }?.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun IrClass.needSerializerFactory(compilerContext: SerializationPluginContext): Boolean {
|
||||||
|
if (!(compilerContext.platform?.isNative() == true || compilerContext.platform.isJs())) return false
|
||||||
|
val serializableClass = getSerializableClassDescriptorByCompanion(this) ?: return false
|
||||||
|
if (serializableClass.isSerializableObject) return true
|
||||||
|
if (serializableClass.isSerializableEnum()) return true
|
||||||
|
if (serializableClass.isAbstractOrSealedSerializableClass) return true
|
||||||
|
if (serializableClass.isSealedSerializableInterface) return true
|
||||||
|
if (serializableClass.typeParameters.isEmpty()) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun getSerializableClassDescriptorByCompanion(companion: IrClass): IrClass? {
|
||||||
|
if (companion.isSerializableObject) return companion
|
||||||
|
if (!companion.isCompanion) return null
|
||||||
|
val classDescriptor = (companion.parent as? IrClass) ?: return null
|
||||||
|
if (!classDescriptor.shouldHaveGeneratedMethodsInCompanion) return null
|
||||||
|
return classDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun IrExpression.isInitializePropertyFromParameter(): Boolean =
|
internal fun IrExpression.isInitializePropertyFromParameter(): Boolean =
|
||||||
this is IrGetValueImpl && this.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
this is IrGetValueImpl && this.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
|
||||||
internal val IrConstructorCall.annotationClass
|
internal val IrConstructorCall.constructedClass
|
||||||
get() = this.symbol.owner.constructedClass
|
get() = this.symbol.owner.constructedClass
|
||||||
|
|
||||||
internal val List<IrConstructorCall>.hasAnySerialAnnotation: Boolean
|
internal val List<IrConstructorCall>.hasAnySerialAnnotation: Boolean
|
||||||
get() = serialNameValue != null || any { it.annotationClass.isSerialInfoAnnotation == true }
|
get() = serialNameValue != null || any { it.constructedClass.isSerialInfoAnnotation }
|
||||||
|
|
||||||
internal val List<IrConstructorCall>.serialNameValue: String?
|
internal val List<IrConstructorCall>.serialNameValue: String?
|
||||||
get() = findAnnotation(SerializationAnnotations.serialNameAnnotationFqName)?.getStringConstArgument(0) // @SerialName("foo")
|
get() = findAnnotation(SerializationAnnotations.serialNameAnnotationFqName)?.getStringConstArgument(0) // @SerialName("foo")
|
||||||
|
|||||||
+2
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
@@ -41,6 +42,7 @@ class IrSerializableProperties(
|
|||||||
override val serializableStandaloneProperties: List<IrSerializableProperty>
|
override val serializableStandaloneProperties: List<IrSerializableProperty>
|
||||||
) : ISerializableProperties<IrSerializableProperty>
|
) : ISerializableProperties<IrSerializableProperty>
|
||||||
|
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
internal fun serializablePropertiesForIrBackend(
|
internal fun serializablePropertiesForIrBackend(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null
|
serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null
|
||||||
|
|||||||
+7
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
|||||||
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
|
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
|
||||||
import org.jetbrains.kotlin.backend.common.ir.addExtensionReceiver
|
import org.jetbrains.kotlin.backend.common.ir.addExtensionReceiver
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -30,12 +31,14 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||||
|
|
||||||
// This doesn't support annotation arguments of type KClass and Array<KClass> because the codegen doesn't compute JVM signatures for
|
// This doesn't support annotation arguments of type KClass and Array<KClass> because the codegen doesn't compute JVM signatures for
|
||||||
// such cases correctly (because inheriting from annotation classes is prohibited in Kotlin).
|
// such cases correctly (because inheriting from annotation classes is prohibited in Kotlin).
|
||||||
// Currently it results in an "accidental override" error where a method with return type KClass conflicts with the one with Class.
|
// Currently it results in an "accidental override" error where a method with return type KClass conflicts with the one with Class.
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
class SerialInfoImplJvmIrGenerator(
|
class SerialInfoImplJvmIrGenerator(
|
||||||
private val context: SerializationPluginContext,
|
private val context: SerializationPluginContext,
|
||||||
private val moduleFragment: IrModuleFragment,
|
private val moduleFragment: IrModuleFragment,
|
||||||
@@ -53,7 +56,7 @@ class SerialInfoImplJvmIrGenerator(
|
|||||||
|
|
||||||
fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass =
|
fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass =
|
||||||
annotationToImpl.getOrPut(serialInfoAnnotationClass) {
|
annotationToImpl.getOrPut(serialInfoAnnotationClass) {
|
||||||
@OptIn(FirIncompatiblePluginAPI::class) // TODO
|
@OptIn(FirIncompatiblePluginAPI::class)
|
||||||
val implClassSymbol = context.referenceClass(serialInfoAnnotationClass.kotlinFqName.child(SerialEntityNames.IMPL_NAME))
|
val implClassSymbol = context.referenceClass(serialInfoAnnotationClass.kotlinFqName.child(SerialEntityNames.IMPL_NAME))
|
||||||
implClassSymbol!!.owner.apply(this::generate)
|
implClassSymbol!!.owner.apply(this::generate)
|
||||||
}
|
}
|
||||||
@@ -112,6 +115,9 @@ class SerialInfoImplJvmIrGenerator(
|
|||||||
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, name))
|
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FirIncompatiblePluginAPI
|
||||||
|
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
|
||||||
|
|
||||||
private fun IrType.kClassToJClassIfNeeded(): IrType = when {
|
private fun IrType.kClassToJClassIfNeeded(): IrType = when {
|
||||||
this.isKClass() -> javaLangType
|
this.isKClass() -> javaLangType
|
||||||
this.isKClassArray() -> compilerContext.irBuiltIns.arrayClass.typeWith(javaLangType)
|
this.isKClassArray() -> compilerContext.irBuiltIns.arrayClass.typeWith(javaLangType)
|
||||||
|
|||||||
+3
-3
@@ -83,14 +83,14 @@ class SerializableCompanionIrGenerator(
|
|||||||
|
|
||||||
val irSerializableClass = if (irClass.isCompanion) irClass.parentAsClass else irClass
|
val irSerializableClass = if (irClass.isCompanion) irClass.parentAsClass else irClass
|
||||||
val serializableWithAlreadyPresent = irSerializableClass.annotations.any {
|
val serializableWithAlreadyPresent = irSerializableClass.annotations.any {
|
||||||
it.symbol.descriptor.constructedClass.fqNameSafe == annotationMarkerClass.owner.fqNameWhenAvailable
|
it.constructedClass.fqNameWhenAvailable == annotationMarkerClass.owner.fqNameWhenAvailable
|
||||||
}
|
}
|
||||||
if (serializableWithAlreadyPresent) return
|
if (serializableWithAlreadyPresent) return
|
||||||
|
|
||||||
val annotationCtor = annotationMarkerClass.constructors.single { it.owner.isPrimary }
|
val annotationCtor = annotationMarkerClass.constructors.single { it.owner.isPrimary }
|
||||||
val annotationType = annotationMarkerClass.defaultType
|
val annotationType = annotationMarkerClass.defaultType
|
||||||
|
|
||||||
val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
|
val annotationCtorCall = IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, annotationType, annotationCtor).apply {
|
||||||
putValueArgument(
|
putValueArgument(
|
||||||
0,
|
0,
|
||||||
createClassReference(
|
createClassReference(
|
||||||
@@ -150,7 +150,7 @@ class SerializableCompanionIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSerializerFactoryIfNeeded(getterDescriptor: IrSimpleFunction) {
|
private fun generateSerializerFactoryIfNeeded(getterDescriptor: IrSimpleFunction) {
|
||||||
if (!irClass.descriptor.needSerializerFactory()) return
|
if (!irClass.needSerializerFactory(compilerContext)) return
|
||||||
val serialFactoryDescriptor = irClass.findDeclaration<IrSimpleFunction> {
|
val serialFactoryDescriptor = irClass.findDeclaration<IrSimpleFunction> {
|
||||||
it.valueParameters.size == 1
|
it.valueParameters.size == 1
|
||||||
&& it.valueParameters.first().isVararg
|
&& it.valueParameters.first().isVararg
|
||||||
|
|||||||
+18
-17
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||||
import org.jetbrains.kotlin.codegen.CompilationException
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
@@ -19,12 +18,10 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
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.js.resolve.diagnostics.findPsi
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.getOrPutNullable
|
import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_DESCRIPTOR_FIELD_NAME
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_DESCRIPTOR_FIELD_NAME
|
||||||
@@ -97,8 +94,9 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Missing field exception parts
|
// Missing field exception parts
|
||||||
val exceptionCtorRef = compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(MISSING_FIELD_EXC)))
|
val exceptionCtorRef =
|
||||||
.single { it.owner.valueParameters.singleOrNull()?.type?.isString() == true }
|
compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(MISSING_FIELD_EXC)))
|
||||||
|
.single { it.owner.valueParameters.singleOrNull()?.type?.isString() == true }
|
||||||
val exceptionType = exceptionCtorRef.owner.returnType
|
val exceptionType = exceptionCtorRef.owner.returnType
|
||||||
|
|
||||||
val seenVarsOffset = serializableProperties.bitMaskSlotCount()
|
val seenVarsOffset = serializableProperties.bitMaskSlotCount()
|
||||||
@@ -244,7 +242,7 @@ class SerializableIrGenerator(
|
|||||||
?: error("Non-serializable parent of serializable $irClass must have no arg constructor")
|
?: error("Non-serializable parent of serializable $irClass must have no arg constructor")
|
||||||
|
|
||||||
|
|
||||||
val call = IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
val call = IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
compilerContext.irBuiltIns.unitType,
|
compilerContext.irBuiltIns.unitType,
|
||||||
@@ -270,13 +268,14 @@ class SerializableIrGenerator(
|
|||||||
propertiesStart: Int
|
propertiesStart: Int
|
||||||
): Int {
|
): Int {
|
||||||
check(superClass.isInternalSerializable)
|
check(superClass.isInternalSerializable)
|
||||||
val superCtorRef = superClass.findSerializableSyntheticConstructor() ?: error("Class serializable internally should have special constructor with marker")
|
val superCtorRef = superClass.findSerializableSyntheticConstructor()
|
||||||
|
?: error("Class serializable internally should have special constructor with marker")
|
||||||
val superProperties = serializablePropertiesForIrBackend(superClass).serializableProperties
|
val superProperties = serializablePropertiesForIrBackend(superClass).serializableProperties
|
||||||
val superSlots = superProperties.bitMaskSlotCount()
|
val superSlots = superProperties.bitMaskSlotCount()
|
||||||
val arguments = allValueParameters.subList(0, superSlots) +
|
val arguments = allValueParameters.subList(0, superSlots) +
|
||||||
allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) +
|
allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) +
|
||||||
allValueParameters.last() // SerializationConstructorMarker
|
allValueParameters.last() // SerializationConstructorMarker
|
||||||
val call = IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
val call = IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
compilerContext.irBuiltIns.unitType,
|
compilerContext.irBuiltIns.unitType,
|
||||||
@@ -307,7 +306,7 @@ class SerializableIrGenerator(
|
|||||||
// Compute offset of properties in superclass
|
// Compute offset of properties in superclass
|
||||||
var ignoreIndexTo = -1
|
var ignoreIndexTo = -1
|
||||||
val superClass = irClass.getSuperClassOrAny()
|
val superClass = irClass.getSuperClassOrAny()
|
||||||
if (superClass.descriptor.isInternalSerializable) {
|
if (superClass.isInternalSerializable) {
|
||||||
ignoreIndexTo = serializablePropertiesForIrBackend(superClass).serializableProperties.size
|
ignoreIndexTo = serializablePropertiesForIrBackend(superClass).serializableProperties.size
|
||||||
|
|
||||||
// call super.writeSelf
|
// call super.writeSelf
|
||||||
@@ -380,16 +379,18 @@ class SerializableIrGenerator(
|
|||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
context: SerializationPluginContext,
|
context: SerializationPluginContext,
|
||||||
) {
|
) {
|
||||||
val serializableClass = irClass.descriptor
|
if (irClass.isInternalSerializable) {
|
||||||
|
|
||||||
if (serializableClass.isInternalSerializable) {
|
|
||||||
SerializableIrGenerator(irClass, context).generate()
|
SerializableIrGenerator(irClass, context).generate()
|
||||||
irClass.patchDeclarationParents(irClass.parent)
|
irClass.patchDeclarationParents(irClass.parent)
|
||||||
} else if (serializableClass.serializableAnnotationIsUseless) {
|
} else {
|
||||||
throw CompilationException(
|
val serializableAnnotationIsUseless = with(irClass) {
|
||||||
"@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " +
|
hasSerializableOrMetaAnnotationWithoutArgs() && !isInternalSerializable && !hasCompanionObjectAsSerializer && kind != ClassKind.ENUM_CLASS && !isSealedSerializableInterface
|
||||||
"Provide serializer manually via e.g. companion object", null, serializableClass.findPsi()
|
}
|
||||||
)
|
if (serializableAnnotationIsUseless)
|
||||||
|
throw AssertionError(
|
||||||
|
"@Serializable annotation on $irClass would be ignored because it is impossible to serialize it automatically. " +
|
||||||
|
"Provide serializer manually via e.g. companion object"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -54,8 +54,7 @@ class SerializerForEnumsGenerator(
|
|||||||
val decode = decoderClass.functionByName(CallingConventions.decodeEnum)
|
val decode = decoderClass.functionByName(CallingConventions.decodeEnum)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
val valuesF = this@SerializerForEnumsGenerator.serializableIrClass.functions.single { it.name == StandardNames.ENUM_VALUES }
|
||||||
val valuesF = serializableIrClass.functions.single { it.name == StandardNames.ENUM_VALUES }
|
|
||||||
val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol)
|
val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol)
|
||||||
|
|
||||||
|
|
||||||
@@ -67,7 +66,7 @@ class SerializerForEnumsGenerator(
|
|||||||
getValues,
|
getValues,
|
||||||
arrayGet.symbol,
|
arrayGet.symbol,
|
||||||
irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter),
|
irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter),
|
||||||
typeHint = serializableIrClass.defaultType
|
typeHint = this@SerializerForEnumsGenerator.serializableIrClass.defaultType
|
||||||
)
|
)
|
||||||
+irReturn(getValueByOrdinal)
|
+irReturn(getValueByOrdinal)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-12
@@ -16,14 +16,11 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.mapValueParametersIndexed
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
@@ -117,7 +114,7 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val anonymousInit = irClass.run {
|
val anonymousInit = irClass.run {
|
||||||
val symbol = IrAnonymousInitializerSymbolImpl(descriptor)
|
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
|
||||||
irClass.factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
irClass.factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
||||||
it.parent = this
|
it.parent = this
|
||||||
declarations.add(it)
|
declarations.add(it)
|
||||||
@@ -207,7 +204,7 @@ open class SerializerIrGenerator(
|
|||||||
addFunctionBody(typedConstructorDescriptor) { ctor ->
|
addFunctionBody(typedConstructorDescriptor) { ctor ->
|
||||||
// generate call to primary ctor to init serialClassDesc and super()
|
// generate call to primary ctor to init serialClassDesc and super()
|
||||||
val primaryCtor = irClass.constructors.primary
|
val primaryCtor = irClass.constructors.primary
|
||||||
+IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
compilerContext.irBuiltIns.unitType,
|
compilerContext.irBuiltIns.unitType,
|
||||||
@@ -268,15 +265,11 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
||||||
|
|
||||||
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
|
// public fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder
|
||||||
val beginFunc =
|
val beginFunc =
|
||||||
encoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
encoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||||
|
|
||||||
val call = irCall(beginFunc, type = kOutputClass.defaultType).mapValueParametersIndexed { _, _ ->
|
val call = irInvoke(irGet(saveFunc.valueParameters[0]), beginFunc, irGet(localSerialDesc), typeHint = kOutputClass.defaultType)
|
||||||
irGet(localSerialDesc)
|
|
||||||
}
|
|
||||||
// can it be done in more concise way? e.g. additional builder function?
|
|
||||||
call.dispatchReceiver = irGet(saveFunc.valueParameters[0])
|
|
||||||
val objectToSerialize = saveFunc.valueParameters[1]
|
val objectToSerialize = saveFunc.valueParameters[1]
|
||||||
val localOutput = irTemporary(call, "output")
|
val localOutput = irTemporary(call, "output")
|
||||||
|
|
||||||
|
|||||||
+2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
|||||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
@@ -93,6 +94,7 @@ private class SerializerClassLowering(
|
|||||||
SerializerIrGenerator.generate(irClass, context, context.metadataPlugin)
|
SerializerIrGenerator.generate(irClass, context, context.metadataPlugin)
|
||||||
SerializableCompanionIrGenerator.generate(irClass, context)
|
SerializableCompanionIrGenerator.generate(irClass, context)
|
||||||
|
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {
|
if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {
|
||||||
serialInfoJvmGenerator.generate(irClass)
|
serialInfoJvmGenerator.generate(irClass)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+14
-1
@@ -20,7 +20,7 @@ enum class Plain {
|
|||||||
class Holder(val p: Plain, val w: WithNames)
|
class Holder(val p: Plain, val w: WithNames)
|
||||||
|
|
||||||
@OptIn(InternalSerializationApi::class)
|
@OptIn(InternalSerializationApi::class)
|
||||||
fun box(): String {
|
fun testSerializers(): String {
|
||||||
val cs = (Holder.serializer() as GeneratedSerializer<*>).childSerializers()
|
val cs = (Holder.serializer() as GeneratedSerializer<*>).childSerializers()
|
||||||
val str1 = cs[0].toString()
|
val str1 = cs[0].toString()
|
||||||
if (!str1.contains("kotlinx.serialization.internal.EnumSerializer")) return str1
|
if (!str1.contains("kotlinx.serialization.internal.EnumSerializer")) return str1
|
||||||
@@ -32,4 +32,17 @@ fun box(): String {
|
|||||||
// val str2 = cs[1].toString()
|
// val str2 = cs[1].toString()
|
||||||
// if (!str2.contains("kotlinx.serialization.internal.EnumSerializer")) return str2
|
// if (!str2.contains("kotlinx.serialization.internal.EnumSerializer")) return str2
|
||||||
return "OK"
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testSerialization(previous: String): String {
|
||||||
|
if (previous != "OK") return previous
|
||||||
|
val h = Holder(Plain.B, WithNames.ENTRY1)
|
||||||
|
val s = Json.encodeToString(Holder.serializer(), h)
|
||||||
|
if (s != """{"p":"B","w":"A"}""") return s
|
||||||
|
if (Json.decodeFromString(Holder.serializer(), s).w != WithNames.ENTRY1) return "Deserialization failure"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return testSerialization(testSerializers())
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user