Remove BindingContext, KotlinType and *Descriptor from IR plugin dependencies
This commit is contained in:
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
|||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
@@ -41,6 +42,7 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
|
|||||||
override val moduleDescriptor: ModuleDescriptor
|
override val moduleDescriptor: ModuleDescriptor
|
||||||
get() = error(ERROR_MESSAGE)
|
get() = error(ERROR_MESSAGE)
|
||||||
|
|
||||||
|
@Suppress("OVERRIDE_DEPRECATION")
|
||||||
@ObsoleteDescriptorBasedAPI
|
@ObsoleteDescriptorBasedAPI
|
||||||
override val bindingContext: BindingContext
|
override val bindingContext: BindingContext
|
||||||
get() = error(ERROR_MESSAGE)
|
get() = error(ERROR_MESSAGE)
|
||||||
@@ -67,7 +69,8 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
|
|||||||
get() = components.session.symbolProvider
|
get() = components.session.symbolProvider
|
||||||
|
|
||||||
override fun referenceClass(classId: ClassId): IrClassSymbol? {
|
override fun referenceClass(classId: ClassId): IrClassSymbol? {
|
||||||
return referenceClassLikeSymbol(classId, symbolProvider::getClassLikeSymbolByClassId, symbolTable::referenceClass)
|
val firSymbol = symbolProvider.getClassLikeSymbolByClassId(classId) as? FirClassSymbol<*> ?: return null
|
||||||
|
return components.classifierStorage.getIrClassSymbol(firSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun referenceTypeAlias(classId: ClassId): IrTypeAliasSymbol? {
|
override fun referenceTypeAlias(classId: ClassId): IrTypeAliasSymbol? {
|
||||||
@@ -135,6 +138,8 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
|
|||||||
error(ERROR_MESSAGE)
|
error(ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated("Use classId overload instead")
|
||||||
override fun referenceClass(fqName: FqName): IrClassSymbol? {
|
override fun referenceClass(fqName: FqName): IrClassSymbol? {
|
||||||
error(ERROR_MESSAGE)
|
error(ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
@@ -147,10 +152,12 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
|
|||||||
error(ERROR_MESSAGE)
|
error(ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use callableId overload instead")
|
||||||
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
|
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
|
||||||
error(ERROR_MESSAGE)
|
error(ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use callableId overload instead")
|
||||||
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
|
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
|
||||||
error(ERROR_MESSAGE)
|
error(ERROR_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -29,11 +29,13 @@ interface IrPluginContext : IrGeneratorContext {
|
|||||||
val moduleDescriptor: ModuleDescriptor
|
val moduleDescriptor: ModuleDescriptor
|
||||||
|
|
||||||
@ObsoleteDescriptorBasedAPI
|
@ObsoleteDescriptorBasedAPI
|
||||||
|
@Deprecated("", level = DeprecationLevel.ERROR)
|
||||||
val bindingContext: BindingContext
|
val bindingContext: BindingContext
|
||||||
|
|
||||||
val symbolTable: ReferenceSymbolTable
|
val symbolTable: ReferenceSymbolTable
|
||||||
|
|
||||||
@ObsoleteDescriptorBasedAPI
|
@ObsoleteDescriptorBasedAPI
|
||||||
|
// @Deprecated("", level = DeprecationLevel.ERROR)
|
||||||
val typeTranslator: TypeTranslator
|
val typeTranslator: TypeTranslator
|
||||||
|
|
||||||
val symbols: BuiltinSymbolsBase
|
val symbols: BuiltinSymbolsBase
|
||||||
@@ -49,10 +51,13 @@ interface IrPluginContext : IrGeneratorContext {
|
|||||||
fun createDiagnosticReporter(pluginId: String): IrMessageLogger
|
fun createDiagnosticReporter(pluginId: String): IrMessageLogger
|
||||||
|
|
||||||
// The following API is experimental
|
// The following API is experimental
|
||||||
|
@Deprecated("Use classId overload instead")
|
||||||
fun referenceClass(fqName: FqName): IrClassSymbol?
|
fun referenceClass(fqName: FqName): IrClassSymbol?
|
||||||
fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol?
|
fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol?
|
||||||
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol>
|
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol>
|
||||||
|
@Deprecated("Use callableId overload instead")
|
||||||
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol>
|
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol>
|
||||||
|
@Deprecated("Use callableId overload instead")
|
||||||
fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol>
|
fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol>
|
||||||
|
|
||||||
// This one is experimental too
|
// This one is experimental too
|
||||||
|
|||||||
+8
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|||||||
|
|
||||||
open class IrPluginContextImpl constructor(
|
open class IrPluginContextImpl constructor(
|
||||||
private val module: ModuleDescriptor,
|
private val module: ModuleDescriptor,
|
||||||
|
@Deprecated("", level = DeprecationLevel.ERROR)
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
override val bindingContext: BindingContext,
|
override val bindingContext: BindingContext,
|
||||||
override val languageVersionSettings: LanguageVersionSettings,
|
override val languageVersionSettings: LanguageVersionSettings,
|
||||||
@@ -97,6 +98,7 @@ open class IrPluginContextImpl constructor(
|
|||||||
return symbols
|
return symbols
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use classId overload instead")
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
override fun referenceClass(fqName: FqName): IrClassSymbol? {
|
override fun referenceClass(fqName: FqName): IrClassSymbol? {
|
||||||
assert(!fqName.isRoot)
|
assert(!fqName.isRoot)
|
||||||
@@ -120,10 +122,12 @@ open class IrPluginContextImpl constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
|
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
|
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
|
||||||
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
|
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use callableId overload instead")
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
|
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
|
||||||
assert(!fqName.isRoot)
|
assert(!fqName.isRoot)
|
||||||
@@ -133,6 +137,7 @@ open class IrPluginContextImpl constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use callableId overload instead")
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
|
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
|
||||||
assert(!fqName.isRoot)
|
assert(!fqName.isRoot)
|
||||||
@@ -143,6 +148,7 @@ open class IrPluginContextImpl constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun referenceClass(classId: ClassId): IrClassSymbol? {
|
override fun referenceClass(classId: ClassId): IrClassSymbol? {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
return referenceClass(classId.asSingleFqName())
|
return referenceClass(classId.asSingleFqName())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,10 +161,12 @@ open class IrPluginContextImpl constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun referenceFunctions(callableId: CallableId): Collection<IrSimpleFunctionSymbol> {
|
override fun referenceFunctions(callableId: CallableId): Collection<IrSimpleFunctionSymbol> {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
return referenceFunctions(callableId.asSingleFqName())
|
return referenceFunctions(callableId.asSingleFqName())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun referenceProperties(callableId: CallableId): Collection<IrPropertySymbol> {
|
override fun referenceProperties(callableId: CallableId): Collection<IrPropertySymbol> {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
return referenceProperties(callableId.asSingleFqName())
|
return referenceProperties(callableId.asSingleFqName())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -120,6 +120,7 @@ private class AndroidIrTransformer(val extension: AndroidIrExtension, val plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: sparse array version intentionally not implemented; this plugin is deprecated
|
// NOTE: sparse array version intentionally not implemented; this plugin is deprecated
|
||||||
|
@Suppress("DEPRECATION") // TODO: check that it still works with FIR
|
||||||
private val mapFactory = pluginContext.referenceFunctions(FqName("kotlin.collections.mutableMapOf"))
|
private val mapFactory = pluginContext.referenceFunctions(FqName("kotlin.collections.mutableMapOf"))
|
||||||
.single { it.owner.valueParameters.isEmpty() }
|
.single { it.owner.valueParameters.isEmpty() }
|
||||||
private val mapGet = pluginContext.irBuiltIns.mapClass.owner.functions
|
private val mapGet = pluginContext.irBuiltIns.mapClass.owner.functions
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:frontend"))
|
compileOnly(project(":compiler:frontend"))
|
||||||
compileOnly(project(":compiler:backend"))
|
compileOnly(project(":compiler:backend"))
|
||||||
compileOnly(project(":compiler:ir.backend.common"))
|
compileOnly(project(":compiler:ir.backend.common"))
|
||||||
|
compileOnly(project(":compiler:backend.jvm"))
|
||||||
compileOnly(project(":compiler:ir.tree"))
|
compileOnly(project(":compiler:ir.tree"))
|
||||||
compileOnly(project(":js:js.frontend"))
|
compileOnly(project(":js:js.frontend"))
|
||||||
compileOnly(project(":js:js.translator"))
|
compileOnly(project(":js:js.translator"))
|
||||||
|
|||||||
+4
-1
@@ -22,9 +22,12 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotat
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor
|
||||||
|
|
||||||
abstract class AbstractSerialGenerator(val bindingContext: BindingContext, val currentDeclaration: ClassDescriptor) {
|
const val K2_ERR_MESSAGE = "K2 not supported yet.\nBindingContext is null, meaning this function is used from the K2 compiler. Please report to devs so we can support this feature."
|
||||||
|
|
||||||
|
abstract class AbstractSerialGenerator(val bindingContext: BindingContext?, val currentDeclaration: ClassDescriptor) {
|
||||||
|
|
||||||
private fun getKClassListFromFileAnnotation(annotationFqName: FqName, declarationInFile: DeclarationDescriptor): List<KotlinType> {
|
private fun getKClassListFromFileAnnotation(annotationFqName: FqName, declarationInFile: DeclarationDescriptor): List<KotlinType> {
|
||||||
|
if (bindingContext == null) return emptyList()// TODO
|
||||||
val annotation = AnnotationsUtils
|
val annotation = AnnotationsUtils
|
||||||
.getContainingFileAnnotations(bindingContext, declarationInFile)
|
.getContainingFileAnnotations(bindingContext, declarationInFile)
|
||||||
.find { it.fqName == annotationFqName }
|
.find { it.fqName == annotationFqName }
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
|||||||
|
|
||||||
abstract class SerializableCodegen(
|
abstract class SerializableCodegen(
|
||||||
protected val serializableDescriptor: ClassDescriptor,
|
protected val serializableDescriptor: ClassDescriptor,
|
||||||
bindingContext: BindingContext
|
bindingContext: BindingContext?
|
||||||
) : AbstractSerialGenerator(bindingContext, serializableDescriptor) {
|
) : AbstractSerialGenerator(bindingContext, serializableDescriptor) {
|
||||||
protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor)
|
protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor)
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.common
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
@@ -15,12 +16,12 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SE
|
|||||||
|
|
||||||
abstract class SerializableCompanionCodegen(
|
abstract class SerializableCompanionCodegen(
|
||||||
protected val companionDescriptor: ClassDescriptor,
|
protected val companionDescriptor: ClassDescriptor,
|
||||||
bindingContext: BindingContext
|
bindingContext: BindingContext?
|
||||||
) : AbstractSerialGenerator(bindingContext, companionDescriptor) {
|
) : AbstractSerialGenerator(bindingContext, companionDescriptor) {
|
||||||
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!!
|
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!!
|
||||||
|
|
||||||
fun generate() {
|
open fun getSerializerGetterDescriptor(): FunctionDescriptor {
|
||||||
val serializerGetterDescriptor = companionDescriptor.unsubstitutedMemberScope.getContributedFunctions(
|
return companionDescriptor.unsubstitutedMemberScope.getContributedFunctions(
|
||||||
SERIALIZER_PROVIDER_NAME,
|
SERIALIZER_PROVIDER_NAME,
|
||||||
NoLookupLocation.FROM_BACKEND
|
NoLookupLocation.FROM_BACKEND
|
||||||
).firstOrNull {
|
).firstOrNull {
|
||||||
@@ -32,6 +33,10 @@ abstract class SerializableCompanionCodegen(
|
|||||||
"Can't find synthesized 'Companion.serializer()' function to generate, " +
|
"Can't find synthesized 'Companion.serializer()' function to generate, " +
|
||||||
"probably clash with user-defined function has occurred"
|
"probably clash with user-defined function has occurred"
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generate() {
|
||||||
|
val serializerGetterDescriptor = getSerializerGetterDescriptor()
|
||||||
|
|
||||||
if (serializableDescriptor.isSerializableObject
|
if (serializableDescriptor.isSerializableObject
|
||||||
|| serializableDescriptor.isAbstractOrSealedSerializableClass()
|
|| serializableDescriptor.isAbstractOrSealedSerializableClass()
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
|||||||
|
|
||||||
abstract class SerializerCodegen(
|
abstract class SerializerCodegen(
|
||||||
protected val serializerDescriptor: ClassDescriptor,
|
protected val serializerDescriptor: ClassDescriptor,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext?,
|
||||||
metadataPlugin: SerializationDescriptorSerializerPlugin?
|
metadataPlugin: SerializationDescriptorSerializerPlugin?
|
||||||
) : AbstractSerialGenerator(bindingContext, serializerDescriptor) {
|
) : AbstractSerialGenerator(bindingContext, serializerDescriptor) {
|
||||||
val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
|
val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
|
||||||
|
|||||||
+73
-17
@@ -6,10 +6,15 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.common
|
package org.jetbrains.kotlinx.serialization.compiler.backend.common
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.CompilationException
|
import org.jetbrains.kotlin.codegen.CompilationException
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.isTypeParameter
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -21,17 +26,32 @@ import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
|
||||||
|
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.SerializationPackages.internalPackageFqName
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
|
||||||
|
|
||||||
|
interface ISerialTypeInfo<C, D, T : KotlinTypeMarker, S : ISerializableProperty<D, T>> {
|
||||||
|
val property: S
|
||||||
|
val elementMethodPrefix: String
|
||||||
|
val serializer: C?
|
||||||
|
}
|
||||||
|
|
||||||
open class SerialTypeInfo(
|
open class SerialTypeInfo(
|
||||||
val property: SerializableProperty,
|
override val property: SerializableProperty,
|
||||||
val elementMethodPrefix: String,
|
override val elementMethodPrefix: String,
|
||||||
val serializer: ClassDescriptor? = null
|
override val serializer: ClassDescriptor? = null
|
||||||
)
|
) : ISerialTypeInfo<ClassDescriptor, PropertyDescriptor, KotlinType, SerializableProperty>
|
||||||
|
|
||||||
|
class IrSerialTypeInfo(
|
||||||
|
override val property: IrSerializableProperty,
|
||||||
|
override val elementMethodPrefix: String,
|
||||||
|
override val serializer: IrClassSymbol? = null
|
||||||
|
) : ISerialTypeInfo<IrClassSymbol, IrProperty, IrSimpleType, IrSerializableProperty>
|
||||||
|
|
||||||
|
|
||||||
fun AbstractSerialGenerator.findAddOnSerializer(propertyType: KotlinType, module: ModuleDescriptor): ClassDescriptor? {
|
fun AbstractSerialGenerator.findAddOnSerializer(propertyType: KotlinType, module: ModuleDescriptor): ClassDescriptor? {
|
||||||
additionalSerializersInScopeOfCurrentFile[propertyType.toClassDescriptor to propertyType.isMarkedNullable]?.let { return it }
|
additionalSerializersInScopeOfCurrentFile[propertyType.toClassDescriptor to propertyType.isMarkedNullable]?.let { return it }
|
||||||
@@ -46,6 +66,33 @@ fun AbstractSerialGenerator.findAddOnSerializer(propertyType: KotlinType, module
|
|||||||
fun KotlinType.isGeneratedSerializableObject() =
|
fun KotlinType.isGeneratedSerializableObject() =
|
||||||
toClassDescriptor?.run { kind == ClassKind.OBJECT && hasSerializableOrMetaAnnotationWithoutArgs } == true
|
toClassDescriptor?.run { kind == ClassKind.OBJECT && hasSerializableOrMetaAnnotationWithoutArgs } == true
|
||||||
|
|
||||||
|
fun AbstractSerialGenerator.getIrSerialTypeInfo(property: IrSerializableProperty, ctx: SerializationPluginContext): IrSerialTypeInfo {
|
||||||
|
fun SerializableInfo(serializer: IrClassSymbol?) =
|
||||||
|
IrSerialTypeInfo(property, if (property.type.isNullable()) "Nullable" else "", serializer)
|
||||||
|
|
||||||
|
val T = property.type
|
||||||
|
property.serializableWith?.let { return SerializableInfo(it.classOrNull!!) }
|
||||||
|
// TODO findAddOnSerializer(T, property.module)?.let { return SerializableInfo(it) }
|
||||||
|
T.overridenSerializer?.let { return SerializableInfo(it.classOrNull!!) }
|
||||||
|
return when {
|
||||||
|
T.isTypeParameter() -> IrSerialTypeInfo(property, if (property.type.isMarkedNullable()) "Nullable" else "", null)
|
||||||
|
T.isPrimitiveType() -> IrSerialTypeInfo(
|
||||||
|
property,
|
||||||
|
T.classFqName!!.asString().removePrefix("kotlin.")
|
||||||
|
)
|
||||||
|
T.isString() -> IrSerialTypeInfo(property, "String")
|
||||||
|
T.isArray() -> {
|
||||||
|
val serializer = property.serializableWith?.classOrNull ?: ctx.getClassFromRuntime(SpecialBuiltins.referenceArraySerializer)
|
||||||
|
SerializableInfo(serializer)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val serializer =
|
||||||
|
findTypeSerializerOrContext(ctx, property.type)
|
||||||
|
SerializableInfo(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName", "LocalVariableName")
|
@Suppress("FunctionName", "LocalVariableName")
|
||||||
fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
||||||
fun SerializableInfo(serializer: ClassDescriptor?) =
|
fun SerializableInfo(serializer: ClassDescriptor?) =
|
||||||
@@ -155,20 +202,32 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescri
|
|||||||
val stdSer = findStandardKotlinTypeSerializer(module, kType) // see if there is a standard serializer
|
val stdSer = findStandardKotlinTypeSerializer(module, kType) // see if there is a standard serializer
|
||||||
?: findEnumTypeSerializer(module, kType)
|
?: findEnumTypeSerializer(module, kType)
|
||||||
if (stdSer != null) return stdSer
|
if (stdSer != null) return stdSer
|
||||||
if (kType.isInterface() && kType.toClassDescriptor?.isSealedSerializableInterface == false) return module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer)
|
if (kType.isInterface() && kType.toClassDescriptor?.isSealedSerializableInterface == false) return module.getClassFromSerializationPackage(
|
||||||
|
SpecialBuiltins.polymorphicSerializer
|
||||||
|
)
|
||||||
return kType.toClassDescriptor?.classSerializer // check for serializer defined on the type
|
return kType.toClassDescriptor?.classSerializer // check for serializer defined on the type
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||||
val name = when (kType.getJetTypeFqName(false)) {
|
val typeName = kType.getJetTypeFqName(false)
|
||||||
"Z" -> if (kType.isBoolean()) "BooleanSerializer" else return null
|
val name = when (typeName) {
|
||||||
"B" -> if (kType.isByte()) "ByteSerializer" else return null
|
"Z" -> if (kType.isBoolean()) "BooleanSerializer" else null
|
||||||
"S" -> if (kType.isShort()) "ShortSerializer" else return null
|
"B" -> if (kType.isByte()) "ByteSerializer" else null
|
||||||
"I" -> if (kType.isInt()) "IntSerializer" else return null
|
"S" -> if (kType.isShort()) "ShortSerializer" else null
|
||||||
"J" -> if (kType.isLong()) "LongSerializer" else return null
|
"I" -> if (kType.isInt()) "IntSerializer" else null
|
||||||
"F" -> if (kType.isFloat()) "FloatSerializer" else return null
|
"J" -> if (kType.isLong()) "LongSerializer" else null
|
||||||
"D" -> if (kType.isDouble()) "DoubleSerializer" else return null
|
"F" -> if (kType.isFloat()) "FloatSerializer" else null
|
||||||
"C" -> if (kType.isChar()) "CharSerializer" else return null
|
"D" -> if (kType.isDouble()) "DoubleSerializer" else null
|
||||||
|
"C" -> if (kType.isChar()) "CharSerializer" else null
|
||||||
|
else -> findStandardKotlinTypeSerializer(typeName)
|
||||||
|
} ?: return null
|
||||||
|
val identifier = Name.identifier(name)
|
||||||
|
return module.findClassAcrossModuleDependencies(ClassId(internalPackageFqName, identifier))
|
||||||
|
?: module.findClassAcrossModuleDependencies(ClassId(SerializationPackages.packageFqName, identifier))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findStandardKotlinTypeSerializer(typeName: String): String? {
|
||||||
|
return when (typeName) {
|
||||||
"kotlin.Unit" -> "UnitSerializer"
|
"kotlin.Unit" -> "UnitSerializer"
|
||||||
"kotlin.Nothing" -> "NothingSerializer"
|
"kotlin.Nothing" -> "NothingSerializer"
|
||||||
"kotlin.Boolean" -> "BooleanSerializer"
|
"kotlin.Boolean" -> "BooleanSerializer"
|
||||||
@@ -223,9 +282,6 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
|
|||||||
"java.util.Map.Entry" -> "MapEntrySerializer"
|
"java.util.Map.Entry" -> "MapEntrySerializer"
|
||||||
else -> return null
|
else -> return null
|
||||||
}
|
}
|
||||||
val identifier = Name.identifier(name)
|
|
||||||
return module.findClassAcrossModuleDependencies(ClassId(internalPackageFqName, identifier))
|
|
||||||
?: module.findClassAcrossModuleDependencies(ClassId(SerializationPackages.packageFqName, identifier))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||||
|
|||||||
+326
@@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* 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.kotlinx.serialization.compiler.backend.common
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.codegen.CompilationException
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.objectSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.fir.SerializationPluginKey
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
|
||||||
|
fun AbstractSerialGenerator.findTypeSerializerOrContextUnchecked(
|
||||||
|
context: SerializationPluginContext, kType: IrType
|
||||||
|
): IrClassSymbol? {
|
||||||
|
val annotations = kType.annotations
|
||||||
|
if (kType.isTypeParameter()) return null
|
||||||
|
annotations.serializableWith()?.let { return it.classOrNull }
|
||||||
|
additionalSerializersInScopeOfCurrentFile[kType.classOrNull?.descriptor to kType.isMarkedNullable()]?.let {
|
||||||
|
return context.referenceClass(
|
||||||
|
ClassId.topLevel(it.fqNameSafe)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (kType.isMarkedNullable()) return findTypeSerializerOrContextUnchecked(context, kType.makeNotNull())
|
||||||
|
if (kType.toKotlinType() in contextualKClassListInCurrentFile) return context.referenceClass(contextSerializerId)
|
||||||
|
return analyzeSpecialSerializers(context, annotations) ?: findTypeSerializer(context, kType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun analyzeSpecialSerializers(
|
||||||
|
context: SerializationPluginContext,
|
||||||
|
annotations: List<IrConstructorCall>
|
||||||
|
): IrClassSymbol? = when {
|
||||||
|
annotations.hasAnnotation(SerializationAnnotations.contextualFqName) || annotations.hasAnnotation(SerializationAnnotations.contextualOnPropertyFqName) ->
|
||||||
|
context.referenceClass(contextSerializerId)
|
||||||
|
// can be annotation on type usage, e.g. List<@Polymorphic Any>
|
||||||
|
annotations.hasAnnotation(SerializationAnnotations.polymorphicFqName) ->
|
||||||
|
context.referenceClass(polymorphicSerializerId)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AbstractSerialGenerator.findTypeSerializerOrContext(
|
||||||
|
context: SerializationPluginContext, kType: IrType,
|
||||||
|
sourceElement: PsiElement? = null
|
||||||
|
): IrClassSymbol? {
|
||||||
|
if (kType.isTypeParameter()) return null
|
||||||
|
return findTypeSerializerOrContextUnchecked(context, kType) ?: throw CompilationException(
|
||||||
|
"Serializer for element of type $kType has not been found.\n" +
|
||||||
|
"To use context serializer as fallback, explicitly annotate element with @Contextual",
|
||||||
|
null,
|
||||||
|
sourceElement
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? {
|
||||||
|
val userOverride = type.overridenSerializer
|
||||||
|
if (userOverride != null) return userOverride.classOrNull
|
||||||
|
if (type.isTypeParameter()) return null
|
||||||
|
if (type.isArray()) return context.referenceClass(referenceArraySerializerId)
|
||||||
|
if (type.isGeneratedSerializableObject()) return context.referenceClass(objectSerializerId)
|
||||||
|
val stdSer = findStandardKotlinTypeSerializer(context, type) // see if there is a standard serializer
|
||||||
|
?: findEnumTypeSerializer(context, type)
|
||||||
|
if (stdSer != null) return stdSer
|
||||||
|
if (type.isInterface() && type.classOrNull?.owner?.isSealedSerializableInterface == false) return context.referenceClass(
|
||||||
|
polymorphicSerializerId
|
||||||
|
)
|
||||||
|
return type.classOrNull?.owner.classSerializer(context) // check for serializer defined on the type
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrClass?.classSerializer(context: SerializationPluginContext): IrClassSymbol? = this?.let {
|
||||||
|
// serializer annotation on class?
|
||||||
|
serializableWith?.let { return it.classOrNull }
|
||||||
|
// companion object serializer?
|
||||||
|
if (hasCompanionObjectAsSerializer) return companionObject()?.symbol
|
||||||
|
// can infer @Poly?
|
||||||
|
polymorphicSerializerIfApplicableAutomatically(context)?.let { return it }
|
||||||
|
// default serializable?
|
||||||
|
if (shouldHaveGeneratedSerializer) {
|
||||||
|
// $serializer nested class
|
||||||
|
return this.declarations
|
||||||
|
.filterIsInstance<IrClass>()
|
||||||
|
.singleOrNull { it.name == SerialEntityNames.SERIALIZER_CLASS_NAME }?.symbol
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrClass.shouldHaveGeneratedSerializer: Boolean
|
||||||
|
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
||||||
|
|| isEnumWithLegacyGeneratedSerializer()
|
||||||
|
|
||||||
|
internal fun IrClass.polymorphicSerializerIfApplicableAutomatically(context: SerializationPluginContext): IrClassSymbol? {
|
||||||
|
val serializer = when {
|
||||||
|
kind == ClassKind.INTERFACE && modality == Modality.SEALED -> SpecialBuiltins.sealedSerializer
|
||||||
|
kind == ClassKind.INTERFACE -> SpecialBuiltins.polymorphicSerializer
|
||||||
|
isInternalSerializable && modality == Modality.ABSTRACT -> SpecialBuiltins.polymorphicSerializer
|
||||||
|
isInternalSerializable && modality == Modality.SEALED -> SpecialBuiltins.sealedSerializer
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
return serializer?.let { context.getClassFromRuntimeOrNull(it, SerializationPackages.packageFqName, SerializationPackages.internalPackageFqName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrClass.isInternalSerializable: Boolean
|
||||||
|
get() {
|
||||||
|
if (kind != ClassKind.CLASS) return false
|
||||||
|
return hasSerializableOrMetaAnnotationWithoutArgs()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrClass.isAbstractOrSealedSerializableClass: Boolean get() = isInternalSerializable && (modality == Modality.ABSTRACT || modality == Modality.SEALED)
|
||||||
|
|
||||||
|
internal val IrClass.isStaticSerializable: Boolean get() = this.typeParameters.isEmpty()
|
||||||
|
|
||||||
|
|
||||||
|
internal val IrClass.hasCompanionObjectAsSerializer: Boolean
|
||||||
|
get() = isInternallySerializableObject || companionObject()?.serializerForClass == this.defaultType
|
||||||
|
|
||||||
|
internal val IrClass.isInternallySerializableObject: Boolean
|
||||||
|
get() = kind == ClassKind.OBJECT && hasSerializableOrMetaAnnotationWithoutArgs()
|
||||||
|
|
||||||
|
internal val IrClass.serializerForClass: IrType?
|
||||||
|
get() = null // TODO("Serializer(forClass)")
|
||||||
|
|
||||||
|
fun findEnumTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? {
|
||||||
|
val classSymbol = type.classOrNull?.owner ?: return null
|
||||||
|
return if (classSymbol.kind == ClassKind.ENUM_CLASS && !classSymbol.isEnumWithLegacyGeneratedSerializer())
|
||||||
|
context.referenceClass(enumSerializerId)
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrClass.isEnumWithLegacyGeneratedSerializer(): Boolean = isInternallySerializableEnum() && useGeneratedEnumSerializer
|
||||||
|
|
||||||
|
internal val IrClass.useGeneratedEnumSerializer: Boolean
|
||||||
|
get() = true // todo ????
|
||||||
|
|
||||||
|
internal val IrClass.isSealedSerializableInterface: Boolean
|
||||||
|
get() = kind == ClassKind.INTERFACE && modality == Modality.SEALED && hasSerializableOrMetaAnnotationWithoutArgs() // in previous version, it was just 'serializableOrMeta'
|
||||||
|
|
||||||
|
internal fun IrClass.isInternallySerializableEnum(): Boolean =
|
||||||
|
kind == ClassKind.ENUM_CLASS && hasSerializableOrMetaAnnotationWithoutArgs()
|
||||||
|
|
||||||
|
fun findStandardKotlinTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? {
|
||||||
|
val typeName = type.classFqName?.toString()
|
||||||
|
val name = when (typeName) {
|
||||||
|
"Z" -> if (type.isBoolean()) "BooleanSerializer" else null
|
||||||
|
"B" -> if (type.isByte()) "ByteSerializer" else null
|
||||||
|
"S" -> if (type.isShort()) "ShortSerializer" else null
|
||||||
|
"I" -> if (type.isInt()) "IntSerializer" else null
|
||||||
|
"J" -> if (type.isLong()) "LongSerializer" else null
|
||||||
|
"F" -> if (type.isFloat()) "FloatSerializer" else null
|
||||||
|
"D" -> if (type.isDouble()) "DoubleSerializer" else null
|
||||||
|
"C" -> if (type.isChar()) "CharSerializer" else null
|
||||||
|
null -> null
|
||||||
|
else -> findStandardKotlinTypeSerializer(typeName)
|
||||||
|
} ?: return null
|
||||||
|
return context.getClassFromRuntimeOrNull(name, SerializationPackages.internalPackageFqName, SerializationPackages.packageFqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrType.isGeneratedSerializableObject(): Boolean {
|
||||||
|
return classOrNull?.run { owner.kind == ClassKind.OBJECT && owner.hasSerializableOrMetaAnnotationWithoutArgs() } == true
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrClass.isSerializableObject: Boolean
|
||||||
|
get() = kind == ClassKind.OBJECT && hasSerializableOrMetaAnnotation()
|
||||||
|
|
||||||
|
// todo: optimize & unify
|
||||||
|
internal fun IrClass.hasSerializableOrMetaAnnotationWithoutArgs(): Boolean {
|
||||||
|
val annot = getAnnotation(SerializationAnnotations.serializableAnnotationFqName)
|
||||||
|
if (annot != null) {
|
||||||
|
for (i in 0 until annot.valueArgumentsCount) {
|
||||||
|
if (annot.getValueArgument(i) != null) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val metaAnnotation = annotations
|
||||||
|
.flatMap { it.symbol.owner.constructedClass.annotations }
|
||||||
|
.find { it.isAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName) }
|
||||||
|
return metaAnnotation != null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SerializationPluginContext.getClassFromRuntimeOrNull(className: String, vararg packages: FqName): IrClassSymbol? {
|
||||||
|
val listToSearch = if (packages.isEmpty()) SerializationPackages.allPublicPackages else packages.toList()
|
||||||
|
for (pkg in listToSearch) {
|
||||||
|
referenceClass(ClassId(pkg, Name.identifier(className)))?.let { return it }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SerializationPluginContext.getClassFromRuntime(className: String, vararg packages: FqName): IrClassSymbol {
|
||||||
|
return getClassFromRuntimeOrNull(className, *packages) ?:
|
||||||
|
error("Class $className wasn't found in ${packages.toList().ifEmpty { SerializationPackages.allPublicPackages }}. " +
|
||||||
|
"Check that you have correct version of serialization runtime in classpath.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SerializationPluginContext.getClassFromInternalSerializationPackage(className: String): IrClassSymbol =
|
||||||
|
getClassFromRuntimeOrNull(className, SerializationPackages.internalPackageFqName)
|
||||||
|
?: error("Class $className wasn't found in ${SerializationPackages.internalPackageFqName}. Check that you have correct version of serialization runtime in classpath.")
|
||||||
|
|
||||||
|
|
||||||
|
internal val IrType.overridenSerializer: IrSimpleType?
|
||||||
|
get() {
|
||||||
|
val desc = this.classOrNull ?: return null
|
||||||
|
desc.owner.serializableWith?.let { return it }
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrClass.serializableWith: IrSimpleType?
|
||||||
|
get() = annotations.serializableWith()
|
||||||
|
|
||||||
|
|
||||||
|
internal fun List<IrConstructorCall>.serializableWith(): IrSimpleType? {
|
||||||
|
// XXX::class
|
||||||
|
// val annotationArg =
|
||||||
|
// firstOrNull { it.type.classFqName == SerializationAnnotations.serializerAnnotationFqName }?.getValueArgument(0) ?: return null
|
||||||
|
// TODO("SerializableWith")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getSerializableClassByCompanion(companionClass: IrClass): IrClass? {
|
||||||
|
if (companionClass.isSerializableObject) return companionClass
|
||||||
|
if (!companionClass.isCompanion) return null
|
||||||
|
val classDescriptor = (companionClass.parent as? IrClass) ?: return null
|
||||||
|
if (!classDescriptor.shouldHaveGeneratedMethodsInCompanion) return null
|
||||||
|
return classDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val IrClass.shouldHaveGeneratedMethodsInCompanion: Boolean
|
||||||
|
get() = this.isSerializableObject || this.isSerializableEnum() || (this.kind == ClassKind.CLASS && hasSerializableOrMetaAnnotation()) || this.isSealedSerializableInterface
|
||||||
|
|
||||||
|
internal fun IrClass.isSerializableEnum(): Boolean = kind == ClassKind.ENUM_CLASS && hasSerializableOrMetaAnnotation()
|
||||||
|
|
||||||
|
fun IrClass.hasSerializableOrMetaAnnotation() = descriptor.hasSerializableOrMetaAnnotation // TODO
|
||||||
|
|
||||||
|
internal val IrType.genericIndex: Int?
|
||||||
|
get() = (this.classifierOrNull as? IrTypeParameterSymbol)?.owner?.index
|
||||||
|
|
||||||
|
fun IrType.serialName(): String = this.classOrNull!!.owner.serialName()
|
||||||
|
fun IrClass.serialName(): String {
|
||||||
|
return descriptor.serialName() // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AbstractSerialGenerator.allSealedSerializableSubclassesFor(
|
||||||
|
irClass: IrClass,
|
||||||
|
context: SerializationPluginContext
|
||||||
|
): Pair<List<IrSimpleType>, List<IrClassSymbol>> {
|
||||||
|
assert(irClass.modality == Modality.SEALED)
|
||||||
|
fun recursiveSealed(klass: IrClass): Collection<IrClass> {
|
||||||
|
return klass.sealedSubclasses.map { it.owner }.flatMap { if (it.modality == Modality.SEALED) recursiveSealed(it) else setOf(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val serializableSubtypes = recursiveSealed(irClass).map { it.defaultType }
|
||||||
|
return serializableSubtypes.mapNotNull { subtype ->
|
||||||
|
findTypeSerializerOrContextUnchecked(context, subtype)?.let { Pair(subtype, it) }
|
||||||
|
}.unzip()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrClass.findEnumValuesMethod() = this.functions.singleOrNull { f ->
|
||||||
|
f.name == Name.identifier("values") && f.valueParameters.isEmpty() && f.extensionReceiverParameter == null
|
||||||
|
} ?: throw AssertionError("Enum class does not have single .values() function")
|
||||||
|
|
||||||
|
internal fun IrClass.enumEntries(): List<IrEnumEntry> {
|
||||||
|
check(this.kind == ClassKind.ENUM_CLASS)
|
||||||
|
return declarations.filterIsInstance<IrEnumEntry>()
|
||||||
|
// .filter { it.kind == ClassKind.ENUM_ENTRY }
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrClass.isEnumWithSerialInfoAnnotation(): Boolean {
|
||||||
|
if (kind != ClassKind.ENUM_CLASS) return false
|
||||||
|
if (annotations.hasAnySerialAnnotation) return true
|
||||||
|
return enumEntries().any { (it.annotations.hasAnySerialAnnotation) }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val List<IrConstructorCall>.hasAnySerialAnnotation: Boolean
|
||||||
|
get() = false // TODO serialNameValue != null || any { it.annotationClass?.isSerialInfoAnnotation == true }
|
||||||
|
|
||||||
|
internal val List<IrConstructorCall>.serialNameValue: String?
|
||||||
|
get() = null // todo("List<IrConstructorCall>.serialNameValue") @SerialName
|
||||||
|
|
||||||
|
internal fun getSerializableClassDescriptorBySerializer(serializer: IrClass): IrClass? {
|
||||||
|
val serializerForClass = serializer.serializerForClass
|
||||||
|
if (serializerForClass != null) return serializerForClass.classOrNull?.owner
|
||||||
|
if (serializer.name !in setOf(
|
||||||
|
SerialEntityNames.SERIALIZER_CLASS_NAME,
|
||||||
|
SerialEntityNames.GENERATED_SERIALIZER_CLASS
|
||||||
|
)
|
||||||
|
) return null
|
||||||
|
val classDescriptor = (serializer.parent as? IrClass) ?: return null
|
||||||
|
if (!classDescriptor.shouldHaveGeneratedSerializer) return null
|
||||||
|
return classDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun isKSerializer(type: IrType): Boolean {
|
||||||
|
val simpleType = type as? IrSimpleType ?: return false
|
||||||
|
val classifier = simpleType.classifier as? IrClassSymbol ?: return false
|
||||||
|
val fqName = classifier.owner.fqNameWhenAvailable
|
||||||
|
return fqName == SerialEntityNames.KSERIALIZER_NAME_FQ || fqName == SerialEntityNames.GENERATED_SERIALIZER_FQ
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrClass.findPluginGeneratedMethod(name: String): IrSimpleFunction? {
|
||||||
|
return this.functions.find { it.name.asString() == name && it.origin == IrDeclarationOrigin.GeneratedByPlugin(SerializationPluginKey) }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrConstructor.isSerializationCtor(): Boolean {
|
||||||
|
/*kind == CallableMemberDescriptor.Kind.SYNTHESIZED does not work because DeserializedClassConstructorDescriptor loses its kind*/
|
||||||
|
return valueParameters.lastOrNull()?.run {
|
||||||
|
name == SerialEntityNames.dummyParamName && type.classFqName == SerializationPackages.internalPackageFqName.child(
|
||||||
|
SerialEntityNames.SERIAL_CTOR_MARKER_NAME
|
||||||
|
)
|
||||||
|
} == true
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||||
|
|
||||||
|
// TODO KT-53096
|
||||||
|
fun IrPluginContext.generateBodyForDefaultConstructor(declaration: IrConstructor): IrBody? {
|
||||||
|
val type = declaration.returnType as? IrSimpleType ?: return null
|
||||||
|
|
||||||
|
val delegatingAnyCall = IrDelegatingConstructorCallImpl(
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
irBuiltIns.anyType,
|
||||||
|
irBuiltIns.anyClass.owner.primaryConstructor?.symbol ?: return null,
|
||||||
|
typeArgumentsCount = 0,
|
||||||
|
valueArgumentsCount = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
val initializerCall = IrInstanceInitializerCallImpl(
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
(declaration.parent as? IrClass)?.symbol ?: return null,
|
||||||
|
type
|
||||||
|
)
|
||||||
|
|
||||||
|
return irFactory.createBlockBody(-1, -1, listOf(delegatingAnyCall, initializerCall))
|
||||||
|
}
|
||||||
|
|
||||||
|
val Sequence<IrConstructor>.primary get() = find { it.isPrimary } ?: error("Expected to have a primary constructor")
|
||||||
+187
-194
@@ -5,9 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||||
|
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||||
|
import org.jetbrains.kotlin.backend.common.sourceElement
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
@@ -23,14 +25,21 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
|||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
||||||
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
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.psi
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.typeConstructor
|
||||||
|
import org.jetbrains.kotlin.types.model.dependsOnTypeConstructor
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
@@ -47,16 +56,16 @@ interface IrBuilderExtension {
|
|||||||
val compilerContext: SerializationPluginContext
|
val compilerContext: SerializationPluginContext
|
||||||
|
|
||||||
private val throwMissedFieldExceptionFunc
|
private val throwMissedFieldExceptionFunc
|
||||||
get() = compilerContext.referenceFunctions(SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_FQ).singleOrNull()
|
get() = compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
||||||
|
|
||||||
private val throwMissedFieldExceptionArrayFunc
|
private val throwMissedFieldExceptionArrayFunc
|
||||||
get() = compilerContext.referenceFunctions(SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_FQ).singleOrNull()
|
get() = compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
||||||
|
|
||||||
private val enumSerializerFactoryFunc
|
private val enumSerializerFactoryFunc
|
||||||
get() = compilerContext.referenceFunctions(SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_FQ).singleOrNull()
|
get() = compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME)).singleOrNull()
|
||||||
|
|
||||||
private val markedEnumSerializerFactoryFunc
|
private val markedEnumSerializerFactoryFunc
|
||||||
get() = compilerContext.referenceFunctions(SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_FQ).singleOrNull()
|
get() = compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)).singleOrNull()
|
||||||
|
|
||||||
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
||||||
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
||||||
@@ -66,6 +75,13 @@ interface IrBuilderExtension {
|
|||||||
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <F: IrFunction> addFunctionBody(function: F, bodyGen: IrBlockBodyBuilder.(F) -> Unit) {
|
||||||
|
function.body = DeclarationIrBuilder(compilerContext, function.symbol, function.startOffset, function.endOffset).irBlockBody(
|
||||||
|
function.startOffset,
|
||||||
|
function.endOffset
|
||||||
|
) { bodyGen(function) }
|
||||||
|
}
|
||||||
|
|
||||||
fun IrClass.contributeFunction(descriptor: FunctionDescriptor, ignoreWhenMissing: Boolean = false, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) {
|
fun IrClass.contributeFunction(descriptor: FunctionDescriptor, ignoreWhenMissing: Boolean = false, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) {
|
||||||
val f: IrSimpleFunction = searchForDeclaration(descriptor)
|
val f: IrSimpleFunction = searchForDeclaration(descriptor)
|
||||||
?: (if (ignoreWhenMissing) return else compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner)
|
?: (if (ignoreWhenMissing) return else compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner)
|
||||||
@@ -104,9 +120,9 @@ interface IrBuilderExtension {
|
|||||||
DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
||||||
function.parent = this
|
function.parent = this
|
||||||
|
|
||||||
val f0Type = module.findClassAcrossModuleDependencies(ClassId.topLevel(FUNCTION0_FQ))!!.defaultType
|
val f0Type = compilerContext.irBuiltIns.functionN(0)
|
||||||
val f0ParamSymbol = compilerContext.symbolTable.referenceTypeParameter(f0Type.constructor.parameters[0])
|
val f0ParamSymbol = f0Type.typeParameters[0].symbol
|
||||||
val f0IrType = f0Type.toIrType().substitute(mapOf(f0ParamSymbol to type))
|
val f0IrType = f0Type.defaultType.substitute(mapOf(f0ParamSymbol to type))
|
||||||
|
|
||||||
return IrFunctionExpressionImpl(
|
return IrFunctionExpressionImpl(
|
||||||
startOffset,
|
startOffset,
|
||||||
@@ -123,13 +139,13 @@ interface IrBuilderExtension {
|
|||||||
name: Name,
|
name: Name,
|
||||||
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
||||||
): IrProperty {
|
): IrProperty {
|
||||||
val lazySafeModeClassDescriptor = compilerContext.referenceClass(LAZY_MODE_FQ)!!.descriptor
|
val lazySafeModeClassDescriptor = compilerContext.referenceClass(ClassId.topLevel(LAZY_MODE_FQ))!!.owner
|
||||||
val lazyFunctionSymbol = compilerContext.referenceFunctions(LAZY_FUNC_FQ).single {
|
val lazyFunctionSymbol = compilerContext.referenceFunctions(CallableId(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, Name.identifier("lazy"))).single {
|
||||||
it.descriptor.valueParameters.size == 2 && it.descriptor.valueParameters[0].type == lazySafeModeClassDescriptor.defaultType
|
it.descriptor.valueParameters.size == 2 && it.descriptor.valueParameters[0].type == lazySafeModeClassDescriptor.defaultType
|
||||||
}
|
}
|
||||||
val publicationEntryDescriptor = lazySafeModeClassDescriptor.enumEntries().single { it.name == LAZY_PUBLICATION_MODE_NAME }
|
val publicationEntryDescriptor = lazySafeModeClassDescriptor.enumEntries().single { it.name == LAZY_PUBLICATION_MODE_NAME }
|
||||||
|
|
||||||
val lazyIrClass = compilerContext.referenceClass(LAZY_FQ)!!.owner
|
val lazyIrClass = compilerContext.referenceClass(ClassId.topLevel(LAZY_FQ))!!.owner
|
||||||
val lazyIrType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType))
|
val lazyIrType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType))
|
||||||
|
|
||||||
val propertyDescriptor =
|
val propertyDescriptor =
|
||||||
@@ -146,8 +162,8 @@ interface IrBuilderExtension {
|
|||||||
val enumElement = IrGetEnumValueImpl(
|
val enumElement = IrGetEnumValueImpl(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
publicationEntryDescriptor.classValueType!!.toIrType(),
|
lazySafeModeClassDescriptor.defaultType,
|
||||||
compilerContext.symbolTable.referenceEnumEntry(publicationEntryDescriptor)
|
publicationEntryDescriptor.symbol
|
||||||
)
|
)
|
||||||
|
|
||||||
val lambdaExpression = containingClass.createLambdaExpression(targetIrType, initializerBuilder)
|
val lambdaExpression = containingClass.createLambdaExpression(targetIrType, initializerBuilder)
|
||||||
@@ -191,7 +207,7 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrBlockBodyBuilder.getLazyValueExpression(thisParam: IrValueParameter, property: IrProperty, type: IrType): IrExpression {
|
fun IrBlockBodyBuilder.getLazyValueExpression(thisParam: IrValueParameter, property: IrProperty, type: IrType): IrExpression {
|
||||||
val lazyIrClass = compilerContext.referenceClass(LAZY_FQ)!!.owner
|
val lazyIrClass = compilerContext.referenceClass(ClassId.topLevel(LAZY_FQ))!!.owner
|
||||||
val valueGetter = lazyIrClass.getPropertyGetter("value")!!
|
val valueGetter = lazyIrClass.getPropertyGetter("value")!!
|
||||||
|
|
||||||
val propertyGetter = property.getter!!
|
val propertyGetter = property.getter!!
|
||||||
@@ -245,16 +261,6 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ClassDescriptor.referenceFunctionSymbol(
|
|
||||||
functionName: String,
|
|
||||||
predicate: (IrSimpleFunction) -> Boolean = { true }
|
|
||||||
): IrFunctionSymbol {
|
|
||||||
val irClass = compilerContext.referenceClass(fqNameSafe)?.owner ?: error("Couldn't load class $this")
|
|
||||||
val simpleFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
|
|
||||||
|
|
||||||
return simpleFunctions.filter { it.name.asString() == functionName }.single { predicate(it) }.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.createPrimitiveArrayOfExpression(
|
fun IrBuilderWithScope.createPrimitiveArrayOfExpression(
|
||||||
elementPrimitiveType: IrType,
|
elementPrimitiveType: IrType,
|
||||||
arrayElements: List<IrExpression>
|
arrayElements: List<IrExpression>
|
||||||
@@ -270,18 +276,10 @@ interface IrBuilderExtension {
|
|||||||
|
|
||||||
fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression {
|
fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression {
|
||||||
val classFqName = (lhs.type as IrSimpleType).classOrNull!!.owner.fqNameWhenAvailable!!
|
val classFqName = (lhs.type as IrSimpleType).classOrNull!!.owner.fqNameWhenAvailable!!
|
||||||
val symbol = compilerContext.referenceFunctions(classFqName.child(name)).single()
|
val symbol = compilerContext.referenceFunctions(CallableId(ClassId.topLevel(classFqName), name)).single()
|
||||||
return irInvoke(lhs, symbol, rhs)
|
return irInvoke(lhs, symbol, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.irGetObject(classDescriptor: ClassDescriptor) =
|
|
||||||
IrGetObjectValueImpl(
|
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
classDescriptor.defaultType.toIrType(),
|
|
||||||
compilerContext.symbolTable.referenceClass(classDescriptor)
|
|
||||||
)
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irGetObject(irObject: IrClass) =
|
fun IrBuilderWithScope.irGetObject(irObject: IrClass) =
|
||||||
IrGetObjectValueImpl(
|
IrGetObjectValueImpl(
|
||||||
startOffset,
|
startOffset,
|
||||||
@@ -297,14 +295,6 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.irEmptyVararg(forValueParameter: ValueParameterDescriptor) =
|
|
||||||
IrVarargImpl(
|
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
forValueParameter.type.toIrType(),
|
|
||||||
forValueParameter.varargElementType!!.toIrType()
|
|
||||||
)
|
|
||||||
|
|
||||||
class BranchBuilder(
|
class BranchBuilder(
|
||||||
val irWhen: IrWhen,
|
val irWhen: IrWhen,
|
||||||
context: IrGeneratorContext,
|
context: IrGeneratorContext,
|
||||||
@@ -330,10 +320,12 @@ interface IrBuilderExtension {
|
|||||||
result
|
result
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Deprecated("", level = DeprecationLevel.ERROR)
|
||||||
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
|
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
|
||||||
|
|
||||||
// note: this method should be used only for properties from current module. Fields from other modules are private and inaccessible.
|
// note: this method should be used only for properties from current module. Fields from other modules are private and inaccessible.
|
||||||
val SerializableProperty.irField: IrField? get() = compilerContext.symbolTable.referenceField(this.descriptor).let { if (it.isBound) it.owner else null }
|
val IrSerializableProperty.irField: IrField?
|
||||||
|
get() = this.descriptor.backingField
|
||||||
|
|
||||||
fun IrClass.searchForProperty(descriptor: PropertyDescriptor): IrProperty {
|
fun IrClass.searchForProperty(descriptor: PropertyDescriptor): IrProperty {
|
||||||
// this API is used to reference both current module descriptors and external ones (because serializable class can be in any of them),
|
// this API is used to reference both current module descriptors and external ones (because serializable class can be in any of them),
|
||||||
@@ -341,13 +333,11 @@ interface IrBuilderExtension {
|
|||||||
return searchForDeclaration(descriptor) ?: if (descriptor.module == compilerContext.moduleDescriptor) {
|
return searchForDeclaration(descriptor) ?: if (descriptor.module == compilerContext.moduleDescriptor) {
|
||||||
compilerContext.symbolTable.referenceProperty(descriptor).owner
|
compilerContext.symbolTable.referenceProperty(descriptor).owner
|
||||||
} else {
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
compilerContext.referenceProperties(descriptor.fqNameSafe).single().owner
|
compilerContext.referenceProperties(descriptor.fqNameSafe).single().owner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SerializableProperty.getIrPropertyFrom(thisClass: IrClass): IrProperty {
|
|
||||||
return thisClass.searchForProperty(descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -356,37 +346,40 @@ interface IrBuilderExtension {
|
|||||||
*/
|
*/
|
||||||
fun IrBuilderWithScope.createPropertyByParamReplacer(
|
fun IrBuilderWithScope.createPropertyByParamReplacer(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
serialProperties: List<SerializableProperty>,
|
serialProperties: List<IrSerializableProperty>,
|
||||||
instance: IrValueParameter,
|
instance: IrValueParameter,
|
||||||
bindingContext: BindingContext
|
bindingContext: BindingContext?
|
||||||
): (ValueParameterDescriptor) -> IrExpression? {
|
): (ValueParameterDescriptor) -> IrExpression? {
|
||||||
fun SerializableProperty.irGet(): IrExpression {
|
fun IrSerializableProperty.irGet(): IrExpression {
|
||||||
val ownerType = instance.symbol.owner.type
|
val ownerType = instance.symbol.owner.type
|
||||||
return getProperty(
|
return getProperty(
|
||||||
irGet(
|
irGet(
|
||||||
type = ownerType,
|
type = ownerType,
|
||||||
variable = instance.symbol
|
variable = instance.symbol
|
||||||
), getIrPropertyFrom(irClass)
|
), descriptor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val serialPropertiesMap = serialProperties.associateBy { it.descriptor }
|
val serialPropertiesMap = serialProperties.associateBy { it.descriptor }
|
||||||
|
|
||||||
val transientPropertiesMap =
|
val transientPropertiesSet =
|
||||||
irClass.declarations.asSequence()
|
irClass.declarations.asSequence()
|
||||||
.filterIsInstance<IrProperty>()
|
.filterIsInstance<IrProperty>()
|
||||||
.filter { it.backingField != null }.filter { !serialPropertiesMap.containsKey(it.descriptor) }
|
.filter { it.backingField != null }
|
||||||
.associateBy { it.symbol.descriptor }
|
.filter { !serialPropertiesMap.containsKey(it) }
|
||||||
|
.toSet()
|
||||||
|
|
||||||
return {
|
return { vpd ->
|
||||||
val propertyDescriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, it]
|
val propertyDescriptor = irClass.properties.find { it.name == vpd.name }
|
||||||
if (propertyDescriptor != null) {
|
if (propertyDescriptor != null) {
|
||||||
val value = serialPropertiesMap[propertyDescriptor]
|
val value = serialPropertiesMap[propertyDescriptor]
|
||||||
value?.irGet() ?: transientPropertiesMap[propertyDescriptor]?.let { prop ->
|
value?.irGet() ?: run {
|
||||||
getProperty(
|
if (propertyDescriptor in transientPropertiesSet)
|
||||||
irGet(instance),
|
getProperty(
|
||||||
prop
|
irGet(instance),
|
||||||
)
|
propertyDescriptor
|
||||||
|
)
|
||||||
|
else null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@@ -428,7 +421,7 @@ interface IrBuilderExtension {
|
|||||||
|
|
||||||
fun IrBlockBodyBuilder.generateGoldenMaskCheck(
|
fun IrBlockBodyBuilder.generateGoldenMaskCheck(
|
||||||
seenVars: List<IrValueDeclaration>,
|
seenVars: List<IrValueDeclaration>,
|
||||||
properties: SerializableProperties,
|
properties: IrSerializableProperties,
|
||||||
serialDescriptor: IrExpression
|
serialDescriptor: IrExpression
|
||||||
) {
|
) {
|
||||||
val fieldsMissedTest: IrExpression
|
val fieldsMissedTest: IrExpression
|
||||||
@@ -539,6 +532,7 @@ interface IrBuilderExtension {
|
|||||||
|
|
||||||
val field = with(propertyDescriptor) {
|
val field = with(propertyDescriptor) {
|
||||||
// TODO: type parameters
|
// TODO: type parameters
|
||||||
|
@Suppress("DEPRECATION_ERROR") // should be called only with old FE
|
||||||
originProperty.factory.createField(
|
originProperty.factory.createField(
|
||||||
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(),
|
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(),
|
||||||
visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null
|
visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null
|
||||||
@@ -564,6 +558,7 @@ interface IrBuilderExtension {
|
|||||||
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
|
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
|
||||||
} ?: run {
|
} ?: run {
|
||||||
with(descriptor) {
|
with(descriptor) {
|
||||||
|
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend
|
||||||
property.factory.createFunction(
|
property.factory.createFunction(
|
||||||
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
|
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
|
||||||
name, visibility, modality, returnType!!.toIrType(),
|
name, visibility, modality, returnType!!.toIrType(),
|
||||||
@@ -572,6 +567,7 @@ interface IrBuilderExtension {
|
|||||||
}.also { f ->
|
}.also { f ->
|
||||||
generateOverriddenFunctionSymbols(f, compilerContext.symbolTable)
|
generateOverriddenFunctionSymbols(f, compilerContext.symbolTable)
|
||||||
f.createParameterDeclarations(descriptor)
|
f.createParameterDeclarations(descriptor)
|
||||||
|
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend
|
||||||
f.returnType = descriptor.returnType!!.toIrType()
|
f.returnType = descriptor.returnType!!.toIrType()
|
||||||
f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol
|
f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol
|
||||||
}
|
}
|
||||||
@@ -601,7 +597,7 @@ interface IrBuilderExtension {
|
|||||||
|
|
||||||
val receiver = generateReceiverExpressionForFieldAccess(irAccessor.dispatchReceiverParameter!!.symbol, property)
|
val receiver = generateReceiverExpressionForFieldAccess(irAccessor.dispatchReceiverParameter!!.symbol, property)
|
||||||
|
|
||||||
val propertyIrType = property.type.toIrType()
|
val propertyIrType = irAccessor.returnType
|
||||||
irBody.statements.add(
|
irBody.statements.add(
|
||||||
IrReturnImpl(
|
IrReturnImpl(
|
||||||
startOffset, endOffset, compilerContext.irBuiltIns.nothingType,
|
startOffset, endOffset, compilerContext.irBuiltIns.nothingType,
|
||||||
@@ -644,7 +640,7 @@ interface IrBuilderExtension {
|
|||||||
return irBody
|
return irBody
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateReceiverExpressionForFieldAccess(
|
fun generateReceiverExpressionForFieldAccess( // todo: remove this
|
||||||
ownerSymbol: IrValueSymbol,
|
ownerSymbol: IrValueSymbol,
|
||||||
property: PropertyDescriptor
|
property: PropertyDescriptor
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
@@ -666,6 +662,7 @@ interface IrBuilderExtension {
|
|||||||
) {
|
) {
|
||||||
val function = this
|
val function = this
|
||||||
fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
|
fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
|
||||||
|
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend
|
||||||
factory.createValueParameter(
|
factory.createValueParameter(
|
||||||
function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this),
|
function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this),
|
||||||
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline,
|
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline,
|
||||||
@@ -700,7 +697,7 @@ interface IrBuilderExtension {
|
|||||||
typeParameter.parent = this
|
typeParameter.parent = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend
|
||||||
newTypeParameters.forEach { typeParameter ->
|
newTypeParameters.forEach { typeParameter ->
|
||||||
typeParameter.superTypes = typeParameter.descriptor.upperBounds.map { it.toIrType() }
|
typeParameter.superTypes = typeParameter.descriptor.upperBounds.map { it.toIrType() }
|
||||||
}
|
}
|
||||||
@@ -708,27 +705,13 @@ interface IrBuilderExtension {
|
|||||||
typeParameters = newTypeParameters
|
typeParameters = newTypeParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createClassReference(classType: KotlinType, startOffset: Int, endOffset: Int): IrClassReference {
|
fun createClassReference(classType: IrType, startOffset: Int, endOffset: Int): IrClassReference {
|
||||||
val clazz = classType.toClassDescriptor!!
|
|
||||||
val classSymbol = compilerContext.referenceClass(clazz.fqNameSafe) ?: error("Couldn't load class $clazz")
|
|
||||||
return IrClassReferenceImpl(
|
return IrClassReferenceImpl(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
compilerContext.irBuiltIns.kClassClass.starProjectedType,
|
compilerContext.irBuiltIns.kClassClass.starProjectedType,
|
||||||
classSymbol,
|
classType.classifierOrFail,
|
||||||
classType.approximateJvmErasure.toIrType()
|
classType
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createClassReference(irClass: IrClass, startOffset: Int, endOffset: Int): IrClassReference {
|
|
||||||
val classType = irClass.descriptor.toSimpleType(false)
|
|
||||||
val classSymbol = irClass.symbol
|
|
||||||
return IrClassReferenceImpl(
|
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
compilerContext.irBuiltIns.kClassClass.starProjectedType,
|
|
||||||
classSymbol,
|
|
||||||
classType.approximateJvmErasure.toIrType()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,7 +738,9 @@ interface IrBuilderExtension {
|
|||||||
else -> error("Unsupported classifier: $this")
|
else -> error("Unsupported classifier: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.classReference(classType: KotlinType): IrClassReference = createClassReference(classType, startOffset, endOffset)
|
|
||||||
|
fun IrBuilderWithScope.classReference(classSymbol: IrType): IrClassReference =
|
||||||
|
createClassReference(classSymbol, startOffset, endOffset)
|
||||||
|
|
||||||
private fun extractDefaultValuesFromConstructor(irClass: IrClass?): Map<ParameterDescriptor, IrExpression?> {
|
private fun extractDefaultValuesFromConstructor(irClass: IrClass?): Map<ParameterDescriptor, IrExpression?> {
|
||||||
if (irClass == null) return emptyMap()
|
if (irClass == null) return emptyMap()
|
||||||
@@ -808,15 +793,6 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findEnumValuesMethod(enumClass: ClassDescriptor): IrFunction {
|
|
||||||
assert(enumClass.kind == ClassKind.ENUM_CLASS)
|
|
||||||
return compilerContext.referenceClass(enumClass.fqNameSafe)?.let {
|
|
||||||
it.owner.functions.singleOrNull { f ->
|
|
||||||
f.name == Name.identifier("values") && f.valueParameters.isEmpty() && f.extensionReceiverParameter == null
|
|
||||||
} ?: throw AssertionError("Enum class does not have single .values() function")
|
|
||||||
} ?: error("Couldn't load class $enumClass")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getEnumMembersNames(enumClass: ClassDescriptor): Sequence<String> {
|
private fun getEnumMembersNames(enumClass: ClassDescriptor): Sequence<String> {
|
||||||
assert(enumClass.kind == ClassKind.ENUM_CLASS)
|
assert(enumClass.kind == ClassKind.ENUM_CLASS)
|
||||||
return enumClass.unsubstitutedMemberScope.getContributedDescriptors().asSequence()
|
return enumClass.unsubstitutedMemberScope.getContributedDescriptors().asSequence()
|
||||||
@@ -850,21 +826,20 @@ interface IrBuilderExtension {
|
|||||||
fun IrBuilderWithScope.serializerTower(
|
fun IrBuilderWithScope.serializerTower(
|
||||||
generator: SerializerIrGenerator,
|
generator: SerializerIrGenerator,
|
||||||
dispatchReceiverParameter: IrValueParameter,
|
dispatchReceiverParameter: IrValueParameter,
|
||||||
property: SerializableProperty
|
property: IrSerializableProperty
|
||||||
): IrExpression? {
|
): IrExpression? {
|
||||||
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableExt).single()
|
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableCallableId).single()
|
||||||
val serializer =
|
val serializer =
|
||||||
property.serializableWith?.toClassDescriptor
|
property.serializableWith?.classOrNull
|
||||||
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
|
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
|
||||||
property.module,
|
compilerContext,
|
||||||
property.type,
|
property.type
|
||||||
property.descriptor.findPsi()
|
|
||||||
) else null
|
) else null
|
||||||
return serializerInstance(
|
return serializerInstance(
|
||||||
generator,
|
generator,
|
||||||
dispatchReceiverParameter,
|
dispatchReceiverParameter,
|
||||||
serializer,
|
serializer,
|
||||||
property.module,
|
compilerContext,
|
||||||
property.type,
|
property.type,
|
||||||
genericIndex = property.genericIndex
|
genericIndex = property.genericIndex
|
||||||
)
|
)
|
||||||
@@ -872,12 +847,12 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.wrapWithNullableSerializerIfNeeded(
|
private fun IrBuilderWithScope.wrapWithNullableSerializerIfNeeded(
|
||||||
type: KotlinType,
|
type: IrType,
|
||||||
expression: IrExpression,
|
expression: IrExpression,
|
||||||
nullableProp: IrPropertySymbol
|
nullableProp: IrPropertySymbol
|
||||||
): IrExpression = if (type.isMarkedNullable) {
|
): IrExpression = if (type.isMarkedNullable()) {
|
||||||
val resultType = type.makeNotNullable()
|
val resultType = type.makeNotNull()
|
||||||
val typeArguments = listOf(resultType.toIrType())
|
val typeArguments = listOf(resultType)
|
||||||
val callee = nullableProp.owner.getter!!
|
val callee = nullableProp.owner.getter!!
|
||||||
|
|
||||||
val returnType = callee.returnType.substitute(callee.typeParameters, typeArguments)
|
val returnType = callee.returnType.substitute(callee.typeParameters, typeArguments)
|
||||||
@@ -892,10 +867,19 @@ interface IrBuilderExtension {
|
|||||||
expression
|
expression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private fun IrBuilderWithScope.wrapWithNullableSerializerIfNeeded(
|
||||||
|
// type: KotlinType,
|
||||||
|
// expression: IrExpression,
|
||||||
|
// nullableProp: IrPropertySymbol
|
||||||
|
// ): IrExpression = wrapWithNullableSerializerIfNeeded(type.toIrType(), expression, nullableProp)
|
||||||
|
|
||||||
fun wrapIrTypeIntoKSerializerIrType(module: ModuleDescriptor, type: IrType, variance: Variance = Variance.INVARIANT): IrType {
|
|
||||||
val serializerFqn = getSerializationPackageFqn(SerialEntityNames.KSERIALIZER_CLASS)
|
fun wrapIrTypeIntoKSerializerIrType(
|
||||||
val kSerClass = compilerContext.referenceClass(serializerFqn) ?: error("Couldn't find class $serializerFqn")
|
type: IrType,
|
||||||
|
variance: Variance = Variance.INVARIANT
|
||||||
|
): IrType {
|
||||||
|
val kSerClass = compilerContext.referenceClass(ClassId(SerializationPackages.packageFqName, SerialEntityNames.KSERIALIZER_NAME))
|
||||||
|
?: error("Couldn't find class ${SerialEntityNames.KSERIALIZER_NAME}")
|
||||||
return IrSimpleTypeImpl(
|
return IrSimpleTypeImpl(
|
||||||
kSerClass, hasQuestionMark = false, arguments = listOf(
|
kSerClass, hasQuestionMark = false, arguments = listOf(
|
||||||
makeTypeProjection(type, variance)
|
makeTypeProjection(type, variance)
|
||||||
@@ -906,14 +890,14 @@ interface IrBuilderExtension {
|
|||||||
fun IrBuilderWithScope.serializerInstance(
|
fun IrBuilderWithScope.serializerInstance(
|
||||||
enclosingGenerator: SerializerIrGenerator,
|
enclosingGenerator: SerializerIrGenerator,
|
||||||
dispatchReceiverParameter: IrValueParameter,
|
dispatchReceiverParameter: IrValueParameter,
|
||||||
serializerClassOriginal: ClassDescriptor?,
|
serializerClassOriginal: IrClassSymbol?,
|
||||||
module: ModuleDescriptor,
|
pluginContext: SerializationPluginContext,
|
||||||
kType: KotlinType,
|
kType: IrType,
|
||||||
genericIndex: Int? = null
|
genericIndex: Int? = null
|
||||||
): IrExpression? = serializerInstance(
|
): IrExpression? = serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
serializerClassOriginal,
|
serializerClassOriginal,
|
||||||
module,
|
pluginContext,
|
||||||
kType,
|
kType,
|
||||||
genericIndex
|
genericIndex
|
||||||
) { it, _ ->
|
) { it, _ ->
|
||||||
@@ -925,23 +909,41 @@ interface IrBuilderExtension {
|
|||||||
enclosingGenerator: AbstractSerialGenerator,
|
enclosingGenerator: AbstractSerialGenerator,
|
||||||
serializerClassOriginal: ClassDescriptor?,
|
serializerClassOriginal: ClassDescriptor?,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
kType: KotlinType,
|
kType: IrType,
|
||||||
genericIndex: Int? = null,
|
genericIndex: Int? = null,
|
||||||
genericGetter: ((Int, KotlinType) -> IrExpression)? = null
|
genericGetter: ((Int) -> IrExpression)? = null
|
||||||
): IrExpression? {
|
): IrExpression? {
|
||||||
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableExt).single()
|
return serializerInstance(
|
||||||
|
enclosingGenerator,
|
||||||
|
serializerClassOriginal?.let { compilerContext.symbolTable.referenceClass(it) },
|
||||||
|
compilerContext,
|
||||||
|
kType,
|
||||||
|
genericIndex,
|
||||||
|
if (genericGetter != null) { i, _ -> genericGetter(i) } else null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.serializerInstance(
|
||||||
|
enclosingGenerator: AbstractSerialGenerator,
|
||||||
|
serializerClassOriginal: IrClassSymbol?,
|
||||||
|
pluginContext: SerializationPluginContext,
|
||||||
|
kType: IrType,
|
||||||
|
genericIndex: Int? = null,
|
||||||
|
genericGetter: ((Int, IrType) -> IrExpression)? = null
|
||||||
|
): IrExpression? {
|
||||||
|
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableCallableId).single()
|
||||||
if (serializerClassOriginal == null) {
|
if (serializerClassOriginal == null) {
|
||||||
if (genericIndex == null) return null
|
if (genericIndex == null) return null
|
||||||
return genericGetter?.invoke(genericIndex, kType)
|
return genericGetter?.invoke(genericIndex, kType)
|
||||||
}
|
}
|
||||||
if (serializerClassOriginal.kind == ClassKind.OBJECT) {
|
if (serializerClassOriginal.owner.kind == ClassKind.OBJECT) {
|
||||||
return irGetObject(serializerClassOriginal)
|
return irGetObject(serializerClassOriginal)
|
||||||
}
|
}
|
||||||
fun instantiate(serializer: ClassDescriptor?, type: KotlinType): IrExpression? {
|
fun instantiate(serializer: IrClassSymbol?, type: IrType): IrExpression? {
|
||||||
val expr = serializerInstance(
|
val expr = serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
serializer,
|
serializer,
|
||||||
module,
|
pluginContext,
|
||||||
type,
|
type,
|
||||||
type.genericIndex,
|
type.genericIndex,
|
||||||
genericGetter
|
genericGetter
|
||||||
@@ -951,11 +953,11 @@ interface IrBuilderExtension {
|
|||||||
|
|
||||||
var serializerClass = serializerClassOriginal
|
var serializerClass = serializerClassOriginal
|
||||||
var args: List<IrExpression>
|
var args: List<IrExpression>
|
||||||
var typeArgs: List<IrType?>
|
var typeArgs: List<IrType>
|
||||||
val thisIrType = kType.toIrType()
|
val thisIrType = (kType as? IrSimpleType) ?: error("Don't know how to work with type ${kType::class}")
|
||||||
var needToCopyAnnotations = false
|
var needToCopyAnnotations = false
|
||||||
|
|
||||||
when (serializerClassOriginal.classId) {
|
when (serializerClassOriginal.owner.classId) {
|
||||||
polymorphicSerializerId -> {
|
polymorphicSerializerId -> {
|
||||||
needToCopyAnnotations = true
|
needToCopyAnnotations = true
|
||||||
args = listOf(classReference(kType))
|
args = listOf(classReference(kType))
|
||||||
@@ -965,29 +967,26 @@ interface IrBuilderExtension {
|
|||||||
args = listOf(classReference(kType))
|
args = listOf(classReference(kType))
|
||||||
typeArgs = listOf(thisIrType)
|
typeArgs = listOf(thisIrType)
|
||||||
|
|
||||||
val hasNewCtxSerCtor =
|
val hasNewCtxSerCtor = compilerContext.referenceConstructors(contextSerializerId).any { it.owner.valueParameters.size == 3 }
|
||||||
serializerClassOriginal.classId == contextSerializerId && compilerContext.referenceConstructors(serializerClass.fqNameSafe)
|
|
||||||
.any { it.owner.valueParameters.size == 3 }
|
|
||||||
|
|
||||||
if (hasNewCtxSerCtor) {
|
if (hasNewCtxSerCtor) {
|
||||||
// new signature of context serializer
|
// new signature of context serializer
|
||||||
args = args + mutableListOf<IrExpression>().apply {
|
args = args + mutableListOf<IrExpression>().apply {
|
||||||
val fallbackDefaultSerializer = findTypeSerializer(module, kType)
|
val fallbackDefaultSerializer = findTypeSerializer(pluginContext, kType)
|
||||||
add(instantiate(fallbackDefaultSerializer, kType) ?: irNull())
|
add(instantiate(fallbackDefaultSerializer, kType) ?: irNull())
|
||||||
add(
|
add(
|
||||||
createArrayOfExpression(
|
createArrayOfExpression(
|
||||||
wrapIrTypeIntoKSerializerIrType(
|
wrapIrTypeIntoKSerializerIrType(
|
||||||
module,
|
|
||||||
thisIrType,
|
thisIrType,
|
||||||
variance = Variance.OUT_VARIANCE
|
variance = Variance.OUT_VARIANCE
|
||||||
),
|
),
|
||||||
kType.arguments.map {
|
thisIrType.arguments.map {
|
||||||
val argSer = enclosingGenerator.findTypeSerializerOrContext(
|
val argSer = enclosingGenerator.findTypeSerializerOrContext(
|
||||||
module,
|
compilerContext,
|
||||||
it.type,
|
it.typeOrNull!!, //todo: handle star projections here
|
||||||
sourceElement = serializerClassOriginal.findPsi()
|
sourceElement = serializerClassOriginal.owner.sourceElement()?.psi
|
||||||
)
|
)
|
||||||
instantiate(argSer, it.type)!!
|
instantiate(argSer, it.typeOrNull!!)!!
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -995,7 +994,7 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
objectSerializerId -> {
|
objectSerializerId -> {
|
||||||
needToCopyAnnotations = true
|
needToCopyAnnotations = true
|
||||||
args = listOf(irString(kType.serialName()), irGetObject(kType.toClassDescriptor!!))
|
args = listOf(irString(kType.serialName()), irGetObject(kType.classOrNull!!))
|
||||||
typeArgs = listOf(thisIrType)
|
typeArgs = listOf(thisIrType)
|
||||||
}
|
}
|
||||||
sealedSerializerId -> {
|
sealedSerializerId -> {
|
||||||
@@ -1004,8 +1003,8 @@ interface IrBuilderExtension {
|
|||||||
add(irString(kType.serialName()))
|
add(irString(kType.serialName()))
|
||||||
add(classReference(kType))
|
add(classReference(kType))
|
||||||
val (subclasses, subSerializers) = enclosingGenerator.allSealedSerializableSubclassesFor(
|
val (subclasses, subSerializers) = enclosingGenerator.allSealedSerializableSubclassesFor(
|
||||||
kType.toClassDescriptor!!,
|
kType.classOrNull!!.owner,
|
||||||
module
|
pluginContext
|
||||||
)
|
)
|
||||||
val projectedOutCurrentKClass =
|
val projectedOutCurrentKClass =
|
||||||
compilerContext.irBuiltIns.kClassClass.typeWithArguments(
|
compilerContext.irBuiltIns.kClassClass.typeWithArguments(
|
||||||
@@ -1019,23 +1018,21 @@ interface IrBuilderExtension {
|
|||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
createArrayOfExpression(
|
createArrayOfExpression(
|
||||||
wrapIrTypeIntoKSerializerIrType(module, thisIrType, variance = Variance.OUT_VARIANCE),
|
wrapIrTypeIntoKSerializerIrType(thisIrType, variance = Variance.OUT_VARIANCE),
|
||||||
subSerializers.mapIndexed { i, serializer ->
|
subSerializers.mapIndexed { i, serializer ->
|
||||||
val type = subclasses[i]
|
val type = subclasses[i]
|
||||||
val expr = serializerInstance(
|
val expr = serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
serializer,
|
serializer,
|
||||||
module,
|
pluginContext,
|
||||||
type,
|
type,
|
||||||
type.genericIndex
|
type.genericIndex
|
||||||
) { _, genericType ->
|
) { _, genericType ->
|
||||||
serializerInstance(
|
serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
module.getClassFromSerializationPackage(
|
pluginContext.referenceClass(polymorphicSerializerId),
|
||||||
SpecialBuiltins.polymorphicSerializer
|
pluginContext,
|
||||||
),
|
(genericType.classifierOrNull as IrTypeParameterSymbol).owner.representativeUpperBound
|
||||||
module,
|
|
||||||
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound
|
|
||||||
)!!
|
)!!
|
||||||
}!!
|
}!!
|
||||||
wrapWithNullableSerializerIfNeeded(type, expr, nullableSerClass)
|
wrapWithNullableSerializerIfNeeded(type, expr, nullableSerClass)
|
||||||
@@ -1046,8 +1043,8 @@ interface IrBuilderExtension {
|
|||||||
typeArgs = listOf(thisIrType)
|
typeArgs = listOf(thisIrType)
|
||||||
}
|
}
|
||||||
enumSerializerId -> {
|
enumSerializerId -> {
|
||||||
serializerClass = module.getClassFromInternalSerializationPackage(SpecialBuiltins.enumSerializer)
|
serializerClass = pluginContext.referenceClass(enumSerializerId)
|
||||||
val enumDescriptor = kType.toClassDescriptor!!
|
val enumDescriptor = kType.classOrNull!!
|
||||||
typeArgs = listOf(thisIrType)
|
typeArgs = listOf(thisIrType)
|
||||||
// instantiate serializer only inside enum Companion
|
// instantiate serializer only inside enum Companion
|
||||||
if (enclosingGenerator !is SerializableCompanionIrGenerator) {
|
if (enclosingGenerator !is SerializableCompanionIrGenerator) {
|
||||||
@@ -1056,21 +1053,22 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val enumArgs = mutableListOf(
|
val enumArgs = mutableListOf(
|
||||||
irString(enumDescriptor.serialName()),
|
irString(thisIrType.serialName()),
|
||||||
irCall(findEnumValuesMethod(enumDescriptor)),
|
irCall(enumDescriptor.owner.findEnumValuesMethod()),
|
||||||
)
|
)
|
||||||
|
|
||||||
val enumSerializerFactoryFunc = enumSerializerFactoryFunc
|
val enumSerializerFactoryFunc = enumSerializerFactoryFunc
|
||||||
val markedEnumSerializerFactoryFunc = markedEnumSerializerFactoryFunc
|
val markedEnumSerializerFactoryFunc = markedEnumSerializerFactoryFunc
|
||||||
if (enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null) {
|
if (enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null) {
|
||||||
// runtime contains enum serializer factory functions
|
// runtime contains enum serializer factory functions
|
||||||
val factoryFunc: IrSimpleFunctionSymbol = if (enumDescriptor.isEnumWithSerialInfoAnnotation()) {
|
val factoryFunc: IrSimpleFunctionSymbol = if (enumDescriptor.owner.isEnumWithSerialInfoAnnotation()) {
|
||||||
// need to store SerialInfo annotation in descriptor
|
// need to store SerialInfo annotation in descriptor
|
||||||
val enumEntries = enumDescriptor.enumEntries()
|
val enumEntries = enumDescriptor.owner.enumEntries()
|
||||||
val entriesNames = enumEntries.map { it.annotations.serialNameValue?.let { n -> irString(n) } ?: irNull() }
|
val entriesNames = enumEntries.map { it.annotations.serialNameValue?.let { n -> irString(n) } ?: irNull() }
|
||||||
val entriesAnnotations = enumEntries.map {
|
val entriesAnnotations = enumEntries.map {
|
||||||
val annotationConstructors = it.annotations.mapNotNull { a ->
|
val annotationConstructors = it.annotations.map { a ->
|
||||||
compilerContext.typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(a)
|
// compilerContext.typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(a)
|
||||||
|
a.deepCopyWithVariables()
|
||||||
}
|
}
|
||||||
val annotationsConstructors = copyAnnotationsFrom(annotationConstructors)
|
val annotationsConstructors = copyAnnotationsFrom(annotationConstructors)
|
||||||
if (annotationsConstructors.isEmpty()) {
|
if (annotationsConstructors.isEmpty()) {
|
||||||
@@ -1100,36 +1098,37 @@ interface IrBuilderExtension {
|
|||||||
else -> {
|
else -> {
|
||||||
args = kType.arguments.map {
|
args = kType.arguments.map {
|
||||||
val argSer = enclosingGenerator.findTypeSerializerOrContext(
|
val argSer = enclosingGenerator.findTypeSerializerOrContext(
|
||||||
module,
|
pluginContext,
|
||||||
it.type,
|
it.typeOrNull!!, // todo: stars
|
||||||
sourceElement = serializerClassOriginal.findPsi()
|
sourceElement = serializerClassOriginal.owner.source.getPsi()
|
||||||
)
|
)
|
||||||
instantiate(argSer, it.type) ?: return null
|
instantiate(argSer, it.typeOrNull!!) ?: return null
|
||||||
}
|
}
|
||||||
typeArgs = kType.arguments.map { it.type.toIrType() }
|
typeArgs = kType.arguments.map { it.typeOrNull!! }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (serializerClassOriginal.classId == referenceArraySerializerId) {
|
if (serializerClassOriginal.owner.classId == referenceArraySerializerId) {
|
||||||
args = listOf(wrapperClassReference(kType.arguments.single().type)) + args
|
args = listOf(wrapperClassReference(kType.arguments.single().typeOrNull!!)) + args
|
||||||
typeArgs = listOf(typeArgs[0].makeNotNull()) + typeArgs
|
typeArgs = listOf(typeArgs[0].makeNotNull()) + typeArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
// If KType is interface, .classSerializer always yields PolymorphicSerializer, which may be unavailable for interfaces from other modules
|
// If KType is interface, .classSerializer always yields PolymorphicSerializer, which may be unavailable for interfaces from other modules
|
||||||
if (!kType.isInterface() && serializerClassOriginal == kType.toClassDescriptor?.classSerializer && enclosingGenerator !is SerializableCompanionIrGenerator) {
|
if (!kType.isInterface() && serializerClassOriginal == kType.classOrNull!!.owner.classSerializer(pluginContext) && enclosingGenerator !is SerializableCompanionIrGenerator) {
|
||||||
// This is default type serializer, we can shortcut through Companion.serializer()
|
// This is default type serializer, we can shortcut through Companion.serializer()
|
||||||
// BUT not during generation of this method itself
|
// BUT not during generation of this method itself
|
||||||
callSerializerFromCompanion(thisIrType, typeArgs, args)?.let { return it }
|
callSerializerFromCompanion(thisIrType, typeArgs, args)?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
|
val serializable = serializerClass?.owner?.let { getSerializableClassDescriptorBySerializer(it) }
|
||||||
val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
|
requireNotNull(serializerClass)
|
||||||
|
val ctor = if (serializable?.typeParameters?.isNotEmpty() == true) {
|
||||||
requireNotNull(
|
requireNotNull(
|
||||||
findSerializerConstructorForTypeArgumentsSerializers(serializerClass)
|
findSerializerConstructorForTypeArgumentsSerializers(serializerClass.owner)
|
||||||
) { "Generated serializer does not have constructor with required number of arguments" }
|
) { "Generated serializer does not have constructor with required number of arguments" }
|
||||||
} else {
|
} else {
|
||||||
val constructors = compilerContext.referenceConstructors(serializerClass.fqNameSafe)
|
val constructors = serializerClass.constructors
|
||||||
// search for new signature of polymorphic/sealed/contextual serializer
|
// search for new signature of polymorphic/sealed/contextual serializer
|
||||||
if (!needToCopyAnnotations) {
|
if (!needToCopyAnnotations) {
|
||||||
constructors.single { it.owner.isPrimary }
|
constructors.single { it.owner.isPrimary }
|
||||||
@@ -1163,7 +1162,8 @@ interface IrBuilderExtension {
|
|||||||
|
|
||||||
fun collectSerialInfoAnnotations(irClass: IrClass): List<IrConstructorCall> {
|
fun collectSerialInfoAnnotations(irClass: IrClass): List<IrConstructorCall> {
|
||||||
if (!(irClass.isInterface || irClass.descriptor.hasSerializableOrMetaAnnotation)) return emptyList()
|
if (!(irClass.isInterface || irClass.descriptor.hasSerializableOrMetaAnnotation)) return emptyList()
|
||||||
val annotationByFq: MutableMap<FqName, IrConstructorCall> = irClass.annotations.associateBy { it.symbol.owner.parentAsClass.descriptor.fqNameSafe }.toMutableMap()
|
val annotationByFq: MutableMap<FqName, IrConstructorCall> =
|
||||||
|
irClass.annotations.associateBy { it.symbol.owner.parentAsClass.descriptor.fqNameSafe }.toMutableMap()
|
||||||
for (clazz in irClass.getAllSuperclasses()) {
|
for (clazz in irClass.getAllSuperclasses()) {
|
||||||
val annotations = clazz.annotations
|
val annotations = clazz.annotations
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
@@ -1195,7 +1195,7 @@ interface IrBuilderExtension {
|
|||||||
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.descriptor.isSealed() || baseClass.descriptor.modality == Modality.ABSTRACT)) {
|
||||||
val serializer = findStandardKotlinTypeSerializer(baseClass.module, context.irBuiltIns.unitType.toKotlinType())!!
|
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) }
|
||||||
} else {
|
} else {
|
||||||
@@ -1219,12 +1219,13 @@ interface IrBuilderExtension {
|
|||||||
return ((lastArgType as? IrSimpleType)?.arguments?.firstOrNull()?.typeOrNull?.classFqName?.toString() == "kotlin.Annotation")
|
return ((lastArgType as? IrSimpleType)?.arguments?.firstOrNull()?.typeOrNull?.classFqName?.toString() == "kotlin.Annotation")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.wrapperClassReference(classType: KotlinType): IrClassReference {
|
private 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"
|
||||||
val wrapperFqName = KotlinBuiltIns.getPrimitiveType(classType)?.let(JvmPrimitiveType::get)?.wrapperFqName
|
// TODO: get rid of descriptor
|
||||||
|
val wrapperFqName = KotlinBuiltIns.getPrimitiveType(classType.classOrNull!!.descriptor)?.let(JvmPrimitiveType::get)?.wrapperFqName
|
||||||
if (wrapperFqName != null) {
|
if (wrapperFqName != null) {
|
||||||
val wrapperClass = compilerContext.moduleDescriptor.findClassAcrossModuleDependencies(ClassId.topLevel(wrapperFqName))
|
val wrapperClass = compilerContext.referenceClass(ClassId.topLevel(wrapperFqName))
|
||||||
?: error("Primitive wrapper class for $classType not found: $wrapperFqName")
|
?: error("Primitive wrapper class for $classType not found: $wrapperFqName")
|
||||||
return classReference(wrapperClass.defaultType)
|
return classReference(wrapperClass.defaultType)
|
||||||
}
|
}
|
||||||
@@ -1232,28 +1233,19 @@ interface IrBuilderExtension {
|
|||||||
return classReference(classType)
|
return classReference(classType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findSerializerConstructorForTypeArgumentsSerializers(serializer: ClassDescriptor): IrConstructorSymbol? {
|
fun findSerializerConstructorForTypeArgumentsSerializers(serializer: IrClass): IrConstructorSymbol? {
|
||||||
val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializer)?.arguments
|
|
||||||
?: throw AssertionError("Serializer does not implement KSerializer??")
|
|
||||||
|
|
||||||
val typeParamsCount = serializableImplementationTypeArguments.size
|
val typeParamsCount = ((serializer.superTypes.find { isKSerializer(it) } as IrSimpleType).arguments.first().typeOrNull!! as IrSimpleType).arguments.size
|
||||||
if (typeParamsCount == 0) return null //don't need it
|
if (typeParamsCount == 0) return null //don't need it
|
||||||
val constructors = compilerContext.referenceConstructors(serializer.fqNameSafe)
|
|
||||||
|
|
||||||
fun isKSerializer(type: IrType): Boolean {
|
return serializer.constructors.singleOrNull {
|
||||||
val simpleType = type as? IrSimpleType ?: return false
|
it.valueParameters.let { vps -> vps.size == typeParamsCount && vps.all { vp -> isKSerializer(vp.type) } }
|
||||||
val classifier = simpleType.classifier as? IrClassSymbol ?: return false
|
}?.symbol
|
||||||
return classifier.owner.fqNameWhenAvailable == SerialEntityNames.KSERIALIZER_NAME_FQ
|
|
||||||
}
|
|
||||||
|
|
||||||
return constructors.singleOrNull {
|
|
||||||
it.owner.valueParameters.let { vps -> vps.size == typeParamsCount && vps.all { vp -> isKSerializer(vp.type) } }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrConstructor.isSerializationCtor(): Boolean {
|
private fun IrConstructor.isSerializationCtor(): Boolean {
|
||||||
val serialMarker =
|
val serialMarker =
|
||||||
compilerContext.referenceClass(SerializationPackages.internalPackageFqName.child(SerialEntityNames.SERIAL_CTOR_MARKER_NAME))
|
compilerContext.referenceClass(ClassId.topLevel(SerializationPackages.internalPackageFqName.child(SerialEntityNames.SERIAL_CTOR_MARKER_NAME)))
|
||||||
|
|
||||||
return valueParameters.lastOrNull()?.run {
|
return valueParameters.lastOrNull()?.run {
|
||||||
name == SerialEntityNames.dummyParamName && type.classifierOrNull == serialMarker
|
name == SerialEntityNames.dummyParamName && type.classifierOrNull == serialMarker
|
||||||
@@ -1279,23 +1271,23 @@ interface IrBuilderExtension {
|
|||||||
fun IrBlockBodyBuilder.serializeAllProperties(
|
fun IrBlockBodyBuilder.serializeAllProperties(
|
||||||
generator: AbstractSerialGenerator,
|
generator: AbstractSerialGenerator,
|
||||||
serializableIrClass: IrClass,
|
serializableIrClass: IrClass,
|
||||||
serializableProperties: List<SerializableProperty>,
|
serializableProperties: List<IrSerializableProperty>,
|
||||||
objectToSerialize: IrValueDeclaration,
|
objectToSerialize: IrValueDeclaration,
|
||||||
localOutput: IrValueDeclaration,
|
localOutput: IrValueDeclaration,
|
||||||
localSerialDesc: IrValueDeclaration,
|
localSerialDesc: IrValueDeclaration,
|
||||||
kOutputClass: ClassDescriptor,
|
kOutputClass: IrClassSymbol,
|
||||||
ignoreIndexTo: Int,
|
ignoreIndexTo: Int,
|
||||||
initializerAdapter: (IrExpressionBody) -> IrExpression,
|
initializerAdapter: (IrExpressionBody) -> IrExpression,
|
||||||
genericGetter: ((Int, KotlinType) -> IrExpression)?
|
genericGetter: ((Int, IrType) -> IrExpression)?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun SerializableProperty.irGet(): IrExpression {
|
fun IrSerializableProperty.irGet(): IrExpression {
|
||||||
val ownerType = objectToSerialize.symbol.owner.type
|
val ownerType = objectToSerialize.symbol.owner.type
|
||||||
return getProperty(
|
return getProperty(
|
||||||
irGet(
|
irGet(
|
||||||
type = ownerType,
|
type = ownerType,
|
||||||
variable = objectToSerialize.symbol
|
variable = objectToSerialize.symbol
|
||||||
), getIrPropertyFrom(serializableIrClass)
|
), descriptor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1307,7 +1299,7 @@ interface IrBuilderExtension {
|
|||||||
irGet(localOutput),
|
irGet(localOutput),
|
||||||
property, { innerSerial, sti ->
|
property, { innerSerial, sti ->
|
||||||
val f =
|
val f =
|
||||||
kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
|
kOutputClass.functionByName("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
|
||||||
f to listOf(
|
f to listOf(
|
||||||
irGet(localSerialDesc),
|
irGet(localSerialDesc),
|
||||||
irInt(index),
|
irInt(index),
|
||||||
@@ -1316,7 +1308,7 @@ interface IrBuilderExtension {
|
|||||||
)
|
)
|
||||||
}, {
|
}, {
|
||||||
val f =
|
val f =
|
||||||
kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
kOutputClass.functionByName("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||||
val args: MutableList<IrExpression> = mutableListOf(irGet(localSerialDesc), irInt(index))
|
val args: MutableList<IrExpression> = mutableListOf(irGet(localSerialDesc), irInt(index))
|
||||||
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
|
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
|
||||||
f to args
|
f to args
|
||||||
@@ -1325,7 +1317,7 @@ interface IrBuilderExtension {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// check for call to .shouldEncodeElementDefault
|
// check for call to .shouldEncodeElementDefault
|
||||||
val encodeDefaults = property.getIrPropertyFrom(serializableIrClass).getEncodeDefaultAnnotationValue()
|
val encodeDefaults = property.descriptor.getEncodeDefaultAnnotationValue()
|
||||||
val field = property.irField // Nullable when property from another module; can't compare it with default value on JS or Native
|
val field = property.irField // Nullable when property from another module; can't compare it with default value on JS or Native
|
||||||
if (!property.optional || encodeDefaults == true || field == null) {
|
if (!property.optional || encodeDefaults == true || field == null) {
|
||||||
// emit call right away
|
// emit call right away
|
||||||
@@ -1340,7 +1332,7 @@ interface IrBuilderExtension {
|
|||||||
// emit check:
|
// emit check:
|
||||||
// if (if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) {
|
// if (if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) {
|
||||||
// output.encodeIntElement(this.descriptor, i, obj.prop)// block {obj.prop != DEFAULT_VALUE} may contain several statements
|
// output.encodeIntElement(this.descriptor, i, obj.prop)// block {obj.prop != DEFAULT_VALUE} may contain several statements
|
||||||
val shouldEncodeFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.shouldEncodeDefault)
|
val shouldEncodeFunc = kOutputClass.functionByName(CallingConventions.shouldEncodeDefault)
|
||||||
val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
|
val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
|
||||||
// Ir infrastructure does not have dedicated symbol for ||, so
|
// Ir infrastructure does not have dedicated symbol for ||, so
|
||||||
// `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror
|
// `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror
|
||||||
@@ -1359,7 +1351,8 @@ interface IrBuilderExtension {
|
|||||||
fun IrProperty.getEncodeDefaultAnnotationValue(): Boolean? {
|
fun IrProperty.getEncodeDefaultAnnotationValue(): Boolean? {
|
||||||
val call = annotations.findAnnotation(SerializationAnnotations.encodeDefaultFqName) ?: return null
|
val call = annotations.findAnnotation(SerializationAnnotations.encodeDefaultFqName) ?: return null
|
||||||
val arg = call.getValueArgument(0) ?: return true // ALWAYS by default
|
val arg = call.getValueArgument(0) ?: return true // ALWAYS by default
|
||||||
val argValue = (arg as? IrGetEnumValue ?: error("Argument of enum constructor expected to implement IrGetEnumValue, got $arg")).symbol.owner.name.toString()
|
val argValue = (arg as? IrGetEnumValue
|
||||||
|
?: error("Argument of enum constructor expected to implement IrGetEnumValue, got $arg")).symbol.owner.name.toString()
|
||||||
return when (argValue) {
|
return when (argValue) {
|
||||||
"ALWAYS" -> true
|
"ALWAYS" -> true
|
||||||
"NEVER" -> false
|
"NEVER" -> false
|
||||||
@@ -1371,23 +1364,23 @@ interface IrBuilderExtension {
|
|||||||
fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
||||||
enclosingGenerator: AbstractSerialGenerator,
|
enclosingGenerator: AbstractSerialGenerator,
|
||||||
encoder: IrExpression,
|
encoder: IrExpression,
|
||||||
property: SerializableProperty,
|
property: IrSerializableProperty,
|
||||||
whenHaveSerializer: (serializer: IrExpression, sti: SerialTypeInfo) -> FunctionWithArgs,
|
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
whenDoNot: (sti: SerialTypeInfo) -> FunctionWithArgs,
|
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
genericGetter: ((Int, KotlinType) -> IrExpression)? = null,
|
genericGetter: ((Int, IrType) -> IrExpression)? = null,
|
||||||
returnTypeHint: IrType? = null
|
returnTypeHint: IrType? = null
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
val sti = enclosingGenerator.getSerialTypeInfo(property)
|
val sti = enclosingGenerator.getIrSerialTypeInfo(property, compilerContext)
|
||||||
val innerSerial = serializerInstance(
|
val innerSerial = serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
sti.serializer,
|
sti.serializer,
|
||||||
property.module,
|
compilerContext,
|
||||||
property.type,
|
property.type,
|
||||||
property.genericIndex,
|
property.genericIndex,
|
||||||
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.toIrType()) else listOf()
|
val typeArgs = if (functionToCall.descriptor.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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.util.constructors
|
|||||||
import org.jetbrains.kotlin.ir.util.createImplicitParameterDeclarationWithWrappedDescriptor
|
import org.jetbrains.kotlin.ir.util.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.kotlinFqName
|
import org.jetbrains.kotlin.ir.util.kotlinFqName
|
||||||
|
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.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -44,7 +45,7 @@ class SerialInfoImplJvmIrGenerator(
|
|||||||
override val compilerContext: SerializationPluginContext
|
override val compilerContext: SerializationPluginContext
|
||||||
get() = context
|
get() = context
|
||||||
|
|
||||||
private val jvmNameClass get() = context.referenceClass(DescriptorUtils.JVM_NAME)!!.owner
|
private val jvmNameClass get() = context.referenceClass(ClassId.topLevel(DescriptorUtils.JVM_NAME))!!.owner
|
||||||
|
|
||||||
private val javaLangClass = createClass(createPackage("java.lang"), "Class", ClassKind.CLASS)
|
private val javaLangClass = createClass(createPackage("java.lang"), "Class", ClassKind.CLASS)
|
||||||
private val javaLangType = javaLangClass.starProjectedType
|
private val javaLangType = javaLangClass.starProjectedType
|
||||||
@@ -54,6 +55,7 @@ class SerialInfoImplJvmIrGenerator(
|
|||||||
|
|
||||||
fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass =
|
fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass =
|
||||||
annotationToImpl.getOrPut(serialInfoAnnotationClass) {
|
annotationToImpl.getOrPut(serialInfoAnnotationClass) {
|
||||||
|
@Suppress("DEPRECATION") // TODO
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-51
@@ -7,58 +7,67 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irInt
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.types.impl.IrErrorClassImpl.endOffset
|
||||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
import org.jetbrains.kotlin.ir.types.impl.IrErrorClassImpl.startOffset
|
||||||
import org.jetbrains.kotlin.ir.util.substitute
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerializableClassByCompanion
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isKSerializer
|
||||||
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.*
|
||||||
|
|
||||||
class SerializableCompanionIrGenerator(
|
class SerializableCompanionIrGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
|
val serializableIrClass: IrClass,
|
||||||
override val compilerContext: SerializationPluginContext,
|
override val compilerContext: SerializationPluginContext,
|
||||||
bindingContext: BindingContext
|
) : SerializableCompanionCodegen(irClass.descriptor, null), IrBuilderExtension {
|
||||||
) : SerializableCompanionCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
|
||||||
|
override fun getSerializerGetterDescriptor(): FunctionDescriptor { // todo: remove .toKotlinType()
|
||||||
|
return irClass.findDeclaration<IrSimpleFunction> {
|
||||||
|
(it.valueParameters.size == serializableDescriptor.declaredTypeParameters.size
|
||||||
|
&& it.valueParameters.all { p -> isKSerializer(p.type.toKotlinType()) }) && isKSerializer(it.returnType.toKotlinType())
|
||||||
|
}?.descriptor ?: throw IllegalStateException(
|
||||||
|
"Can't find synthesized 'Companion.serializer()' function to generate, " +
|
||||||
|
"probably clash with user-defined function has occurred"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun generate(
|
fun generate(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
context: SerializationPluginContext,
|
context: SerializationPluginContext,
|
||||||
bindingContext: BindingContext
|
|
||||||
) {
|
) {
|
||||||
val companionDescriptor = irClass.descriptor
|
val companionDescriptor = irClass.descriptor
|
||||||
val serializableClass = getSerializableClassDescriptorByCompanion(companionDescriptor) ?: return
|
val serializableClass = getSerializableClassDescriptorByCompanion(companionDescriptor) ?: return
|
||||||
if (serializableClass.shouldHaveGeneratedMethodsInCompanion) {
|
if (serializableClass.shouldHaveGeneratedMethodsInCompanion) {
|
||||||
SerializableCompanionIrGenerator(irClass, context, bindingContext).generate()
|
SerializableCompanionIrGenerator(irClass, getSerializableClassByCompanion(irClass)!!, context).generate()
|
||||||
|
val declaration = irClass.constructors.primary // todo: move to appropriate place
|
||||||
|
if (declaration.body == null) declaration.body = context.generateBodyForDefaultConstructor(declaration)
|
||||||
irClass.patchDeclarationParents(irClass.parent)
|
irClass.patchDeclarationParents(irClass.parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.patchSerializableClassWithMarkerAnnotation(serializer: ClassDescriptor) {
|
private fun IrBuilderWithScope.patchSerializableClassWithMarkerAnnotation(serializer: IrClass) {
|
||||||
if (serializer.kind != ClassKind.OBJECT) {
|
if (serializer.kind != ClassKind.OBJECT) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val annotationMarkerClass = serializer.module.findClassAcrossModuleDependencies(
|
val annotationMarkerClass = compilerContext.referenceClass(
|
||||||
ClassId(
|
ClassId(
|
||||||
SerializationPackages.packageFqName,
|
SerializationPackages.packageFqName,
|
||||||
Name.identifier(SerialEntityNames.ANNOTATION_MARKER_CLASS)
|
Name.identifier(SerialEntityNames.ANNOTATION_MARKER_CLASS)
|
||||||
@@ -67,29 +76,18 @@ 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.fqNameSafe
|
it.symbol.descriptor.constructedClass.fqNameSafe == annotationMarkerClass.owner.fqNameWhenAvailable
|
||||||
}
|
}
|
||||||
if (serializableWithAlreadyPresent) return
|
if (serializableWithAlreadyPresent) return
|
||||||
|
|
||||||
val annotationCtor = compilerContext.referenceConstructors(annotationMarkerClass.fqNameSafe).single { it.owner.isPrimary }
|
val annotationCtor = annotationMarkerClass.constructors.single { it.owner.isPrimary }
|
||||||
val annotationType = annotationMarkerClass.defaultType.toIrType()
|
val annotationType = annotationMarkerClass.defaultType
|
||||||
|
|
||||||
val serializerIrClass = if (serializableDescriptor.isInternalSerializable) {
|
|
||||||
// internally generated serializer always declared inside serializable class
|
|
||||||
irSerializableClass.declarations
|
|
||||||
.filterIsInstanceAnd<IrClass> { it.name == serializer.name }
|
|
||||||
.singleOrNull() ?: throw Exception("No class with name ${serializer.fqNameSafe}")
|
|
||||||
} else {
|
|
||||||
// FIXME referenceClass not supports local classes so it should be replaced in future
|
|
||||||
compilerContext.referenceClass(serializer.fqNameSafe)!!.owner
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
|
val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
|
||||||
putValueArgument(
|
putValueArgument(
|
||||||
0,
|
0,
|
||||||
createClassReference(
|
createClassReference(
|
||||||
serializerIrClass,
|
serializer.defaultType,
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset
|
endOffset
|
||||||
)
|
)
|
||||||
@@ -100,24 +98,23 @@ class SerializableCompanionIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
override fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
val serializerDescriptor = requireNotNull(
|
val serializer = requireNotNull(
|
||||||
findTypeSerializer(
|
findTypeSerializer(
|
||||||
serializableDescriptor.module,
|
compilerContext,
|
||||||
serializableDescriptor.toSimpleType()
|
serializableIrClass.defaultType
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val kSerializerIrClass = compilerContext.referenceClass(SerialEntityNames.KSERIALIZER_NAME_FQ)!!.owner
|
val kSerializerIrClass = serializer.owner
|
||||||
val targetIrType =
|
val targetIrType =
|
||||||
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType))
|
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType))
|
||||||
|
|
||||||
val property = createLazyProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
|
val property = createLazyProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
|
||||||
val expr = serializerInstance(
|
val expr = serializerInstance(
|
||||||
this@SerializableCompanionIrGenerator,
|
this@SerializableCompanionIrGenerator,
|
||||||
serializerDescriptor, serializableDescriptor.module,
|
serializer, compilerContext, kSerializerIrClass.defaultType
|
||||||
serializableDescriptor.defaultType
|
|
||||||
)
|
)
|
||||||
patchSerializableClassWithMarkerAnnotation(serializerDescriptor)
|
patchSerializableClassWithMarkerAnnotation(kSerializerIrClass)
|
||||||
+irReturn(requireNotNull(expr))
|
+irReturn(requireNotNull(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,17 +128,17 @@ class SerializableCompanionIrGenerator(
|
|||||||
irClass.contributeFunction(methodDescriptor) { getter ->
|
irClass.contributeFunction(methodDescriptor) { getter ->
|
||||||
val serializer = requireNotNull(
|
val serializer = requireNotNull(
|
||||||
findTypeSerializer(
|
findTypeSerializer(
|
||||||
serializableDescriptor.module,
|
compilerContext,
|
||||||
serializableDescriptor.toSimpleType()
|
serializableIrClass.defaultType
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val args: List<IrExpression> = getter.valueParameters.map { irGet(it) }
|
val args: List<IrExpression> = getter.valueParameters.map { irGet(it) }
|
||||||
val expr = serializerInstance(
|
val expr = serializerInstance(
|
||||||
this@SerializableCompanionIrGenerator,
|
this@SerializableCompanionIrGenerator,
|
||||||
serializer, serializableDescriptor.module,
|
serializer, compilerContext,
|
||||||
serializableDescriptor.defaultType
|
serializableIrClass.defaultType
|
||||||
) { it, _ -> args[it] }
|
) { it, _ -> args[it] }
|
||||||
patchSerializableClassWithMarkerAnnotation(serializer)
|
patchSerializableClassWithMarkerAnnotation(serializer.owner)
|
||||||
+irReturn(requireNotNull(expr))
|
+irReturn(requireNotNull(expr))
|
||||||
}
|
}
|
||||||
generateSerializerFactoryIfNeeded(methodDescriptor)
|
generateSerializerFactoryIfNeeded(methodDescriptor)
|
||||||
@@ -149,16 +146,13 @@ class SerializableCompanionIrGenerator(
|
|||||||
|
|
||||||
private fun generateSerializerFactoryIfNeeded(getterDescriptor: FunctionDescriptor) {
|
private fun generateSerializerFactoryIfNeeded(getterDescriptor: FunctionDescriptor) {
|
||||||
if (!companionDescriptor.needSerializerFactory()) return
|
if (!companionDescriptor.needSerializerFactory()) return
|
||||||
val serialFactoryDescriptor = companionDescriptor.unsubstitutedMemberScope.getContributedFunctions(
|
val serialFactoryDescriptor = irClass.findDeclaration<IrSimpleFunction> {
|
||||||
SerialEntityNames.SERIALIZER_PROVIDER_NAME,
|
|
||||||
NoLookupLocation.FROM_BACKEND
|
|
||||||
).firstOrNull {
|
|
||||||
it.valueParameters.size == 1
|
it.valueParameters.size == 1
|
||||||
&& it.valueParameters.first().isVararg
|
&& it.valueParameters.first().isVararg
|
||||||
&& it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
// && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||||
&& it.returnType != null && isKSerializer(it.returnType)
|
&& isKSerializer(it.returnType)
|
||||||
} ?: return
|
} ?: return
|
||||||
irClass.contributeFunction(serialFactoryDescriptor) { factory ->
|
addFunctionBody(serialFactoryDescriptor) { factory ->
|
||||||
val kSerializerStarType = factory.returnType
|
val kSerializerStarType = factory.returnType
|
||||||
val array = factory.valueParameters.first()
|
val array = factory.valueParameters.first()
|
||||||
val argsSize = serializableDescriptor.declaredTypeParameters.size
|
val argsSize = serializableDescriptor.declaredTypeParameters.size
|
||||||
@@ -177,8 +171,9 @@ class SerializableCompanionIrGenerator(
|
|||||||
returnTypeHint = kSerializerStarType
|
returnTypeHint = kSerializerStarType
|
||||||
)
|
)
|
||||||
+irReturn(call)
|
+irReturn(call)
|
||||||
patchSerializableClassWithMarkerAnnotation(companionDescriptor)
|
patchSerializableClassWithMarkerAnnotation(irClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+91
-63
@@ -5,71 +5,70 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
|
||||||
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.codegen.CompilationException
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
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.expressions.*
|
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
|
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.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
|
||||||
import org.jetbrains.kotlin.ir.types.isString
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
|
||||||
|
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
||||||
import org.jetbrains.kotlin.utils.getOrPutNullable
|
import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isStaticSerializable
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isStaticSerializable
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
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
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.LOAD
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SAVE
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESC_FIELD
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESC_FIELD
|
||||||
|
|
||||||
class SerializableIrGenerator(
|
class SerializableIrGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
override val compilerContext: SerializationPluginContext,
|
override val compilerContext: SerializationPluginContext
|
||||||
bindingContext: BindingContext
|
) : AbstractSerialGenerator(null, irClass.descriptor), IrBuilderExtension {
|
||||||
) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
|
||||||
|
|
||||||
private val serialDescClass: ClassDescriptor = serializableDescriptor.module
|
protected val properties = bindingContext.serializablePropertiesForIrBackend(irClass)
|
||||||
.getClassFromSerializationDescriptorsPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS)
|
|
||||||
|
|
||||||
private val serialDescImplClass: ClassDescriptor = serializableDescriptor
|
private val serialDescriptorClass = compilerContext.referenceClass(
|
||||||
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL)
|
ClassId(
|
||||||
|
SerializationPackages.descriptorsPackageFqName,
|
||||||
|
Name.identifier(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS)
|
||||||
|
)
|
||||||
|
)!!.owner
|
||||||
|
|
||||||
private val addElementFun = serialDescImplClass.referenceFunctionSymbol(CallingConventions.addElement)
|
private val serialDescriptorImplClass = compilerContext.referenceClass(
|
||||||
|
ClassId(
|
||||||
|
SerializationPackages.internalPackageFqName,
|
||||||
|
Name.identifier(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL)
|
||||||
|
)
|
||||||
|
)!!.owner
|
||||||
|
|
||||||
private fun IrClass.hasSerializableOrMetaAnnotationWithoutArgs(): Boolean {
|
private val addElementFun =
|
||||||
val annot = getAnnotation(SerializationAnnotations.serializableAnnotationFqName)
|
serialDescriptorImplClass.findDeclaration<IrFunction> { it.name.toString() == CallingConventions.addElement }!!.symbol
|
||||||
if (annot != null) {
|
|
||||||
for (i in 0 until annot.valueArgumentsCount) {
|
|
||||||
if (annot.getValueArgument(i) != null) return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
val metaAnnotation = annotations
|
|
||||||
.flatMap { it.symbol.owner.constructedClass.annotations }
|
|
||||||
.find { it.isAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName) }
|
|
||||||
return metaAnnotation != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private val IrClass.isInternalSerializable: Boolean get() = kind == ClassKind.CLASS && hasSerializableOrMetaAnnotationWithoutArgs()
|
private val IrClass.isInternalSerializable: Boolean get() = kind == ClassKind.CLASS && hasSerializableOrMetaAnnotationWithoutArgs()
|
||||||
|
|
||||||
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) =
|
fun generateInternalConstructor(constructorDescriptor: IrConstructor) =
|
||||||
irClass.contributeConstructor(constructorDescriptor) { ctor ->
|
addFunctionBody(constructorDescriptor) { ctor ->
|
||||||
val thiz = irClass.thisReceiver!!
|
val thiz = irClass.thisReceiver!!
|
||||||
val serializableProperties = properties.serializableProperties
|
val serializableProperties = properties.serializableProperties
|
||||||
|
|
||||||
@@ -81,14 +80,14 @@ class SerializableIrGenerator(
|
|||||||
val initializerAdapter: (IrExpressionBody) -> IrExpression = createInitializerAdapter(irClass, propertyByParamReplacer)
|
val initializerAdapter: (IrExpressionBody) -> IrExpression = createInitializerAdapter(irClass, propertyByParamReplacer)
|
||||||
|
|
||||||
|
|
||||||
var current: PropertyDescriptor? = null
|
var current: IrProperty? = null
|
||||||
val statementsAfterSerializableProperty: MutableMap<PropertyDescriptor?, MutableList<IrStatement>> = mutableMapOf()
|
val statementsAfterSerializableProperty: MutableMap<IrProperty?, MutableList<IrStatement>> = mutableMapOf()
|
||||||
irClass.declarations.asSequence().forEach {
|
irClass.declarations.asSequence().forEach {
|
||||||
when {
|
when {
|
||||||
// only properties with backing field
|
// only properties with backing field
|
||||||
it is IrProperty && it.backingField != null -> {
|
it is IrProperty && it.backingField != null -> {
|
||||||
if (it.descriptor in serialDescs) {
|
if (it in serialDescs) {
|
||||||
current = it.descriptor
|
current = it
|
||||||
} else if (it.backingField?.initializer != null) {
|
} else if (it.backingField?.initializer != null) {
|
||||||
// skip transient lateinit or deferred properties (with null initializer)
|
// skip transient lateinit or deferred properties (with null initializer)
|
||||||
val expression = initializerAdapter(it.backingField!!.initializer!!)
|
val expression = initializerAdapter(it.backingField!!.initializer!!)
|
||||||
@@ -121,9 +120,9 @@ class SerializableIrGenerator(
|
|||||||
|
|
||||||
if (useFieldMissingOptimization() &&
|
if (useFieldMissingOptimization() &&
|
||||||
// for abstract classes fields MUST BE checked in child classes
|
// for abstract classes fields MUST BE checked in child classes
|
||||||
!serializableDescriptor.isAbstractOrSealedSerializableClass()
|
!irClass.isAbstractOrSealedSerializableClass
|
||||||
) {
|
) {
|
||||||
val getDescriptorExpr = if (serializableDescriptor.isStaticSerializable) {
|
val getDescriptorExpr = if (irClass.isStaticSerializable) {
|
||||||
getStaticSerialDescriptorExpr()
|
getStaticSerialDescriptorExpr()
|
||||||
} else {
|
} else {
|
||||||
// synthetic constructor is created only for internally serializable classes - so companion definitely exists
|
// synthetic constructor is created only for internally serializable classes - so companion definitely exists
|
||||||
@@ -133,7 +132,7 @@ class SerializableIrGenerator(
|
|||||||
generateGoldenMaskCheck(seenVars, properties, getDescriptorExpr)
|
generateGoldenMaskCheck(seenVars, properties, getDescriptorExpr)
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
superClass.symbol == compilerContext.irBuiltIns.anyClass -> generateAnySuperConstructorCall(toBuilder = this@contributeConstructor)
|
superClass.symbol == compilerContext.irBuiltIns.anyClass -> generateAnySuperConstructorCall(toBuilder = this@addFunctionBody)
|
||||||
superClass.isInternalSerializable -> {
|
superClass.isInternalSerializable -> {
|
||||||
startPropOffset = generateSuperSerializableCall(superClass, ctor.valueParameters, seenVarsOffset)
|
startPropOffset = generateSuperSerializableCall(superClass, ctor.valueParameters, seenVarsOffset)
|
||||||
}
|
}
|
||||||
@@ -146,7 +145,7 @@ class SerializableIrGenerator(
|
|||||||
val paramRef = ctor.valueParameters[index + seenVarsOffset]
|
val paramRef = ctor.valueParameters[index + seenVarsOffset]
|
||||||
// Assign this.a = a in else branch
|
// Assign this.a = a in else branch
|
||||||
// Set field directly w/o setter to match behavior of old backend plugin
|
// Set field directly w/o setter to match behavior of old backend plugin
|
||||||
val backingFieldToAssign = prop.getIrPropertyFrom(irClass).backingField!!
|
val backingFieldToAssign = prop.descriptor.backingField!!
|
||||||
val assignParamExpr = irSetField(irGet(thiz), backingFieldToAssign, irGet(paramRef))
|
val assignParamExpr = irSetField(irGet(thiz), backingFieldToAssign, irGet(paramRef))
|
||||||
|
|
||||||
val ifNotSeenExpr: IrExpression = if (prop.optional) {
|
val ifNotSeenExpr: IrExpression = if (prop.optional) {
|
||||||
@@ -196,17 +195,17 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.getStaticSerialDescriptorExpr(): IrExpression {
|
private fun IrBlockBodyBuilder.getStaticSerialDescriptorExpr(): IrExpression {
|
||||||
val serializer = serializableDescriptor.classSerializer!!
|
val serializerIrClass = irClass.classSerializer(compilerContext)!!.owner
|
||||||
// internally generated serializer always declared inside serializable class
|
// internally generated serializer always declared inside serializable class
|
||||||
val serializerIrClass = irClass.declarations
|
// val serializerIrClass = irClass.declarations
|
||||||
.filterIsInstanceAnd<IrClass> { it.name == serializer.name }
|
// .filterIsInstanceAnd<IrClass> { it.name == serializer.name }
|
||||||
.singleOrNull() ?: throw Exception("No class with name ${serializer.fqNameSafe}")
|
// .singleOrNull() ?: throw Exception("No class with name ${serializer.fqNameSafe}")
|
||||||
|
|
||||||
val serialDescriptorGetter =
|
val serialDescriptorGetter =
|
||||||
serializerIrClass.getPropertyGetter(SERIAL_DESC_FIELD)!!
|
serializerIrClass.getPropertyGetter(SERIAL_DESC_FIELD)!!
|
||||||
return irGet(
|
return irGet(
|
||||||
serializerIrClass.defaultType,
|
serializerIrClass.defaultType,
|
||||||
irGetObject(serializer),
|
irGetObject(serializerIrClass),
|
||||||
serialDescriptorGetter.owner.symbol
|
serialDescriptorGetter.owner.symbol
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -216,7 +215,7 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
|
private fun IrBlockBodyBuilder.createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
|
||||||
val serialDescIrType = serialDescClass.defaultType.toIrType()
|
val serialDescIrType = serialDescriptorClass.defaultType
|
||||||
|
|
||||||
return createCompanionValProperty(companionObject, serialDescIrType, CACHED_DESCRIPTOR_FIELD_NAME) {
|
return createCompanionValProperty(companionObject, serialDescIrType, CACHED_DESCRIPTOR_FIELD_NAME) {
|
||||||
val serialDescVar = irTemporary(
|
val serialDescVar = irTemporary(
|
||||||
@@ -231,16 +230,16 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.getInstantiateDescriptorExpr(): IrExpression {
|
private fun IrBlockBodyBuilder.getInstantiateDescriptorExpr(): IrExpression {
|
||||||
val classConstructors = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe)
|
val classConstructors = compilerContext.referenceConstructors(serialDescriptorImplClass.kotlinFqName) //todo: remove reference
|
||||||
val serialClassDescImplCtor = classConstructors.single { it.owner.isPrimary }
|
val serialClassDescImplCtor = classConstructors.single { it.owner.isPrimary }
|
||||||
return irInvoke(
|
return irInvoke(
|
||||||
null, serialClassDescImplCtor,
|
null, serialClassDescImplCtor,
|
||||||
irString(serializableDescriptor.serialName()), irNull(), irInt(properties.serializableProperties.size)
|
irString(irClass.serialName()), irNull(), irInt(properties.serializableProperties.size)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.getAddElementToDescriptorExpr(
|
private fun IrBlockBodyBuilder.getAddElementToDescriptorExpr(
|
||||||
property: SerializableProperty,
|
property: IrSerializableProperty,
|
||||||
serialDescVar: IrVariable
|
serialDescVar: IrVariable
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
return irInvoke(
|
return irInvoke(
|
||||||
@@ -254,7 +253,7 @@ class SerializableIrGenerator(
|
|||||||
|
|
||||||
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: IrClass) {
|
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: IrClass) {
|
||||||
val ctorRef = superClass.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.valueParameters.isEmpty() }
|
val ctorRef = superClass.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.valueParameters.isEmpty() }
|
||||||
?: error("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor")
|
?: error("Non-serializable parent of serializable $irClass must have no arg constructor")
|
||||||
|
|
||||||
|
|
||||||
val call = IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
val call = IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
||||||
@@ -301,13 +300,13 @@ class SerializableIrGenerator(
|
|||||||
return superProperties.size
|
return superProperties.size
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateWriteSelfMethod(methodDescriptor: FunctionDescriptor) {
|
fun generateWriteSelfMethod(methodDescriptor: IrSimpleFunction) {
|
||||||
irClass.contributeFunction(methodDescriptor, ignoreWhenMissing = true) { writeSelfFunction ->
|
addFunctionBody(methodDescriptor) { writeSelfFunction ->
|
||||||
val objectToSerialize = writeSelfFunction.valueParameters[0]
|
val objectToSerialize = writeSelfFunction.valueParameters[0]
|
||||||
val localOutput = writeSelfFunction.valueParameters[1]
|
val localOutput = writeSelfFunction.valueParameters[1]
|
||||||
val localSerialDesc = writeSelfFunction.valueParameters[2]
|
val localSerialDesc = writeSelfFunction.valueParameters[2]
|
||||||
val serializableProperties = properties.serializableProperties
|
val serializableProperties = properties.serializableProperties
|
||||||
val kOutputClass = serializableDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
|
val kOutputClass = compilerContext.getClassFromRuntime(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
|
||||||
|
|
||||||
val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? =
|
val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? =
|
||||||
createPropertyByParamReplacer(irClass, serializableProperties, objectToSerialize, bindingContext)
|
createPropertyByParamReplacer(irClass, serializableProperties, objectToSerialize, bindingContext)
|
||||||
@@ -339,21 +338,21 @@ class SerializableIrGenerator(
|
|||||||
val args = mutableListOf<IrExpression>(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc))
|
val args = mutableListOf<IrExpression>(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc))
|
||||||
|
|
||||||
val typeArgsForParent =
|
val typeArgsForParent =
|
||||||
serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments
|
(irClass.superTypes.single { it.classOrNull?.owner?.isInternalSerializable == true } as? IrSimpleType)?.arguments.orEmpty()
|
||||||
val parentWriteSelfSerializers = typeArgsForParent.map { arg ->
|
val parentWriteSelfSerializers = typeArgsForParent.map { arg ->
|
||||||
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(arg).let { if (it == -1) null else it }
|
val genericIdx = irClass.defaultType.arguments.indexOf(arg).let { if (it == -1) null else it }
|
||||||
val serial = findTypeSerializerOrContext(serializableDescriptor.module, arg.type)
|
val serial = findTypeSerializerOrContext(compilerContext, arg.typeOrNull!!)
|
||||||
serializerInstance(
|
serializerInstance(
|
||||||
this@SerializableIrGenerator,
|
this@SerializableIrGenerator,
|
||||||
serial,
|
serial,
|
||||||
serializableDescriptor.module,
|
compilerContext,
|
||||||
arg.type,
|
arg.typeOrNull!!,
|
||||||
genericIdx
|
genericIdx
|
||||||
) { it, _ ->
|
) { it, _ ->
|
||||||
irGet(writeSelfFunction.valueParameters[3 + it])
|
irGet(writeSelfFunction.valueParameters[3 + it])
|
||||||
}!!
|
}!!
|
||||||
}
|
}
|
||||||
+irInvoke(null, superWriteSelfF.symbol, typeArgsForParent.map { it.type.toIrType() }, args + parentWriteSelfSerializers)
|
+irInvoke(null, superWriteSelfF.symbol, typeArgsForParent.map { it.typeOrNull!! }, args + parentWriteSelfSerializers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,16 +366,45 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generate() {
|
||||||
|
generateSyntheticInternalConstructor()
|
||||||
|
generateSyntheticMethods()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun IrClass.shouldHaveSpecificSyntheticMethods(functionPresenceChecker: () -> IrSimpleFunction?) =
|
||||||
|
!isValue && (isAbstractOrSealedSerializableClass || functionPresenceChecker() != null)
|
||||||
|
|
||||||
|
private fun generateSyntheticInternalConstructor() { // TODO: this doesn't work with OLD FE
|
||||||
|
val serializerDescriptor = irClass.classSerializer(compilerContext)?.owner ?: return
|
||||||
|
if (irClass.shouldHaveSpecificSyntheticMethods { serializerDescriptor.findPluginGeneratedMethod(LOAD) }) {
|
||||||
|
val constrDesc = irClass.constructors.find(IrConstructor::isSerializationCtor) ?: return
|
||||||
|
generateInternalConstructor(constrDesc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateSyntheticMethods() {
|
||||||
|
val serializerDescriptor = irClass.classSerializer(compilerContext)?.owner ?: return
|
||||||
|
if (irClass.shouldHaveSpecificSyntheticMethods { serializerDescriptor.findPluginGeneratedMethod(SAVE) }) {
|
||||||
|
val func =
|
||||||
|
irClass.functions.singleOrNull { function ->
|
||||||
|
function.name == SerialEntityNames.WRITE_SELF_NAME &&
|
||||||
|
function.modality == Modality.FINAL &&
|
||||||
|
function.returnType.isUnit()
|
||||||
|
} ?: return
|
||||||
|
generateWriteSelfMethod(func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun generate(
|
fun generate(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
context: SerializationPluginContext,
|
context: SerializationPluginContext,
|
||||||
bindingContext: BindingContext
|
|
||||||
) {
|
) {
|
||||||
val serializableClass = irClass.descriptor
|
val serializableClass = irClass.descriptor
|
||||||
|
|
||||||
if (serializableClass.isInternalSerializable) {
|
if (serializableClass.isInternalSerializable) {
|
||||||
SerializableIrGenerator(irClass, context, bindingContext).generate()
|
SerializableIrGenerator(irClass, context).generate()
|
||||||
irClass.patchDeclarationParents(irClass.parent)
|
irClass.patchDeclarationParents(irClass.parent)
|
||||||
} else if (serializableClass.serializableAnnotationIsUseless) {
|
} else if (serializableClass.serializableAnnotationIsUseless) {
|
||||||
throw CompilationException(
|
throw CompilationException(
|
||||||
|
|||||||
+25
-22
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
@@ -12,31 +13,37 @@ 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.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
|
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.functions
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
import org.jetbrains.kotlin.ir.util.properties
|
import org.jetbrains.kotlin.ir.util.properties
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.enumEntries
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getClassFromInternalSerializationPackage
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getClassFromRuntime
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialNameValue
|
||||||
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.*
|
||||||
|
|
||||||
class SerializerForEnumsGenerator(
|
class SerializerForEnumsGenerator(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
compilerContext: SerializationPluginContext,
|
compilerContext: SerializationPluginContext,
|
||||||
bindingContext: BindingContext,
|
|
||||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||||
) : SerializerIrGenerator(irClass, compilerContext, bindingContext, null, serialInfoJvmGenerator) {
|
) : SerializerIrGenerator(irClass, compilerContext, null, serialInfoJvmGenerator) {
|
||||||
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
|
override fun generateSave(function: IrSimpleFunction) = addFunctionBody(function) { saveFunc ->
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
||||||
|
|
||||||
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
val encoderClass = compilerContext.getClassFromRuntime(SerialEntityNames.ENCODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.getter!!.symbol
|
||||||
val encodeEnum = encoderClass.referenceFunctionSymbol(CallingConventions.encodeEnum)
|
val encodeEnum = encoderClass.functionByName(CallingConventions.encodeEnum)
|
||||||
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 serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
||||||
@@ -46,13 +53,13 @@ class SerializerForEnumsGenerator(
|
|||||||
+call
|
+call
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function) { loadFunc ->
|
override fun generateLoad(function: IrSimpleFunction) = addFunctionBody(function) { loadFunc ->
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
|
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
|
||||||
|
|
||||||
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
val decoderClass = compilerContext.getClassFromRuntime(SerialEntityNames.DECODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.getter!!.symbol
|
||||||
val decode = decoderClass.referenceFunctionSymbol(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 serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
||||||
@@ -73,27 +80,23 @@ class SerializerForEnumsGenerator(
|
|||||||
+irReturn(getValueByOrdinal)
|
+irReturn(getValueByOrdinal)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val serialDescImplClass: ClassDescriptor = serializerDescriptor
|
override val serialDescImplClass: IrClassSymbol = compilerContext.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_ENUM)
|
||||||
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_ENUM)
|
|
||||||
|
|
||||||
override fun IrBlockBodyBuilder.instantiateNewDescriptor(
|
override fun IrBlockBodyBuilder.instantiateNewDescriptor(serialDescImplClass: IrClassSymbol, correctThis: IrExpression): IrExpression {
|
||||||
serialDescImplClass: ClassDescriptor,
|
val ctor = serialDescImplClass.constructors.single { it.owner.isPrimary }
|
||||||
correctThis: IrExpression
|
|
||||||
): IrExpression {
|
|
||||||
val ctor = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe).single { it.owner.isPrimary }
|
|
||||||
return irInvoke(
|
return irInvoke(
|
||||||
null, ctor,
|
null, ctor,
|
||||||
irString(serialName),
|
irString(serialName),
|
||||||
irInt(serializableDescriptor.enumEntries().size)
|
irInt(serializableIrClass.enumEntries().size)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrBlockBodyBuilder.addElementsContentToDescriptor(
|
override fun IrBlockBodyBuilder.addElementsContentToDescriptor(
|
||||||
serialDescImplClass: ClassDescriptor,
|
serialDescImplClass: IrClassSymbol,
|
||||||
localDescriptor: IrVariable,
|
localDescriptor: IrVariable,
|
||||||
addFunction: IrFunctionSymbol
|
addFunction: IrFunctionSymbol
|
||||||
) {
|
) {
|
||||||
val enumEntries = serializableDescriptor.enumEntries()
|
val enumEntries = serializableIrClass.enumEntries()
|
||||||
for (entry in enumEntries) {
|
for (entry in enumEntries) {
|
||||||
// regular .serialName() produces fqName here, which is kinda inconvenient for enum entry
|
// regular .serialName() produces fqName here, which is kinda inconvenient for enum entry
|
||||||
val serialName = entry.annotations.serialNameValue ?: entry.name.toString()
|
val serialName = entry.annotations.serialNameValue ?: entry.name.toString()
|
||||||
@@ -107,9 +110,9 @@ class SerializerForEnumsGenerator(
|
|||||||
+call
|
+call
|
||||||
// serialDesc.pushAnnotation(...)
|
// serialDesc.pushAnnotation(...)
|
||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
entry.annotations.mapNotNull(compilerContext.typeTranslator.constantValueGenerator::generateAnnotationConstructorCall),
|
entry.annotations.map {it.deepCopyWithVariables()},
|
||||||
localDescriptor,
|
localDescriptor,
|
||||||
serialDescImplClass.referenceFunctionSymbol(CallingConventions.addAnnotation)
|
serialDescImplClass.functionByName(CallingConventions.addAnnotation)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-24
@@ -5,34 +5,38 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
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.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getClassFromInternalSerializationPackage
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getClassFromRuntime
|
||||||
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.*
|
||||||
|
|
||||||
class SerializerForInlineClassGenerator(
|
class SerializerForInlineClassGenerator(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
compilerContext: SerializationPluginContext,
|
compilerContext: SerializationPluginContext,
|
||||||
bindingContext: BindingContext,
|
|
||||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||||
) : SerializerIrGenerator(irClass, compilerContext, bindingContext, null, serialInfoJvmGenerator) {
|
) : SerializerIrGenerator(irClass, compilerContext, null, serialInfoJvmGenerator) {
|
||||||
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
|
override fun generateSave(function: IrSimpleFunction) = addFunctionBody(function) { saveFunc ->
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
||||||
|
|
||||||
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
val encoderClass = compilerContext.getClassFromRuntime(SerialEntityNames.ENCODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.getter!!.symbol
|
||||||
val encodeInline = encoderClass.referenceFunctionSymbol(CallingConventions.encodeInline)
|
val encodeInline = encoderClass.functionByName(CallingConventions.encodeInline)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
// val inlineEncoder = encoder.encodeInline()
|
// val inlineEncoder = encoder.encodeInline()
|
||||||
@@ -45,14 +49,14 @@ class SerializerForInlineClassGenerator(
|
|||||||
// inlineEncoder.encodeInt/String/SerializableValue
|
// inlineEncoder.encodeInt/String/SerializableValue
|
||||||
val elementCall = formEncodeDecodePropertyCall(irGet(inlineEncoder), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
val elementCall = formEncodeDecodePropertyCall(irGet(inlineEncoder), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||||
val f =
|
val f =
|
||||||
encoderClass.referenceFunctionSymbol("${CallingConventions.encode}${sti.elementMethodPrefix}SerializableValue")
|
encoderClass.functionByName("${CallingConventions.encode}${sti.elementMethodPrefix}SerializableValue")
|
||||||
f to listOf(
|
f to listOf(
|
||||||
innerSerial,
|
innerSerial,
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
}, {
|
}, {
|
||||||
val f =
|
val f =
|
||||||
encoderClass.referenceFunctionSymbol("${CallingConventions.encode}${it.elementMethodPrefix}")
|
encoderClass.functionByName("${CallingConventions.encode}${it.elementMethodPrefix}")
|
||||||
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
||||||
f to args
|
f to args
|
||||||
})
|
})
|
||||||
@@ -61,37 +65,33 @@ class SerializerForInlineClassGenerator(
|
|||||||
+actualEncodeCall
|
+actualEncodeCall
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function) { loadFunc ->
|
override fun generateLoad(function: IrSimpleFunction) = addFunctionBody(function) { loadFunc ->
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
|
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
|
||||||
|
|
||||||
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
val decoderClass = compilerContext.getClassFromRuntime(SerialEntityNames.DECODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.getter!!.symbol
|
||||||
val decodeInline = decoderClass.referenceFunctionSymbol(CallingConventions.decodeInline)
|
val decodeInline = decoderClass.functionByName(CallingConventions.decodeInline)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
// val inlineDecoder = decoder.decodeInline()
|
// val inlineDecoder = decoder.decodeInline()
|
||||||
val inlineDecoder: IrExpression = irInvoke(irGet(loadFunc.valueParameters[0]), decodeInline, serialDescGetter)
|
val inlineDecoder: IrExpression = irInvoke(irGet(loadFunc.valueParameters[0]), decodeInline, serialDescGetter)
|
||||||
|
|
||||||
val property = serializableProperties.first()
|
val property = serializableProperties.first()
|
||||||
val inlinedType = property.type.toIrType()
|
val inlinedType = property.type
|
||||||
val actualCall = formEncodeDecodePropertyCall(inlineDecoder, loadFunc.dispatchReceiverParameter!!, property, { innerSerial, sti ->
|
val actualCall = formEncodeDecodePropertyCall(inlineDecoder, loadFunc.dispatchReceiverParameter!!, property, { innerSerial, sti ->
|
||||||
decoderClass.referenceFunctionSymbol( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
decoderClass.functionByName( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
||||||
}, {
|
}, {
|
||||||
decoderClass.referenceFunctionSymbol("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
decoderClass.functionByName("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
||||||
}, returnTypeHint = inlinedType)
|
}, returnTypeHint = inlinedType)
|
||||||
val value = coerceToBox(actualCall, loadFunc.returnType)
|
val value = coerceToBox(actualCall, loadFunc.returnType)
|
||||||
+irReturn(value)
|
+irReturn(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val serialDescImplClass: ClassDescriptor = serializerDescriptor
|
override val serialDescImplClass: IrClassSymbol = compilerContext.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_INLINE)
|
||||||
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_INLINE)
|
|
||||||
|
|
||||||
override fun IrBlockBodyBuilder.instantiateNewDescriptor(
|
override fun IrBlockBodyBuilder.instantiateNewDescriptor(serialDescImplClass: IrClassSymbol, correctThis: IrExpression): IrExpression {
|
||||||
serialDescImplClass: ClassDescriptor,
|
val ctor = serialDescImplClass.constructors.single { it.owner.isPrimary }
|
||||||
correctThis: IrExpression
|
|
||||||
): IrExpression {
|
|
||||||
val ctor = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe).single { it.owner.isPrimary }
|
|
||||||
return irInvoke(
|
return irInvoke(
|
||||||
null, ctor,
|
null, ctor,
|
||||||
irString(serialName),
|
irString(serialName),
|
||||||
@@ -109,6 +109,6 @@ class SerializerForInlineClassGenerator(
|
|||||||
listOf(expression)
|
listOf(expression)
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.getFromBox(expression: IrExpression, serializableProperty: SerializableProperty): IrExpression =
|
private fun IrBlockBodyBuilder.getFromBox(expression: IrExpression, serializableProperty: IrSerializableProperty): IrExpression =
|
||||||
getProperty(expression, serializableProperty.getIrPropertyFrom(serializableIrClass))
|
getProperty(expression, serializableProperty.descriptor)
|
||||||
}
|
}
|
||||||
|
|||||||
+146
-91
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.codegen.CompilationException
|
import org.jetbrains.kotlin.codegen.CompilationException
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -16,29 +17,29 @@ import org.jetbrains.kotlin.ir.builders.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.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
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||||
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.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInfo
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
|
||||||
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.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SAVE
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_DECODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_DECODER_CLASS
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_ENCODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_ENCODER_CLASS
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UNKNOWN_FIELD_EXC
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UNKNOWN_FIELD_EXC
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.isEnumWithLegacyGeneratedSerializer
|
||||||
|
|
||||||
object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER", true)
|
object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER", true)
|
||||||
|
|
||||||
@@ -47,31 +48,63 @@ internal typealias FunctionWithArgs = Pair<IrFunctionSymbol, List<IrExpression>>
|
|||||||
open class SerializerIrGenerator(
|
open class SerializerIrGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
final override val compilerContext: SerializationPluginContext,
|
final override val compilerContext: SerializationPluginContext,
|
||||||
bindingContext: BindingContext,
|
|
||||||
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
||||||
private val serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
private val serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||||
) : SerializerCodegen(irClass.descriptor, bindingContext, metadataPlugin), IrBuilderExtension {
|
) : AbstractSerialGenerator(null, irClass.descriptor), IrBuilderExtension {
|
||||||
protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).owner
|
protected val serializableIrClass = getSerializableClassDescriptorBySerializer(irClass)!!
|
||||||
protected val irAnySerialDescProperty = anySerialDescProperty?.let { compilerContext.symbolTable.referenceProperty(it) }
|
|
||||||
|
protected val serialName: String = serializableIrClass.serialName()
|
||||||
|
protected val properties = bindingContext.serializablePropertiesForIrBackend(serializableIrClass, metadataPlugin)
|
||||||
|
protected val serializableProperties = properties.serializableProperties
|
||||||
|
protected val isGeneratedSerializer = irClass.descriptor.typeConstructor.supertypes.any(::isGeneratedKSerializer) // TODO TODO
|
||||||
|
|
||||||
|
protected val generatedSerialDescPropertyDescriptor = getProperty(
|
||||||
|
SerialEntityNames.SERIAL_DESC_FIELD,
|
||||||
|
{ true }
|
||||||
|
)?.takeIf { it.origin == IrDeclarationOrigin.GeneratedByPlugin(SerializationPluginKey) }
|
||||||
|
|
||||||
|
protected val anySerialDescProperty = getProperty(
|
||||||
|
SerialEntityNames.SERIAL_DESC_FIELD,
|
||||||
|
) { true } // TODO REMOVE TRUE
|
||||||
|
|
||||||
|
protected val irAnySerialDescProperty = anySerialDescProperty
|
||||||
|
|
||||||
|
fun getProperty(
|
||||||
|
name: String,
|
||||||
|
isReturnTypeOk: (IrProperty) -> Boolean
|
||||||
|
): IrProperty? {
|
||||||
|
return irClass.properties.singleOrNull { it.name.asString() == name && isReturnTypeOk(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
var localSerializersFieldsDescriptors: List<Pair<PropertyDescriptor, IrProperty>> = emptyList()
|
||||||
|
protected set
|
||||||
|
protected fun findLocalSerializersFieldDescriptors(): List<IrProperty> {
|
||||||
|
val count = serializableIrClass.typeParameters.size
|
||||||
|
if (count == 0) return emptyList()
|
||||||
|
val propNames = (0 until count).map { "${SerialEntityNames.typeArgPrefix}$it" }
|
||||||
|
return propNames.mapNotNull { name ->
|
||||||
|
getProperty(name) { isKSerializer(it.getter!!.returnType) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open val serialDescImplClass: ClassDescriptor = serializerDescriptor
|
protected open val serialDescImplClass: IrClassSymbol =
|
||||||
.getClassFromInternalSerializationPackage(SERIAL_DESCRIPTOR_CLASS_IMPL)
|
compilerContext.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL)
|
||||||
|
|
||||||
override fun generateSerialDesc() {
|
fun generateSerialDesc() {
|
||||||
val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return
|
val desc = generatedSerialDescPropertyDescriptor ?: return
|
||||||
val addFuncS = serialDescImplClass.referenceFunctionSymbol(CallingConventions.addElement)
|
val addFuncS = serialDescImplClass.functionByName(CallingConventions.addElement)
|
||||||
|
|
||||||
val thisAsReceiverParameter = irClass.thisReceiver!!
|
val thisAsReceiverParameter = irClass.thisReceiver!!
|
||||||
lateinit var prop: IrProperty
|
lateinit var prop: IrProperty
|
||||||
|
|
||||||
// how to (auto)create backing field and getter/setter?
|
// how to (auto)create backing field and getter/setter?
|
||||||
compilerContext.symbolTable.withReferenceScope(irClass) {
|
compilerContext.symbolTable.withReferenceScope(irClass) {
|
||||||
prop = generateSimplePropertyWithBackingField(desc, irClass)
|
prop = generateSimplePropertyWithBackingField(desc.descriptor, irClass) // TODO check if this works correctly with old FE
|
||||||
|
|
||||||
// TODO: Do not use descriptors here
|
// TODO: Do not use descriptors here
|
||||||
localSerializersFieldsDescriptors = findLocalSerializersFieldDescriptors().map { descriptor ->
|
localSerializersFieldsDescriptors = findLocalSerializersFieldDescriptors().map { prop ->
|
||||||
descriptor to generateSimplePropertyWithBackingField(descriptor, irClass)
|
prop.descriptor to generateSimplePropertyWithBackingField(prop.descriptor, irClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,14 +130,14 @@ open class SerializerIrGenerator(
|
|||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
collectSerialInfoAnnotations(serializableIrClass),
|
collectSerialInfoAnnotations(serializableIrClass),
|
||||||
localDesc,
|
localDesc,
|
||||||
serialDescImplClass.referenceFunctionSymbol(CallingConventions.addClassAnnotation)
|
serialDescImplClass.functionByName(CallingConventions.addClassAnnotation)
|
||||||
)
|
)
|
||||||
|
|
||||||
// save local descriptor to field
|
// save local descriptor to field
|
||||||
+irSetField(
|
+irSetField(
|
||||||
generateReceiverExpressionForFieldAccess(
|
generateReceiverExpressionForFieldAccess(
|
||||||
thisAsReceiverParameter.symbol,
|
thisAsReceiverParameter.symbol,
|
||||||
generatedSerialDescPropertyDescriptor
|
generatedSerialDescPropertyDescriptor.descriptor
|
||||||
),
|
),
|
||||||
prop.backingField!!,
|
prop.backingField!!,
|
||||||
irGet(localDesc)
|
irGet(localDesc)
|
||||||
@@ -115,11 +148,11 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun IrBlockBodyBuilder.instantiateNewDescriptor(
|
protected open fun IrBlockBodyBuilder.instantiateNewDescriptor(
|
||||||
serialDescImplClass: ClassDescriptor,
|
serialDescImplClass: IrClassSymbol,
|
||||||
correctThis: IrExpression
|
correctThis: IrExpression
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
val classConstructors = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe)
|
// val classConstructors = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe)
|
||||||
val serialClassDescImplCtor = classConstructors.single { it.owner.isPrimary }
|
val serialClassDescImplCtor = serialDescImplClass.constructors.single { it.owner.isPrimary }
|
||||||
return irInvoke(
|
return irInvoke(
|
||||||
null, serialClassDescImplCtor,
|
null, serialClassDescImplCtor,
|
||||||
irString(serialName), if (isGeneratedSerializer) correctThis else irNull(), irInt(serializableProperties.size)
|
irString(serialName), if (isGeneratedSerializer) correctThis else irNull(), irInt(serializableProperties.size)
|
||||||
@@ -127,11 +160,11 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun IrBlockBodyBuilder.addElementsContentToDescriptor(
|
protected open fun IrBlockBodyBuilder.addElementsContentToDescriptor(
|
||||||
serialDescImplClass: ClassDescriptor,
|
serialDescImplClass: IrClassSymbol,
|
||||||
localDescriptor: IrVariable,
|
localDescriptor: IrVariable,
|
||||||
addFunction: IrFunctionSymbol
|
addFunction: IrFunctionSymbol
|
||||||
) {
|
) {
|
||||||
fun addFieldCall(prop: SerializableProperty) = irInvoke(
|
fun addFieldCall(prop: IrSerializableProperty) = irInvoke(
|
||||||
irGet(localDescriptor),
|
irGet(localDescriptor),
|
||||||
addFunction,
|
addFunction,
|
||||||
irString(prop.name),
|
irString(prop.name),
|
||||||
@@ -143,11 +176,11 @@ open class SerializerIrGenerator(
|
|||||||
if (classProp.transient) continue
|
if (classProp.transient) continue
|
||||||
+addFieldCall(classProp)
|
+addFieldCall(classProp)
|
||||||
// add property annotations
|
// add property annotations
|
||||||
val property = classProp.getIrPropertyFrom(serializableIrClass)
|
val property = classProp.descriptor//.getIrPropertyFrom(serializableIrClass)
|
||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
property.annotations,
|
property.annotations,
|
||||||
localDescriptor,
|
localDescriptor,
|
||||||
serialDescImplClass.referenceFunctionSymbol(CallingConventions.addAnnotation)
|
serialDescImplClass.functionByName(CallingConventions.addAnnotation)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,11 +195,10 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ClassConstructorDescriptor) =
|
fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: IrConstructor) =
|
||||||
irClass.contributeConstructor(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.find { it.isPrimary }
|
val primaryCtor = irClass.constructors.primary
|
||||||
?: throw AssertionError("Serializer class must have primary constructor")
|
|
||||||
+IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
+IrDelegatingConstructorCallImpl.fromSymbolDescriptor(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
@@ -191,7 +223,7 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateChildSerializersGetter(function: FunctionDescriptor) = irClass.contributeFunction(function) { irFun ->
|
open fun generateChildSerializersGetter(function: IrSimpleFunction) = addFunctionBody(function) { irFun ->
|
||||||
val allSerializers = serializableProperties.map {
|
val allSerializers = serializableProperties.map {
|
||||||
requireNotNull(
|
requireNotNull(
|
||||||
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)
|
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)
|
||||||
@@ -203,8 +235,8 @@ open class SerializerIrGenerator(
|
|||||||
+irReturn(array)
|
+irReturn(array)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateTypeParamsSerializersGetter(function: FunctionDescriptor) = irClass.contributeFunction(function) { irFun ->
|
open fun generateTypeParamsSerializersGetter(function: IrSimpleFunction) = addFunctionBody(function) { irFun ->
|
||||||
val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ ->
|
val typeParams = serializableIrClass.typeParameters.mapIndexed { idx, _ ->
|
||||||
irGetField(
|
irGetField(
|
||||||
irGet(irFun.dispatchReceiverParameter!!),
|
irGet(irFun.dispatchReceiverParameter!!),
|
||||||
localSerializersFieldsDescriptors[idx].second.backingField!!
|
localSerializersFieldsDescriptors[idx].second.backingField!!
|
||||||
@@ -215,26 +247,26 @@ open class SerializerIrGenerator(
|
|||||||
+irReturn(array)
|
+irReturn(array)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSerializableClassProperty(property: PropertyDescriptor) {
|
open fun generateSerializableClassProperty(property: IrProperty) {
|
||||||
/* Already implemented in .generateSerialClassDesc ? */
|
/* Already implemented in .generateSerialClassDesc ? */
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
|
open fun generateSave(function: IrSimpleFunction) = addFunctionBody(function) { saveFunc ->
|
||||||
|
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
||||||
|
|
||||||
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_ENCODER_CLASS)
|
val kOutputClass = compilerContext.getClassFromRuntime(STRUCTURE_ENCODER_CLASS)
|
||||||
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(ENCODER_CLASS)
|
val encoderClass = compilerContext.getClassFromRuntime(ENCODER_CLASS)
|
||||||
|
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.getter!!.symbol
|
||||||
|
|
||||||
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
|
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
|
||||||
val beginFunc = encoderClass.referenceFunctionSymbol(CallingConventions.begin) { it.valueParameters.size == 1 }
|
val beginFunc = encoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||||
|
|
||||||
val call = irCall(beginFunc, type = kOutputClass.defaultType.toIrType()).mapValueParametersIndexed { _, _ ->
|
val call = irCall(beginFunc, type = kOutputClass.defaultType).mapValueParametersIndexed { _, _ ->
|
||||||
irGet(localSerialDesc)
|
irGet(localSerialDesc)
|
||||||
}
|
}
|
||||||
// can it be done in more concise way? e.g. additional builder function?
|
// can it be done in more concise way? e.g. additional builder function?
|
||||||
@@ -274,16 +306,16 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// output.writeEnd(serialClassDesc)
|
// output.writeEnd(serialClassDesc)
|
||||||
val wEndFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.end)
|
val wEndFunc = kOutputClass.functionByName(CallingConventions.end)
|
||||||
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
|
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
protected fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
||||||
encoder: IrExpression,
|
encoder: IrExpression,
|
||||||
dispatchReceiver: IrValueParameter,
|
dispatchReceiver: IrValueParameter,
|
||||||
property: SerializableProperty,
|
property: IrSerializableProperty,
|
||||||
whenHaveSerializer: (serializer: IrExpression, sti: SerialTypeInfo) -> FunctionWithArgs,
|
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
whenDoNot: (sti: SerialTypeInfo) -> FunctionWithArgs,
|
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
returnTypeHint: IrType? = null
|
returnTypeHint: IrType? = null
|
||||||
): IrExpression = formEncodeDecodePropertyCall(
|
): IrExpression = formEncodeDecodePropertyCall(
|
||||||
this@SerializerIrGenerator,
|
this@SerializerIrGenerator,
|
||||||
@@ -299,9 +331,8 @@ open class SerializerIrGenerator(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// returns null: Any? for boxed types and 0: <number type> for primitives
|
// returns null: Any? for boxed types and 0: <number type> for primitives
|
||||||
private fun IrBuilderWithScope.defaultValueAndType(descriptor: PropertyDescriptor): Pair<IrExpression, IrType> {
|
private fun IrBuilderWithScope.defaultValueAndType(descriptor: IrProperty): Pair<IrExpression, IrType> {
|
||||||
val kType = descriptor.returnType!!
|
val T = descriptor.getter!!.returnType
|
||||||
val T = kType.toIrType()
|
|
||||||
val defaultPrimitive: IrExpression? =
|
val defaultPrimitive: IrExpression? =
|
||||||
if (T.isMarkedNullable()) null
|
if (T.isMarkedNullable()) null
|
||||||
else when (T.getPrimitiveType()) {
|
else when (T.getPrimitiveType()) {
|
||||||
@@ -321,9 +352,9 @@ open class SerializerIrGenerator(
|
|||||||
defaultPrimitive to T
|
defaultPrimitive to T
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function) { loadFunc ->
|
open fun generateLoad(function: IrSimpleFunction) = addFunctionBody(function) { loadFunc ->
|
||||||
if (serializableDescriptor.modality == Modality.ABSTRACT || serializableDescriptor.modality == Modality.SEALED) {
|
if (serializableIrClass.modality == Modality.ABSTRACT || serializableIrClass.modality == Modality.SEALED) {
|
||||||
return@contributeFunction
|
return@addFunctionBody
|
||||||
}
|
}
|
||||||
|
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
@@ -331,9 +362,9 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
fun IrVariable.get() = irGet(this)
|
fun IrVariable.get() = irGet(this)
|
||||||
|
|
||||||
val inputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_DECODER_CLASS)
|
val inputClass = compilerContext.getClassFromRuntime(STRUCTURE_DECODER_CLASS)
|
||||||
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(DECODER_CLASS)
|
val decoderClass = compilerContext.getClassFromRuntime(DECODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.getter!!.symbol
|
||||||
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
||||||
|
|
||||||
// workaround due to unavailability of labels (KT-25386)
|
// workaround due to unavailability of labels (KT-25386)
|
||||||
@@ -350,7 +381,7 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
val transients = serializableIrClass.declarations.asSequence()
|
val transients = serializableIrClass.declarations.asSequence()
|
||||||
.filterIsInstance<IrProperty>()
|
.filterIsInstance<IrProperty>()
|
||||||
.filter { !serialPropertiesIndexes.containsKey(it.descriptor) }
|
.filter { !serialPropertiesIndexes.contains(it) }
|
||||||
.filter { it.backingField != null }
|
.filter { it.backingField != null }
|
||||||
|
|
||||||
// var bitMask0 = 0, bitMask1 = 0...
|
// var bitMask0 = 0, bitMask1 = 0...
|
||||||
@@ -361,18 +392,18 @@ open class SerializerIrGenerator(
|
|||||||
descriptor to irTemporary(expr, "local$i", type, isMutable = true)
|
descriptor to irTemporary(expr, "local$i", type, isMutable = true)
|
||||||
}
|
}
|
||||||
// var transient0 = null, transient0 = null ...
|
// var transient0 = null, transient0 = null ...
|
||||||
val transientsPropertiesMap = transients.mapIndexed { i, prop -> i to prop.descriptor }.associate { (i, descriptor) ->
|
val transientsPropertiesMap = transients.mapIndexed { i, prop -> i to prop }.associate { (i, descriptor) ->
|
||||||
val (expr, type) = defaultValueAndType(descriptor)
|
val (expr, type) = defaultValueAndType(descriptor)
|
||||||
descriptor to irTemporary(expr, "transient$i", type, isMutable = true)
|
descriptor to irTemporary(expr, "transient$i", type, isMutable = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
//input = input.beginStructure(...)
|
//input = input.beginStructure(...)
|
||||||
val beginFunc = decoderClass.referenceFunctionSymbol(CallingConventions.begin) { it.valueParameters.size == 1 }
|
val beginFunc = decoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||||
val call = irInvoke(
|
val call = irInvoke(
|
||||||
irGet(loadFunc.valueParameters[0]),
|
irGet(loadFunc.valueParameters[0]),
|
||||||
beginFunc,
|
beginFunc,
|
||||||
irGet(localSerialDesc),
|
irGet(localSerialDesc),
|
||||||
typeHint = inputClass.defaultType.toIrType()
|
typeHint = inputClass.defaultType
|
||||||
)
|
)
|
||||||
val localInput = irTemporary(call, "input")
|
val localInput = irTemporary(call, "input")
|
||||||
|
|
||||||
@@ -380,19 +411,20 @@ open class SerializerIrGenerator(
|
|||||||
val decoderCalls: List<Pair<Int, IrExpression>> =
|
val decoderCalls: List<Pair<Int, IrExpression>> =
|
||||||
serializableProperties.mapIndexed { index, property ->
|
serializableProperties.mapIndexed { index, property ->
|
||||||
val body = irBlock {
|
val body = irBlock {
|
||||||
val decodeFuncToCall = formEncodeDecodePropertyCall(localInput.get(), loadFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
val decodeFuncToCall =
|
||||||
inputClass.referenceFunctionSymbol(
|
formEncodeDecodePropertyCall(localInput.get(), loadFunc.dispatchReceiverParameter!!, property, { innerSerial, sti ->
|
||||||
"${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}", {it.valueParameters.size == 4}
|
inputClass.functions.single {
|
||||||
) to listOf(
|
it.owner.name.asString() == "${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}" &&
|
||||||
localSerialDesc.get(), irInt(index), innerSerial, serialPropertiesMap.getValue(property.descriptor).get()
|
it.owner.valueParameters.size == 4
|
||||||
)
|
} to listOf(
|
||||||
}, {
|
localSerialDesc.get(), irInt(index), innerSerial, serialPropertiesMap.getValue(property.descriptor).get()
|
||||||
inputClass.referenceFunctionSymbol(
|
)
|
||||||
"${CallingConventions.decode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}", {it.valueParameters.size == 2}
|
}, {sti ->
|
||||||
) to listOf(
|
inputClass.functions.single {
|
||||||
localSerialDesc.get(), irInt(index)
|
it.owner.name.asString() == "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}" &&
|
||||||
)
|
it.owner.valueParameters.size == 2
|
||||||
}, returnTypeHint = property.type.toIrType())
|
} to listOf(localSerialDesc.get(), irInt(index))
|
||||||
|
}, returnTypeHint = property.type)
|
||||||
// local$i = localInput.decode...(...)
|
// local$i = localInput.decode...(...)
|
||||||
+irSet(
|
+irSet(
|
||||||
serialPropertiesMap.getValue(property.descriptor).symbol,
|
serialPropertiesMap.getValue(property.descriptor).symbol,
|
||||||
@@ -407,7 +439,7 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if (decoder.decodeSequentially())
|
// if (decoder.decodeSequentially())
|
||||||
val decodeSequentiallyCall = irInvoke(localInput.get(), inputClass.referenceFunctionSymbol(CallingConventions.decodeSequentially))
|
val decodeSequentiallyCall = irInvoke(localInput.get(), inputClass.functionByName(CallingConventions.decodeSequentially))
|
||||||
|
|
||||||
val sequentialPart = irBlock {
|
val sequentialPart = irBlock {
|
||||||
decoderCalls.forEach { (_, expr) -> +expr.deepCopyWithVariables() }
|
decoderCalls.forEach { (_, expr) -> +expr.deepCopyWithVariables() }
|
||||||
@@ -416,7 +448,7 @@ open class SerializerIrGenerator(
|
|||||||
val byIndexPart: IrExpression = irWhile().also { loop ->
|
val byIndexPart: IrExpression = irWhile().also { loop ->
|
||||||
loop.condition = flagVar.get()
|
loop.condition = flagVar.get()
|
||||||
loop.body = irBlock {
|
loop.body = irBlock {
|
||||||
val readElementF = inputClass.referenceFunctionSymbol(CallingConventions.decodeElementIndex)
|
val readElementF = inputClass.functionByName(CallingConventions.decodeElementIndex)
|
||||||
+irSet(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
|
+irSet(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
|
||||||
+irWhen {
|
+irWhen {
|
||||||
// if index == -1 (READ_DONE) break loop
|
// if index == -1 (READ_DONE) break loop
|
||||||
@@ -445,7 +477,7 @@ open class SerializerIrGenerator(
|
|||||||
+irIfThenElse(compilerContext.irBuiltIns.unitType, decodeSequentiallyCall, sequentialPart, byIndexPart)
|
+irIfThenElse(compilerContext.irBuiltIns.unitType, decodeSequentiallyCall, sequentialPart, byIndexPart)
|
||||||
|
|
||||||
//input.endStructure(...)
|
//input.endStructure(...)
|
||||||
val endFunc = inputClass.referenceFunctionSymbol(CallingConventions.end)
|
val endFunc = inputClass.functionByName(CallingConventions.end)
|
||||||
+irInvoke(
|
+irInvoke(
|
||||||
localInput.get(),
|
localInput.get(),
|
||||||
endFunc,
|
endFunc,
|
||||||
@@ -453,16 +485,16 @@ open class SerializerIrGenerator(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val typeArgs = (loadFunc.returnType as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
|
val typeArgs = (loadFunc.returnType as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
|
||||||
if (serializableDescriptor.isInternalSerializable) {
|
if (serializableIrClass.isInternalSerializable) {
|
||||||
var args: List<IrExpression> = serializableProperties.map { serialPropertiesMap.getValue(it.descriptor).get() }
|
var args: List<IrExpression> = serializableProperties.map { serialPropertiesMap.getValue(it.descriptor).get() }
|
||||||
args = bitMasks.map { irGet(it) } + args + irNull()
|
args = bitMasks.map { irGet(it) } + args + irNull()
|
||||||
val ctor: IrConstructorSymbol = serializableSyntheticConstructor(serializableIrClass)
|
val ctor: IrConstructorSymbol = serializableSyntheticConstructor(serializableIrClass)
|
||||||
+irReturn(irInvoke(null, ctor, typeArgs, args))
|
+irReturn(irInvoke(null, ctor, typeArgs, args))
|
||||||
} else {
|
} else {
|
||||||
if (DescriptorUtils.isLocal(serializerDescriptor)) {
|
if (irClass.isLocal) {
|
||||||
// if the serializer is local, then the serializable class too, since they must be in the same scope
|
// if the serializer is local, then the serializable class too, since they must be in the same scope
|
||||||
throw CompilationException(
|
throw CompilationException(
|
||||||
"External serializer class `${serializerDescriptor.fqNameSafe}` is local. Local external serializers are not supported yet.",
|
"External serializer class `${irClass.fqNameWhenAvailable}` is local. Local external serializers are not supported yet.",
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
@@ -470,13 +502,11 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
generateGoldenMaskCheck(bitMasks, properties, localSerialDesc.get())
|
generateGoldenMaskCheck(bitMasks, properties, localSerialDesc.get())
|
||||||
|
|
||||||
val ctor: IrConstructorSymbol =
|
val ctor: IrConstructorSymbol = serializableIrClass.constructors.primary.symbol
|
||||||
compilerContext.referenceConstructors(serializableDescriptor.fqNameSafe).single { it.owner.isPrimary }
|
|
||||||
val params = ctor.owner.valueParameters
|
val params = ctor.owner.valueParameters
|
||||||
|
|
||||||
|
val variableByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = { vpd ->
|
||||||
val variableByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = {
|
val propertyDescriptor = serializableIrClass.properties.find { it.name == vpd.name }
|
||||||
val propertyDescriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, it]
|
|
||||||
if (propertyDescriptor != null) {
|
if (propertyDescriptor != null) {
|
||||||
val serializable = serialPropertiesMap[propertyDescriptor]
|
val serializable = serialPropertiesMap[propertyDescriptor]
|
||||||
(serializable ?: transientsPropertiesMap[propertyDescriptor])?.get()
|
(serializable ?: transientsPropertiesMap[propertyDescriptor])?.get()
|
||||||
@@ -489,8 +519,8 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
// constructor args:
|
// constructor args:
|
||||||
val ctorArgs = params.map { parameter ->
|
val ctorArgs = params.map { parameter ->
|
||||||
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor
|
val propertyDescriptor = serializableIrClass.properties.find { it.name == parameter.name }!! // todo: check with tests
|
||||||
val propertyDescriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameterDescriptor]!!
|
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor // TODO: remove descriptor here
|
||||||
val serialProperty = serialPropertiesMap[propertyDescriptor]
|
val serialProperty = serialPropertiesMap[propertyDescriptor]
|
||||||
|
|
||||||
// null if transient
|
// null if transient
|
||||||
@@ -532,14 +562,14 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
private fun IrBlockBodyBuilder.generateSetStandaloneProperties(
|
private fun IrBlockBodyBuilder.generateSetStandaloneProperties(
|
||||||
serializableVar: IrVariable,
|
serializableVar: IrVariable,
|
||||||
propVars: (PropertyDescriptor) -> IrVariable,
|
propVars: (IrProperty) -> IrVariable,
|
||||||
propIndexes: (PropertyDescriptor) -> Int,
|
propIndexes: (IrProperty) -> Int,
|
||||||
bitMasks: List<IrVariable>
|
bitMasks: List<IrVariable>
|
||||||
) {
|
) {
|
||||||
for (property in properties.serializableStandaloneProperties) {
|
for (property in properties.serializableStandaloneProperties) {
|
||||||
val localPropIndex = propIndexes(property.descriptor)
|
val localPropIndex = propIndexes(property.descriptor)
|
||||||
// generate setter call
|
// generate setter call
|
||||||
val setter = property.getIrPropertyFrom(serializableIrClass).setter!!
|
val setter = property.descriptor.setter!!
|
||||||
val propSeenTest =
|
val propSeenTest =
|
||||||
irNotEquals(
|
irNotEquals(
|
||||||
irInt(0),
|
irInt(0),
|
||||||
@@ -556,21 +586,46 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// !!! TODO: this doesn't work with OLD FE !!!
|
||||||
|
fun generate() {
|
||||||
|
val prop = generatedSerialDescPropertyDescriptor?.let { generateSerializableClassProperty(it); true } ?: false
|
||||||
|
if (prop)
|
||||||
|
generateSerialDesc()
|
||||||
|
val save = irClass.findPluginGeneratedMethod(SAVE)?.let { generateSave(it); true } ?: false
|
||||||
|
val load = irClass.findPluginGeneratedMethod(SAVE)?.let { generateSave(it); true } ?: false
|
||||||
|
irClass.findPluginGeneratedMethod(SerialEntityNames.CHILD_SERIALIZERS_GETTER.identifier)?.let { generateChildSerializersGetter(it) }
|
||||||
|
irClass.findPluginGeneratedMethod(SerialEntityNames.TYPE_PARAMS_SERIALIZERS_GETTER.identifier)?.let { generateTypeParamsSerializersGetter(it) }
|
||||||
|
if (!prop && (save || load))
|
||||||
|
generateSerialDesc()
|
||||||
|
if (serializableIrClass.typeParameters.isNotEmpty()) {
|
||||||
|
findSerializerConstructorForTypeArgumentsSerializers(irClass)?.let {
|
||||||
|
generateGenericFieldsAndConstructor(it.owner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun generate(
|
fun generate(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
context: SerializationPluginContext,
|
context: SerializationPluginContext,
|
||||||
bindingContext: BindingContext,
|
|
||||||
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
||||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||||
) {
|
) {
|
||||||
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
|
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
|
||||||
val generator = when {
|
val generator = when {
|
||||||
serializableDesc.isEnumWithLegacyGeneratedSerializer() -> SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
serializableDesc.isEnumWithLegacyGeneratedSerializer() -> SerializerForEnumsGenerator(
|
||||||
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
irClass,
|
||||||
else -> SerializerIrGenerator(irClass, context, bindingContext, metadataPlugin, serialInfoJvmGenerator)
|
context,
|
||||||
|
serialInfoJvmGenerator
|
||||||
|
)
|
||||||
|
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context, serialInfoJvmGenerator)
|
||||||
|
else -> SerializerIrGenerator(irClass, context, metadataPlugin, serialInfoJvmGenerator)
|
||||||
}
|
}
|
||||||
generator.generate()
|
generator.generate()
|
||||||
|
val declaration = irClass.constructors.primary // todo: move to appropriate place
|
||||||
|
if (declaration.body == null) declaration.body = context.generateBodyForDefaultConstructor(declaration)
|
||||||
irClass.patchDeclarationParents(irClass.parent)
|
irClass.patchDeclarationParents(irClass.parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -51,8 +51,8 @@ object VersionReader {
|
|||||||
return versions
|
return versions
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVersionsForCurrentModuleFromContext(module: ModuleDescriptor, context: BindingContext): RuntimeVersions? {
|
fun getVersionsForCurrentModuleFromContext(module: ModuleDescriptor, context: BindingContext?): RuntimeVersions? {
|
||||||
context.get(VERSIONS_SLICE, module)?.let { return it }
|
context?.get(VERSIONS_SLICE, module)?.let { return it }
|
||||||
return getVersionsForCurrentModule(module)
|
return getVersionsForCurrentModule(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -56,9 +56,9 @@ private class SerializerClassLowering(
|
|||||||
private val serialInfoJvmGenerator = SerialInfoImplJvmIrGenerator(context, moduleFragment).also { context.serialInfoImplJvmIrGenerator = it }
|
private val serialInfoJvmGenerator = SerialInfoImplJvmIrGenerator(context, moduleFragment).also { context.serialInfoImplJvmIrGenerator = it }
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
SerializableIrGenerator.generate(irClass, context, context.bindingContext)
|
SerializableIrGenerator.generate(irClass, context)
|
||||||
SerializerIrGenerator.generate(irClass, context, context.bindingContext, context.metadataPlugin, serialInfoJvmGenerator)
|
SerializerIrGenerator.generate(irClass, context, context.metadataPlugin, serialInfoJvmGenerator)
|
||||||
SerializableCompanionIrGenerator.generate(irClass, context, context.bindingContext)
|
SerializableCompanionIrGenerator.generate(irClass, context)
|
||||||
|
|
||||||
if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {
|
if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {
|
||||||
serialInfoJvmGenerator.generate(irClass)
|
serialInfoJvmGenerator.generate(irClass)
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.name.CallableId
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
|
|
||||||
// FIXME: this has to be shared (copied from plugin example)
|
// FIXME KT-53096: this has to be shared (copied from plugin example)
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
fun FirDeclarationGenerationExtension.buildConstructor(classId: ClassId, isInner: Boolean, key: GeneratedDeclarationKey): FirConstructor {
|
fun FirDeclarationGenerationExtension.buildConstructor(classId: ClassId, isInner: Boolean, key: GeneratedDeclarationKey): FirConstructor {
|
||||||
val lookupTag = ConeClassLikeLookupTagImpl(classId)
|
val lookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||||
|
|||||||
+1
-1
@@ -212,7 +212,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
|||||||
return f.symbol
|
return f.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class) // TODO: localSerializersFieldDescriptors
|
||||||
override fun generateProperties(callableId: CallableId, context: MemberGenerationContext?): List<FirPropertySymbol> {
|
override fun generateProperties(callableId: CallableId, context: MemberGenerationContext?): List<FirPropertySymbol> {
|
||||||
val owner = context?.owner ?: return emptyList()
|
val owner = context?.owner ?: return emptyList()
|
||||||
if (owner.name != SerialEntityNames.SERIALIZER_CLASS_NAME) return emptyList()
|
if (owner.name != SerialEntityNames.SERIALIZER_CLASS_NAME) return emptyList()
|
||||||
|
|||||||
+3
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
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
|
||||||
|
|
||||||
@@ -110,6 +112,7 @@ object SerialEntityNames {
|
|||||||
internal const val typeArgPrefix = "typeSerial"
|
internal const val typeArgPrefix = "typeSerial"
|
||||||
|
|
||||||
internal val wrapIntoNullableExt = SerializationPackages.builtinsPackageFqName.child(Name.identifier("nullable"))
|
internal val wrapIntoNullableExt = SerializationPackages.builtinsPackageFqName.child(Name.identifier("nullable"))
|
||||||
|
internal val wrapIntoNullableCallableId = CallableId(SerializationPackages.builtinsPackageFqName, Name.identifier("nullable"))
|
||||||
}
|
}
|
||||||
|
|
||||||
object SpecialBuiltins {
|
object SpecialBuiltins {
|
||||||
|
|||||||
+114
-13
@@ -6,6 +6,15 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.lazy.IrMaybeDeserializedClass
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
|
import org.jetbrains.kotlin.ir.types.isAny
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer
|
import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
@@ -17,25 +26,43 @@ import org.jetbrains.kotlin.resolve.source.getPsi
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.isInterface
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isInternalSerializable
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isInternallySerializableEnum
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SERIALIZABLE_PROPERTIES
|
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SERIALIZABLE_PROPERTIES
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginMetadataExtensions
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginMetadataExtensions
|
||||||
|
|
||||||
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) {
|
interface ISerializableProperties<D, T, S : ISerializableProperty<D, T>> {
|
||||||
|
val serializableProperties: List<S>
|
||||||
|
val isExternallySerializable: Boolean
|
||||||
|
val serializableConstructorProperties: List<S>
|
||||||
|
val serializableStandaloneProperties: List<S>
|
||||||
|
}
|
||||||
|
|
||||||
|
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext?) :
|
||||||
|
ISerializableProperties<PropertyDescriptor, KotlinType, SerializableProperty> {
|
||||||
private val primaryConstructorParameters: List<ValueParameterDescriptor> =
|
private val primaryConstructorParameters: List<ValueParameterDescriptor> =
|
||||||
serializableClass.unsubstitutedPrimaryConstructor?.valueParameters ?: emptyList()
|
serializableClass.unsubstitutedPrimaryConstructor?.valueParameters ?: emptyList()
|
||||||
|
|
||||||
val serializableProperties: List<SerializableProperty>
|
override val serializableProperties: List<SerializableProperty>
|
||||||
val isExternallySerializable: Boolean
|
override val isExternallySerializable: Boolean
|
||||||
private val primaryConstructorProperties: Map<PropertyDescriptor, Boolean>
|
private val primaryConstructorProperties: Map<PropertyDescriptor, Boolean>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val descriptorsSequence = serializableClass.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES)
|
val descriptorsSequence = serializableClass.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
// call to any BindingContext.get should be only AFTER MemberScope.getContributedDescriptors
|
// call to any BindingContext.get should be only AFTER MemberScope.getContributedDescriptors
|
||||||
|
// TODO: fix binding context shit
|
||||||
primaryConstructorProperties =
|
primaryConstructorProperties =
|
||||||
primaryConstructorParameters.asSequence()
|
primaryConstructorParameters.asSequence()
|
||||||
.map { parameter -> bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter] to parameter.declaresDefaultValue() }
|
.map { parameter ->
|
||||||
|
bindingContext?.get(
|
||||||
|
BindingContext.VALUE_PARAMETER_AS_PROPERTY,
|
||||||
|
parameter
|
||||||
|
) to parameter.declaresDefaultValue()
|
||||||
|
}
|
||||||
.mapNotNull { (a, b) -> if (a == null) null else a to b }
|
.mapNotNull { (a, b) -> if (a == null) null else a to b }
|
||||||
.toMap()
|
.toMap()
|
||||||
|
|
||||||
@@ -56,7 +83,8 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
|
|||||||
prop.hasBackingField(bindingContext) || (prop is DeserializedPropertyDescriptor && prop.backingField != null) // workaround for TODO in .hasBackingField
|
prop.hasBackingField(bindingContext) || (prop is DeserializedPropertyDescriptor && prop.backingField != null) // workaround for TODO in .hasBackingField
|
||||||
// workaround for overridden getter (val) and getter+setter (var) - in this case hasBackingField returning false
|
// workaround for overridden getter (val) and getter+setter (var) - in this case hasBackingField returning false
|
||||||
// but initializer presents only for property with backing field
|
// but initializer presents only for property with backing field
|
||||||
|| declaresDefaultValue,
|
|| declaresDefaultValue
|
||||||
|
|| prop.backingField != null, // todo: find out what happens next
|
||||||
declaresDefaultValue
|
declaresDefaultValue
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -76,12 +104,12 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val serializableConstructorProperties: List<SerializableProperty> =
|
override val serializableConstructorProperties: List<SerializableProperty> =
|
||||||
serializableProperties.asSequence()
|
serializableProperties.asSequence()
|
||||||
.filter { primaryConstructorProperties.contains(it.descriptor) }
|
.filter { primaryConstructorProperties.contains(it.descriptor) }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val serializableStandaloneProperties: List<SerializableProperty> =
|
override val serializableStandaloneProperties: List<SerializableProperty> =
|
||||||
serializableProperties.minus(serializableConstructorProperties)
|
serializableProperties.minus(serializableConstructorProperties)
|
||||||
|
|
||||||
val size = serializableProperties.size
|
val size = serializableProperties.size
|
||||||
@@ -92,7 +120,7 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
|
|||||||
?.original?.valueParameters?.any { it.declaresDefaultValue() } ?: false
|
?.original?.valueParameters?.any { it.declaresDefaultValue() } ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PropertyDescriptor.declaresDefaultValue(): Boolean{
|
fun PropertyDescriptor.declaresDefaultValue(): Boolean {
|
||||||
when (val declaration = this.source.getPsi()) {
|
when (val declaration = this.source.getPsi()) {
|
||||||
is KtDeclarationWithInitializer -> return declaration.initializer != null
|
is KtDeclarationWithInitializer -> return declaration.initializer != null
|
||||||
is KtParameter -> return declaration.defaultValue != null
|
is KtParameter -> return declaration.defaultValue != null
|
||||||
@@ -112,7 +140,7 @@ fun PropertyDescriptor.declaresDefaultValue(): Boolean{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal val SerializableProperties.goldenMask: Int
|
internal val ISerializableProperties<*, *, *>.goldenMask: Int
|
||||||
get() {
|
get() {
|
||||||
var goldenMask = 0
|
var goldenMask = 0
|
||||||
var requiredBit = 1
|
var requiredBit = 1
|
||||||
@@ -125,7 +153,7 @@ internal val SerializableProperties.goldenMask: Int
|
|||||||
return goldenMask
|
return goldenMask
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val SerializableProperties.goldenMaskList: List<Int>
|
internal val ISerializableProperties<*, *, *>.goldenMaskList: List<Int>
|
||||||
get() {
|
get() {
|
||||||
val maskSlotCount = serializableProperties.bitMaskSlotCount()
|
val maskSlotCount = serializableProperties.bitMaskSlotCount()
|
||||||
val goldenMaskList = MutableList(maskSlotCount) { 0 }
|
val goldenMaskList = MutableList(maskSlotCount) { 0 }
|
||||||
@@ -140,11 +168,14 @@ internal val SerializableProperties.goldenMaskList: List<Int>
|
|||||||
return goldenMaskList
|
return goldenMaskList
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun List<SerializableProperty>.bitMaskSlotCount() = size / 32 + 1
|
internal fun List<ISerializableProperty<*, *>>.bitMaskSlotCount() = size / 32 + 1
|
||||||
internal fun bitMaskSlotAt(propertyIndex: Int) = propertyIndex / 32
|
internal fun bitMaskSlotAt(propertyIndex: Int) = propertyIndex / 32
|
||||||
|
|
||||||
internal fun BindingContext.serializablePropertiesFor(classDescriptor: ClassDescriptor, serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null): SerializableProperties {
|
internal fun BindingContext?.serializablePropertiesFor(
|
||||||
val props = this.get(SERIALIZABLE_PROPERTIES, classDescriptor) ?: SerializableProperties(classDescriptor, this)
|
classDescriptor: ClassDescriptor,
|
||||||
|
serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null
|
||||||
|
): SerializableProperties {
|
||||||
|
val props = this?.get(SERIALIZABLE_PROPERTIES, classDescriptor) ?: SerializableProperties(classDescriptor, this)
|
||||||
serializationDescriptorSerializer?.putIfNeeded(classDescriptor, props)
|
serializationDescriptorSerializer?.putIfNeeded(classDescriptor, props)
|
||||||
return props
|
return props
|
||||||
}
|
}
|
||||||
@@ -156,3 +187,73 @@ private fun unsort(descriptor: ClassDescriptor, props: List<SerializableProperty
|
|||||||
val propsMap = props.associateBy { it.descriptor.name }
|
val propsMap = props.associateBy { it.descriptor.name }
|
||||||
return correctOrder.map { propsMap.getValue(it) }
|
return correctOrder.map { propsMap.getValue(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IrSerializableProperties(
|
||||||
|
override val serializableProperties: List<IrSerializableProperty>,
|
||||||
|
override val isExternallySerializable: Boolean,
|
||||||
|
override val serializableConstructorProperties: List<IrSerializableProperty>,
|
||||||
|
override val serializableStandaloneProperties: List<IrSerializableProperty>
|
||||||
|
) : ISerializableProperties<IrProperty, IrSimpleType, IrSerializableProperty> {
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun BindingContext?.serializablePropertiesForIrBackend(
|
||||||
|
classDescriptor: IrClass,
|
||||||
|
serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null
|
||||||
|
): IrSerializableProperties {
|
||||||
|
if (this != null) {
|
||||||
|
// can work with old FE
|
||||||
|
TODO("Support this for old FE")
|
||||||
|
} else {
|
||||||
|
val properties = classDescriptor.properties.toList()
|
||||||
|
val primaryConstructorParams = classDescriptor.primaryConstructor?.valueParameters.orEmpty()
|
||||||
|
val primaryParamsAsProps = properties.associateBy { it.name }.let { namesMap ->
|
||||||
|
primaryConstructorParams.mapNotNull {
|
||||||
|
if (it.name !in namesMap) null else namesMap.getValue(it.name) to it.hasDefaultValue()
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isPropSerializable(it: IrProperty) =
|
||||||
|
if (classDescriptor.isInternalSerializable) !it.annotations.hasAnnotation(SerializationAnnotations.serialTransientFqName)
|
||||||
|
else !DescriptorVisibilities.isPrivate(it.visibility) && ((it.isVar && !it.annotations.hasAnnotation(SerializationAnnotations.serialTransientFqName)) || primaryParamsAsProps.contains(
|
||||||
|
it
|
||||||
|
))
|
||||||
|
|
||||||
|
val (primaryCtorSerializableProps, bodySerializableProps) = properties
|
||||||
|
.filter { !it.isFakeOverride && !it.isDelegated }
|
||||||
|
.filter(::isPropSerializable)
|
||||||
|
.map {
|
||||||
|
val isConstructorParameterWithDefault = primaryParamsAsProps[it] ?: false
|
||||||
|
IrSerializableProperty(
|
||||||
|
it,
|
||||||
|
isConstructorParameterWithDefault,
|
||||||
|
it.backingField != null,
|
||||||
|
it.backingField?.initializer != null || isConstructorParameterWithDefault
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.partition { primaryParamsAsProps.contains(it.descriptor) }
|
||||||
|
|
||||||
|
val serializableProps = run {
|
||||||
|
val supers = classDescriptor.getParentClassNotAny()
|
||||||
|
if (supers == null || !supers.isInternalSerializable)
|
||||||
|
primaryCtorSerializableProps + bodySerializableProps
|
||||||
|
else
|
||||||
|
serializablePropertiesForIrBackend(
|
||||||
|
supers,
|
||||||
|
serializationDescriptorSerializer
|
||||||
|
).serializableProperties + primaryCtorSerializableProps + bodySerializableProps
|
||||||
|
} // todo: implement unsorting
|
||||||
|
|
||||||
|
val isExternallySerializable =
|
||||||
|
classDescriptor.isInternallySerializableEnum() || primaryConstructorParams.size == primaryParamsAsProps.size
|
||||||
|
|
||||||
|
return IrSerializableProperties(serializableProps, isExternallySerializable, primaryCtorSerializableProps, bodySerializableProps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrClass.getParentClassNotAny(): IrClass? {
|
||||||
|
val parentClass =
|
||||||
|
superTypes
|
||||||
|
.mapNotNull { it.classOrNull?.owner }
|
||||||
|
.singleOrNull { it.kind == ClassKind.CLASS || it.kind == ClassKind.ENUM_CLASS } ?: return null
|
||||||
|
return if (parentClass.defaultType.isAny()) null else parentClass
|
||||||
|
}
|
||||||
+46
-9
@@ -19,26 +19,63 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.overrides
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||||
|
import org.jetbrains.kotlin.ir.util.module
|
||||||
import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer
|
import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.ValueArgument
|
import org.jetbrains.kotlin.psi.ValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.asSimpleType
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.analyzeSpecialSerializers
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.analyzeSpecialSerializers
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.genericIndex
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.overridenSerializer
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialNameValue
|
||||||
|
|
||||||
class SerializableProperty(
|
class SerializableProperty(
|
||||||
val descriptor: PropertyDescriptor,
|
override val descriptor: PropertyDescriptor,
|
||||||
val isConstructorParameterWithDefault: Boolean,
|
override val isConstructorParameterWithDefault: Boolean,
|
||||||
hasBackingField: Boolean,
|
hasBackingField: Boolean,
|
||||||
declaresDefaultValue: Boolean
|
declaresDefaultValue: Boolean
|
||||||
) {
|
) : ISerializableProperty<PropertyDescriptor, KotlinType> {
|
||||||
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
override val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
||||||
val type = descriptor.type
|
override val type = descriptor.type
|
||||||
val genericIndex = type.genericIndex
|
override val genericIndex = type.genericIndex
|
||||||
val module = descriptor.module
|
val module = descriptor.module
|
||||||
val serializableWith = descriptor.serializableWith ?: analyzeSpecialSerializers(module, descriptor.annotations)?.defaultType
|
override val serializableWith = descriptor.serializableWith ?: analyzeSpecialSerializers(module, descriptor.annotations)?.defaultType
|
||||||
val optional = !descriptor.annotations.serialRequired && declaresDefaultValue
|
override val optional = !descriptor.annotations.serialRequired && declaresDefaultValue
|
||||||
val transient = descriptor.annotations.serialTransient || !hasBackingField
|
override val transient = descriptor.annotations.serialTransient || !hasBackingField
|
||||||
val annotationsWithArguments: List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
|
val annotationsWithArguments: List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
|
||||||
descriptor.annotationsWithArguments()
|
descriptor.annotationsWithArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ISerializableProperty<D, T> {
|
||||||
|
val descriptor: D
|
||||||
|
val isConstructorParameterWithDefault: Boolean
|
||||||
|
val name: String
|
||||||
|
val type: T
|
||||||
|
val genericIndex: Int?
|
||||||
|
val serializableWith: T?
|
||||||
|
val optional: Boolean
|
||||||
|
val transient: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class IrSerializableProperty(
|
||||||
|
override val descriptor: IrProperty,
|
||||||
|
override val isConstructorParameterWithDefault: Boolean,
|
||||||
|
hasBackingField: Boolean,
|
||||||
|
declaresDefaultValue: Boolean
|
||||||
|
) : ISerializableProperty<IrProperty, IrSimpleType> {
|
||||||
|
override val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
||||||
|
override val type = descriptor.getter!!.returnType as IrSimpleType
|
||||||
|
override val genericIndex = type.genericIndex
|
||||||
|
override val serializableWith = type.overridenSerializer /* ?:analyzeSpecialSerializers(module, descriptor.annotations)?.defaultType */ // TODO
|
||||||
|
override val optional = !descriptor.annotations.hasAnnotation(SerializationAnnotations.requiredAnnotationFqName) && declaresDefaultValue
|
||||||
|
override val transient = descriptor.annotations.hasAnnotation(SerializationAnnotations.serialTransientFqName) || !hasBackingField
|
||||||
|
}
|
||||||
+16
-5
@@ -8,17 +8,22 @@ package org.jetbrains.kotlinx.serialization
|
|||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
|
||||||
import org.jetbrains.kotlin.test.TargetBackend
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
import org.jetbrains.kotlin.test.backend.BlackBoxCodegenSuppressor
|
import org.jetbrains.kotlin.test.backend.BlackBoxCodegenSuppressor
|
||||||
import org.jetbrains.kotlin.test.backend.handlers.*
|
import org.jetbrains.kotlin.test.backend.handlers.IrTextDumpHandler
|
||||||
|
import org.jetbrains.kotlin.test.backend.handlers.IrTreeVerifierHandler
|
||||||
|
import org.jetbrains.kotlin.test.backend.handlers.JvmBoxRunner
|
||||||
import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade
|
import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade
|
||||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
import org.jetbrains.kotlin.test.builders.fir2IrStep
|
import org.jetbrains.kotlin.test.builders.fir2IrStep
|
||||||
import org.jetbrains.kotlin.test.builders.irHandlersStep
|
import org.jetbrains.kotlin.test.builders.irHandlersStep
|
||||||
import org.jetbrains.kotlin.test.builders.jvmArtifactsHandlersStep
|
import org.jetbrains.kotlin.test.builders.jvmArtifactsHandlersStep
|
||||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
||||||
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
||||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
|
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
|
||||||
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
|
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
|
||||||
|
import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.fir.FirSerializationExtensionRegistrar
|
import org.jetbrains.kotlinx.serialization.compiler.fir.FirSerializationExtensionRegistrar
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
abstract class AbstractSerializationFirMembersTest: AbstractKotlinCompilerTest() {
|
abstract class AbstractSerializationFirMembersTest: AbstractKotlinCompilerTest() {
|
||||||
override fun TestConfigurationBuilder.configuration() {
|
override fun TestConfigurationBuilder.configuration() {
|
||||||
@@ -38,6 +43,16 @@ abstract class AbstractSerializationFirMembersTest: AbstractKotlinCompilerTest()
|
|||||||
open class AbstractSerializationFirBlackBoxTest : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) {
|
open class AbstractSerializationFirBlackBoxTest : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) {
|
||||||
override fun TestConfigurationBuilder.configuration() {
|
override fun TestConfigurationBuilder.configuration() {
|
||||||
baseFirDiagnosticTestConfiguration()
|
baseFirDiagnosticTestConfiguration()
|
||||||
|
configureForKotlinxSerialization(listOf(getSerializationCoreLibraryJar()!!)) {
|
||||||
|
FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())
|
||||||
|
}
|
||||||
|
useCustomRuntimeClasspathProviders({ ts ->
|
||||||
|
object : RuntimeClasspathProvider(ts) {
|
||||||
|
override fun runtimeClassPaths(module: TestModule): List<File> {
|
||||||
|
return listOf(getSerializationCoreLibraryJar()!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
defaultDirectives {
|
defaultDirectives {
|
||||||
+FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES
|
+FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES
|
||||||
}
|
}
|
||||||
@@ -55,9 +70,5 @@ open class AbstractSerializationFirBlackBoxTest : AbstractKotlinCompilerWithTarg
|
|||||||
}
|
}
|
||||||
|
|
||||||
useAfterAnalysisCheckers(::BlackBoxCodegenSuppressor)
|
useAfterAnalysisCheckers(::BlackBoxCodegenSuppressor)
|
||||||
|
|
||||||
configureForKotlinxSerialization(listOf(getSerializationCoreLibraryJar()!!)) {
|
|
||||||
FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user