diff --git a/libraries/tools/kotlin-maven-serialization/pom.xml b/libraries/tools/kotlin-maven-serialization/pom.xml
index ddcc00b6962..276b806feb4 100755
--- a/libraries/tools/kotlin-maven-serialization/pom.xml
+++ b/libraries/tools/kotlin-maven-serialization/pom.xml
@@ -19,7 +19,7 @@
org.jetbrains.kotlinx
kotlinx-maven-serialization-plugin
jar
- 0.5.0
+ 0.5.2-SNAPSHOT
Serialization plugin for Maven
diff --git a/libraries/tools/kotlin-serialization/build.gradle b/libraries/tools/kotlin-serialization/build.gradle
index d6afcd7da8b..82164013133 100644
--- a/libraries/tools/kotlin-serialization/build.gradle
+++ b/libraries/tools/kotlin-serialization/build.gradle
@@ -8,7 +8,7 @@ configureJvmProject(project)
configurePublishing(project)
group = 'org.jetbrains.kotlinx'
-version = '0.5.0'
+version = '0.5.2'
if (!project.hasProperty("deploy")) {
version = "$version-SNAPSHOT"
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md b/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md
index bb31a32e291..e1c22d6f49b 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/README.md
@@ -8,7 +8,7 @@ Compiler plugins are uploaded on bintray: https://bintray.com/kotlin/kotlinx/kot
## Building and usage
### Prerequisites:
-Before all, follow the instructions from root README.md to download dependencies and build Kotlin compiler. (`ant -f update_dependencies.xml && ./gradlew dist`)
+Before all, follow the instructions from root README.md to download dependencies and build Kotlin compiler. (`./gradlew dist`)
**Plugin works only with IntelliJIDEA 2017.2 and higher.**
@@ -29,5 +29,5 @@ Run `./gradlew :kotlinx-gradle-serialization-plugin:install`
## Building maven plugin
-Go to `$kotlin_root/libraries/tools/kotlin-maven-serialization`. Run `mvn install`
+Make all prerequisites from libraries' README.md for Maven projects. Go to `$kotlin_root/libraries/tools/kotlin-maven-serialization`. Run `mvn install`
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml
index 71c492bf9f9..fa08b08e9ef 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/META-INF/plugin.xml
@@ -1,7 +1,7 @@
Kotlin-serialization
org.jetbrains.kotlinx.serialization
- 0.5.0
+ 0.5.2-SNAPSHOT
org.jetbrains.kotlin
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt
index 3fc779ec541..fcdabed30c3 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt
@@ -30,7 +30,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescripto
abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) {
protected val serializerDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext)
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
- protected val serialName: String = serializableDescriptor.fqNameUnsafe.asString()
+ protected val serialName: String = serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString()
protected val properties = SerializableProperties(serializableDescriptor, bindingContext)
protected val orderedProperties = properties.serializableProperties
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt
index 6c4296a6696..014ab3faa32 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt
@@ -18,6 +18,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.js
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.js.translate.declaration.DefaultPropertyTranslator
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
-import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
@@ -67,6 +67,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
// adding elements via serialDesc.addElement(...)
val addFunc = serialDescImplClass.getFuncDesc("addElement").single()
val pushFunc = serialDescImplClass.getFuncDesc("pushAnnotation").single()
+ val pushClassFunc = serialDescImplClass.getFuncDesc("pushClassAnnotation").single()
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor), JsThisRef())
for (prop in orderedProperties) {
@@ -74,14 +75,21 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val call = JsInvocation(JsNameRef(context.getNameForDescriptor(addFunc), serialClassDescRef), JsStringLiteral(prop.name))
translator.addInitializerStatement(call.makeStmt())
// serialDesc.pushAnnotation(...)
- for ((annotationClass , args, _) in prop.annotationsWithArguments) {
- val argExprs = args.map { arg ->
- Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
- }
- val classRef = context.translateQualifiedReference(annotationClass)
- val invok = JsInvocation(JsNameRef(context.getNameForDescriptor(pushFunc), serialClassDescRef), JsNew(classRef, argExprs))
- translator.addInitializerStatement(invok.makeStmt())
+ pushAnnotationsInto(prop.descriptor, pushFunc, serialClassDescRef)
+ }
+
+ // push class annotations
+ pushAnnotationsInto(serializableDescriptor, pushClassFunc, serialClassDescRef)
+ }
+
+ private fun pushAnnotationsInto(annotated: Annotated, pushFunction: DeclarationDescriptor, intoRef: JsNameRef) {
+ for ((annotationClass , args, _) in annotated.annotationsWithArguments()) {
+ val argExprs = args.map { arg ->
+ Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
}
+ val classRef = context.translateQualifiedReference(annotationClass)
+ val invok = JsInvocation(JsNameRef(context.getNameForDescriptor(pushFunction), intoRef), JsNew(classRef, argExprs))
+ translator.addInitializerStatement(invok.makeStmt())
}
}
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt
index 9d533cb06d3..cd057cdc4c9 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt
@@ -17,15 +17,14 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
import org.jetbrains.kotlin.codegen.*
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
+import org.jetbrains.kotlinx.serialization.compiler.resolve.annotationsWithArguments
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
import org.jetbrains.org.objectweb.asm.Label
@@ -91,29 +90,45 @@ class SerializerCodegenImpl(
for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(classDescVar, descImplType)
- val implType = codegen.typeMapper.mapType(annotationClass).internalName + "\$" + KSerializerDescriptorResolver.IMPL_NAME.identifier
- // new Annotation$Impl(...)
- anew(Type.getObjectType(implType))
- dup()
- val sb = StringBuilder("(")
- for (i in consParams.indices) {
- val decl = args[i]
- val desc = consParams[i]
- val valAsmType = codegen.typeMapper.mapType(desc.type)
- expr.gen(decl.getArgumentExpression(), valAsmType)
- sb.append(valAsmType.descriptor)
- }
- sb.append(")V")
- invokespecial(implType, "", sb.toString(), false)
- // serialDesc.pushAnnotation(..)
+ expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
invokevirtual(descImplType.internalName, "pushAnnotation", "(Ljava/lang/annotation/Annotation;)V", false)
}
}
+ // add annotations on class itself
+ for ((annotationClass, args, consParams) in serializableDescriptor.annotationsWithArguments()) {
+ if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
+ load(classDescVar, descImplType)
+ expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
+ invokevirtual(descImplType.internalName, "pushClassAnnotation", "(Ljava/lang/annotation/Annotation;)V", false)
+ }
load(classDescVar, descImplType)
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
}
}
+ private fun ExpressionCodegen.generateSyntheticAnnotationOnStack(
+ annotationClass: ClassDescriptor,
+ args: List,
+ ctorParams: List
+ ) {
+ val implType = codegen.typeMapper.mapType(annotationClass).internalName + "\$" + KSerializerDescriptorResolver.IMPL_NAME.identifier
+ with(v) {
+ // new Annotation$Impl(...)
+ anew(Type.getObjectType(implType))
+ dup()
+ val sb = StringBuilder("(")
+ for (i in ctorParams.indices) {
+ val decl = args[i]
+ val desc = ctorParams[i]
+ val valAsmType = codegen.typeMapper.mapType(desc.type)
+ this@generateSyntheticAnnotationOnStack.gen(decl.getArgumentExpression(), valAsmType)
+ sb.append(valAsmType.descriptor)
+ }
+ sb.append(")V")
+ invokespecial(implType, "", sb.toString(), false)
+ }
+ }
+
private fun InstructionAdapter.serialCLassDescToLocalVar(classDescVar: Int) {
getstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
store(classDescVar, descType)
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt
index 8ce11e9609e..18f2fd67ac5 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt
@@ -18,10 +18,12 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
@@ -124,8 +126,10 @@ val KotlinType?.toClassDescriptor: ClassDescriptor?
val ClassDescriptor.isInternalSerializable: Boolean //todo normal checking
get() {
if (!annotations.hasAnnotation(serializableAnnotationFqName)) return false
+ // If provided descriptor is lazy, carefully look at psi in order not to trigger full resolve which may be recursive.
+ // Otherwise, this descriptor is deserialized from another module and it is OK to check value right away.
val lazyDesc = annotations.findAnnotation(serializableAnnotationFqName)
- as? LazyAnnotationDescriptor ?: return false
+ as? LazyAnnotationDescriptor ?: return (annotations.serializableWith == null)
val psi = lazyDesc.annotationEntry
return psi.valueArguments.isEmpty()
}
@@ -232,3 +236,14 @@ fun ClassDescriptor.getClassFromInternalSerializationPackage(classSimpleName: St
module.getClassFromInternalSerializationPackage(classSimpleName)
fun ClassDescriptor.toSimpleType(nullable: Boolean = true) = KotlinTypeFactory.simpleType(Annotations.EMPTY, this.typeConstructor, emptyList(), nullable)
+
+fun Annotated.annotationsWithArguments(): List, List>> =
+ annotations.asSequence()
+ .filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(serialInfoFqName) == true }
+ .filterIsInstance()
+ .mapNotNull { annDesc ->
+ annDesc.type.toClassDescriptor?.let {
+ Triple(it, annDesc.annotationEntry.valueArguments, it.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty())
+ }
+ }
+ .toList()
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperties.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperties.kt
index 487b7b3e477..c4a7a7dc057 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperties.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperties.kt
@@ -19,7 +19,6 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
-import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) {
@@ -71,5 +70,6 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
operator fun get(index: Int) = serializableProperties[index]
operator fun iterator() = serializableProperties.iterator()
- val primaryConstructorWithDefaults = serializableClass.unsubstitutedPrimaryConstructor?.hasOwnParametersWithDefaultValue() ?: false
+ val primaryConstructorWithDefaults = serializableClass.unsubstitutedPrimaryConstructor
+ ?.original?.valueParameters?.any { it.declaresDefaultValue() } ?: false
}
\ No newline at end of file
diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt
index ba6a9dd1972..706810159fe 100644
--- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt
+++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SerializableProperty.kt
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.module
-import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructorParameterWithDefault: Boolean) {
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
@@ -32,13 +31,5 @@ class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructor
val optional = descriptor.annotations.serialOptional
val transient = descriptor.annotations.serialTransient
val annotationsWithArguments: List, List>> =
- descriptor.annotations.asSequence()
- .filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(serialInfoFqName) == true }
- .filterIsInstance()
- .mapNotNull { annDesc ->
- annDesc.type.toClassDescriptor?.let {
- Triple(it, annDesc.annotationEntry.valueArguments, it.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty())
- }
- }
- .toList()
+ descriptor.annotationsWithArguments()
}