[Serialization] Implement serialization checker for K2 version of plugin
^KT-53178 Fixed
This commit is contained in:
committed by
teamcity
parent
e048ffcf6d
commit
671083c701
@@ -8,6 +8,7 @@ plugins {
|
||||
dependencies {
|
||||
compileOnly(project(":compiler:util"))
|
||||
compileOnly(project(":core:compiler.common"))
|
||||
compileOnly(project(":core:deserialization.common.jvm"))
|
||||
compileOnly(intellijCore())
|
||||
}
|
||||
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlinx.serialization.compiler.diagnostic
|
||||
|
||||
import com.intellij.openapi.util.io.JarUtil
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
import java.io.File
|
||||
import java.util.jar.Attributes
|
||||
|
||||
data class RuntimeVersions(val implementationVersion: ApiVersion?, val requireKotlinVersion: ApiVersion?) {
|
||||
companion object {
|
||||
val MINIMAL_SUPPORTED_VERSION = ApiVersion.parse("1.0-M1-SNAPSHOT")!!
|
||||
val MINIMAL_VERSION_FOR_INLINE_CLASSES = ApiVersion.parse("1.1-M1-SNAPSHOT")!!
|
||||
}
|
||||
|
||||
fun currentCompilerMatchRequired(): Boolean {
|
||||
val current = requireNotNull(KotlinCompilerVersion.getVersion()?.let(ApiVersion.Companion::parse))
|
||||
return requireKotlinVersion == null || requireKotlinVersion <= current
|
||||
}
|
||||
|
||||
fun implementationVersionMatchSupported(): Boolean {
|
||||
return implementationVersion != null && implementationVersion >= MINIMAL_SUPPORTED_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
object CommonVersionReader {
|
||||
private val REQUIRE_KOTLIN_VERSION = Attributes.Name("Require-Kotlin-Version")
|
||||
private const val CLASS_SUFFIX = "!/kotlinx/serialization/KSerializer.class"
|
||||
|
||||
fun computeRuntimeVersions(sourceElement: SourceElement?): RuntimeVersions? {
|
||||
val location = (sourceElement as? KotlinJvmBinarySourceElement)?.binaryClass?.location ?: return null
|
||||
val jarFile = location.removeSuffix(CLASS_SUFFIX)
|
||||
if (!jarFile.endsWith(".jar")) return null
|
||||
val file = File(jarFile)
|
||||
if (!file.exists()) return null
|
||||
return getVersionsFromManifest(file)
|
||||
}
|
||||
|
||||
fun getVersionsFromManifest(runtimeLibraryPath: File): RuntimeVersions {
|
||||
val version = JarUtil.getJarAttribute(runtimeLibraryPath, Attributes.Name.IMPLEMENTATION_VERSION)?.let(ApiVersion.Companion::parse)
|
||||
val kotlinVersion = JarUtil.getJarAttribute(runtimeLibraryPath, REQUIRE_KOTLIN_VERSION)?.let(ApiVersion.Companion::parse)
|
||||
return RuntimeVersions(version, kotlinVersion)
|
||||
}
|
||||
|
||||
fun canSupportInlineClasses(currentVersion: RuntimeVersions?): Boolean {
|
||||
if (currentVersion == null) return true
|
||||
val implVersion = currentVersion.implementationVersion ?: return false
|
||||
return implVersion >= RuntimeVersions.MINIMAL_VERSION_FOR_INLINE_CLASSES
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||
|
||||
interface ISerializableProperties<S : ISerializableProperty> {
|
||||
val serializableProperties: List<S>
|
||||
val isExternallySerializable: Boolean
|
||||
val serializableConstructorProperties: List<S>
|
||||
val serializableStandaloneProperties: List<S>
|
||||
}
|
||||
|
||||
val ISerializableProperties<*>.goldenMask: Int
|
||||
get() {
|
||||
var goldenMask = 0
|
||||
var requiredBit = 1
|
||||
for (property in serializableProperties) {
|
||||
if (!property.optional) {
|
||||
goldenMask = goldenMask or requiredBit
|
||||
}
|
||||
requiredBit = requiredBit shl 1
|
||||
}
|
||||
return goldenMask
|
||||
}
|
||||
|
||||
val ISerializableProperties<*>.goldenMaskList: List<Int>
|
||||
get() {
|
||||
val maskSlotCount = serializableProperties.bitMaskSlotCount()
|
||||
val goldenMaskList = MutableList(maskSlotCount) { 0 }
|
||||
|
||||
for (i in serializableProperties.indices) {
|
||||
if (!serializableProperties[i].optional) {
|
||||
val slotNumber = i / 32
|
||||
val bitInSlot = i % 32
|
||||
goldenMaskList[slotNumber] = goldenMaskList[slotNumber] or (1 shl bitInSlot)
|
||||
}
|
||||
}
|
||||
return goldenMaskList
|
||||
}
|
||||
|
||||
fun List<ISerializableProperty>.bitMaskSlotCount(): Int = size / 32 + 1
|
||||
fun bitMaskSlotAt(propertyIndex: Int): Int = propertyIndex / 32
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
interface ISerializableProperty {
|
||||
val isConstructorParameterWithDefault: Boolean
|
||||
val name: String
|
||||
val originalDescriptorName: Name
|
||||
val optional: Boolean
|
||||
val transient: Boolean
|
||||
}
|
||||
+109
@@ -41,6 +41,22 @@ object SerializationAnnotations {
|
||||
val contextualOnPropertyFqName = FqName("kotlinx.serialization.Contextual")
|
||||
val polymorphicFqName = FqName("kotlinx.serialization.Polymorphic")
|
||||
val additionalSerializersFqName = FqName("kotlinx.serialization.UseSerializers")
|
||||
|
||||
val serializableAnnotationClassId = ClassId.topLevel(serializableAnnotationFqName)
|
||||
val serializerAnnotationClassId = ClassId.topLevel(serializerAnnotationFqName)
|
||||
val serialNameAnnotationClassId = ClassId.topLevel(serialNameAnnotationFqName)
|
||||
val requiredAnnotationClassId = ClassId.topLevel(requiredAnnotationFqName)
|
||||
val serialTransientClassId = ClassId.topLevel(serialTransientFqName)
|
||||
val serialInfoClassId = ClassId.topLevel(serialInfoFqName)
|
||||
val inheritableSerialInfoClassId = ClassId.topLevel(inheritableSerialInfoFqName)
|
||||
val metaSerializableAnnotationClassId = ClassId.topLevel(metaSerializableAnnotationFqName)
|
||||
val encodeDefaultClassId = ClassId.topLevel(encodeDefaultFqName)
|
||||
|
||||
val contextualClassId = ClassId.topLevel(contextualFqName)
|
||||
val contextualOnFileClassId = ClassId.topLevel(contextualOnFileFqName)
|
||||
val contextualOnPropertyClassId = ClassId.topLevel(contextualOnPropertyFqName)
|
||||
val polymorphicClassId = ClassId.topLevel(polymorphicFqName)
|
||||
val additionalSerializersClassId = ClassId.topLevel(additionalSerializersFqName)
|
||||
}
|
||||
|
||||
object SerialEntityNames {
|
||||
@@ -55,9 +71,12 @@ object SerialEntityNames {
|
||||
|
||||
// classes
|
||||
val KCLASS_NAME_FQ = FqName("kotlin.reflect.KClass")
|
||||
val KCLASS_NAME_CLASS_ID = ClassId.topLevel(KCLASS_NAME_FQ)
|
||||
val KSERIALIZER_NAME = Name.identifier(KSERIALIZER_CLASS)
|
||||
val SERIAL_CTOR_MARKER_NAME = Name.identifier("SerializationConstructorMarker")
|
||||
val KSERIALIZER_NAME_FQ = SerializationPackages.packageFqName.child(KSERIALIZER_NAME)
|
||||
val KSERIALIZER_CLASS_ID = ClassId.topLevel(KSERIALIZER_NAME_FQ)
|
||||
|
||||
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
|
||||
val IMPL_NAME = Name.identifier("Impl")
|
||||
|
||||
@@ -123,8 +142,30 @@ object SpecialBuiltins {
|
||||
const val sealedSerializer = "SealedClassSerializer"
|
||||
const val contextSerializer = "ContextualSerializer"
|
||||
const val nullableSerializer = "NullableSerializer"
|
||||
|
||||
object Names {
|
||||
val referenceArraySerializer = Name.identifier(SpecialBuiltins.referenceArraySerializer)
|
||||
val objectSerializer = Name.identifier(SpecialBuiltins.objectSerializer)
|
||||
val enumSerializer = Name.identifier(SpecialBuiltins.enumSerializer)
|
||||
val polymorphicSerializer = Name.identifier(SpecialBuiltins.polymorphicSerializer)
|
||||
val sealedSerializer = Name.identifier(SpecialBuiltins.sealedSerializer)
|
||||
val contextSerializer = Name.identifier(SpecialBuiltins.contextSerializer)
|
||||
val nullableSerializer = Name.identifier(SpecialBuiltins.nullableSerializer)
|
||||
}
|
||||
}
|
||||
|
||||
object PrimitiveBuiltins {
|
||||
const val booleanSerializer = "BooleanSerializer"
|
||||
const val byteSerializer = "ByteSerializer"
|
||||
const val shortSerializer = "ShortSerializer"
|
||||
const val intSerializer = "IntSerializer"
|
||||
const val longSerializer = "LongSerializer"
|
||||
const val floatSerializer = "FloatSerializer"
|
||||
const val doubleSerializer = "DoubleSerializer"
|
||||
const val charSerializer = "CharSerializer"
|
||||
}
|
||||
|
||||
|
||||
object CallingConventions {
|
||||
const val begin = "beginStructure"
|
||||
const val end = "endStructure"
|
||||
@@ -153,3 +194,71 @@ object SerializationDependencies {
|
||||
val FUNCTION0_FQ = FqName("kotlin.Function0")
|
||||
val LAZY_PUBLICATION_MODE_NAME = Name.identifier("PUBLICATION")
|
||||
}
|
||||
|
||||
object SerializersClassIds {
|
||||
val enumSerializerId = ClassId(SerializationPackages.internalPackageFqName, Name.identifier(SpecialBuiltins.enumSerializer))
|
||||
val polymorphicSerializerId = ClassId(SerializationPackages.packageFqName, Name.identifier(SpecialBuiltins.polymorphicSerializer))
|
||||
val referenceArraySerializerId = ClassId(SerializationPackages.internalPackageFqName, Name.identifier(SpecialBuiltins.referenceArraySerializer))
|
||||
val objectSerializerId = ClassId(SerializationPackages.internalPackageFqName, Name.identifier(SpecialBuiltins.objectSerializer))
|
||||
val sealedSerializerId = ClassId(SerializationPackages.packageFqName, Name.identifier(SpecialBuiltins.sealedSerializer))
|
||||
val contextSerializerId = ClassId(SerializationPackages.packageFqName, Name.identifier(SpecialBuiltins.contextSerializer))
|
||||
}
|
||||
|
||||
fun findStandardKotlinTypeSerializerName(typeName: String?): String? {
|
||||
return when (typeName) {
|
||||
null -> null
|
||||
"kotlin.Unit" -> "UnitSerializer"
|
||||
"kotlin.Nothing" -> "NothingSerializer"
|
||||
"kotlin.Boolean" -> "BooleanSerializer"
|
||||
"kotlin.Byte" -> "ByteSerializer"
|
||||
"kotlin.Short" -> "ShortSerializer"
|
||||
"kotlin.Int" -> "IntSerializer"
|
||||
"kotlin.Long" -> "LongSerializer"
|
||||
"kotlin.Float" -> "FloatSerializer"
|
||||
"kotlin.Double" -> "DoubleSerializer"
|
||||
"kotlin.Char" -> "CharSerializer"
|
||||
"kotlin.UInt" -> "UIntSerializer"
|
||||
"kotlin.ULong" -> "ULongSerializer"
|
||||
"kotlin.UByte" -> "UByteSerializer"
|
||||
"kotlin.UShort" -> "UShortSerializer"
|
||||
"kotlin.String" -> "StringSerializer"
|
||||
"kotlin.Pair" -> "PairSerializer"
|
||||
"kotlin.Triple" -> "TripleSerializer"
|
||||
"kotlin.collections.Collection", "kotlin.collections.List",
|
||||
"kotlin.collections.ArrayList", "kotlin.collections.MutableList" -> "ArrayListSerializer"
|
||||
"kotlin.collections.Set", "kotlin.collections.LinkedHashSet", "kotlin.collections.MutableSet" -> "LinkedHashSetSerializer"
|
||||
"kotlin.collections.HashSet" -> "HashSetSerializer"
|
||||
"kotlin.collections.Map", "kotlin.collections.LinkedHashMap", "kotlin.collections.MutableMap" -> "LinkedHashMapSerializer"
|
||||
"kotlin.collections.HashMap" -> "HashMapSerializer"
|
||||
"kotlin.collections.Map.Entry" -> "MapEntrySerializer"
|
||||
"kotlin.ByteArray" -> "ByteArraySerializer"
|
||||
"kotlin.ShortArray" -> "ShortArraySerializer"
|
||||
"kotlin.IntArray" -> "IntArraySerializer"
|
||||
"kotlin.LongArray" -> "LongArraySerializer"
|
||||
"kotlin.UByteArray" -> "UByteArraySerializer"
|
||||
"kotlin.UShortArray" -> "UShortArraySerializer"
|
||||
"kotlin.UIntArray" -> "UIntArraySerializer"
|
||||
"kotlin.ULongArray" -> "ULongArraySerializer"
|
||||
"kotlin.CharArray" -> "CharArraySerializer"
|
||||
"kotlin.FloatArray" -> "FloatArraySerializer"
|
||||
"kotlin.DoubleArray" -> "DoubleArraySerializer"
|
||||
"kotlin.BooleanArray" -> "BooleanArraySerializer"
|
||||
"kotlin.time.Duration" -> "DurationSerializer"
|
||||
"java.lang.Boolean" -> "BooleanSerializer"
|
||||
"java.lang.Byte" -> "ByteSerializer"
|
||||
"java.lang.Short" -> "ShortSerializer"
|
||||
"java.lang.Integer" -> "IntSerializer"
|
||||
"java.lang.Long" -> "LongSerializer"
|
||||
"java.lang.Float" -> "FloatSerializer"
|
||||
"java.lang.Double" -> "DoubleSerializer"
|
||||
"java.lang.Character" -> "CharSerializer"
|
||||
"java.lang.String" -> "StringSerializer"
|
||||
"java.util.Collection", "java.util.List", "java.util.ArrayList" -> "ArrayListSerializer"
|
||||
"java.util.Set", "java.util.LinkedHashSet" -> "LinkedHashSetSerializer"
|
||||
"java.util.HashSet" -> "HashSetSerializer"
|
||||
"java.util.Map", "java.util.LinkedHashMap" -> "LinkedHashMapSerializer"
|
||||
"java.util.HashMap" -> "HashMapSerializer"
|
||||
"java.util.Map.Entry" -> "MapEntrySerializer"
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user