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