Update version to 0.4
Optimize references in generated code. Also fixes Kotlin/kotlinx.serialization/issues/65 Fix (again) broken char boxing Rebased on 1.2.40 and fixed broken compatibility Fix https://github.com/Kotlin/kotlinx.serialization/issues/107 and code reformatting (cherry picked from commit d4c307d) Add correct type parameter information to synthetic declarations Needed by kapt due to https://github.com/Kotlin/kotlinx.serialization/issues/76 Make correct call to sealed class constructor Fixes https://github.com/Kotlin/kotlinx.serialization/issues/112 Bump version 1.2.50-eap-1 compatible
This commit is contained in:
@@ -17,8 +17,9 @@ dependencies {
|
|||||||
|
|
||||||
val ideaPluginDir: File by rootProject.extra
|
val ideaPluginDir: File by rootProject.extra
|
||||||
val ideaSandboxDir: File by rootProject.extra
|
val ideaSandboxDir: File by rootProject.extra
|
||||||
|
val serialPluginDir: File by rootProject.extra
|
||||||
|
|
||||||
runIdeTask("runIde", ideaPluginDir, ideaSandboxDir) {
|
runIdeTask("runIde", ideaPluginDir, ideaSandboxDir, serialPluginDir) {
|
||||||
// TODO: add serialization plugin to pluginDir
|
// TODO: add serialization plugin to pluginDir
|
||||||
dependsOn(":dist", ":ideaPlugin", ":kotlinx-serialization-compiler-plugin:dist")
|
dependsOn(":dist", ":ideaPlugin", ":kotlinx-serialization-compiler-plugin:dist")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
<groupId>org.jetbrains.kotlinx</groupId>
|
||||||
<artifactId>kotlinx-maven-serialization-plugin</artifactId>
|
<artifactId>kotlinx-maven-serialization-plugin</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>0.3</version>
|
<version>0.5.0</version>
|
||||||
<description>Serialization plugin for Maven</description>
|
<description>Serialization plugin for Maven</description>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ configureJvmProject(project)
|
|||||||
configurePublishing(project)
|
configurePublishing(project)
|
||||||
|
|
||||||
group = 'org.jetbrains.kotlinx'
|
group = 'org.jetbrains.kotlinx'
|
||||||
version = '0.3'
|
version = '0.5.0'
|
||||||
if (!project.hasProperty("deploy")) {
|
if (!project.hasProperty("deploy")) {
|
||||||
version = "$version-SNAPSHOT"
|
version = "$version-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
|
|
||||||
description = "Kotlin Serialization Compiler Plugin"
|
description = "Kotlin Serialization Compiler Plugin"
|
||||||
|
|
||||||
apply { plugin("kotlin") }
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("jps-compatible")
|
||||||
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(ideaSdkCoreDeps("intellij-core"))
|
// val compileOnly by configurations
|
||||||
compileOnly(ideaPluginDeps("maven", plugin = "maven"))
|
// val runtime by configurations
|
||||||
|
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||||
|
compileOnly(intellijDep())
|
||||||
|
compileOnly(intellijPluginDep("maven"))
|
||||||
compileOnly(project(":jps-plugin"))
|
compileOnly(project(":jps-plugin"))
|
||||||
compileOnly(project(":compiler:plugin-api"))
|
compileOnly(project(":compiler:plugin-api"))
|
||||||
compileOnly(project(":compiler:frontend"))
|
compileOnly(project(":compiler:frontend"))
|
||||||
@@ -19,8 +24,6 @@ dependencies {
|
|||||||
|
|
||||||
runtime(projectRuntimeJar(":kotlin-compiler"))
|
runtime(projectRuntimeJar(":kotlin-compiler"))
|
||||||
runtime(projectDist(":kotlin-stdlib"))
|
runtime(projectDist(":kotlin-stdlib"))
|
||||||
// val compileOnly by configurations
|
|
||||||
// val runtime by configurations
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<idea-plugin url="https://github.com/Kotlin/kotlinx.serialization" >
|
<idea-plugin url="https://github.com/Kotlin/kotlinx.serialization" >
|
||||||
<name>Kotlin-serialization</name>
|
<name>Kotlin-serialization</name>
|
||||||
<id>org.jetbrains.kotlinx.serialization</id>
|
<id>org.jetbrains.kotlinx.serialization</id>
|
||||||
<version>0.3</version>
|
<version>0.5.0</version>
|
||||||
|
|
||||||
<depends>org.jetbrains.kotlin</depends>
|
<depends>org.jetbrains.kotlin</depends>
|
||||||
<idea-version since-build="172"/>
|
<idea-version since-build="172"/>
|
||||||
|
|||||||
+33
-24
@@ -28,7 +28,10 @@ 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.*
|
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.isTypeParameter
|
||||||
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
|
||||||
@@ -36,29 +39,32 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySe
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
|
||||||
open class SerialTypeInfo(
|
open class SerialTypeInfo(
|
||||||
val property: SerializableProperty,
|
val property: SerializableProperty,
|
||||||
val elementMethodPrefix: String,
|
val elementMethodPrefix: String,
|
||||||
val serializer: ClassDescriptor? = null,
|
val serializer: ClassDescriptor? = null,
|
||||||
val unit: Boolean = false
|
val unit: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
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.isTypeParameter() -> SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", null)
|
||||||
T.isPrimitiveNumberType() or T.isBoolean() -> SerialTypeInfo(property,
|
T.isPrimitiveNumberType() or T.isBoolean() -> SerialTypeInfo(
|
||||||
T.nameIfStandardType.toString().capitalize())
|
property,
|
||||||
|
T.nameIfStandardType.toString().capitalize()
|
||||||
|
)
|
||||||
KotlinBuiltIns.isString(T) -> SerialTypeInfo(property, "String")
|
KotlinBuiltIns.isString(T) -> SerialTypeInfo(property, "String")
|
||||||
KotlinBuiltIns.isUnit(T) -> SerialTypeInfo(property, "Unit", unit = true)
|
KotlinBuiltIns.isUnit(T) -> SerialTypeInfo(property, "Unit", unit = true)
|
||||||
KotlinBuiltIns.isPrimitiveArray(T) -> TODO("primitive arrays are not supported yet")
|
KotlinBuiltIns.isPrimitiveArray(T) -> TODO("primitive arrays are not supported yet")
|
||||||
KotlinBuiltIns.isNonPrimitiveArray(T.toClassDescriptor!!) -> {
|
KotlinBuiltIns.isNonPrimitiveArray(T.toClassDescriptor!!) -> {
|
||||||
val serializer = property.serializableWith?.toClassDescriptor ?:
|
val serializer = property.serializableWith?.toClassDescriptor ?: property.module.findClassAcrossModuleDependencies(
|
||||||
property.module.findClassAcrossModuleDependencies(referenceArraySerializerId)
|
referenceArraySerializerId
|
||||||
|
)
|
||||||
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
||||||
}
|
}
|
||||||
T.toClassDescriptor?.kind == ClassKind.ENUM_CLASS -> {
|
T.toClassDescriptor?.kind == ClassKind.ENUM_CLASS -> {
|
||||||
val serializer = property.serializableWith?.toClassDescriptor ?:
|
val serializer =
|
||||||
property.module.findClassAcrossModuleDependencies(enumSerializerId)
|
property.serializableWith?.toClassDescriptor ?: property.module.findClassAcrossModuleDependencies(enumSerializerId)
|
||||||
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -72,9 +78,9 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescri
|
|||||||
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
|
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
|
||||||
else if (kType.isTypeParameter()) return null
|
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)
|
||||||
?: module.findClassAcrossModuleDependencies(contextSerializerId)
|
?: module.findClassAcrossModuleDependencies(contextSerializerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||||
@@ -110,8 +116,8 @@ fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDe
|
|||||||
|
|
||||||
fun KotlinType.requiresPolymorphism(): Boolean {
|
fun KotlinType.requiresPolymorphism(): Boolean {
|
||||||
return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true
|
return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true
|
||||||
|| (this.toClassDescriptor?.modality == Modality.OPEN && this.toClassDescriptor?.unsubstitutedPrimaryConstructor != null) // open not java class
|
|| (this.toClassDescriptor?.modality == Modality.OPEN && this.toClassDescriptor?.unsubstitutedPrimaryConstructor != null) // open not java class
|
||||||
|| this.containsTypeProjectionsInTopLevelArguments() // List<*>
|
|| this.containsTypeProjectionsInTopLevelArguments() // List<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findPolymorphicSerializer(module: ModuleDescriptor): ClassDescriptor {
|
fun findPolymorphicSerializer(module: ModuleDescriptor): ClassDescriptor {
|
||||||
@@ -119,20 +125,23 @@ fun findPolymorphicSerializer(module: ModuleDescriptor): ClassDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun KtPureClassOrObject.bodyPropertiesDescriptorsMap(bindingContext: BindingContext): Map<PropertyDescriptor, KtProperty> = declarations
|
fun KtPureClassOrObject.bodyPropertiesDescriptorsMap(bindingContext: BindingContext): Map<PropertyDescriptor, KtProperty> = declarations
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filterIsInstance<KtProperty>()
|
.filterIsInstance<KtProperty>()
|
||||||
.associateBy { (bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as? PropertyDescriptor)!! }
|
// can filter here because it's impossible to create body property w/ backing field w/o explicit delegating or initializing
|
||||||
|
.filter { it.delegateExpressionOrInitializer != null }
|
||||||
|
.associateBy { (bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as? PropertyDescriptor)!! }
|
||||||
|
|
||||||
fun KtPureClassOrObject.primaryPropertiesDescriptorsMap(bindingContext: BindingContext): Map<PropertyDescriptor, KtParameter> = primaryConstructorParameters
|
fun KtPureClassOrObject.primaryPropertiesDescriptorsMap(bindingContext: BindingContext): Map<PropertyDescriptor, KtParameter> =
|
||||||
|
primaryConstructorParameters
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { it.hasValOrVar() }
|
.filter { it.hasValOrVar() }
|
||||||
.associateBy { bindingContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it]!! }
|
.associateBy { bindingContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it]!! }
|
||||||
|
|
||||||
fun KtPureClassOrObject.anonymousInitializers() = declarations
|
fun KtPureClassOrObject.anonymousInitializers() = declarations
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filterIsInstance<KtAnonymousInitializer>()
|
.filterIsInstance<KtAnonymousInitializer>()
|
||||||
.mapNotNull { it.body }
|
.mapNotNull { it.body }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
fun SerializableProperty.annotationVarsAndDesc(annotationClass: ClassDescriptor): Pair<List<ValueArgument>, List<ValueParameterDescriptor>> {
|
fun SerializableProperty.annotationVarsAndDesc(annotationClass: ClassDescriptor): Pair<List<ValueArgument>, List<ValueParameterDescriptor>> {
|
||||||
val args: List<ValueArgument> = (this.descriptor.annotations.findAnnotation(annotationClass.fqNameSafe) as? LazyAnnotationDescriptor)?.annotationEntry?.valueArguments.orEmpty()
|
val args: List<ValueArgument> = (this.descriptor.annotations.findAnnotation(annotationClass.fqNameSafe) as? LazyAnnotationDescriptor)?.annotationEntry?.valueArguments.orEmpty()
|
||||||
|
|||||||
+11
-1
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.js
|
package org.jetbrains.kotlinx.serialization.compiler.backend.js
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
|
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
|
||||||
|
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
|
||||||
internal class JsBlockBuilder {
|
internal class JsBlockBuilder {
|
||||||
@@ -91,4 +93,12 @@ internal fun propNotSeenTest(seenVar: JsNameRef, index: Int): JsBinaryOperation
|
|||||||
JsIntLiteral(1 shl (index % 32))
|
JsIntLiteral(1 shl (index % 32))
|
||||||
),
|
),
|
||||||
JsIntLiteral(0)
|
JsIntLiteral(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal fun TranslationContext.serializerObjectGetter(serializer: ClassDescriptor): JsExpression {
|
||||||
|
return ReferenceTranslator.translateAsValueReference(serializer, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun TranslationContext.translateQualifiedReference(clazz: ClassDescriptor): JsExpression {
|
||||||
|
return ReferenceTranslator.translateAsTypeReference(clazz, this)
|
||||||
|
}
|
||||||
+4
-2
@@ -17,7 +17,9 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.js
|
package org.jetbrains.kotlinx.serialization.compiler.backend.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
|
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsReturn
|
import org.jetbrains.kotlin.js.backend.ast.JsReturn
|
||||||
@@ -33,8 +35,8 @@ class SerializableCompanionJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
val f = context.buildFunction(methodDescriptor) {jsFun, context ->
|
val f = context.buildFunction(methodDescriptor) {jsFun, context ->
|
||||||
val serializer = serializableDescriptor.classSerializer?.toClassDescriptor!!
|
val serializer = serializableDescriptor.classSerializer?.toClassDescriptor!!
|
||||||
val stmt = if (serializableDescriptor.declaredTypeParameters.isEmpty()) {
|
val stmt: JsExpression = if (serializer.kind == ClassKind.OBJECT) {
|
||||||
context.getQualifiedReference(serializer)
|
context.serializerObjectGetter(serializer)
|
||||||
} else {
|
} else {
|
||||||
val args = jsFun.parameters.map { JsNameRef(it.name) }
|
val args = jsFun.parameters.map { JsNameRef(it.name) }
|
||||||
val ref = context.getInnerNameForDescriptor(
|
val ref = context.getInnerNameForDescriptor(
|
||||||
|
|||||||
+24
-13
@@ -35,25 +35,32 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryProper
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
|
||||||
|
|
||||||
class SerializableJsTranslator(val declaration: KtPureClassOrObject,
|
class SerializableJsTranslator(
|
||||||
val translator: DeclarationBodyVisitor,
|
val declaration: KtPureClassOrObject,
|
||||||
val context: TranslationContext) : SerializableCodegen(declaration, context.bindingContext()) {
|
val translator: DeclarationBodyVisitor,
|
||||||
|
val context: TranslationContext
|
||||||
|
) : SerializableCodegen(declaration, context.bindingContext()) {
|
||||||
|
|
||||||
val initMap: Map<PropertyDescriptor, KtExpression?> = declaration.run {
|
private val initMap: Map<PropertyDescriptor, KtExpression?> = declaration.run {
|
||||||
(bodyPropertiesDescriptorsMap(context.bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } +
|
(bodyPropertiesDescriptorsMap(context.bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } +
|
||||||
primaryPropertiesDescriptorsMap(context.bindingContext()).mapValues { it.value.defaultValue })
|
primaryPropertiesDescriptorsMap(context.bindingContext()).mapValues { it.value.defaultValue })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) {
|
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) {
|
||||||
|
|
||||||
val missingExceptionClassRef = serializableDescriptor.getClassFromSerializationPackage("MissingFieldException")
|
val missingExceptionClassRef = serializableDescriptor.getClassFromSerializationPackage("MissingFieldException")
|
||||||
.let { context.getQualifiedReference(it) }
|
.let { context.translateQualifiedReference(it) }
|
||||||
|
|
||||||
val f = context.buildFunction(constructorDescriptor) { jsFun, context ->
|
val f = context.buildFunction(constructorDescriptor) { jsFun, context ->
|
||||||
val thiz = jsFun.scope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME).makeRef()
|
val thiz = jsFun.scope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME).makeRef()
|
||||||
val context = context.innerContextWithAliased(serializableDescriptor.thisAsReceiverParameter, thiz)
|
val context = context.innerContextWithAliased(serializableDescriptor.thisAsReceiverParameter, thiz)
|
||||||
|
|
||||||
+JsVars(JsVars.JsVar(thiz.name, Namer.createObjectWithPrototypeFrom(context.getQualifiedReference(serializableDescriptor))))
|
+JsVars(
|
||||||
|
JsVars.JsVar(
|
||||||
|
thiz.name,
|
||||||
|
Namer.createObjectWithPrototypeFrom(context.getInnerNameForDescriptor(serializableDescriptor).makeRef())
|
||||||
|
)
|
||||||
|
)
|
||||||
val seenVar = jsFun.parameters[0].name.makeRef()
|
val seenVar = jsFun.parameters[0].name.makeRef()
|
||||||
for ((index, prop) in properties.serializableProperties.withIndex()) {
|
for ((index, prop) in properties.serializableProperties.withIndex()) {
|
||||||
val paramRef = jsFun.parameters[index + 1].name.makeRef()
|
val paramRef = jsFun.parameters[index + 1].name.makeRef()
|
||||||
@@ -64,8 +71,7 @@ class SerializableJsTranslator(val declaration: KtPureClassOrObject,
|
|||||||
val initializer = initMap.getValue(prop.descriptor) ?: throw IllegalArgumentException("optional without an initializer")
|
val initializer = initMap.getValue(prop.descriptor) ?: throw IllegalArgumentException("optional without an initializer")
|
||||||
val initExpr = Translation.translateAsExpression(initializer, context)
|
val initExpr = Translation.translateAsExpression(initializer, context)
|
||||||
TranslationUtils.assignmentToBackingField(context, prop.descriptor, initExpr).makeStmt()
|
TranslationUtils.assignmentToBackingField(context, prop.descriptor, initExpr).makeStmt()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
JsThrow(JsNew(missingExceptionClassRef, listOf(JsStringLiteral(prop.name))))
|
JsThrow(JsNew(missingExceptionClassRef, listOf(JsStringLiteral(prop.name))))
|
||||||
}
|
}
|
||||||
// (seen & 1 << i == 0) -- not seen
|
// (seen & 1 << i == 0) -- not seen
|
||||||
@@ -75,14 +81,14 @@ class SerializableJsTranslator(val declaration: KtPureClassOrObject,
|
|||||||
|
|
||||||
//transient initializers and init blocks
|
//transient initializers and init blocks
|
||||||
val serialDescs = properties.serializableProperties.map { it.descriptor }
|
val serialDescs = properties.serializableProperties.map { it.descriptor }
|
||||||
(initMap - serialDescs).forEach { (desc, expr) ->
|
(initMap - serialDescs).forEach { (desc, expr) ->
|
||||||
val e = requireNotNull(expr) {"transient without an initializer"}
|
val e = requireNotNull(expr) { "transient without an initializer" }
|
||||||
val initExpr = Translation.translateAsExpression(e, context)
|
val initExpr = Translation.translateAsExpression(e, context)
|
||||||
+TranslationUtils.assignmentToBackingField(context, desc, initExpr).makeStmt()
|
+TranslationUtils.assignmentToBackingField(context, desc, initExpr).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
declaration.anonymousInitializers()
|
declaration.anonymousInitializers()
|
||||||
.forEach { Translation.translateAsExpression(it, context, this.block) }
|
.forEach { Translation.translateAsExpression(it, context, this.block) }
|
||||||
|
|
||||||
+JsReturn(thiz)
|
+JsReturn(thiz)
|
||||||
}
|
}
|
||||||
@@ -96,7 +102,12 @@ class SerializableJsTranslator(val declaration: KtPureClassOrObject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun translate(declaration: KtPureClassOrObject, descriptor: ClassDescriptor, translator: DeclarationBodyVisitor, context: TranslationContext) {
|
fun translate(
|
||||||
|
declaration: KtPureClassOrObject,
|
||||||
|
descriptor: ClassDescriptor,
|
||||||
|
translator: DeclarationBodyVisitor,
|
||||||
|
context: TranslationContext
|
||||||
|
) {
|
||||||
if (descriptor.isInternalSerializable)
|
if (descriptor.isInternalSerializable)
|
||||||
SerializableJsTranslator(declaration, translator, context).generate()
|
SerializableJsTranslator(declaration, translator, context).generate()
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-13
@@ -80,7 +80,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
val argExprs = args.map { arg ->
|
val argExprs = args.map { arg ->
|
||||||
Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
|
Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
|
||||||
}
|
}
|
||||||
val classRef = context.getQualifiedReference(annotationClass)
|
val classRef = context.translateQualifiedReference(annotationClass)
|
||||||
val invok = JsInvocation(JsNameRef(context.getNameForDescriptor(pushFunc), serialClassDescRef), JsNew(classRef, argExprs))
|
val invok = JsInvocation(JsNameRef(context.getNameForDescriptor(pushFunc), serialClassDescRef), JsNew(classRef, argExprs))
|
||||||
translator.addInitializerStatement(invok.makeStmt())
|
translator.addInitializerStatement(invok.makeStmt())
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
val f = context.buildFunction(typedConstructorDescriptor) { jsFun, context ->
|
val f = context.buildFunction(typedConstructorDescriptor) { jsFun, context ->
|
||||||
val thiz = jsFun.scope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME).makeRef()
|
val thiz = jsFun.scope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME).makeRef()
|
||||||
|
|
||||||
+JsVars(JsVars.JsVar(thiz.name, JsNew(getQualifiedClassReferenceName(serializerDescriptor))))
|
+JsVars(JsVars.JsVar(thiz.name, JsNew(context.getInnerNameForDescriptor(serializerDescriptor).makeRef())))
|
||||||
jsFun.parameters.forEachIndexed { i, parameter ->
|
jsFun.parameters.forEachIndexed { i, parameter ->
|
||||||
val thisFRef = JsNameRef(context.scope().declareName("$typeArgPrefix$i"), thiz)
|
val thisFRef = JsNameRef(context.scope().declareName("$typeArgPrefix$i"), thiz)
|
||||||
+JsAstUtils.assignment(thisFRef, JsNameRef(parameter.name)).makeStmt()
|
+JsAstUtils.assignment(thisFRef, JsNameRef(parameter.name)).makeStmt()
|
||||||
@@ -170,19 +170,15 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
+JsInvocation(JsNameRef(wEndFunc, localOutputRef), serialClassDescRef).makeStmt()
|
+JsInvocation(JsNameRef(wEndFunc, localOutputRef), serialClassDescRef).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getQualifiedClassReferenceName(classDescriptor: ClassDescriptor): JsExpression {
|
|
||||||
return context.getQualifiedReference(classDescriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun serializerInstance(serializerClass: ClassDescriptor?, module: ModuleDescriptor, kType: KotlinType, genericIndex: Int? = null): JsExpression? {
|
private fun serializerInstance(serializerClass: ClassDescriptor?, module: ModuleDescriptor, kType: KotlinType, genericIndex: Int? = null): JsExpression? {
|
||||||
val nullableSerClass = getQualifiedClassReferenceName(requireNotNull(
|
val nullableSerClass = context.translateQualifiedReference(requireNotNull(
|
||||||
module.findClassAcrossModuleDependencies(ClassId(internalPackageFqName, Name.identifier("NullableSerializer")))))
|
module.findClassAcrossModuleDependencies(ClassId(internalPackageFqName, Name.identifier("NullableSerializer")))))
|
||||||
if (serializerClass == null) {
|
if (serializerClass == null) {
|
||||||
if (genericIndex == null) return null
|
if (genericIndex == null) return null
|
||||||
return JsNameRef(context.scope().declareName("$typeArgPrefix$genericIndex"), JsThisRef())
|
return JsNameRef(context.scope().declareName("$typeArgPrefix$genericIndex"), JsThisRef())
|
||||||
}
|
}
|
||||||
if (serializerClass.kind == ClassKind.OBJECT) {
|
if (serializerClass.kind == ClassKind.OBJECT) {
|
||||||
return getQualifiedClassReferenceName(serializerClass)
|
return context.serializerObjectGetter(serializerClass)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
|
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
|
||||||
@@ -197,9 +193,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
|
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
|
||||||
val ref = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
|
val ref = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
|
||||||
val desc = KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor(serializerClass, serializableDescriptor)
|
val desc = KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor(serializerClass, serializableDescriptor)
|
||||||
JsInvocation(context.getInnerNameForDescriptor(desc).makeRef(), args)
|
JsInvocation(context.getInnerReference(desc), args)
|
||||||
} else {
|
} else {
|
||||||
JsNew(getQualifiedClassReferenceName(serializerClass), args)
|
JsNew(context.translateQualifiedReference(serializerClass), args)
|
||||||
}
|
}
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
@@ -207,7 +203,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
|
|
||||||
private fun createGetKClassExpression(classDescriptor: ClassDescriptor): JsExpression =
|
private fun createGetKClassExpression(classDescriptor: ClassDescriptor): JsExpression =
|
||||||
JsInvocation(context.namer().kotlin("getKClass"),
|
JsInvocation(context.namer().kotlin("getKClass"),
|
||||||
getQualifiedClassReferenceName(classDescriptor))
|
context.translateQualifiedReference(classDescriptor))
|
||||||
|
|
||||||
|
|
||||||
override fun generateLoad(function: FunctionDescriptor) = generateFunction(function) { jsFun, context ->
|
override fun generateLoad(function: FunctionDescriptor) = generateFunction(function) { jsFun, context ->
|
||||||
@@ -312,9 +308,15 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
}
|
}
|
||||||
// char unboxing crutch
|
// char unboxing crutch
|
||||||
if (KotlinBuiltIns.isCharOrNullableChar(property.type)) {
|
if (KotlinBuiltIns.isCharOrNullableChar(property.type)) {
|
||||||
|
// can't use KotlinCompilerVersion.VERSION because javac inlines final string literal :(
|
||||||
|
val coerceTo = if (KotlinVersion.CURRENT.run { major == 1 && minor == 2 && patch in (0..10) }) {
|
||||||
|
context.currentModule.builtIns.charType
|
||||||
|
} else {
|
||||||
|
TranslationUtils.getReturnTypeForCoercion(property.descriptor)
|
||||||
|
}
|
||||||
+JsAstUtils.assignment(
|
+JsAstUtils.assignment(
|
||||||
localProps[i],
|
localProps[i],
|
||||||
TranslationUtils.coerce(context, localProps[i], context.currentModule.builtIns.charType)
|
TranslationUtils.coerce(context, localProps[i], coerceTo)
|
||||||
).makeStmt()
|
).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +337,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
// default: throw
|
// default: throw
|
||||||
default {
|
default {
|
||||||
val excClassRef = serializableDescriptor.getClassFromSerializationPackage("UnknownFieldException")
|
val excClassRef = serializableDescriptor.getClassFromSerializationPackage("UnknownFieldException")
|
||||||
.let { context.getQualifiedReference(it) }
|
.let { context.translateQualifiedReference(it) }
|
||||||
+JsThrow(JsNew(excClassRef, listOf(indexVar)))
|
+JsThrow(JsNew(excClassRef, listOf(indexVar)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
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.DescriptorUtils
|
||||||
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.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -182,7 +183,15 @@ class SerializableCodegenImpl(
|
|||||||
{ "Non-serializable parent of serializable $serializableDescriptor must have no arg constructor" })
|
{ "Non-serializable parent of serializable $serializableDescriptor must have no arg constructor" })
|
||||||
|
|
||||||
// call
|
// call
|
||||||
invokespecial(superType, "<init>", "()V", false)
|
// Sealed classes have private <init> so they cannot be inherited from Java src
|
||||||
|
// public <init> is synthetic and contains additional parameter
|
||||||
|
val desc = if (DescriptorUtils.isSealedClass(superClass)) {
|
||||||
|
aconst(null)
|
||||||
|
"(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"
|
||||||
|
} else {
|
||||||
|
"()V"
|
||||||
|
}
|
||||||
|
invokespecial(superType, "<init>", desc, false)
|
||||||
return 0 to propStartVar
|
return 0 to propStartVar
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+3
@@ -30,4 +30,7 @@ class SerializationCodegenExtension : ExpressionCodegenExtension {
|
|||||||
SerializerCodegenImpl.generateSerializerExtensions(codegen)
|
SerializerCodegenImpl.generateSerializerExtensions(codegen)
|
||||||
SerializableCompanionCodegenImpl.generateSerializableExtensions(codegen)
|
SerializableCompanionCodegenImpl.generateSerializableExtensions(codegen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean
|
||||||
|
get() = false
|
||||||
}
|
}
|
||||||
+26
-6
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
||||||
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
|
||||||
@@ -42,30 +43,49 @@ class SerializationResolveExtension : SyntheticResolveExtension {
|
|||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
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 &&
|
else if (thisDescriptor.isInternalSerializable && name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME &&
|
||||||
result.none { it.name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME })
|
result.none { it.name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME }
|
||||||
|
)
|
||||||
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
|
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? =
|
override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? =
|
||||||
if (thisDescriptor.isInternalSerializable) SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
if (thisDescriptor.isInternalSerializable) SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
||||||
else null
|
else null
|
||||||
|
|
||||||
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.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,
|
||||||
|
bindingContext: BindingContext,
|
||||||
|
fromSupertypes: List<SimpleFunctionDescriptor>,
|
||||||
|
result: MutableCollection<SimpleFunctionDescriptor>
|
||||||
|
) {
|
||||||
KSerializerDescriptorResolver.generateSerializerMethods(thisDescriptor, fromSupertypes, name, result)
|
KSerializerDescriptorResolver.generateSerializerMethods(thisDescriptor, fromSupertypes, name, result)
|
||||||
KSerializerDescriptorResolver.generateCompanionObjectMethods(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,
|
||||||
|
bindingContext: BindingContext,
|
||||||
|
fromSupertypes: ArrayList<PropertyDescriptor>,
|
||||||
|
result: MutableSet<PropertyDescriptor>
|
||||||
|
) {
|
||||||
KSerializerDescriptorResolver.generateDescriptorsForAnnotationImpl(thisDescriptor, name, fromSupertypes, result)
|
KSerializerDescriptorResolver.generateDescriptorsForAnnotationImpl(thisDescriptor, name, fromSupertypes, result)
|
||||||
KSerializerDescriptorResolver.generateSerializerProperties(thisDescriptor, fromSupertypes, name, result)
|
KSerializerDescriptorResolver.generateSerializerProperties(thisDescriptor, fromSupertypes, name, result)
|
||||||
}
|
}
|
||||||
|
|||||||
+76
-33
@@ -28,7 +28,10 @@ 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.*
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
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.*
|
||||||
@@ -74,7 +77,7 @@ object KSerializerDescriptorResolver {
|
|||||||
val interfaceDecl = declarationProvider.correspondingClassOrObject!!
|
val interfaceDecl = declarationProvider.correspondingClassOrObject!!
|
||||||
val scope = ctx.declarationScopeProvider.getResolutionScopeForDeclaration(declarationProvider.ownerInfo!!.scopeAnchor)
|
val scope = ctx.declarationScopeProvider.getResolutionScopeForDeclaration(declarationProvider.ownerInfo!!.scopeAnchor)
|
||||||
|
|
||||||
return SyntheticClassOrObjectDescriptor(ctx,
|
val descriptor = SyntheticClassOrObjectDescriptor(ctx,
|
||||||
interfaceDecl,
|
interfaceDecl,
|
||||||
interfaceDesc,
|
interfaceDesc,
|
||||||
IMPL_NAME,
|
IMPL_NAME,
|
||||||
@@ -85,18 +88,35 @@ object KSerializerDescriptorResolver {
|
|||||||
Visibilities.PRIVATE,
|
Visibilities.PRIVATE,
|
||||||
ClassKind.CLASS,
|
ClassKind.CLASS,
|
||||||
false)
|
false)
|
||||||
|
descriptor.initialize()
|
||||||
|
return descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSerializerImplClass(thisDescriptor: ClassDescriptor, declarationProvider: ClassMemberDeclarationProvider, ctx: LazyClassContext): ClassDescriptor {
|
fun addSerializerImplClass(
|
||||||
|
thisDescriptor: ClassDescriptor,
|
||||||
|
declarationProvider: ClassMemberDeclarationProvider,
|
||||||
|
ctx: LazyClassContext
|
||||||
|
): ClassDescriptor {
|
||||||
val thisDeclaration = declarationProvider.correspondingClassOrObject!!
|
val thisDeclaration = declarationProvider.correspondingClassOrObject!!
|
||||||
val scope = ctx.declarationScopeProvider.getResolutionScopeForDeclaration(declarationProvider.ownerInfo!!.scopeAnchor)
|
val scope = ctx.declarationScopeProvider.getResolutionScopeForDeclaration(declarationProvider.ownerInfo!!.scopeAnchor)
|
||||||
val serializerKind = if (thisDescriptor.declaredTypeParameters.isNotEmpty()) ClassKind.CLASS else ClassKind.OBJECT
|
val serializerKind = if (thisDescriptor.declaredTypeParameters.isNotEmpty()) ClassKind.CLASS else ClassKind.OBJECT
|
||||||
return SyntheticClassOrObjectDescriptor(ctx,
|
val serializerDescriptor = SyntheticClassOrObjectDescriptor(
|
||||||
thisDeclaration,
|
ctx,
|
||||||
thisDescriptor, SERIALIZER_CLASS_NAME, thisDescriptor.source,
|
thisDeclaration,
|
||||||
scope,
|
thisDescriptor, SERIALIZER_CLASS_NAME, thisDescriptor.source,
|
||||||
Modality.FINAL, Visibilities.PUBLIC, Visibilities.PRIVATE,
|
scope,
|
||||||
serializerKind, false)
|
Modality.FINAL, Visibilities.PUBLIC, Visibilities.PRIVATE,
|
||||||
|
serializerKind, false
|
||||||
|
)
|
||||||
|
val typeParameters: List<TypeParameterDescriptor> =
|
||||||
|
thisDescriptor.declaredTypeParameters.mapIndexed { index, param ->
|
||||||
|
TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||||
|
serializerDescriptor, Annotations.EMPTY, false, Variance.INVARIANT,
|
||||||
|
param.name, index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
serializerDescriptor.initialize(typeParameters)
|
||||||
|
return serializerDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateSerializerProperties(thisDescriptor: ClassDescriptor,
|
fun generateSerializerProperties(thisDescriptor: ClassDescriptor,
|
||||||
@@ -110,10 +130,12 @@ object KSerializerDescriptorResolver {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateCompanionObjectMethods(thisDescriptor: ClassDescriptor,
|
fun generateCompanionObjectMethods(
|
||||||
fromSupertypes: List<SimpleFunctionDescriptor>,
|
thisDescriptor: ClassDescriptor,
|
||||||
name: Name,
|
fromSupertypes: List<SimpleFunctionDescriptor>,
|
||||||
result: MutableCollection<SimpleFunctionDescriptor>) {
|
name: Name,
|
||||||
|
result: MutableCollection<SimpleFunctionDescriptor>
|
||||||
|
) {
|
||||||
val classDescriptor = getSerializableClassDescriptorByCompanion(thisDescriptor) ?: return
|
val classDescriptor = getSerializableClassDescriptorByCompanion(thisDescriptor) ?: return
|
||||||
|
|
||||||
if (name == SERIALIZER_PROVIDER_NAME && result.none { it.valueParameters.size == classDescriptor.declaredTypeParameters.size }) {
|
if (name == SERIALIZER_PROVIDER_NAME && result.none { it.valueParameters.size == classDescriptor.declaredTypeParameters.size }) {
|
||||||
@@ -248,24 +270,32 @@ object KSerializerDescriptorResolver {
|
|||||||
return functionDescriptor
|
return functionDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createTypedSerializerConstructorDescriptor(classDescriptor: ClassDescriptor, serializableDescriptor: ClassDescriptor): ConstructorDescriptor {
|
fun createTypedSerializerConstructorDescriptor(
|
||||||
|
classDescriptor: ClassDescriptor,
|
||||||
|
serializableDescriptor: ClassDescriptor
|
||||||
|
): ConstructorDescriptor {
|
||||||
val constrDesc = ClassConstructorDescriptorImpl.createSynthesized(
|
val constrDesc = ClassConstructorDescriptorImpl.createSynthesized(
|
||||||
classDescriptor,
|
classDescriptor,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
false,
|
false,
|
||||||
classDescriptor.source
|
classDescriptor.source
|
||||||
)
|
)
|
||||||
val serializerClass = classDescriptor.getClassFromSerializationPackage("KSerializer")
|
val serializerClass = classDescriptor.getClassFromSerializationPackage("KSerializer")
|
||||||
val targs = mutableListOf<TypeParameterDescriptor>()
|
val targs = mutableListOf<TypeParameterDescriptor>()
|
||||||
val args = serializableDescriptor.declaredTypeParameters.mapIndexed { index, _ ->
|
val args = serializableDescriptor.declaredTypeParameters.mapIndexed { index, param ->
|
||||||
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(constrDesc, Annotations.EMPTY, false, Variance.INVARIANT,
|
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||||
Name.identifier("T$index"), index)
|
constrDesc, Annotations.EMPTY, false, Variance.INVARIANT,
|
||||||
|
param.name, index
|
||||||
|
)
|
||||||
|
|
||||||
val pType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(targ.defaultType)))
|
val pType =
|
||||||
|
KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(targ.defaultType)))
|
||||||
|
|
||||||
targs.add(targ)
|
targs.add(targ)
|
||||||
ValueParameterDescriptorImpl(constrDesc, null, index, Annotations.EMPTY, Name.identifier("$typeArgPrefix$index"), pType,
|
ValueParameterDescriptorImpl(
|
||||||
false, false, false, null, constrDesc.source)
|
constrDesc, null, index, Annotations.EMPTY, Name.identifier("$typeArgPrefix$index"), pType,
|
||||||
|
false, false, false, null, constrDesc.source
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
constrDesc.initialize(args, Visibilities.PUBLIC, targs)
|
constrDesc.initialize(args, Visibilities.PUBLIC, targs)
|
||||||
@@ -274,7 +304,13 @@ object KSerializerDescriptorResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createSerializerGetterDescriptor(thisClass: ClassDescriptor, serializableClass: ClassDescriptor): SimpleFunctionDescriptor {
|
fun createSerializerGetterDescriptor(thisClass: ClassDescriptor, serializableClass: ClassDescriptor): SimpleFunctionDescriptor {
|
||||||
val f = SimpleFunctionDescriptorImpl.create(thisClass, Annotations.EMPTY, SERIALIZER_PROVIDER_NAME, CallableMemberDescriptor.Kind.SYNTHESIZED, thisClass.source)
|
val f = SimpleFunctionDescriptorImpl.create(
|
||||||
|
thisClass,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
SERIALIZER_PROVIDER_NAME,
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
thisClass.source
|
||||||
|
)
|
||||||
val serializerClass = thisClass.getClassFromSerializationPackage("KSerializer")
|
val serializerClass = thisClass.getClassFromSerializationPackage("KSerializer")
|
||||||
|
|
||||||
val args = mutableListOf<ValueParameterDescriptor>()
|
val args = mutableListOf<ValueParameterDescriptor>()
|
||||||
@@ -282,31 +318,38 @@ object KSerializerDescriptorResolver {
|
|||||||
var i = 0
|
var i = 0
|
||||||
|
|
||||||
serializableClass.declaredTypeParameters.forEach { it ->
|
serializableClass.declaredTypeParameters.forEach { it ->
|
||||||
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(f, Annotations.EMPTY, false, Variance.INVARIANT,
|
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||||
Name.identifier("T$i"), i)
|
f, Annotations.EMPTY, false, Variance.INVARIANT,
|
||||||
|
Name.identifier("T$i"), i
|
||||||
|
)
|
||||||
|
|
||||||
val pType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(targ.defaultType)))
|
val pType =
|
||||||
|
KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(targ.defaultType)))
|
||||||
|
|
||||||
args.add(ValueParameterDescriptorImpl(
|
args.add(
|
||||||
|
ValueParameterDescriptorImpl(
|
||||||
f,
|
f,
|
||||||
null,
|
null,
|
||||||
i,
|
i,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
Name.identifier("$typeArgPrefix${i}"),
|
Name.identifier("$typeArgPrefix$i"),
|
||||||
pType,
|
pType,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
f.source
|
f.source
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
typeArgs.add(targ)
|
typeArgs.add(targ)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
val newSerializableType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializableClass, typeArgs.map { TypeProjectionImpl(it.defaultType) })
|
val newSerializableType =
|
||||||
val serialReturnType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, serializerClass, listOf(TypeProjectionImpl(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)
|
f.initialize(null, thisClass.thisAsReceiverParameter, typeArgs, args, serialReturnType, Modality.FINAL, Visibilities.PUBLIC)
|
||||||
return f
|
return f
|
||||||
|
|||||||
+28
-27
@@ -19,51 +19,52 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
|
||||||
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) {
|
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) {
|
||||||
private val primaryConstructorParameters: List<ValueParameterDescriptor> =
|
private val primaryConstructorParameters: List<ValueParameterDescriptor> =
|
||||||
serializableClass.unsubstitutedPrimaryConstructor?.valueParameters ?: emptyList()
|
serializableClass.unsubstitutedPrimaryConstructor?.valueParameters ?: emptyList()
|
||||||
|
|
||||||
private val primaryConstructorProperties: Map<PropertyDescriptor, Boolean> =
|
private val primaryConstructorProperties: Map<PropertyDescriptor, Boolean> =
|
||||||
primaryConstructorParameters.asSequence()
|
primaryConstructorParameters.asSequence()
|
||||||
.map { parameter -> bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter] to parameter.hasDefaultValue() }
|
.map { parameter -> bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter] to parameter.declaresDefaultValue() }
|
||||||
.mapNotNull { (a, b) -> if (a == null) null else a to b }
|
.mapNotNull { (a, b) -> if (a == null) null else a to b }
|
||||||
.toMap()
|
.toMap()
|
||||||
|
|
||||||
val isExternallySerializable: Boolean =
|
val isExternallySerializable: Boolean =
|
||||||
primaryConstructorParameters.size == primaryConstructorProperties.size
|
primaryConstructorParameters.size == primaryConstructorProperties.size
|
||||||
|
|
||||||
val serializableProperties: List<SerializableProperty> =
|
val serializableProperties: List<SerializableProperty> =
|
||||||
serializableClass.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES)
|
serializableClass.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filterIsInstance<PropertyDescriptor>()
|
.filterIsInstance<PropertyDescriptor>()
|
||||||
.filter { it.kind == CallableMemberDescriptor.Kind.DECLARATION }
|
.filter { it.kind == CallableMemberDescriptor.Kind.DECLARATION }
|
||||||
.filter(this::isPropSerializable)
|
.filter(this::isPropSerializable)
|
||||||
.map { prop -> SerializableProperty(prop, primaryConstructorProperties[prop] ?: false) }
|
.map { prop -> SerializableProperty(prop, primaryConstructorProperties[prop] ?: false) }
|
||||||
.partition { primaryConstructorProperties.contains(it.descriptor) }
|
.partition { primaryConstructorProperties.contains(it.descriptor) }
|
||||||
.run {
|
.run {
|
||||||
val supers = serializableClass.getSuperClassNotAny()
|
val supers = serializableClass.getSuperClassNotAny()
|
||||||
if (supers == null || !supers.isInternalSerializable)
|
if (supers == null || !supers.isInternalSerializable)
|
||||||
first + second
|
first + second
|
||||||
else
|
else
|
||||||
SerializableProperties(supers, bindingContext).serializableProperties + first + second
|
SerializableProperties(supers, bindingContext).serializableProperties + first + second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun isPropSerializable(it: PropertyDescriptor) =
|
private fun isPropSerializable(it: PropertyDescriptor) =
|
||||||
if (serializableClass.isInternalSerializable) !it.annotations.serialTransient
|
if (serializableClass.isInternalSerializable) !it.annotations.serialTransient
|
||||||
else !Visibilities.isPrivate(it.visibility) && ((it.isVar && !it.annotations.serialTransient) || primaryConstructorProperties.contains(it))
|
else !Visibilities.isPrivate(it.visibility) && ((it.isVar && !it.annotations.serialTransient) || primaryConstructorProperties.contains(
|
||||||
|
it
|
||||||
|
))
|
||||||
|
|
||||||
val serializableConstructorProperties: List<SerializableProperty> =
|
val serializableConstructorProperties: List<SerializableProperty> =
|
||||||
serializableProperties.asSequence()
|
serializableProperties.asSequence()
|
||||||
.filter { primaryConstructorProperties.contains(it.descriptor) }
|
.filter { primaryConstructorProperties.contains(it.descriptor) }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val serializableStandaloneProperties: List<SerializableProperty> =
|
val serializableStandaloneProperties: List<SerializableProperty> =
|
||||||
serializableProperties.minus(serializableConstructorProperties)
|
serializableProperties.minus(serializableConstructorProperties)
|
||||||
|
|
||||||
val size = serializableProperties.size
|
val size = serializableProperties.size
|
||||||
val indices = serializableProperties.indices
|
val indices = serializableProperties.indices
|
||||||
|
|||||||
+8
-7
@@ -34,12 +34,13 @@ class KotlinSerializationJpsPlugin : KotlinJpsCompilerArgumentsProvider {
|
|||||||
override fun getClasspath(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String> {
|
override fun getClasspath(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String> {
|
||||||
val inJar = File(PathUtil.getJarPathForClass(this::class.java)).isFile
|
val inJar = File(PathUtil.getJarPathForClass(this::class.java)).isFile
|
||||||
return listOf(
|
return listOf(
|
||||||
if (inJar) {
|
if (inJar) {
|
||||||
File(PathUtil.getJarPathForClass(this::class.java)).absolutePath
|
File(PathUtil.getJarPathForClass(this::class.java)).absolutePath
|
||||||
} else {
|
} else {
|
||||||
// We're in tests now
|
// We're in tests now
|
||||||
val kotlinProjectDirectory = File(PathUtil.getJarPathForClass(javaClass)).parentFile.parentFile.parentFile
|
val kotlinProjectDirectory = File(PathUtil.getJarPathForClass(javaClass)).parentFile.parentFile.parentFile
|
||||||
File(kotlinProjectDirectory, "dist/artifacts/Serialization/lib/$JAR_FILE_NAME").absolutePath
|
File(kotlinProjectDirectory, "dist/artifacts/Serialization/lib/$JAR_FILE_NAME").absolutePath
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ val intellijUltimateEnabled : Boolean by rootProject.extra
|
|||||||
|
|
||||||
val ideaUltimatePluginDir: File by rootProject.extra
|
val ideaUltimatePluginDir: File by rootProject.extra
|
||||||
val ideaUltimateSandboxDir: File by rootProject.extra
|
val ideaUltimateSandboxDir: File by rootProject.extra
|
||||||
|
val serialPluginDir: File by rootProject.extra
|
||||||
|
|
||||||
if (intellijUltimateEnabled) {
|
if (intellijUltimateEnabled) {
|
||||||
runIdeTask("runUltimate", ideaUltimatePluginDir, ideaUltimateSandboxDir) {
|
runIdeTask("runUltimate", ideaUltimatePluginDir, ideaUltimateSandboxDir, serialPluginDir) {
|
||||||
dependsOn(":dist", ":ideaPlugin", ":ultimate:ideaUltimatePlugin")
|
dependsOn(":dist", ":ideaPlugin", ":ultimate:ideaUltimatePlugin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user