diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index b6c2c94df07..820fee8b1e8 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -588,15 +588,11 @@ interface IrBuilderExtension { typeArgs = listOf(thisIrType) } enumSerializerId -> { - serializerClass = module.getClassFromInternalSerializationPackage("CommonEnumSerializer") + serializerClass = module.getClassFromInternalSerializationPackage(SpecialBuiltins.enumSerializer) args = kType.toClassDescriptor!!.let { enumDesc -> listOf( irString(enumDesc.serialName()), - irCall(findEnumValuesMethod(enumDesc)), - createArrayOfExpression( - compilerContext.irBuiltIns.stringType, - getEnumMembersNames(enumDesc).map { irString(it) }.toList() - ) + irCall(findEnumValuesMethod(enumDesc)) ) } typeArgs = listOf(thisIrType) 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 8266f872cd2..e8c7222d949 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 @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtPureClassOrObject +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.types.KotlinType @@ -160,8 +161,16 @@ internal fun AbstractSerialGenerator.serializerInstance( ExpressionVisitor.getObjectKClass(context, kType.toClassDescriptor!!) ) serializerClass.classId == enumSerializerId -> listOf( - ExpressionVisitor.getObjectKClass(context, kType.toClassDescriptor!!), - JsStringLiteral(kType.serialName()) + JsStringLiteral(kType.serialName()), + // EnumClass.values() invocation + JsInvocation( + context.getInnerNameForDescriptor( + DescriptorUtils.getFunctionByName( + kType.toClassDescriptor!!.staticScope, + DescriptorUtils.ENUM_VALUES + ) + ).makeRef() + ) ) serializerClass.classId == objectSerializerId -> listOf( JsStringLiteral(kType.serialName()), 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 15b9fc7300b..1ac655a503c 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 @@ -83,11 +83,11 @@ internal fun InstructionAdapter.genValidateProperty(index: Int, bitMaskAddress: iconst(0) } -internal fun InstructionAdapter.genExceptionThrow(exceptionClass: String, message: String) { - anew(Type.getObjectType(exceptionClass)) +internal fun InstructionAdapter.genMissingFieldExceptionThrow(fieldName: String) { + anew(Type.getObjectType(serializationExceptionMissingFieldName)) dup() - aconst(message) - invokespecial(exceptionClass, "", "(Ljava/lang/String;)V", false) + aconst(fieldName) + invokespecial(serializationExceptionMissingFieldName, "", "(Ljava/lang/String;)V", false) checkcast(Type.getObjectType("java/lang/Throwable")) athrow() } @@ -287,7 +287,16 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class val serialName = kType.serialName() when (serializer.classId) { - enumSerializerId, contextSerializerId, polymorphicSerializerId -> { + enumSerializerId -> { + aconst(serialName) + signature.append("Ljava/lang/String;") + val enumJavaType = codegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT) + val javaEnumArray = Type.getType("[Ljava/lang/Enum;") + invokestatic(enumJavaType.internalName, "values","()[${enumJavaType.descriptor}", false) + checkcast(javaEnumArray) + signature.append(javaEnumArray.descriptor) + } + contextSerializerId, polymorphicSerializerId -> { // a special way to instantiate enum -- need a enum KClass reference // GENERIC_ARGUMENT forces boxing in order to obtain KClass aconst(codegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializableCodegenImpl.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializableCodegenImpl.kt index e63e2fd782f..2c0aabd2f09 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializableCodegenImpl.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializableCodegenImpl.kt @@ -191,7 +191,7 @@ class SerializableCodegenImpl( genValidateProperty(i, bitMaskOff(i)) val nonThrowLabel = Label() ificmpne(nonThrowLabel) - genExceptionThrow(serializationExceptionMissingFieldName, prop.name) + genMissingFieldExceptionThrow(prop.name) visitLabel(nonThrowLabel) // setting field load(0, thisAsmType) 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 4d3688a7212..56f966a8d65 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 @@ -406,11 +406,8 @@ open class SerializerCodegenImpl( ) if (!serializableDescriptor.isInternalSerializable) { //validate all required (constructor) fields - val nonThrowLabel = Label() - val throwLabel = Label() for ((i, property) in properties.serializableConstructorProperties.withIndex()) { if (property.optional || property.transient) { - // todo: Normal reporting of error if (!property.isConstructorParameterWithDefault) throw CompilationException( "Property ${property.name} was declared as optional/transient but has no default value", @@ -419,15 +416,12 @@ open class SerializerCodegenImpl( ) } else { genValidateProperty(i, bitMaskOff(i)) - // todo: print name of each variable? - ificmpeq(throwLabel) + val nonThrowLabel = Label() + ificmpne(nonThrowLabel) + genMissingFieldExceptionThrow(property.name) + visitLabel(nonThrowLabel) } } - goTo(nonThrowLabel) - // throwing an exception - visitLabel(throwLabel) - genExceptionThrow(serializationExceptionName, "Not all required constructor fields were specified") - visitLabel(nonThrowLabel) } // create object with constructor anew(serializableAsmType) @@ -564,7 +558,7 @@ open class SerializerCodegenImpl( // throw // set ificmpne(nextLabel) - genExceptionThrow(serializationExceptionMissingFieldName, property.name) + genMissingFieldExceptionThrow(property.name) visitLabel(nextLabel) } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerForEnumsCodegen.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerForEnumsCodegen.kt index 2af773256df..3dff6372cab 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerForEnumsCodegen.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerForEnumsCodegen.kt @@ -57,7 +57,8 @@ class SerializerForEnumsCodegen( // regular .serialName() produces fqName here, which is kinda inconvenient for enum entry val serialName = entry.annotations.serialNameValue ?: entry.name.toString() aconst(serialName) - invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;)V", false) + iconst(0) + invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;Z)V", false) // pushing annotations addSyntheticAnnotationsToDescriptor(descriptorVar, entry, CallingConventions.addAnnotation) }