diff --git a/libraries/tools/kotlin-maven-serialization/pom.xml b/libraries/tools/kotlin-maven-serialization/pom.xml
index 33098bdf480..eb9e851fe89 100755
--- a/libraries/tools/kotlin-maven-serialization/pom.xml
+++ b/libraries/tools/kotlin-maven-serialization/pom.xml
@@ -7,9 +7,11 @@
3.0.5
${basedir}/../../../plugins/kotlin-serialization/kotlin-serialization-compiler/src/
+ ${basedir}/../../../plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler
${basedir}/src/main/kotlin
${basedir}/src/main/resources
${basedir}/target/src/main/kotlin
+ ${basedir}/target/src/main/kotlin/org/jetbrains/kotlinx/serialization/compiler
${basedir}/target/resource
1.2-SNAPSHOT
@@ -17,7 +19,7 @@
org.jetbrains.kotlinx
kotlinx-maven-serialization-plugin
jar
- 0.2
+ 0.3
Serialization plugin for Maven
@@ -56,7 +58,7 @@
3.0.0
- copy-sources
+ copy-maven-sources
validate
copy-resources
@@ -64,11 +66,23 @@
${serialization.target-src}
- ${serialization.src}
${serialization.maven.plugin.src}
+
+ copy-sources
+ validate
+
+ copy-resources
+
+
+ ${serialization.target-src.kt}
+
+ ${serialization.src.kt}
+
+
+
copy-resources
validate
diff --git a/libraries/tools/kotlin-serialization/build.gradle b/libraries/tools/kotlin-serialization/build.gradle
index a356756a6d6..2f2627e07b9 100644
--- a/libraries/tools/kotlin-serialization/build.gradle
+++ b/libraries/tools/kotlin-serialization/build.gradle
@@ -8,7 +8,7 @@ configureJvmProject(project)
configurePublishing(project)
group = 'org.jetbrains.kotlinx'
-version = '0.2'
+version = '0.3'
if (!project.hasProperty("deploy")) {
version = "$version-SNAPSHOT"
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md b/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md
index 698ebf79b3c..bb31a32e291 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md
@@ -1,12 +1,7 @@
# Kotlin serialization IDEA plugin
Kotlin serialization plugin consists of three parts: a compiler plugin, an IntelliJ plugin and a runtime library.
-This is the IDEA plugin. Gradle and Maven plugins can be found in `libraries` folder.
-
-Please note that this plugin currently works only for highlighting and resolving symbols, and it doesn't work with embedded IDEA compiler.
-To build any project with serialization within IDEA, you'll need to delegate all build actions to gradle:
-`File - Settings - Build, Execution, Deployment - Build Tools - Gradle - Runner -` tick `Delegate IDE build/run actions to gradle`.
-IntelliJ projects currently are not supported.
+This is the folder with common source for all plugins, IDEA plugin is built from here. Gradle and Maven plugins can be found in `libraries` folder.
Compiler plugins are uploaded on bintray: https://bintray.com/kotlin/kotlinx/kotlinx.serialization.plugin
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml
index 3b9aa950cb8..d64f51754fd 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml
@@ -1,7 +1,7 @@
-
+
Kotlin-serialization
org.jetbrains.kotlinx.serialization
- 0.2
+ 0.3
org.jetbrains.kotlin
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt
index 767bf5c2e72..cfa0d638740 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt
@@ -90,10 +90,12 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
"C", "kotlin.Char" -> "CharSerializer"
"kotlin.String" -> "StringSerializer"
"kotlin.Pair" -> "PairSerializer"
- "kotlin.collections.Collection", "kotlin.collections.List", "kotlin.collections.ArrayList" -> "ArrayListSerializer"
- "kotlin.collections.Set", "kotlin.collections.LinkedHashSet" -> "LinkedHashSetSerializer"
+ "kotlin.Triple" -> "TripleSerializer"
+ "kotlin.collections.Collection", "kotlin.collections.List",
+ "kotlin.collections.ArrayList", "kotlin.collections.MutableList" -> "ArrayListSerializer"
+ "kotlin.collections.Set", "kotlin.collections.LinkedHashSet", "kotlin.collections.MutableSet" -> "LinkedHashSetSerializer"
"kotlin.collections.HashSet" -> "HashSetSerializer"
- "kotlin.collections.Map", "kotlin.collections.LinkedHashMap" -> "LinkedHashMapSerializer"
+ "kotlin.collections.Map", "kotlin.collections.LinkedHashMap", "kotlin.collections.MutableMap" -> "LinkedHashMapSerializer"
"kotlin.collections.HashMap" -> "HashMapSerializer"
"kotlin.collections.Map.Entry" -> "MapEntrySerializer"
else -> return null
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt
index 15cf66f413e..41d97e9f006 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
+import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
internal class JsBlockBuilder {
val block: JsBlock = JsBlock()
@@ -81,4 +82,13 @@ internal fun TranslationContext.buildFunction(descriptor: FunctionDescriptor, bo
b.bodyGen(functionObject, innerCtx)
functionObject.body.statements += b.body
return functionObject
-}
\ No newline at end of file
+}
+
+internal fun propNotSeenTest(seenVar: JsNameRef, index: Int): JsBinaryOperation = JsAstUtils.equality(
+ JsBinaryOperation(
+ JsBinaryOperator.BIT_AND,
+ seenVar,
+ JsIntLiteral(1 shl (index % 32))
+ ),
+ JsIntLiteral(0)
+)
\ No newline at end of file
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt
index 8bf1930e1e4..eb10b5d2f40 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt
@@ -25,10 +25,8 @@ import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
import org.jetbrains.kotlin.js.translate.general.Translation
-import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.psi.KtExpression
-import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers
@@ -53,7 +51,7 @@ class SerializableJsTranslator(val declaration: KtPureClassOrObject,
val f = context.buildFunction(constructorDescriptor) { jsFun, context ->
val thiz = jsFun.scope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME).makeRef()
- val context = context.innerContextWithAliased(serializableDescriptor, thiz)
+ val context = context.innerContextWithAliased(serializableDescriptor.thisAsReceiverParameter, thiz)
+JsVars(JsVars.JsVar(thiz.name, Namer.createObjectWithPrototypeFrom(context.getQualifiedReference(serializableDescriptor))))
val seenVar = jsFun.parameters[0].name.makeRef()
@@ -71,14 +69,7 @@ class SerializableJsTranslator(val declaration: KtPureClassOrObject,
JsThrow(JsNew(missingExceptionClassRef, listOf(JsStringLiteral(prop.name))))
}
// (seen & 1 << i == 0) -- not seen
- val notSeenTest = JsAstUtils.equality(
- JsBinaryOperation(
- JsBinaryOperator.BIT_AND,
- seenVar,
- JsIntLiteral(1 shl (index % 32))
- ),
- JsIntLiteral(0)
- )
+ val notSeenTest = propNotSeenTest(seenVar, index)
+JsIf(notSeenTest, ifNotSeenStmt, assignParamStmt)
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt
index c744c2b10e7..af1f96288c1 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt
@@ -228,7 +228,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
+JsVars(bitMasks.map { JsVars.JsVar(it.name, JsIntLiteral(0)) }, false)
// var localProp0, localProp1, ...
- val localProps = orderedProperties.map { JsNameRef(jsFun.scope.declareFreshName(it.name)) }
+ val localProps = orderedProperties.mapIndexed {i, _ -> JsNameRef(jsFun.scope.declareFreshName("local$i")) }
+JsVars(localProps.map { JsVars.JsVar(it.name) }, true)
//input = input.readBegin(...)
@@ -266,7 +266,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
// input.readXxxElementValue
val sti = getSerialTypeInfo(property)
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
- val call = if (innerSerial == null) {
+ val call: JsExpression = if (innerSerial == null) {
val unknownSer = (sti.elementMethodPrefix.isEmpty())
val readFunc =
inputClass.getFuncDesc("read${sti.elementMethodPrefix}ElementValue")
@@ -278,13 +278,25 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
JsInvocation(JsNameRef(readFunc, inputVar), readArgs)
}
else {
+ val notSeenTest = propNotSeenTest(bitMasks[i / 32], i)
val readFunc =
inputClass.getFuncDesc("read${sti.elementMethodPrefix}SerializableElementValue").single()
.let { context.getNameForDescriptor(it) }
- JsInvocation(JsNameRef(readFunc, inputVar),
- serialClassDescRef,
- JsIntLiteral(i),
- innerSerial)
+ val updateFunc =
+ inputClass.getFuncDesc("update${sti.elementMethodPrefix}SerializableElementValue").single()
+ .let { context.getNameForDescriptor(it) }
+ JsConditional(notSeenTest,
+ JsInvocation(JsNameRef(readFunc, inputVar),
+ serialClassDescRef,
+ JsIntLiteral(i),
+ innerSerial),
+ JsInvocation(JsNameRef(updateFunc, inputVar),
+ serialClassDescRef,
+ JsIntLiteral(i),
+ innerSerial,
+ localProps[i]
+ )
+ )
}
// localPropI = ...
+JsAstUtils.assignment(
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt
index 30775e8f4a4..bc30e461564 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt
@@ -282,5 +282,6 @@ internal val org.jetbrains.org.objectweb.asm.Type.standardSerializer: String? ge
"Ljava/util/HashMap;" -> "HashMapSerializer"
"Ljava/util/Map\$Entry;" -> "MapEntrySerializer"
"Lkotlin/Pair;" -> "PairSerializer"
+ "Lkotlin/Triple;" -> "TripleSerializer"
else -> null
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerialInfoCodegenImpl.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerialInfoCodegenImpl.kt
index 7714114202d..e20f846e995 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerialInfoCodegenImpl.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerialInfoCodegenImpl.kt
@@ -76,12 +76,14 @@ class SerialInfoCodegenImpl(val codegen: ImplementationBodyCodegen, val thisClas
codegen.generateMethod(constr, { _, _ ->
load(0, thisAsmType)
invokespecial("java/lang/Object", "", "()V", false)
- props.forEachIndexed { index, prop ->
+ var varOffset = 1
+ props.forEach { prop ->
val propType = codegen.typeMapper.mapType(prop.type)
val propFieldName = "_" + prop.name.identifier
load(0, thisAsmType)
- load(index + 1, propType)
+ load(varOffset, propType)
putfield(thisAsmType.internalName, propFieldName, propType.descriptor)
+ varOffset += propType.size
}
areturn(Type.VOID_TYPE)
})
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt
index 069b40026bc..ce66df5496d 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt
@@ -280,12 +280,34 @@ class SerializerCodegenImpl(
aconst(codegen.typeMapper.mapType(property.type))
AsmUtil.wrapJavaClassIntoKClass(this)
}
- invokevirtual(kInputType.internalName,
- "read" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue",
- "(" + descType.descriptor + "I" +
- (if (useSerializer) kSerialLoaderType.descriptor else "")
- + (if (unknownSer) AsmTypes.K_CLASS_TYPE.descriptor else "")
- + ")" + (if (sti.unit) "V" else sti.type.descriptor), false)
+
+ fun produceCall(update: Boolean) {
+ invokevirtual(kInputType.internalName,
+ (if (update) "update" else "read") + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue",
+ "(" + descType.descriptor + "I" +
+ (if (useSerializer) kSerialLoaderType.descriptor else "")
+ + (if (unknownSer) AsmTypes.K_CLASS_TYPE.descriptor else "")
+ + (if (update) sti.type.descriptor else "")
+ + ")" + (if (sti.unit) "V" else sti.type.descriptor), false)
+ }
+
+ if (useSerializer) {
+ // we can choose either it is read or update
+ val readLabel = Label()
+ val endL = Label()
+ genValidateProperty(index, ::bitMaskOff)
+ ificmpeq(readLabel)
+ load(propVar, propertyType)
+ produceCall(true)
+ goTo(endL)
+ visitLabel(readLabel)
+ produceCall(false)
+ visitLabel(endL)
+ } else {
+ // update not supported for primitive types
+ produceCall(false)
+ }
+
if (sti.unit) {
StackValue.putUnitInstance(this)
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt
index bea2c55e825..c207a753d75 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt
@@ -25,16 +25,14 @@ import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
-import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
-import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
-import org.jetbrains.kotlinx.serialization.compiler.resolve.serialInfoFqName
+import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import java.util.*
class SerializationResolveExtension : SyntheticResolveExtension {
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List = when {
thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(KSerializerDescriptorResolver.IMPL_NAME)
- thisDescriptor.isInternalSerializable -> listOf(KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
+ thisDescriptor.isInternalSerializable && !thisDescriptor.hasCompanionObjectAsSerializer ->
+ listOf(KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
else -> listOf()
}
@@ -47,7 +45,8 @@ class SerializationResolveExtension : SyntheticResolveExtension {
override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name, ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, result: MutableSet) {
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == KSerializerDescriptorResolver.IMPL_NAME)
result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx))
- else if (thisDescriptor.isInternalSerializable && name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
+ else if (thisDescriptor.isInternalSerializable && name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME &&
+ result.none { it.name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME })
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
return
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt
index ef6a154965f..d665e1c8bef 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
+import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME
internal val packageFqName = FqName("kotlinx.serialization")
@@ -122,15 +123,33 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
// serializer annotation on class?
annotations.serializableWith?.let { return it }
// default serializable?
- if (isInternalSerializable) return this.unsubstitutedMemberScope
- .getDescriptorsFiltered(nameFilter = {it == SERIALIZER_CLASS_NAME})
- .filterIsInstance().singleOrNull()?.defaultType
+ if (isInternalSerializable) {
+ // companion object serializer?
+ if (hasCompanionObjectAsSerializer) return companionObjectDescriptor?.defaultType
+ // $serializer nested class
+ return this.unsubstitutedMemberScope
+ .getDescriptorsFiltered(nameFilter = {it == SERIALIZER_CLASS_NAME})
+ .filterIsInstance().singleOrNull()?.defaultType
+ }
return null
}
+internal val ClassDescriptor.hasCompanionObjectAsSerializer: Boolean
+ get() = companionObjectDescriptor?.annotations?.serializerForClass == this.defaultType
+
+internal fun checkSerializerNullability(classType: KotlinType, serializerType: KotlinType): KotlinType {
+ val castedToKSerial = requireNotNull(
+ serializerType.supertypes().find { isKSerializer(it) },
+ { "KSerializer is not a supertype of $serializerType" }
+ )
+ if (!classType.isMarkedNullable && castedToKSerial.arguments.first().type.isMarkedNullable)
+ throw IllegalStateException("Can't serialize non-nullable field of type ${classType} with nullable serializer ${serializerType}")
+ return serializerType
+}
+
// serializer that was declared for this specific type or annotation from a class declaration
val KotlinType.typeSerializer: KotlinType?
- get() = this.annotations.serializableWith ?: (this.toClassDescriptor).classSerializer
+ get() = (this.annotations.serializableWith ?: (this.toClassDescriptor).classSerializer)?.let { checkSerializerNullability(this, it) }
val KotlinType.genericIndex: Int?
get() = (this.constructor.declarationDescriptor as? TypeParameterDescriptor)?.index
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt
index 0fb2dc3d097..0f82c7616c1 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt
@@ -24,7 +24,7 @@ class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructor
val type = descriptor.type
val genericIndex = type.genericIndex
val module = descriptor.module
- val serializableWith = descriptor.annotations.serializableWith
+ val serializableWith = descriptor.annotations.serializableWith?.let { checkSerializerNullability(type, it) }
val optional = descriptor.annotations.serialOptional
val transient = descriptor.annotations.serialTransient
val annotations = descriptor.annotations