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:
@@ -5,6 +5,7 @@ apply { plugin("kotlin") }
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(ideaSdkCoreDeps("intellij-core"))
|
compileOnly(ideaSdkCoreDeps("intellij-core"))
|
||||||
|
compileOnly(project(":jps-plugin"))
|
||||||
compileOnly(project(":compiler:plugin-api"))
|
compileOnly(project(":compiler:plugin-api"))
|
||||||
compileOnly(project(":compiler:frontend"))
|
compileOnly(project(":compiler:frontend"))
|
||||||
compileOnly(project(":compiler:backend"))
|
compileOnly(project(":compiler:backend"))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<name>Kotlin-serialization</name>
|
<name>Kotlin-serialization</name>
|
||||||
<id>org.jetbrains.kotlinx.serialization</id>
|
<id>org.jetbrains.kotlinx.serialization</id>
|
||||||
<version>0.1-SNAPSHOT</version>
|
<version>0.2</version>
|
||||||
|
|
||||||
<depends>org.jetbrains.kotlin</depends>
|
<depends>org.jetbrains.kotlin</depends>
|
||||||
<idea-version since-build="172"/>
|
<idea-version since-build="172"/>
|
||||||
@@ -11,4 +11,9 @@
|
|||||||
<syntheticResolveExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationResolveExtension"/>
|
<syntheticResolveExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationResolveExtension"/>
|
||||||
<jsSyntheticTranslateExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationJsExtension"/>
|
<jsSyntheticTranslateExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationJsExtension"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<compileServer.plugin classpath="kotlinx-serialization-compiler-plugin.jar"/>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
+17
@@ -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
|
||||||
+37
@@ -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)
|
||||||
|
}
|
||||||
+6
-1
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
|||||||
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
|
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
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
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties
|
||||||
|
|
||||||
abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) {
|
abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) {
|
||||||
@@ -43,12 +43,17 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
|
|||||||
val load = generateLoadIfNeeded()
|
val load = generateLoadIfNeeded()
|
||||||
if (save || load || prop)
|
if (save || load || prop)
|
||||||
generateSerialDesc()
|
generateSerialDesc()
|
||||||
|
if (serializableDescriptor.declaredTypeParameters.isNotEmpty()) {
|
||||||
|
generateGenericFieldsAndConstructor(createTypedSerializerConstructorDescriptor(serializerDescriptor, serializableDescriptor))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SERIAL_DESC_FIELD,
|
protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SERIAL_DESC_FIELD,
|
||||||
serializerDescriptor::checkSerializableClassPropertyResult)
|
serializerDescriptor::checkSerializableClassPropertyResult)
|
||||||
protected abstract fun generateSerialDesc()
|
protected abstract fun generateSerialDesc()
|
||||||
|
|
||||||
|
protected abstract fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ConstructorDescriptor)
|
||||||
|
|
||||||
protected abstract fun generateSerializableClassProperty(property: PropertyDescriptor)
|
protected abstract fun generateSerializableClassProperty(property: PropertyDescriptor)
|
||||||
|
|
||||||
protected abstract fun generateSave(function: FunctionDescriptor)
|
protected abstract fun generateSave(function: FunctionDescriptor)
|
||||||
|
|||||||
+4
-3
@@ -28,9 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.containsTypeProjectionsInTopLevelArguments
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
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.enumSerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId
|
||||||
@@ -47,6 +45,7 @@ open class SerialTypeInfo(
|
|||||||
fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
||||||
val T = property.type
|
val T = property.type
|
||||||
return when {
|
return when {
|
||||||
|
T.isTypeParameter() -> SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", null)
|
||||||
T.isPrimitiveNumberType() or T.isBoolean() -> SerialTypeInfo(property,
|
T.isPrimitiveNumberType() or T.isBoolean() -> SerialTypeInfo(property,
|
||||||
T.nameIfStandardType.toString().capitalize())
|
T.nameIfStandardType.toString().capitalize())
|
||||||
KotlinBuiltIns.isString(T) -> SerialTypeInfo(property, "String")
|
KotlinBuiltIns.isString(T) -> SerialTypeInfo(property, "String")
|
||||||
@@ -71,6 +70,7 @@ fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
|||||||
|
|
||||||
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||||
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
|
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
|
||||||
|
else if (kType.isTypeParameter()) return null
|
||||||
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
||||||
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
|
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
|
||||||
?: findEnumTypeSerializer(module, kType)
|
?: findEnumTypeSerializer(module, kType)
|
||||||
@@ -89,6 +89,7 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
|
|||||||
"D", "kotlin.Double" -> "DoubleSerializer"
|
"D", "kotlin.Double" -> "DoubleSerializer"
|
||||||
"C", "kotlin.Char" -> "CharSerializer"
|
"C", "kotlin.Char" -> "CharSerializer"
|
||||||
"kotlin.String" -> "StringSerializer"
|
"kotlin.String" -> "StringSerializer"
|
||||||
|
"kotlin.Pair" -> "PairSerializer"
|
||||||
"kotlin.collections.Collection", "kotlin.collections.List", "kotlin.collections.ArrayList" -> "ArrayListSerializer"
|
"kotlin.collections.Collection", "kotlin.collections.List", "kotlin.collections.ArrayList" -> "ArrayListSerializer"
|
||||||
"kotlin.collections.Set", "kotlin.collections.LinkedHashSet" -> "LinkedHashSetSerializer"
|
"kotlin.collections.Set", "kotlin.collections.LinkedHashSet" -> "LinkedHashSetSerializer"
|
||||||
"kotlin.collections.HashSet" -> "HashSetSerializer"
|
"kotlin.collections.HashSet" -> "HashSetSerializer"
|
||||||
|
|||||||
+56
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
-8
@@ -19,12 +19,14 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.js
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
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.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
|
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
|
||||||
import org.jetbrains.kotlin.js.translate.declaration.DefaultPropertyTranslator
|
import org.jetbrains.kotlin.js.translate.declaration.DefaultPropertyTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
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.enumSerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
|
||||||
|
|
||||||
class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
||||||
val translator: DeclarationBodyVisitor,
|
val translator: DeclarationBodyVisitor,
|
||||||
@@ -94,6 +97,22 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
translator.addProperty(propDesc, getterExpr, null)
|
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) =
|
private fun ClassDescriptor.getFuncDesc(funcName: String) =
|
||||||
unsubstitutedMemberScope.getDescriptorsFiltered { it == Name.identifier(funcName) }
|
unsubstitutedMemberScope.getDescriptorsFiltered { it == Name.identifier(funcName) }
|
||||||
|
|
||||||
@@ -120,7 +139,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
if (property.transient) continue
|
if (property.transient) continue
|
||||||
// output.writeXxxElementValue(classDesc, index, value)
|
// output.writeXxxElementValue(classDesc, index, value)
|
||||||
val sti = getSerialTypeInfo(property)
|
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) {
|
if (innerSerial == null) {
|
||||||
val writeFunc =
|
val writeFunc =
|
||||||
kOutputClass.getFuncDesc("write${sti.elementMethodPrefix}ElementValue").single()
|
kOutputClass.getFuncDesc("write${sti.elementMethodPrefix}ElementValue").single()
|
||||||
@@ -152,9 +171,13 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
return context.getQualifiedReference(classDescriptor)
|
return context.getQualifiedReference(classDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serializerInstance(serializerClass: ClassDescriptor, module: ModuleDescriptor, kType: KotlinType): JsExpression? {
|
private fun serializerInstance(serializerClass: ClassDescriptor?, module: ModuleDescriptor, kType: KotlinType, genericIndex: Int? = null): JsExpression? {
|
||||||
val nullableSerClass = getQualifiedClassReferenceName(
|
val nullableSerClass = getQualifiedClassReferenceName(requireNotNull(
|
||||||
serializerClass.getClassFromInternalSerializationPackage("NullableSerializer"))
|
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) {
|
if (serializerClass.kind == ClassKind.OBJECT) {
|
||||||
return getQualifiedClassReferenceName(serializerClass)
|
return getQualifiedClassReferenceName(serializerClass)
|
||||||
}
|
}
|
||||||
@@ -162,13 +185,20 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
|
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
|
||||||
listOf(createGetKClassExpression(kType.toClassDescriptor!!))
|
listOf(createGetKClassExpression(kType.toClassDescriptor!!))
|
||||||
else kType.arguments.map {
|
else kType.arguments.map {
|
||||||
val argSer = findTypeSerializer(module, it.type) ?: return null
|
val argSer = findTypeSerializer(module, it.type)
|
||||||
val expr = serializerInstance(argSer, module, it.type) ?: return null
|
val expr = serializerInstance(argSer, module, it.type, it.type.genericIndex) ?: return null
|
||||||
if (it.type.isMarkedNullable) JsNew(nullableSerClass, listOf(expr)) else expr
|
if (it.type.isMarkedNullable) JsNew(nullableSerClass, listOf(expr)) else expr
|
||||||
}
|
}
|
||||||
if (serializerClass.classId == referenceArraySerializerId)
|
if (serializerClass.classId == referenceArraySerializerId)
|
||||||
args = listOf(createGetKClassExpression(kType.arguments[0].type.toClassDescriptor!!)) + args
|
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)) {
|
case(JsIntLiteral(i)) {
|
||||||
// input.readXxxElementValue
|
// input.readXxxElementValue
|
||||||
val sti = getSerialTypeInfo(property)
|
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 call = if (innerSerial == null) {
|
||||||
val unknownSer = (sti.elementMethodPrefix.isEmpty())
|
val unknownSer = (sti.elementMethodPrefix.isEmpty())
|
||||||
val readFunc =
|
val readFunc =
|
||||||
|
|||||||
+32
-11
@@ -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.findPolymorphicSerializer
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.requiresPolymorphism
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.requiresPolymorphism
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
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.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
@@ -71,10 +72,12 @@ internal fun InstructionAdapter.genExceptionThrow(exceptionClass: String, messag
|
|||||||
athrow()
|
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 propertyType = classCodegen.typeMapper.mapType(property.type)
|
||||||
val sti = getSerialTypeInfo(property, propertyType)
|
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)
|
if (!sti.unit) classCodegen.genPropertyOnStack(this, expressionCodegen.context, property.descriptor, propertyOwnerType, ownerVar)
|
||||||
invokevirtual(kOutputType.internalName,
|
invokevirtual(kOutputType.internalName,
|
||||||
"write" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue",
|
"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 referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier("ReferenceArraySerializer"))
|
||||||
internal val contextSerializerId = ClassId(packageFqName, Name.identifier("ContextSerializer"))
|
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
|
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
|
// returns false is cannot not use serializer
|
||||||
// use iv == null to check only (do not emit serializer onto stack)
|
// use iv == null to check only (do not emit serializer onto stack)
|
||||||
internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, serializer: ClassDescriptor,
|
internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||||
iv: InstructionAdapter?): Boolean {
|
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) {
|
if (serializer.kind == ClassKind.OBJECT) {
|
||||||
// singleton serializer -- just get it
|
// singleton serializer -- just get it
|
||||||
if (iv != null)
|
if (iv != null)
|
||||||
@@ -133,11 +152,12 @@ internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: Mod
|
|||||||
// serializer is not singleton object and shall be instantiated
|
// serializer is not singleton object and shall be instantiated
|
||||||
val argSerializers = kType.arguments.map { projection ->
|
val argSerializers = kType.arguments.map { projection ->
|
||||||
// bail out from stackValueSerializerInstance if any type argument is not serializable
|
// 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
|
// 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
|
return false
|
||||||
Pair(projection.type, argSerializer)
|
Pair(argType, argSerializer)
|
||||||
}
|
}
|
||||||
// new serializer if needed
|
// new serializer if needed
|
||||||
iv?.apply {
|
iv?.apply {
|
||||||
@@ -163,7 +183,7 @@ internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: Mod
|
|||||||
}
|
}
|
||||||
// all serializers get arguments with serializers of their generic types
|
// all serializers get arguments with serializers of their generic types
|
||||||
argSerializers.forEach { (argType, argSerializer) ->
|
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
|
// wrap into nullable serializer if argType is nullable
|
||||||
if (argType.isMarkedNullable) {
|
if (argType.isMarkedNullable) {
|
||||||
invokestatic("kotlinx/serialization/internal/BuiltinSerializersKt", "makeNullable",
|
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/Map;", "Ljava/util/LinkedHashMap;" -> "LinkedHashMapSerializer"
|
||||||
"Ljava/util/HashMap;" -> "HashMapSerializer"
|
"Ljava/util/HashMap;" -> "HashMapSerializer"
|
||||||
"Ljava/util/Map\$Entry;" -> "MapEntrySerializer"
|
"Ljava/util/Map\$Entry;" -> "MapEntrySerializer"
|
||||||
|
"Lkotlin/Pair;" -> "PairSerializer"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-8
@@ -26,14 +26,13 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
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.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
|
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.anonymousInitializers
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryPropertiesDescriptorsMap
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryPropertiesDescriptorsMap
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperty
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
@@ -73,22 +72,29 @@ class SerializableCodegenImpl(
|
|||||||
val thisI = 0
|
val thisI = 0
|
||||||
val outputI = 1
|
val outputI = 1
|
||||||
val serialDescI = 2
|
val serialDescI = 2
|
||||||
// val offsetI = 3
|
val offsetI = 3
|
||||||
|
|
||||||
val superClass = serializableDescriptor.getSuperClassOrAny()
|
val superClass = serializableDescriptor.getSuperClassOrAny()
|
||||||
val myPropsStart: Int
|
val myPropsStart: Int
|
||||||
if (superClass.isInternalSerializable) {
|
if (superClass.isInternalSerializable) {
|
||||||
myPropsStart = SerializableProperties(superClass, classCodegen.bindingContext).serializableProperties.size
|
myPropsStart = SerializableProperties(superClass, classCodegen.bindingContext).serializableProperties.size
|
||||||
|
val superTypeArguments = serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments
|
||||||
//super.writeSelf(output, serialDesc)
|
//super.writeSelf(output, serialDesc)
|
||||||
load(thisI, thisAsmType)
|
load(thisI, thisAsmType)
|
||||||
load(outputI, kOutputType)
|
load(outputI, kOutputType)
|
||||||
load(serialDescI, descType)
|
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 {
|
else {
|
||||||
myPropsStart = 0
|
myPropsStart = 0
|
||||||
// offset = 0
|
|
||||||
// iconst(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in myPropsStart until properties.serializableProperties.size) {
|
for (i in myPropsStart until properties.serializableProperties.size) {
|
||||||
@@ -97,7 +103,7 @@ class SerializableCodegenImpl(
|
|||||||
load(outputI, kOutputType)
|
load(outputI, kOutputType)
|
||||||
load(serialDescI, descType)
|
load(serialDescI, descType)
|
||||||
iconst(i)
|
iconst(i)
|
||||||
genKOutputMethodCall(property, classCodegen, exprCodegen, thisAsmType, thisI)
|
genKOutputMethodCall(property, classCodegen, exprCodegen, thisAsmType, thisI, offsetI)
|
||||||
}
|
}
|
||||||
|
|
||||||
areturn(Type.VOID_TYPE)
|
areturn(Type.VOID_TYPE)
|
||||||
|
|||||||
+45
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
-2
@@ -18,6 +18,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
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.SerializerCodegen
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc
|
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
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
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() {
|
override fun generateSerialDesc() {
|
||||||
codegen.v.newField(OtherOrigin(codegen.myClass.psiOrParent), ACC_PRIVATE or ACC_STATIC or ACC_FINAL or ACC_SYNTHETIC,
|
codegen.v.newField(OtherOrigin(codegen.myClass.psiOrParent), ACC_PRIVATE or ACC_STATIC or ACC_FINAL or ACC_SYNTHETIC,
|
||||||
serialDescField, descType.descriptor, null, null)
|
serialDescField, descType.descriptor, null, null)
|
||||||
@@ -126,12 +147,19 @@ class SerializerCodegenImpl(
|
|||||||
")" + kOutputType.descriptor, false)
|
")" + kOutputType.descriptor, false)
|
||||||
store(outputVar, kOutputType)
|
store(outputVar, kOutputType)
|
||||||
if (serializableDescriptor.isInternalSerializable) {
|
if (serializableDescriptor.isInternalSerializable) {
|
||||||
|
val sig = StringBuilder("(${kOutputType.descriptor}${descType.descriptor}")
|
||||||
// call obj.write$Self(output, classDesc)
|
// call obj.write$Self(output, classDesc)
|
||||||
load(objVar, objType)
|
load(objVar, objType)
|
||||||
load(outputVar, kOutputType)
|
load(outputVar, kOutputType)
|
||||||
load(descVar, descType)
|
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(),
|
invokevirtual(objType.internalName, KSerializerDescriptorResolver.WRITE_SELF_NAME.asString(),
|
||||||
"(${kOutputType.descriptor}${descType.descriptor})V", false)
|
sig.toString(), false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// loop for all properties
|
// loop for all properties
|
||||||
@@ -235,7 +263,7 @@ class SerializerCodegenImpl(
|
|||||||
iconst(labelNum)
|
iconst(labelNum)
|
||||||
|
|
||||||
val sti = getSerialTypeInfo(property, propertyType)
|
val sti = getSerialTypeInfo(property, propertyType)
|
||||||
val useSerializer = stackValueSerializerInstance(codegen, sti)
|
val useSerializer = stackValueSerializerInstanceFromSerializer(codegen, sti)
|
||||||
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
|
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
|
||||||
if (unknownSer) {
|
if (unknownSer) {
|
||||||
aconst(codegen.typeMapper.mapType(property.type))
|
aconst(codegen.typeMapper.mapType(property.type))
|
||||||
|
|||||||
+2
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
|||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerialInfoCodegenImpl
|
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.SerializableCodegenImpl
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCompanionCodegenImpl
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerCodegenImpl
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerCodegenImpl
|
||||||
|
|
||||||
class SerializationCodegenExtension : ExpressionCodegenExtension {
|
class SerializationCodegenExtension : ExpressionCodegenExtension {
|
||||||
@@ -27,5 +28,6 @@ class SerializationCodegenExtension : ExpressionCodegenExtension {
|
|||||||
SerialInfoCodegenImpl.generateSerialInfoImplBody(codegen)
|
SerialInfoCodegenImpl.generateSerialInfoImplBody(codegen)
|
||||||
SerializableCodegenImpl.generateSerializableExtensions(codegen)
|
SerializableCodegenImpl.generateSerializableExtensions(codegen)
|
||||||
SerializerCodegenImpl.generateSerializerExtensions(codegen)
|
SerializerCodegenImpl.generateSerializerExtensions(codegen)
|
||||||
|
SerializableCompanionCodegenImpl.generateSerializableExtensions(codegen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
@@ -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.declaration.DeclarationBodyVisitor
|
||||||
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
|
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
|
||||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
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.SerializableJsTranslator
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializerJsTranslator
|
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) {
|
override fun generateClassSyntheticParts(declaration: KtPureClassOrObject, descriptor: ClassDescriptor, translator: DeclarationBodyVisitor, context: TranslationContext) {
|
||||||
SerializerJsTranslator.translate(declaration, descriptor, translator, context)
|
SerializerJsTranslator.translate(declaration, descriptor, translator, context)
|
||||||
SerializableJsTranslator.translate(declaration, descriptor, translator, context)
|
SerializableJsTranslator.translate(declaration, descriptor, translator, context)
|
||||||
|
SerializableCompanionJsTranslator.translate(declaration, descriptor, translator, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-6
@@ -31,16 +31,17 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.serialInfoFqName
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SerializationResolveExtension : SyntheticResolveExtension {
|
class SerializationResolveExtension : SyntheticResolveExtension {
|
||||||
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> {
|
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = when {
|
||||||
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName))
|
thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(KSerializerDescriptorResolver.IMPL_NAME)
|
||||||
return listOf(KSerializerDescriptorResolver.IMPL_NAME)
|
thisDescriptor.isInternalSerializable -> listOf(KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
|
||||||
else
|
else -> listOf()
|
||||||
return listOf()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name, ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, result: MutableSet<ClassDescriptor>) {
|
override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name, ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, result: MutableSet<ClassDescriptor>) {
|
||||||
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == KSerializerDescriptorResolver.IMPL_NAME)
|
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == KSerializerDescriptorResolver.IMPL_NAME)
|
||||||
result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx))
|
result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx))
|
||||||
|
else if (thisDescriptor.isInternalSerializable && name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
|
||||||
|
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,12 +51,12 @@ class SerializationResolveExtension : SyntheticResolveExtension {
|
|||||||
|
|
||||||
override fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
|
override fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
|
||||||
KSerializerDescriptorResolver.addSerialInfoSuperType(thisDescriptor, supertypes)
|
KSerializerDescriptorResolver.addSerialInfoSuperType(thisDescriptor, supertypes)
|
||||||
KSerializerDescriptorResolver.addSerializableSupertypes(thisDescriptor, supertypes)
|
|
||||||
KSerializerDescriptorResolver.addSerializerSupertypes(thisDescriptor, supertypes)
|
KSerializerDescriptorResolver.addSerializerSupertypes(thisDescriptor, supertypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name, fromSupertypes: List<SimpleFunctionDescriptor>, result: MutableCollection<SimpleFunctionDescriptor>) {
|
override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name, fromSupertypes: List<SimpleFunctionDescriptor>, result: MutableCollection<SimpleFunctionDescriptor>) {
|
||||||
KSerializerDescriptorResolver.generateSerializerMethods(thisDescriptor, fromSupertypes, name, result)
|
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>) {
|
override fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, name: Name, fromSupertypes: ArrayList<PropertyDescriptor>, result: MutableSet<PropertyDescriptor>) {
|
||||||
|
|||||||
+16
-6
@@ -17,17 +17,16 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
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 packageFqName = FqName("kotlinx.serialization")
|
||||||
internal val internalPackageFqName = FqName("kotlinx.serialization.internal")
|
internal val internalPackageFqName = FqName("kotlinx.serialization.internal")
|
||||||
@@ -123,7 +122,9 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
|
|||||||
// serializer annotation on class?
|
// serializer annotation on class?
|
||||||
annotations.serializableWith?.let { return it }
|
annotations.serializableWith?.let { return it }
|
||||||
// default serializable?
|
// default serializable?
|
||||||
if (isInternalSerializable) return companionObjectDescriptor?.defaultType
|
if (isInternalSerializable) return this.unsubstitutedMemberScope
|
||||||
|
.getDescriptorsFiltered(nameFilter = {it == SERIALIZER_CLASS_NAME})
|
||||||
|
.filterIsInstance<ClassDescriptor>().singleOrNull()?.defaultType
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,11 +132,20 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
|
|||||||
val KotlinType.typeSerializer: KotlinType?
|
val KotlinType.typeSerializer: KotlinType?
|
||||||
get() = this.annotations.serializableWith ?: (this.toClassDescriptor).classSerializer
|
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? {
|
fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? {
|
||||||
val serializerForClass = serializerDescriptor.annotations.serializerForClass
|
val serializerForClass = serializerDescriptor.annotations.serializerForClass
|
||||||
if (serializerForClass != null) return serializerForClass.toClassDescriptor
|
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
|
val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
|
||||||
if (!classDescriptor.isInternalSerializable) return null
|
if (!classDescriptor.isInternalSerializable) return null
|
||||||
return classDescriptor
|
return classDescriptor
|
||||||
|
|||||||
+115
-12
@@ -28,8 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
|
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -39,6 +38,9 @@ object KSerializerDescriptorResolver {
|
|||||||
val SERIAL_DESC_FIELD = "serialClassDesc"
|
val SERIAL_DESC_FIELD = "serialClassDesc"
|
||||||
val SAVE = "save"
|
val SAVE = "save"
|
||||||
val LOAD = "load"
|
val LOAD = "load"
|
||||||
|
val SERIALIZER_CLASS = "\$serializer"
|
||||||
|
|
||||||
|
internal val typeArgPrefix = "typeSerial"
|
||||||
|
|
||||||
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
|
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
|
||||||
val SAVE_NAME = Name.identifier(SAVE)
|
val SAVE_NAME = Name.identifier(SAVE)
|
||||||
@@ -46,13 +48,8 @@ object KSerializerDescriptorResolver {
|
|||||||
val DUMMY_PARAM_NAME = Name.identifier("serializationConstructorMarker")
|
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 WRITE_SELF_NAME = Name.identifier("write\$Self") //todo: add it as a supertype to synthetic resolving
|
||||||
val IMPL_NAME = Name.identifier("Impl")
|
val IMPL_NAME = Name.identifier("Impl")
|
||||||
|
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
|
||||||
|
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
|
||||||
fun addSerializableSupertypes(classDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
|
|
||||||
if (classDescriptor.isInternalSerializable && supertypes.none(::isJavaSerializable)) {
|
|
||||||
classDescriptor.getJavaSerializableType()?.let { supertypes.add(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean {
|
fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean {
|
||||||
return thisDescriptor.name == IMPL_NAME
|
return thisDescriptor.name == IMPL_NAME
|
||||||
@@ -90,17 +87,40 @@ object KSerializerDescriptorResolver {
|
|||||||
false)
|
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,
|
fun generateSerializerProperties(thisDescriptor: ClassDescriptor,
|
||||||
fromSupertypes: ArrayList<PropertyDescriptor>,
|
fromSupertypes: ArrayList<PropertyDescriptor>,
|
||||||
name: Name,
|
name: Name,
|
||||||
result: MutableSet<PropertyDescriptor>) {
|
result: MutableSet<PropertyDescriptor>) {
|
||||||
val classDescriptor = getSerializableClassDescriptorBySerializer(thisDescriptor) ?: return
|
val classDescriptor = getSerializableClassDescriptorBySerializer(thisDescriptor) ?: return
|
||||||
if (name == SERIAL_DESC_FIELD_NAME && result.none(thisDescriptor::checkSerializableClassPropertyResult) &&
|
if (name == SERIAL_DESC_FIELD_NAME && result.none(thisDescriptor::checkSerializableClassPropertyResult) &&
|
||||||
fromSupertypes.none { thisDescriptor.checkSerializableClassPropertyResult(it) && it.modality == Modality.FINAL} )
|
fromSupertypes.none { thisDescriptor.checkSerializableClassPropertyResult(it) && it.modality == Modality.FINAL })
|
||||||
result.add(createSerializableClassPropertyDescriptor(thisDescriptor, classDescriptor))
|
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,
|
fun generateSerializerMethods(thisDescriptor: ClassDescriptor,
|
||||||
fromSupertypes: List<SimpleFunctionDescriptor>,
|
fromSupertypes: List<SimpleFunctionDescriptor>,
|
||||||
name: Name,
|
name: Name,
|
||||||
@@ -228,6 +248,71 @@ object KSerializerDescriptorResolver {
|
|||||||
return functionDescriptor
|
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() =
|
private fun KotlinType.makeNullableIfNotPrimitive() =
|
||||||
if (KotlinBuiltIns.isPrimitiveType(this)) this
|
if (KotlinBuiltIns.isPrimitiveType(this)) this
|
||||||
else this.makeNullable()
|
else this.makeNullable()
|
||||||
@@ -266,6 +351,24 @@ object KSerializerDescriptorResolver {
|
|||||||
f.source)
|
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(
|
f.initialize(
|
||||||
null,
|
null,
|
||||||
thisClass.thisAsReceiverParameter,
|
thisClass.thisAsReceiverParameter,
|
||||||
|
|||||||
+1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|||||||
class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructorParameterWithDefault: Boolean) {
|
class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructorParameterWithDefault: Boolean) {
|
||||||
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
||||||
val type = descriptor.type
|
val type = descriptor.type
|
||||||
|
val genericIndex = type.genericIndex
|
||||||
val module = descriptor.module
|
val module = descriptor.module
|
||||||
val serializableWith = descriptor.annotations.serializableWith
|
val serializableWith = descriptor.annotations.serializableWith
|
||||||
val optional = descriptor.annotations.serialOptional
|
val optional = descriptor.annotations.serialOptional
|
||||||
|
|||||||
+45
@@ -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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user