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<*>> {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += "-opt-in=org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI"
|
||||
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.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.isSealed
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
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.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
|
||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
||||
private val throwMissedFieldExceptionFunc = compilerContext.referenceFunctions(
|
||||
CallableId(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME
|
||||
)
|
||||
).singleOrNull()
|
||||
|
||||
private val throwMissedFieldExceptionArrayFunc
|
||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
||||
private val throwMissedFieldExceptionArrayFunc = compilerContext.referenceFunctions(
|
||||
CallableId(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME
|
||||
)
|
||||
).singleOrNull()
|
||||
|
||||
private val enumSerializerFactoryFunc
|
||||
= compilerContext.enumSerializerFactoryFunc
|
||||
private val enumSerializerFactoryFunc = compilerContext.enumSerializerFactoryFunc
|
||||
|
||||
private val markedEnumSerializerFactoryFunc
|
||||
= compilerContext.markedEnumSerializerFactoryFunc
|
||||
private val markedEnumSerializerFactoryFunc = compilerContext.markedEnumSerializerFactoryFunc
|
||||
|
||||
fun useFieldMissingOptimization(): Boolean {
|
||||
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
||||
@@ -250,7 +256,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
genericGetter
|
||||
)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -267,7 +273,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
|
||||
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) && (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)!!
|
||||
// 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) }
|
||||
|
||||
+2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
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.irGet
|
||||
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.
|
||||
Also adapter may replace IR expression of getting `this` value by another expression.
|
||||
*/
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun createInitializerAdapter(
|
||||
irClass: IrClass,
|
||||
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.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.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.Name
|
||||
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.types.KotlinType
|
||||
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_MODE_FQ
|
||||
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 {
|
||||
@@ -134,7 +131,7 @@ interface IrBuilderWithPluginContext {
|
||||
}
|
||||
|
||||
fun IrClass.contributeAnonymousInitializer(bodyGen: IrBlockBodyBuilder.() -> Unit) {
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(descriptor)
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
|
||||
factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
||||
it.parent = this
|
||||
declarations.add(it)
|
||||
@@ -256,9 +253,6 @@ interface IrBuilderWithPluginContext {
|
||||
result
|
||||
)
|
||||
|
||||
@FirIncompatiblePluginAPI
|
||||
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
|
||||
|
||||
fun IrBuilderWithScope.setProperty(receiver: IrExpression, property: IrProperty, value: IrExpression): IrExpression {
|
||||
return if (property.setter != null)
|
||||
irSet(property.setter!!.returnType, receiver, property.setter!!.symbol, value)
|
||||
@@ -269,7 +263,7 @@ interface IrBuilderWithPluginContext {
|
||||
fun IrBuilderWithScope.generateAnySuperConstructorCall(toBuilder: IrBlockBodyBuilder) {
|
||||
val anyConstructor = compilerContext.irBuiltIns.anyClass.owner.declarations.single { it is IrConstructor } as IrConstructor
|
||||
with(toBuilder) {
|
||||
+IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
||||
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset, endOffset,
|
||||
compilerContext.irBuiltIns.unitType,
|
||||
anyConstructor.symbol
|
||||
@@ -348,14 +342,14 @@ interface IrBuilderWithPluginContext {
|
||||
createClassReference(classSymbol.starProjectedType, startOffset, endOffset)
|
||||
|
||||
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> =
|
||||
irClass.annotations.associateBy { it.symbol.owner.parentAsClass.descriptor.fqNameSafe }.toMutableMap()
|
||||
irClass.annotations.associateBy { it.symbol.owner.parentAsClass.fqNameWhenAvailable!! }.toMutableMap()
|
||||
for (clazz in irClass.getAllSuperclasses()) {
|
||||
val annotations = clazz.annotations
|
||||
.mapNotNull {
|
||||
val descriptor = it.symbol.owner.parentAsClass.descriptor
|
||||
if (descriptor.isInheritableSerialInfoAnnotation) descriptor.fqNameSafe to it else null
|
||||
val parent = it.symbol.owner.parentAsClass
|
||||
if (parent.isInheritableSerialInfoAnnotation) parent.fqNameWhenAvailable!! to it else null
|
||||
}
|
||||
annotations.forEach { (fqname, call) ->
|
||||
if (fqname !in annotationByFq) {
|
||||
@@ -371,7 +365,7 @@ interface IrBuilderWithPluginContext {
|
||||
fun IrBuilderWithScope.copyAnnotationsFrom(annotations: List<IrConstructorCall>): List<IrExpression> =
|
||||
annotations.mapNotNull { annotationCall ->
|
||||
val annotationClass = annotationCall.symbol.owner.parentAsClass
|
||||
if (!annotationClass.descriptor.isSerialInfoAnnotation) return@mapNotNull null
|
||||
if (!annotationClass.isSerialInfoAnnotation) return@mapNotNull null
|
||||
|
||||
if (compilerContext.platform.isJvm()) {
|
||||
val implClass = compilerContext.serialInfoImplJvmIrGenerator.getImplClass(annotationClass)
|
||||
@@ -389,6 +383,7 @@ interface IrBuilderWithPluginContext {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrBuilderWithScope.wrapperClassReference(classType: IrType): IrClassReference {
|
||||
if (compilerContext.platform.isJvm()) {
|
||||
// "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.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
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.util.*
|
||||
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.fir.SerializationPluginKey
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
|
||||
internal fun IrType.isKSerializer(): Boolean {
|
||||
val simpleType = this as? IrSimpleType ?: return false
|
||||
@@ -89,7 +90,7 @@ private fun IrClass.checkSerializableOrMetaAnnotationArgs(mustDoNotHaveArgs: Boo
|
||||
return true
|
||||
}
|
||||
return annotations
|
||||
.map { it.annotationClass.annotations }
|
||||
.map { it.constructedClass.annotations }
|
||||
.any { it.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName) }
|
||||
}
|
||||
|
||||
@@ -98,6 +99,9 @@ internal val IrClass.isSerialInfoAnnotation: Boolean
|
||||
|| annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName)
|
||||
|| annotations.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName)
|
||||
|
||||
internal val IrClass.isInheritableSerialInfoAnnotation: Boolean
|
||||
get() = annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName)
|
||||
|
||||
internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationPluginContext): Boolean
|
||||
= (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
||||
|| isEnumWithLegacyGeneratedSerializer(context)
|
||||
@@ -142,6 +146,7 @@ fun IrClass.getSuperClassNotAny(): IrClass? {
|
||||
return if (parentClass.defaultType.isAny()) null else parentClass
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal fun IrDeclaration.isFromPlugin(): Boolean =
|
||||
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
|
||||
}
|
||||
|
||||
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 =
|
||||
this is IrGetValueImpl && this.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
|
||||
internal val IrConstructorCall.annotationClass
|
||||
internal val IrConstructorCall.constructedClass
|
||||
get() = this.symbol.owner.constructedClass
|
||||
|
||||
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?
|
||||
get() = findAnnotation(SerializationAnnotations.serialNameAnnotationFqName)?.getStringConstArgument(0) // @SerialName("foo")
|
||||
|
||||
+2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
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.IrProperty
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
@@ -41,6 +42,7 @@ class IrSerializableProperties(
|
||||
override val serializableStandaloneProperties: List<IrSerializableProperty>
|
||||
) : ISerializableProperties<IrSerializableProperty>
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal fun serializablePropertiesForIrBackend(
|
||||
irClass: IrClass,
|
||||
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.ir.addExtensionReceiver
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.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.resolve.DescriptorUtils
|
||||
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.resolve.SerialEntityNames
|
||||
|
||||
// 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).
|
||||
// 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(
|
||||
private val context: SerializationPluginContext,
|
||||
private val moduleFragment: IrModuleFragment,
|
||||
@@ -53,7 +56,7 @@ class SerialInfoImplJvmIrGenerator(
|
||||
|
||||
fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass =
|
||||
annotationToImpl.getOrPut(serialInfoAnnotationClass) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // TODO
|
||||
@OptIn(FirIncompatiblePluginAPI::class)
|
||||
val implClassSymbol = context.referenceClass(serialInfoAnnotationClass.kotlinFqName.child(SerialEntityNames.IMPL_NAME))
|
||||
implClassSymbol!!.owner.apply(this::generate)
|
||||
}
|
||||
@@ -112,6 +115,9 @@ class SerialInfoImplJvmIrGenerator(
|
||||
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 {
|
||||
this.isKClass() -> 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 serializableWithAlreadyPresent = irSerializableClass.annotations.any {
|
||||
it.symbol.descriptor.constructedClass.fqNameSafe == annotationMarkerClass.owner.fqNameWhenAvailable
|
||||
it.constructedClass.fqNameWhenAvailable == annotationMarkerClass.owner.fqNameWhenAvailable
|
||||
}
|
||||
if (serializableWithAlreadyPresent) return
|
||||
|
||||
val annotationCtor = annotationMarkerClass.constructors.single { it.owner.isPrimary }
|
||||
val annotationType = annotationMarkerClass.defaultType
|
||||
|
||||
val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
|
||||
val annotationCtorCall = IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, annotationType, annotationCtor).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
createClassReference(
|
||||
@@ -150,7 +150,7 @@ class SerializableCompanionIrGenerator(
|
||||
}
|
||||
|
||||
private fun generateSerializerFactoryIfNeeded(getterDescriptor: IrSimpleFunction) {
|
||||
if (!irClass.descriptor.needSerializerFactory()) return
|
||||
if (!irClass.needSerializerFactory(compilerContext)) return
|
||||
val serialFactoryDescriptor = irClass.findDeclaration<IrSimpleFunction> {
|
||||
it.valueParameters.size == 1
|
||||
&& it.valueParameters.first().isVararg
|
||||
|
||||
+18
-17
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
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.ValueParameterDescriptor
|
||||
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.types.*
|
||||
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.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
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.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_DESCRIPTOR_FIELD_NAME
|
||||
@@ -97,8 +94,9 @@ class SerializableIrGenerator(
|
||||
}
|
||||
|
||||
// Missing field exception parts
|
||||
val exceptionCtorRef = compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(MISSING_FIELD_EXC)))
|
||||
.single { it.owner.valueParameters.singleOrNull()?.type?.isString() == true }
|
||||
val exceptionCtorRef =
|
||||
compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(MISSING_FIELD_EXC)))
|
||||
.single { it.owner.valueParameters.singleOrNull()?.type?.isString() == true }
|
||||
val exceptionType = exceptionCtorRef.owner.returnType
|
||||
|
||||
val seenVarsOffset = serializableProperties.bitMaskSlotCount()
|
||||
@@ -244,7 +242,7 @@ class SerializableIrGenerator(
|
||||
?: error("Non-serializable parent of serializable $irClass must have no arg constructor")
|
||||
|
||||
|
||||
val call = IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
||||
val call = IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
compilerContext.irBuiltIns.unitType,
|
||||
@@ -270,13 +268,14 @@ class SerializableIrGenerator(
|
||||
propertiesStart: Int
|
||||
): Int {
|
||||
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 superSlots = superProperties.bitMaskSlotCount()
|
||||
val arguments = allValueParameters.subList(0, superSlots) +
|
||||
allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) +
|
||||
allValueParameters.last() // SerializationConstructorMarker
|
||||
val call = IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
||||
val call = IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
compilerContext.irBuiltIns.unitType,
|
||||
@@ -307,7 +306,7 @@ class SerializableIrGenerator(
|
||||
// Compute offset of properties in superclass
|
||||
var ignoreIndexTo = -1
|
||||
val superClass = irClass.getSuperClassOrAny()
|
||||
if (superClass.descriptor.isInternalSerializable) {
|
||||
if (superClass.isInternalSerializable) {
|
||||
ignoreIndexTo = serializablePropertiesForIrBackend(superClass).serializableProperties.size
|
||||
|
||||
// call super.writeSelf
|
||||
@@ -380,16 +379,18 @@ class SerializableIrGenerator(
|
||||
irClass: IrClass,
|
||||
context: SerializationPluginContext,
|
||||
) {
|
||||
val serializableClass = irClass.descriptor
|
||||
|
||||
if (serializableClass.isInternalSerializable) {
|
||||
if (irClass.isInternalSerializable) {
|
||||
SerializableIrGenerator(irClass, context).generate()
|
||||
irClass.patchDeclarationParents(irClass.parent)
|
||||
} else if (serializableClass.serializableAnnotationIsUseless) {
|
||||
throw CompilationException(
|
||||
"@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " +
|
||||
"Provide serializer manually via e.g. companion object", null, serializableClass.findPsi()
|
||||
)
|
||||
} else {
|
||||
val serializableAnnotationIsUseless = with(irClass) {
|
||||
hasSerializableOrMetaAnnotationWithoutArgs() && !isInternalSerializable && !hasCompanionObjectAsSerializer && kind != ClassKind.ENUM_CLASS && !isSealedSerializableInterface
|
||||
}
|
||||
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 serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||
|
||||
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
||||
val valuesF = serializableIrClass.functions.single { it.name == StandardNames.ENUM_VALUES }
|
||||
val valuesF = this@SerializerForEnumsGenerator.serializableIrClass.functions.single { it.name == StandardNames.ENUM_VALUES }
|
||||
val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol)
|
||||
|
||||
|
||||
@@ -67,7 +66,7 @@ class SerializerForEnumsGenerator(
|
||||
getValues,
|
||||
arrayGet.symbol,
|
||||
irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter),
|
||||
typeHint = serializableIrClass.defaultType
|
||||
typeHint = this@SerializerForEnumsGenerator.serializableIrClass.defaultType
|
||||
)
|
||||
+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.declarations.*
|
||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
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.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
@@ -117,7 +114,7 @@ open class SerializerIrGenerator(
|
||||
}
|
||||
|
||||
val anonymousInit = irClass.run {
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(descriptor)
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
|
||||
irClass.factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
||||
it.parent = this
|
||||
declarations.add(it)
|
||||
@@ -207,7 +204,7 @@ open class SerializerIrGenerator(
|
||||
addFunctionBody(typedConstructorDescriptor) { ctor ->
|
||||
// generate call to primary ctor to init serialClassDesc and super()
|
||||
val primaryCtor = irClass.constructors.primary
|
||||
+IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
||||
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
compilerContext.irBuiltIns.unitType,
|
||||
@@ -268,15 +265,11 @@ open class SerializerIrGenerator(
|
||||
|
||||
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 =
|
||||
encoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||
|
||||
val call = irCall(beginFunc, type = kOutputClass.defaultType).mapValueParametersIndexed { _, _ ->
|
||||
irGet(localSerialDesc)
|
||||
}
|
||||
// can it be done in more concise way? e.g. additional builder function?
|
||||
call.dispatchReceiver = irGet(saveFunc.valueParameters[0])
|
||||
val call = irInvoke(irGet(saveFunc.valueParameters[0]), beginFunc, irGet(localSerialDesc), typeHint = kOutputClass.defaultType)
|
||||
val objectToSerialize = saveFunc.valueParameters[1]
|
||||
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.jvm.ir.fileParent
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
@@ -93,6 +94,7 @@ private class SerializerClassLowering(
|
||||
SerializerIrGenerator.generate(irClass, context, context.metadataPlugin)
|
||||
SerializableCompanionIrGenerator.generate(irClass, context)
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {
|
||||
serialInfoJvmGenerator.generate(irClass)
|
||||
}
|
||||
|
||||
Vendored
+14
-1
@@ -20,7 +20,7 @@ enum class Plain {
|
||||
class Holder(val p: Plain, val w: WithNames)
|
||||
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
fun box(): String {
|
||||
fun testSerializers(): String {
|
||||
val cs = (Holder.serializer() as GeneratedSerializer<*>).childSerializers()
|
||||
val str1 = cs[0].toString()
|
||||
if (!str1.contains("kotlinx.serialization.internal.EnumSerializer")) return str1
|
||||
@@ -32,4 +32,17 @@ fun box(): String {
|
||||
// val str2 = cs[1].toString()
|
||||
// if (!str2.contains("kotlinx.serialization.internal.EnumSerializer")) return str2
|
||||
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