JPS plugin

Breaking changes in compiler plugin:

* Remove java.Serializable supertype
* Move serializer impl from companion to special inner class
* Add generic serializer fields in $serializer and serializer getter
in companion

kotlin.Pair serializer

Generating getter also for non-generic serializers

Generic serializers in JS
This commit is contained in:
Leonid Startsev
2017-10-25 16:09:23 +03:00
parent f42767fcc2
commit 703d715334
19 changed files with 474 additions and 58 deletions
@@ -5,6 +5,7 @@ apply { plugin("kotlin") }
dependencies {
compileOnly(ideaSdkCoreDeps("intellij-core"))
compileOnly(project(":jps-plugin"))
compileOnly(project(":compiler:plugin-api"))
compileOnly(project(":compiler:frontend"))
compileOnly(project(":compiler:backend"))
@@ -1,7 +1,7 @@
<idea-plugin>
<name>Kotlin-serialization</name>
<id>org.jetbrains.kotlinx.serialization</id>
<version>0.1-SNAPSHOT</version>
<version>0.2</version>
<depends>org.jetbrains.kotlin</depends>
<idea-version since-build="172"/>
@@ -11,4 +11,9 @@
<syntheticResolveExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationResolveExtension"/>
<jsSyntheticTranslateExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationJsExtension"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<compileServer.plugin classpath="kotlinx-serialization-compiler-plugin.jar"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,17 @@
#
# Copyright 2010-2017 JetBrains s.r.o.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.jetbrains.kotlinx.serialization.jps.KotlinSerializationJpsPlugin
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlinx.serialization.compiler.backend.common
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
abstract class SerializableCompanionCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) {
protected val companionDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext)
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!!
fun generate() {
val fser = KSerializerDescriptorResolver.createSerializerGetterDescriptor(companionDescriptor, serializableDescriptor)
generateSerializerGetter(fser)
}
protected abstract fun generateSerializerGetter(methodDescriptor: FunctionDescriptor)
}
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties
abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) {
@@ -43,12 +43,17 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
val load = generateLoadIfNeeded()
if (save || load || prop)
generateSerialDesc()
if (serializableDescriptor.declaredTypeParameters.isNotEmpty()) {
generateGenericFieldsAndConstructor(createTypedSerializerConstructorDescriptor(serializerDescriptor, serializableDescriptor))
}
}
protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SERIAL_DESC_FIELD,
serializerDescriptor::checkSerializableClassPropertyResult)
protected abstract fun generateSerialDesc()
protected abstract fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ConstructorDescriptor)
protected abstract fun generateSerializableClassProperty(property: PropertyDescriptor)
protected abstract fun generateSave(function: FunctionDescriptor)
@@ -28,9 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.containsTypeProjectionsInTopLevelArguments
import org.jetbrains.kotlin.types.typeUtil.isBoolean
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
import org.jetbrains.kotlin.types.typeUtil.*
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.polymorphicSerializerId
@@ -47,6 +45,7 @@ open class SerialTypeInfo(
fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
val T = property.type
return when {
T.isTypeParameter() -> SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", null)
T.isPrimitiveNumberType() or T.isBoolean() -> SerialTypeInfo(property,
T.nameIfStandardType.toString().capitalize())
KotlinBuiltIns.isString(T) -> SerialTypeInfo(property, "String")
@@ -71,6 +70,7 @@ fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
else if (kType.isTypeParameter()) return null
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
?: findEnumTypeSerializer(module, kType)
@@ -89,6 +89,7 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
"D", "kotlin.Double" -> "DoubleSerializer"
"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.collections.HashSet" -> "HashSetSerializer"
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlinx.serialization.compiler.backend.js
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
import org.jetbrains.kotlin.js.backend.ast.JsReturn
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
class SerializableCompanionJsTranslator(declaration: KtPureClassOrObject,
val translator: DeclarationBodyVisitor,
val context: TranslationContext): SerializableCompanionCodegen(declaration, context.bindingContext()) {
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
val f = context.buildFunction(methodDescriptor) {jsFun, context ->
val serializer = serializableDescriptor.classSerializer?.toClassDescriptor!!
val stmt = if (serializableDescriptor.declaredTypeParameters.isEmpty()) {
context.getQualifiedReference(serializer)
} else {
val args = jsFun.parameters.map { JsNameRef(it.name) }
val ref = context.getInnerNameForDescriptor(
KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor(serializer, serializableDescriptor))
JsInvocation(ref.makeRef(), args)
}
+JsReturn(stmt)
}
translator.addFunction(methodDescriptor, f, null)
}
companion object {
fun translate(declaration: KtPureClassOrObject, descriptor: ClassDescriptor, translator: DeclarationBodyVisitor, context: TranslationContext) {
val serializableClass = getSerializableClassDescriptorByCompanion(descriptor) ?: return
if (serializableClass.isInternalSerializable)
SerializableCompanionJsTranslator(declaration, translator, context).generate()
}
}
}
@@ -19,12 +19,14 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.js
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.backend.ast.*
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.declaration.DefaultPropertyTranslator
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.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
@@ -39,6 +41,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerialize
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
class SerializerJsTranslator(declaration: KtPureClassOrObject,
val translator: DeclarationBodyVisitor,
@@ -94,6 +97,22 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
translator.addProperty(propDesc, getterExpr, null)
}
override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ConstructorDescriptor) {
val f = context.buildFunction(typedConstructorDescriptor) { jsFun, context ->
val thiz = jsFun.scope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME).makeRef()
+JsVars(JsVars.JsVar(thiz.name, JsNew(getQualifiedClassReferenceName(serializerDescriptor))))
jsFun.parameters.forEachIndexed { i, parameter ->
val thisFRef = JsNameRef(context.scope().declareName("$typeArgPrefix$i"), thiz)
+JsAstUtils.assignment(thisFRef, JsNameRef(parameter.name)).makeStmt()
}
+JsReturn(thiz)
}
f.name = context.getInnerNameForDescriptor(typedConstructorDescriptor);
context.addDeclarationStatement(f.makeStmt())
}
private fun ClassDescriptor.getFuncDesc(funcName: String) =
unsubstitutedMemberScope.getDescriptorsFiltered { it == Name.identifier(funcName) }
@@ -120,7 +139,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
if (property.transient) continue
// output.writeXxxElementValue(classDesc, index, value)
val sti = getSerialTypeInfo(property)
val innerSerial = if (sti.serializer == null) null else serializerInstance(sti.serializer, property.module, property.type)
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
if (innerSerial == null) {
val writeFunc =
kOutputClass.getFuncDesc("write${sti.elementMethodPrefix}ElementValue").single()
@@ -152,9 +171,13 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
return context.getQualifiedReference(classDescriptor)
}
private fun serializerInstance(serializerClass: ClassDescriptor, module: ModuleDescriptor, kType: KotlinType): JsExpression? {
val nullableSerClass = getQualifiedClassReferenceName(
serializerClass.getClassFromInternalSerializationPackage("NullableSerializer"))
private fun serializerInstance(serializerClass: ClassDescriptor?, module: ModuleDescriptor, kType: KotlinType, genericIndex: Int? = null): JsExpression? {
val nullableSerClass = getQualifiedClassReferenceName(requireNotNull(
module.findClassAcrossModuleDependencies(ClassId(internalPackageFqName, Name.identifier("NullableSerializer")))))
if (serializerClass == null) {
if (genericIndex == null) return null
return JsNameRef(context.scope().declareName("$typeArgPrefix$genericIndex"), JsThisRef())
}
if (serializerClass.kind == ClassKind.OBJECT) {
return getQualifiedClassReferenceName(serializerClass)
}
@@ -162,13 +185,20 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
listOf(createGetKClassExpression(kType.toClassDescriptor!!))
else kType.arguments.map {
val argSer = findTypeSerializer(module, it.type) ?: return null
val expr = serializerInstance(argSer, module, it.type) ?: return null
val argSer = findTypeSerializer(module, it.type)
val expr = serializerInstance(argSer, module, it.type, it.type.genericIndex) ?: return null
if (it.type.isMarkedNullable) JsNew(nullableSerClass, listOf(expr)) else expr
}
if (serializerClass.classId == referenceArraySerializerId)
args = listOf(createGetKClassExpression(kType.arguments[0].type.toClassDescriptor!!)) + args
return JsNew(getQualifiedClassReferenceName(serializerClass), args)
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
val ref = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
val desc = KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor(serializerClass, serializableDescriptor)
JsInvocation(context.getInnerNameForDescriptor(desc).makeRef(), args)
} else {
JsNew(getQualifiedClassReferenceName(serializerClass), args)
}
return ref
}
}
@@ -229,7 +259,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
case(JsIntLiteral(i)) {
// input.readXxxElementValue
val sti = getSerialTypeInfo(property)
val innerSerial = if (sti.serializer == null) null else serializerInstance(sti.serializer, property.module, property.type)
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
val call = if (innerSerial == null) {
val unknownSer = (sti.elementMethodPrefix.isEmpty())
val readFunc =
@@ -32,6 +32,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.findEnumTypeS
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findPolymorphicSerializer
import org.jetbrains.kotlinx.serialization.compiler.backend.common.requiresPolymorphism
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -71,10 +72,12 @@ internal fun InstructionAdapter.genExceptionThrow(exceptionClass: String, messag
athrow()
}
fun InstructionAdapter.genKOutputMethodCall(property: SerializableProperty, classCodegen: ImplementationBodyCodegen, expressionCodegen: ExpressionCodegen, propertyOwnerType: Type, ownerVar: Int) {
fun InstructionAdapter.genKOutputMethodCall(property: SerializableProperty, classCodegen: ImplementationBodyCodegen, expressionCodegen: ExpressionCodegen,
propertyOwnerType: Type, ownerVar: Int, fromClassStartVar: Int? = null) {
val propertyType = classCodegen.typeMapper.mapType(property.type)
val sti = getSerialTypeInfo(property, propertyType)
val useSerializer = stackValueSerializerInstance(classCodegen, sti)
val useSerializer = if (fromClassStartVar == null) stackValueSerializerInstanceFromSerializer(classCodegen, sti)
else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar)
if (!sti.unit) classCodegen.genPropertyOnStack(this, expressionCodegen.context, property.descriptor, propertyOwnerType, ownerVar)
invokevirtual(kOutputType.internalName,
"write" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue",
@@ -114,16 +117,32 @@ internal val polymorphicSerializerId = ClassId(packageFqName, Name.identifier("P
internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier("ReferenceArraySerializer"))
internal val contextSerializerId = ClassId(packageFqName, Name.identifier("ContextSerializer"))
// returns false is property should not use serializer
internal fun InstructionAdapter.stackValueSerializerInstance(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo): Boolean {
internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, varIndexStart: Int): Boolean {
val serializer = sti.serializer ?: return false
return stackValueSerializerInstance(codegen, sti.property.module, sti.property.type, serializer, this)
return stackValueSerializerInstance(codegen, sti.property.module, sti.property.type, serializer, this, sti.property.genericIndex) { idx ->
load(varIndexStart + idx, kSerializerType)
}
}
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo): Boolean {
val serializer = sti.serializer ?: return false
return stackValueSerializerInstance(codegen, sti.property.module, sti.property.type, serializer, this, sti.property.genericIndex) { idx ->
load(0, kSerializerType)
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$idx", kSerializerType.descriptor)
}
}
// returns false is cannot not use serializer
// use iv == null to check only (do not emit serializer onto stack)
internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, serializer: ClassDescriptor,
iv: InstructionAdapter?): Boolean {
internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
iv: InstructionAdapter?, genericIndex: Int? = null, genericSerializerFieldGetter: (InstructionAdapter.(Int) -> Unit)? = null): Boolean {
if (genericIndex != null) {
// get field from serializer object
iv?.run { genericSerializerFieldGetter?.invoke(this, genericIndex) }
return true
}
val serializer = requireNotNull(maybeSerializer)
if (serializer.kind == ClassKind.OBJECT) {
// singleton serializer -- just get it
if (iv != null)
@@ -133,11 +152,12 @@ internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: Mod
// serializer is not singleton object and shall be instantiated
val argSerializers = kType.arguments.map { projection ->
// bail out from stackValueSerializerInstance if any type argument is not serializable
val argSerializer = findTypeSerializer(module, projection.type, codegen.typeMapper.mapType(projection.type)) ?: return false
val argType = projection.type
val argSerializer = findTypeSerializer(module, argType, codegen.typeMapper.mapType(argType)) ?: return false
// check if it can be properly serialized with its args recursively
if (!stackValueSerializerInstance(codegen, module, projection.type, argSerializer, null))
if (!stackValueSerializerInstance(codegen, module, argType, argSerializer, null, argType.genericIndex, genericSerializerFieldGetter))
return false
Pair(projection.type, argSerializer)
Pair(argType, argSerializer)
}
// new serializer if needed
iv?.apply {
@@ -163,7 +183,7 @@ internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: Mod
}
// all serializers get arguments with serializers of their generic types
argSerializers.forEach { (argType, argSerializer) ->
assert(stackValueSerializerInstance(codegen, module, argType, argSerializer, this))
assert(stackValueSerializerInstance(codegen, module, argType, argSerializer, this, argType.genericIndex, genericSerializerFieldGetter))
// wrap into nullable serializer if argType is nullable
if (argType.isMarkedNullable) {
invokestatic("kotlinx/serialization/internal/BuiltinSerializersKt", "makeNullable",
@@ -261,5 +281,6 @@ internal val org.jetbrains.org.objectweb.asm.Type.standardSerializer: String? ge
"Ljava/util/Map;", "Ljava/util/LinkedHashMap;" -> "LinkedHashMapSerializer"
"Ljava/util/HashMap;" -> "HashMapSerializer"
"Ljava/util/Map\$Entry;" -> "MapEntrySerializer"
"Lkotlin/Pair;" -> "PairSerializer"
else -> null
}
@@ -26,14 +26,13 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers
import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap
import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryPropertiesDescriptorsMap
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperty
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -73,22 +72,29 @@ class SerializableCodegenImpl(
val thisI = 0
val outputI = 1
val serialDescI = 2
// val offsetI = 3
val offsetI = 3
val superClass = serializableDescriptor.getSuperClassOrAny()
val myPropsStart: Int
if (superClass.isInternalSerializable) {
myPropsStart = SerializableProperties(superClass, classCodegen.bindingContext).serializableProperties.size
val superTypeArguments = serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments
//super.writeSelf(output, serialDesc)
load(thisI, thisAsmType)
load(outputI, kOutputType)
load(serialDescI, descType)
invokespecial(classCodegen.typeMapper.mapType(superClass).internalName, signature.asmMethod.name, signature.asmMethod.descriptor, false)
superTypeArguments.forEach {
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(it).let { if (it == -1) null else it }
val serial = findTypeSerializer(serializableDescriptor.module, it.type, classCodegen.typeMapper.mapType(it.type))
stackValueSerializerInstance(classCodegen, serializableDescriptor.module, it.type, serial, this, genericIdx) {
load(offsetI + it, kSerializerType)
}
}
val superSignature = classCodegen.typeMapper.mapSignatureSkipGeneric(KSerializerDescriptorResolver.createWriteSelfFunctionDescriptor(superClass))
invokespecial(classCodegen.typeMapper.mapType(superClass).internalName, superSignature.asmMethod.name, superSignature.asmMethod.descriptor, false)
}
else {
myPropsStart = 0
// offset = 0
// iconst(0)
}
for (i in myPropsStart until properties.serializableProperties.size) {
@@ -97,7 +103,7 @@ class SerializableCodegenImpl(
load(outputI, kOutputType)
load(serialDescI, descType)
iconst(i)
genKOutputMethodCall(property, classCodegen, exprCodegen, thisAsmType, thisI)
genKOutputMethodCall(property, classCodegen, exprCodegen, thisAsmType, thisI, offsetI)
}
areturn(Type.VOID_TYPE)
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
class SerializableCompanionCodegenImpl(private val codegen: ImplementationBodyCodegen) :
SerializableCompanionCodegen(codegen.myClass, codegen.bindingContext) {
companion object {
fun generateSerializableExtensions(codegen: ImplementationBodyCodegen) {
val serializableClass = getSerializableClassDescriptorByCompanion(codegen.descriptor) ?: return
if (serializableClass.isInternalSerializable)
SerializableCompanionCodegenImpl(codegen).generate()
}
}
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
val serial = serializableDescriptor.classSerializer?.toClassDescriptor ?: return
codegen.generateMethod(methodDescriptor) {sig, expr ->
stackValueSerializerInstance(codegen, serializableDescriptor.module, serializableDescriptor.defaultType, serial, this, null) {
load(it+1, kSerializerType)
}
areturn(kSerializerType)
}
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
import org.jetbrains.org.objectweb.asm.Label
@@ -50,6 +52,25 @@ class SerializerCodegenImpl(
}
}
override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ConstructorDescriptor) {
serializableDescriptor.declaredTypeParameters.forEachIndexed { i, _ ->
codegen.v.newField(OtherOrigin(codegen.myClass.psiOrParent), ACC_PRIVATE or ACC_SYNTHETIC,
"$typeArgPrefix$i", kSerializerType.descriptor, null, null )
}
codegen.generateMethod(typedConstructorDescriptor) { sig, exprCodegen ->
load(0, serializerAsmType)
invokespecial("java/lang/Object", "<init>", "()V", false)
serializableDescriptor.declaredTypeParameters.forEachIndexed { i, _ ->
load(0, serializerAsmType)
load(i+1, kSerializerType)
putfield(serializerAsmType.internalName, "$typeArgPrefix$i", kSerializerType.descriptor)
}
areturn(Type.VOID_TYPE)
}
}
override fun generateSerialDesc() {
codegen.v.newField(OtherOrigin(codegen.myClass.psiOrParent), ACC_PRIVATE or ACC_STATIC or ACC_FINAL or ACC_SYNTHETIC,
serialDescField, descType.descriptor, null, null)
@@ -126,12 +147,19 @@ class SerializerCodegenImpl(
")" + kOutputType.descriptor, false)
store(outputVar, kOutputType)
if (serializableDescriptor.isInternalSerializable) {
val sig = StringBuilder("(${kOutputType.descriptor}${descType.descriptor}")
// call obj.write$Self(output, classDesc)
load(objVar, objType)
load(outputVar, kOutputType)
load(descVar, descType)
serializableDescriptor.declaredTypeParameters.forEachIndexed {i, _ ->
load(0, kSerializerType)
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$i", kSerializerType.descriptor)
sig.append(kSerializerType.descriptor)
}
sig.append(")V")
invokevirtual(objType.internalName, KSerializerDescriptorResolver.WRITE_SELF_NAME.asString(),
"(${kOutputType.descriptor}${descType.descriptor})V", false)
sig.toString(), false)
}
else {
// loop for all properties
@@ -235,7 +263,7 @@ class SerializerCodegenImpl(
iconst(labelNum)
val sti = getSerialTypeInfo(property, propertyType)
val useSerializer = stackValueSerializerInstance(codegen, sti)
val useSerializer = stackValueSerializerInstanceFromSerializer(codegen, sti)
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
if (unknownSer) {
aconst(codegen.typeMapper.mapType(property.type))
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerialInfoCodegenImpl
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCompanionCodegenImpl
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerCodegenImpl
class SerializationCodegenExtension : ExpressionCodegenExtension {
@@ -27,5 +28,6 @@ class SerializationCodegenExtension : ExpressionCodegenExtension {
SerialInfoCodegenImpl.generateSerialInfoImplBody(codegen)
SerializableCodegenImpl.generateSerializableExtensions(codegen)
SerializerCodegenImpl.generateSerializerExtensions(codegen)
SerializableCompanionCodegenImpl.generateSerializableExtensions(codegen)
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializableCompanionJsTranslator
import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializableJsTranslator
import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializerJsTranslator
@@ -28,5 +29,6 @@ class SerializationJsExtension: JsSyntheticTranslateExtension {
override fun generateClassSyntheticParts(declaration: KtPureClassOrObject, descriptor: ClassDescriptor, translator: DeclarationBodyVisitor, context: TranslationContext) {
SerializerJsTranslator.translate(declaration, descriptor, translator, context)
SerializableJsTranslator.translate(declaration, descriptor, translator, context)
SerializableCompanionJsTranslator.translate(declaration, descriptor, translator, context)
}
}
@@ -31,16 +31,17 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.serialInfoFqName
import java.util.*
class SerializationResolveExtension : SyntheticResolveExtension {
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> {
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName))
return listOf(KSerializerDescriptorResolver.IMPL_NAME)
else
return listOf()
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = when {
thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(KSerializerDescriptorResolver.IMPL_NAME)
thisDescriptor.isInternalSerializable -> listOf(KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
else -> listOf()
}
override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name, ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, result: MutableSet<ClassDescriptor>) {
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)
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
return
}
@@ -50,12 +51,12 @@ class SerializationResolveExtension : SyntheticResolveExtension {
override fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
KSerializerDescriptorResolver.addSerialInfoSuperType(thisDescriptor, supertypes)
KSerializerDescriptorResolver.addSerializableSupertypes(thisDescriptor, supertypes)
KSerializerDescriptorResolver.addSerializerSupertypes(thisDescriptor, supertypes)
}
override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name, fromSupertypes: List<SimpleFunctionDescriptor>, result: MutableCollection<SimpleFunctionDescriptor>) {
KSerializerDescriptorResolver.generateSerializerMethods(thisDescriptor, fromSupertypes, name, result)
KSerializerDescriptorResolver.generateCompanionObjectMethods(thisDescriptor, fromSupertypes, name, result)
}
override fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, name: Name, fromSupertypes: ArrayList<PropertyDescriptor>, result: MutableSet<PropertyDescriptor>) {
@@ -17,17 +17,16 @@
package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
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.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME
internal val packageFqName = FqName("kotlinx.serialization")
internal val internalPackageFqName = FqName("kotlinx.serialization.internal")
@@ -123,7 +122,9 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
// serializer annotation on class?
annotations.serializableWith?.let { return it }
// default serializable?
if (isInternalSerializable) return companionObjectDescriptor?.defaultType
if (isInternalSerializable) return this.unsubstitutedMemberScope
.getDescriptorsFiltered(nameFilter = {it == SERIALIZER_CLASS_NAME})
.filterIsInstance<ClassDescriptor>().singleOrNull()?.defaultType
return null
}
@@ -131,11 +132,20 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
val KotlinType.typeSerializer: KotlinType?
get() = this.annotations.serializableWith ?: (this.toClassDescriptor).classSerializer
val KotlinType.genericIndex: Int?
get() = (this.constructor.declarationDescriptor as? TypeParameterDescriptor)?.index
fun getSerializableClassDescriptorByCompanion(thisDescriptor: ClassDescriptor): ClassDescriptor? {
if (!thisDescriptor.isCompanionObject) return null
val classDescriptor = (thisDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
if (!classDescriptor.isInternalSerializable) return null
return classDescriptor
}
fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? {
val serializerForClass = serializerDescriptor.annotations.serializerForClass
if (serializerForClass != null) return serializerForClass.toClassDescriptor
if (!serializerDescriptor.isCompanionObject) return null
if (serializerDescriptor.name != SERIALIZER_CLASS_NAME) return null
val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
if (!classDescriptor.isInternalSerializable) return null
return classDescriptor
@@ -28,8 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.createProjection
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import java.util.*
@@ -39,6 +38,9 @@ object KSerializerDescriptorResolver {
val SERIAL_DESC_FIELD = "serialClassDesc"
val SAVE = "save"
val LOAD = "load"
val SERIALIZER_CLASS = "\$serializer"
internal val typeArgPrefix = "typeSerial"
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
val SAVE_NAME = Name.identifier(SAVE)
@@ -46,13 +48,8 @@ object KSerializerDescriptorResolver {
val DUMMY_PARAM_NAME = Name.identifier("serializationConstructorMarker")
val WRITE_SELF_NAME = Name.identifier("write\$Self") //todo: add it as a supertype to synthetic resolving
val IMPL_NAME = Name.identifier("Impl")
fun addSerializableSupertypes(classDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
if (classDescriptor.isInternalSerializable && supertypes.none(::isJavaSerializable)) {
classDescriptor.getJavaSerializableType()?.let { supertypes.add(it) }
}
}
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean {
return thisDescriptor.name == IMPL_NAME
@@ -90,17 +87,40 @@ object KSerializerDescriptorResolver {
false)
}
fun addSerializerImplClass(thisDescriptor: ClassDescriptor, declarationProvider: ClassMemberDeclarationProvider, ctx: LazyClassContext): ClassDescriptor {
val thisDeclaration = declarationProvider.correspondingClassOrObject!!
val scope = ctx.declarationScopeProvider.getResolutionScopeForDeclaration(declarationProvider.ownerInfo!!.scopeAnchor)
val serializerKind = if (thisDescriptor.declaredTypeParameters.isNotEmpty()) ClassKind.CLASS else ClassKind.OBJECT
return SyntheticClassOrObjectDescriptor(ctx,
thisDeclaration,
thisDescriptor, SERIALIZER_CLASS_NAME, thisDescriptor.source,
scope,
Modality.FINAL, Visibilities.PUBLIC, Visibilities.PRIVATE,
serializerKind, false)
}
fun generateSerializerProperties(thisDescriptor: ClassDescriptor,
fromSupertypes: ArrayList<PropertyDescriptor>,
name: Name,
result: MutableSet<PropertyDescriptor>) {
val classDescriptor = getSerializableClassDescriptorBySerializer(thisDescriptor) ?: return
val classDescriptor = getSerializableClassDescriptorBySerializer(thisDescriptor) ?: return
if (name == SERIAL_DESC_FIELD_NAME && result.none(thisDescriptor::checkSerializableClassPropertyResult) &&
fromSupertypes.none { thisDescriptor.checkSerializableClassPropertyResult(it) && it.modality == Modality.FINAL} )
result.add(createSerializableClassPropertyDescriptor(thisDescriptor, classDescriptor))
fromSupertypes.none { thisDescriptor.checkSerializableClassPropertyResult(it) && it.modality == Modality.FINAL })
result.add(createSerializableClassPropertyDescriptor(thisDescriptor, classDescriptor))
}
fun generateCompanionObjectMethods(thisDescriptor: ClassDescriptor,
fromSupertypes: List<SimpleFunctionDescriptor>,
name: Name,
result: MutableCollection<SimpleFunctionDescriptor>) {
val classDescriptor = getSerializableClassDescriptorByCompanion(thisDescriptor) ?: return
if (name == SERIALIZER_PROVIDER_NAME && result.none { it.valueParameters.size == classDescriptor.declaredTypeParameters.size }) {
result.add(createSerializerGetterDescriptor(thisDescriptor, classDescriptor))
}
}
fun generateSerializerMethods(thisDescriptor: ClassDescriptor,
fromSupertypes: List<SimpleFunctionDescriptor>,
name: Name,
@@ -228,6 +248,71 @@ object KSerializerDescriptorResolver {
return functionDescriptor
}
fun createTypedSerializerConstructorDescriptor(classDescriptor: ClassDescriptor, serializableDescriptor: ClassDescriptor): ConstructorDescriptor {
val constrDesc = ClassConstructorDescriptorImpl.createSynthesized(
classDescriptor,
Annotations.EMPTY,
false,
classDescriptor.source
)
val serializerClass = classDescriptor.getClassFromSerializationPackage("KSerializer")
val targs = mutableListOf<TypeParameterDescriptor>()
val args = serializableDescriptor.declaredTypeParameters.mapIndexed { index, _ ->
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(constrDesc, Annotations.EMPTY, false, Variance.INVARIANT,
Name.identifier("T$index"), index)
val pType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(targ.defaultType)))
targs.add(targ)
ValueParameterDescriptorImpl(constrDesc, null, index, Annotations.EMPTY, Name.identifier("$typeArgPrefix$index"), pType,
false, false, false, null, constrDesc.source)
}
constrDesc.initialize(args, Visibilities.PUBLIC, targs)
constrDesc.returnType = classDescriptor.defaultType
return constrDesc
}
fun createSerializerGetterDescriptor(thisClass: ClassDescriptor, serializableClass: ClassDescriptor): SimpleFunctionDescriptor {
val f = SimpleFunctionDescriptorImpl.create(thisClass, Annotations.EMPTY, SERIALIZER_PROVIDER_NAME, CallableMemberDescriptor.Kind.SYNTHESIZED, thisClass.source)
val serializerClass = thisClass.getClassFromSerializationPackage("KSerializer")
val args = mutableListOf<ValueParameterDescriptor>()
val typeArgs = mutableListOf<TypeParameterDescriptor>()
var i = 0
serializableClass.declaredTypeParameters.forEach { it ->
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(f, Annotations.EMPTY, false, Variance.INVARIANT,
Name.identifier("T$i"), i)
val pType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(targ.defaultType)))
args.add(ValueParameterDescriptorImpl(
f,
null,
i,
Annotations.EMPTY,
Name.identifier("$typeArgPrefix${i}"),
pType,
false,
false,
false,
null,
f.source
))
typeArgs.add(targ)
i++
}
val newSerializableType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializableClass, typeArgs.map { TypeProjectionImpl(it.defaultType) })
val serialReturnType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(newSerializableType)))
f.initialize(null, thisClass.thisAsReceiverParameter, typeArgs, args, serialReturnType, Modality.FINAL, Visibilities.PUBLIC)
return f
}
private fun KotlinType.makeNullableIfNotPrimitive() =
if (KotlinBuiltIns.isPrimitiveType(this)) this
else this.makeNullable()
@@ -266,6 +351,24 @@ object KSerializerDescriptorResolver {
f.source)
)
val kSerialClass = thisClass.getClassFromSerializationPackage("KSerializer").toSimpleType(false)
thisClass.declaredTypeParameters.forEach {
args.add(ValueParameterDescriptorImpl(
f,
null,
i++,
Annotations.EMPTY,
Name.identifier("$typeArgPrefix${i-3}"),
kSerialClass,
false,
false,
false,
null,
f.source
))
}
f.initialize(
null,
thisClass.thisAsReceiverParameter,
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructorParameterWithDefault: Boolean) {
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
val type = descriptor.type
val genericIndex = type.genericIndex
val module = descriptor.module
val serializableWith = descriptor.annotations.serializableWith
val optional = descriptor.annotations.serialOptional
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlinx.serialization.jps
import com.intellij.util.PathUtil
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.jps.build.KotlinJpsCompilerArgumentsProvider
import java.io.File
class KotlinSerializationJpsPlugin : KotlinJpsCompilerArgumentsProvider {
val JAR_FILE_NAME = "kotlinx-serialization-compiler-plugin.jar"
override fun getExtraArguments(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String> {
return emptyList()
}
override fun getClasspath(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String> {
val inJar = File(PathUtil.getJarPathForClass(this::class.java)).isFile
return listOf(
if (inJar) {
File(PathUtil.getJarPathForClass(this::class.java)).absolutePath
} else {
// We're in tests now
val kotlinProjectDirectory = File(PathUtil.getJarPathForClass(javaClass)).parentFile.parentFile.parentFile
File(kotlinProjectDirectory, "dist/artifacts/Serialization/lib/$JAR_FILE_NAME").absolutePath
})
}
}