Support serializable inline classes in IR plugin
as well as standard unsigned types.
This commit is contained in:
+7
-15
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 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.backend.common
|
||||
@@ -41,9 +30,12 @@ abstract class SerializableCodegen(
|
||||
generateSyntheticMethods()
|
||||
}
|
||||
|
||||
private inline fun ClassDescriptor.shouldHaveSpecificSyntheticMethods(functionPresenceChecker: () -> FunctionDescriptor?) =
|
||||
!isInline && (isAbstractSerializableClass() || isSealedSerializableClass() || functionPresenceChecker() != null)
|
||||
|
||||
private fun generateSyntheticInternalConstructor() {
|
||||
val serializerDescriptor = serializableDescriptor.classSerializer ?: return
|
||||
if (serializableDescriptor.isAbstractSerializableClass() || serializableDescriptor.isSealedSerializableClass() || SerializerCodegen.getSyntheticLoadMember(serializerDescriptor) != null) {
|
||||
if (serializableDescriptor.shouldHaveSpecificSyntheticMethods { SerializerCodegen.getSyntheticLoadMember(serializerDescriptor) }) {
|
||||
val constrDesc = serializableDescriptor.secondaryConstructors.find(ClassConstructorDescriptor::isSerializationCtor) ?: return
|
||||
generateInternalConstructor(constrDesc)
|
||||
}
|
||||
@@ -51,7 +43,7 @@ abstract class SerializableCodegen(
|
||||
|
||||
private fun generateSyntheticMethods() {
|
||||
val serializerDescriptor = serializableDescriptor.classSerializer ?: return
|
||||
if (serializableDescriptor.isAbstractSerializableClass() || serializableDescriptor.isSealedSerializableClass() || SerializerCodegen.getSyntheticSaveMember(serializerDescriptor) != null) {
|
||||
if (serializableDescriptor.shouldHaveSpecificSyntheticMethods { SerializerCodegen.getSyntheticSaveMember(serializerDescriptor) }) {
|
||||
val func = KSerializerDescriptorResolver.createWriteSelfFunctionDescriptor(serializableDescriptor)
|
||||
generateWriteSelfMethod(func)
|
||||
}
|
||||
|
||||
+4
@@ -168,6 +168,10 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
|
||||
"F", "kotlin.Float" -> "FloatSerializer"
|
||||
"D", "kotlin.Double" -> "DoubleSerializer"
|
||||
"C", "kotlin.Char" -> "CharSerializer"
|
||||
"kotlin.UInt" -> "UIntSerializer"
|
||||
"kotlin.ULong" -> "ULongSerializer"
|
||||
"kotlin.UByte" -> "UByteSerializer"
|
||||
"kotlin.UShort" -> "UShortSerializer"
|
||||
"kotlin.String" -> "StringSerializer"
|
||||
"kotlin.Pair" -> "PairSerializer"
|
||||
"kotlin.Triple" -> "TripleSerializer"
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ interface IrBuilderExtension {
|
||||
typeHint: IrType? = null
|
||||
): IrMemberAccessExpression<*> {
|
||||
assert(callee.isBound) { "Symbol $callee expected to be bound" }
|
||||
val returnType = typeHint ?: callee.run { owner.returnType }
|
||||
val returnType = typeHint ?: callee.owner.returnType
|
||||
val call = irCall(callee, type = returnType)
|
||||
call.dispatchReceiver = dispatchReceiver
|
||||
args.forEachIndexed(call::putValueArgument)
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ class SerialInfoImplJvmIrGenerator(
|
||||
override val compilerContext: SerializationPluginContext
|
||||
get() = context
|
||||
|
||||
private val jvmNameClass = context.referenceClass(DescriptorUtils.JVM_NAME)!!.owner
|
||||
private val jvmNameClass get() = context.referenceClass(DescriptorUtils.JVM_NAME)!!.owner
|
||||
|
||||
private val implGenerated = mutableSetOf<IrClass>()
|
||||
private val annotationToImpl = mutableMapOf<IrClass, IrClass>()
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.backend.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addTypeParameter
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
|
||||
private fun SerializationPluginContext.coerceInlineClasses(argument: IrExpression, from: IrType, to: IrType): IrExpression {
|
||||
if (this.platform?.isJvm() != true) return argument.apply { type = to }
|
||||
val unsafeCoerce = irFactory.buildFun {
|
||||
name = Name.special("<unsafe-coerce>")
|
||||
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
}.apply {
|
||||
parent = IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(moduleDescriptor, FqName("kotlin.jvm.internal"))
|
||||
val src = addTypeParameter("T", irBuiltIns.anyNType)
|
||||
val dst = addTypeParameter("R", irBuiltIns.anyNType)
|
||||
addValueParameter("v", src.defaultType)
|
||||
returnType = dst.defaultType
|
||||
}.symbol
|
||||
return IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, to, unsafeCoerce).apply {
|
||||
putTypeArgument(0, from)
|
||||
putTypeArgument(1, to)
|
||||
putValueArgument(0, argument)
|
||||
}
|
||||
}
|
||||
|
||||
class SerializerForInlineClassGenerator(
|
||||
irClass: IrClass,
|
||||
compilerContext: SerializationPluginContext,
|
||||
bindingContext: BindingContext,
|
||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||
) : SerializerIrGenerator(irClass, compilerContext, bindingContext, null, serialInfoJvmGenerator) {
|
||||
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
|
||||
fun irThis(): IrExpression =
|
||||
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
||||
val encodeInline = encoderClass.referenceMethod(CallingConventions.encodeInline)
|
||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||
|
||||
// val inlineEncoder = encoder.encodeInline()
|
||||
val encodeInlineCall: IrExpression = irInvoke(irGet(saveFunc.valueParameters[0]), encodeInline, serialDescGetter)
|
||||
val inlineEncoder = irTemporary(encodeInlineCall, nameHint = "inlineEncoder")
|
||||
|
||||
val property = serializableProperties.first()
|
||||
val value = getFromBox(irGet(saveFunc.valueParameters[1]), property)
|
||||
|
||||
// inlineEncoder.encodeInt/String/SerializableValue
|
||||
val elementCall = formEncodeDecodePropertyCall(irGet(inlineEncoder), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||
val f =
|
||||
encoderClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}SerializableValue")
|
||||
f to listOf(
|
||||
innerSerial,
|
||||
value
|
||||
)
|
||||
}, {
|
||||
val f =
|
||||
encoderClass.referenceMethod("${CallingConventions.encode}${it.elementMethodPrefix}")
|
||||
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
||||
f to args
|
||||
})
|
||||
|
||||
val actualEncodeCall = irIfNull(compilerContext.irBuiltIns.unitType, irGet(inlineEncoder), irNull(), elementCall)
|
||||
+actualEncodeCall
|
||||
}
|
||||
|
||||
override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function) { loadFunc ->
|
||||
fun irThis(): IrExpression =
|
||||
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
||||
val decodeInline = decoderClass.referenceMethod(CallingConventions.decodeInline)
|
||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||
|
||||
// val inlineDecoder = decoder.decodeInline()
|
||||
val inlineDecoder: IrExpression = irInvoke(irGet(loadFunc.valueParameters[0]), decodeInline, serialDescGetter)
|
||||
|
||||
val property = serializableProperties.first()
|
||||
val inlinedType = property.type.toIrType()
|
||||
val actualCall = formEncodeDecodePropertyCall(inlineDecoder, loadFunc.dispatchReceiverParameter!!, property, { innerSerial, sti ->
|
||||
decoderClass.referenceMethod( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
||||
}, {
|
||||
decoderClass.referenceMethod("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
||||
}, returnTypeHint = inlinedType)
|
||||
val value = coerceToBox(actualCall, inlinedType, loadFunc.returnType)
|
||||
+irReturn(value)
|
||||
}
|
||||
|
||||
override val serialDescImplClass: ClassDescriptor = serializerDescriptor
|
||||
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_INLINE)
|
||||
|
||||
override fun IrBlockBodyBuilder.instantiateNewDescriptor(
|
||||
serialDescImplClass: ClassDescriptor,
|
||||
correctThis: IrExpression
|
||||
): IrExpression {
|
||||
val ctor = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe).single { it.owner.isPrimary }
|
||||
return irInvoke(
|
||||
null, ctor,
|
||||
irString(serialName),
|
||||
correctThis
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Compiler will elide these in corresponding inline class lowerings (when serialize/deserialize functions will be split in two)
|
||||
|
||||
fun IrBlockBodyBuilder.coerceToBox(expression: IrExpression, propertyType: IrType, inlineClassBoxType: IrType): IrExpression {
|
||||
return irInvoke(null, serializableIrClass.constructors.single { it.isPrimary }.symbol, (inlineClassBoxType as IrSimpleType).arguments.map { it.typeOrNull }, listOf(expression))
|
||||
}
|
||||
|
||||
fun IrBlockBodyBuilder.getFromBox(expression: IrExpression, serializableProperty: SerializableProperty): IrExpression {
|
||||
return getProperty(expression, serializableProperty.irProp)
|
||||
}
|
||||
}
|
||||
+54
-47
@@ -25,8 +25,11 @@ import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInfo
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerCodegenImpl
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerForEnumsCodegen
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
@@ -39,6 +42,8 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UN
|
||||
|
||||
object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER", true)
|
||||
|
||||
internal typealias FunctionWithArgs = Pair<IrFunctionSymbol, List<IrExpression>>
|
||||
|
||||
open class SerializerIrGenerator(
|
||||
val irClass: IrClass,
|
||||
final override val compilerContext: SerializationPluginContext,
|
||||
@@ -286,22 +291,7 @@ open class SerializerIrGenerator(
|
||||
// internal serialization via virtual calls?
|
||||
for ((index, property) in serializableProperties.filter { !it.transient }.withIndex()) {
|
||||
// output.writeXxxElementValue(classDesc, index, value)
|
||||
val sti = getSerialTypeInfo(property)
|
||||
val innerSerial = serializerInstance(
|
||||
this@SerializerIrGenerator,
|
||||
saveFunc.dispatchReceiverParameter!!,
|
||||
sti.serializer,
|
||||
property.module,
|
||||
property.type,
|
||||
genericIndex = property.genericIndex
|
||||
)
|
||||
val (writeFunc, args: List<IrExpression>) = if (innerSerial == null) {
|
||||
val f =
|
||||
kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||
val args: MutableList<IrExpression> = mutableListOf(irGet(localSerialDesc), irInt(index))
|
||||
if (sti.elementMethodPrefix != "Unit") args.add(property.irGet())
|
||||
f to args
|
||||
} else {
|
||||
val elementCall = formEncodeDecodePropertyCall(irGet(localOutput), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||
val f =
|
||||
kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
|
||||
f to listOf(
|
||||
@@ -310,9 +300,13 @@ open class SerializerIrGenerator(
|
||||
innerSerial,
|
||||
property.irGet()
|
||||
)
|
||||
}
|
||||
val typeArgs = if (writeFunc.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
|
||||
val elementCall = irInvoke(irGet(localOutput), writeFunc, typeArguments = typeArgs, valueArguments = args)
|
||||
}, {
|
||||
val f =
|
||||
kOutputClass.referenceMethod("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||
val args: MutableList<IrExpression> = mutableListOf(irGet(localSerialDesc), irInt(index))
|
||||
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
|
||||
f to args
|
||||
})
|
||||
|
||||
// check for call to .shouldEncodeElementDefault
|
||||
if (!property.optional || index < ignoreIndexTo) {
|
||||
@@ -337,6 +331,28 @@ open class SerializerIrGenerator(
|
||||
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
|
||||
}
|
||||
|
||||
protected inline fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
||||
encoder: IrExpression,
|
||||
dispatchReceiver: IrValueParameter,
|
||||
property: SerializableProperty,
|
||||
whenHaveSerializer: (serializer: IrExpression, sti: SerialTypeInfo) -> FunctionWithArgs,
|
||||
whenDoNot: (sti: SerialTypeInfo) -> FunctionWithArgs,
|
||||
returnTypeHint: IrType? = null
|
||||
): IrExpression {
|
||||
val sti = getSerialTypeInfo(property)
|
||||
val innerSerial = serializerInstance(
|
||||
this@SerializerIrGenerator,
|
||||
dispatchReceiver,
|
||||
sti.serializer,
|
||||
property.module,
|
||||
property.type,
|
||||
genericIndex = property.genericIndex
|
||||
)
|
||||
val (functionToCall, args: List<IrExpression>) = if (innerSerial != null) whenHaveSerializer(innerSerial, sti) else whenDoNot(sti)
|
||||
val typeArgs = if (functionToCall.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
|
||||
return irInvoke(encoder, functionToCall, typeArguments = typeArgs, valueArguments = args, returnTypeHint = returnTypeHint)
|
||||
}
|
||||
|
||||
// returns null: Any? for boxed types and 0: <number type> for primitives
|
||||
private fun IrBuilderWithScope.defaultValueAndType(prop: SerializableProperty): Pair<IrExpression, IrType> {
|
||||
val kType = prop.descriptor.returnType!!
|
||||
@@ -403,33 +419,23 @@ open class SerializerIrGenerator(
|
||||
val decoderCalls: List<Pair<Int, IrExpression>> =
|
||||
serializableProperties.mapIndexed { index, property ->
|
||||
val body = irBlock {
|
||||
val sti = getSerialTypeInfo(property)
|
||||
val innerSerial = serializerInstance(
|
||||
this@SerializerIrGenerator,
|
||||
loadFunc.dispatchReceiverParameter!!,
|
||||
sti.serializer,
|
||||
property.module,
|
||||
property.type,
|
||||
genericIndex = property.genericIndex
|
||||
)
|
||||
val isSerializable = innerSerial != null
|
||||
val decodeFuncToCall =
|
||||
(if (isSerializable) "${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}"
|
||||
else "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||
.let {
|
||||
inputClass.referenceMethod(it) { it.valueParameters.size == if (isSerializable) 4 else 2 }
|
||||
}
|
||||
val typeArgs =
|
||||
if (decodeFuncToCall.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
|
||||
val args = mutableListOf<IrExpression>(localSerialDesc.get(), irInt(index))
|
||||
if (isSerializable) {
|
||||
args.add(innerSerial!!)
|
||||
args.add(localProps[index].get())
|
||||
}
|
||||
val decodeFuncToCall = formEncodeDecodePropertyCall(localInput.get(), loadFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||
inputClass.referenceMethod(
|
||||
"${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}", {it.valueParameters.size == 4}
|
||||
) to listOf(
|
||||
localSerialDesc.get(), irInt(index), innerSerial, localProps[index].get()
|
||||
)
|
||||
}, {
|
||||
inputClass.referenceMethod(
|
||||
"${CallingConventions.decode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}", {it.valueParameters.size == 2}
|
||||
) to listOf(
|
||||
localSerialDesc.get(), irInt(index)
|
||||
)
|
||||
}, returnTypeHint = property.type.toIrType())
|
||||
// local$i = localInput.decode...(...)
|
||||
+irSet(
|
||||
localProps[index].symbol,
|
||||
irInvoke(localInput.get(), decodeFuncToCall, typeArgs, args, returnTypeHint = property.type.toIrType())
|
||||
decodeFuncToCall
|
||||
)
|
||||
// bitMask[i] |= 1 << x
|
||||
val bitPos = 1 shl (index % 32)
|
||||
@@ -507,11 +513,12 @@ open class SerializerIrGenerator(
|
||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||
) {
|
||||
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
|
||||
if (serializableDesc.isSerializableEnum()) {
|
||||
SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator).generate()
|
||||
} else {
|
||||
SerializerIrGenerator(irClass, context, bindingContext, metadataPlugin, serialInfoJvmGenerator).generate()
|
||||
val generator = when {
|
||||
serializableDesc.isSerializableEnum() -> SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
||||
serializableDesc.isInline -> SerializerForInlineClassGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
||||
else -> SerializerIrGenerator(irClass, context, bindingContext, metadataPlugin, serialInfoJvmGenerator)
|
||||
}
|
||||
generator.generate()
|
||||
irClass.patchDeclarationParents(irClass.parent)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -123,10 +123,10 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
||||
return false
|
||||
}
|
||||
|
||||
if (descriptor.isInlineClass()) {
|
||||
trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED)
|
||||
return false
|
||||
}
|
||||
// if (descriptor.isInlineClass()) {
|
||||
// trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED)
|
||||
// return false
|
||||
// }
|
||||
if (!descriptor.hasSerializableAnnotationWithoutArgs) return false
|
||||
|
||||
if (descriptor.serializableAnnotationIsUseless) {
|
||||
@@ -258,9 +258,9 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
||||
) {
|
||||
if (type.genericIndex != null) return // type arguments always have serializer stored in class' field
|
||||
val element = ktType?.typeElement
|
||||
if (type.isUnsupportedInlineType()) {
|
||||
trace.report(SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED.on(element ?: fallbackElement))
|
||||
}
|
||||
// if (type.isUnsupportedInlineType()) {
|
||||
// trace.report(SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED.on(element ?: fallbackElement))
|
||||
// }
|
||||
val serializer = findTypeSerializerOrContextUnchecked(module, type)
|
||||
if (serializer != null) {
|
||||
checkCustomSerializerMatch(module, type, type, element, trace, fallbackElement)
|
||||
|
||||
+4
-13
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 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.extensions
|
||||
@@ -26,6 +15,7 @@ import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
|
||||
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -87,6 +77,7 @@ open class SerializationResolveExtension @JvmOverloads constructor(val metadataP
|
||||
if (thisDescriptor.isInternalSerializable) {
|
||||
// do not add synthetic deserialization constructor if .deserialize method is customized
|
||||
if (thisDescriptor.hasCompanionObjectAsSerializer && SerializerCodegen.getSyntheticLoadMember(thisDescriptor.companionObjectDescriptor!!) == null) return
|
||||
if (thisDescriptor.isInline) return
|
||||
result.add(KSerializerDescriptorResolver.createLoadConstructorDescriptor(thisDescriptor, bindingContext, metadataPlugin))
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -69,6 +69,7 @@ object SerialEntityNames {
|
||||
const val SERIAL_DESCRIPTOR_CLASS = "SerialDescriptor"
|
||||
const val SERIAL_DESCRIPTOR_CLASS_IMPL = "PluginGeneratedSerialDescriptor"
|
||||
const val SERIAL_DESCRIPTOR_FOR_ENUM = "EnumDescriptor"
|
||||
const val SERIAL_DESCRIPTOR_FOR_INLINE = "InlineClassDescriptor"
|
||||
|
||||
const val PLUGIN_EXCEPTIONS_FILE = "PluginExceptions"
|
||||
|
||||
@@ -114,6 +115,8 @@ object CallingConventions {
|
||||
const val encode = "encode"
|
||||
const val encodeEnum = "encodeEnum"
|
||||
const val decodeEnum = "decodeEnum"
|
||||
const val encodeInline = "encodeInline"
|
||||
const val decodeInline = "decodeInline"
|
||||
const val decodeElementIndex = "decodeElementIndex"
|
||||
const val decodeSequentially = "decodeSequentially"
|
||||
const val elementPostfix = "Element"
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
|
||||
@@ -8,10 +8,12 @@ package org.jetbrains.kotlinx.serialization.compiler.extensions
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
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.idea.runIfEnabledIn
|
||||
import org.jetbrains.kotlinx.serialization.idea.runIfEnabledOn
|
||||
|
||||
class SerializationIDECodegenExtension : SerializationCodegenExtension() {
|
||||
@@ -31,7 +33,10 @@ class SerializationIDEJsExtension : SerializationJsExtension() {
|
||||
}
|
||||
|
||||
class SerializationIDEIrExtension : SerializationLoweringExtension() {
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
|
||||
/* No-op – don't enable IR extensions in IDE */
|
||||
runIfEnabledIn(pluginContext.moduleDescriptor) {
|
||||
super.generate(moduleFragment, pluginContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
|
||||
@@ -7,16 +7,23 @@ package org.jetbrains.kotlinx.serialization.idea
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.unwrapModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
fun <T> getIfEnabledOn(clazz: ClassDescriptor, body: () -> T): T? {
|
||||
val module = clazz.module.getCapability(ModuleInfo.Capability)?.unwrapModuleSourceInfo()?.module ?: return null
|
||||
val facet = KotlinFacet.get(module) ?: return null
|
||||
val pluginClasspath = facet.configuration.settings.compilerArguments?.pluginClasspaths ?: return null
|
||||
if (pluginClasspath.none(KotlinSerializationImportHandler::isPluginJarPath)) return null
|
||||
return body()
|
||||
private fun isEnabledIn(moduleDescriptor: ModuleDescriptor): Boolean {
|
||||
val module = moduleDescriptor.getCapability(ModuleInfo.Capability)?.unwrapModuleSourceInfo()?.module ?: return false
|
||||
val facet = KotlinFacet.get(module) ?: return false
|
||||
val pluginClasspath = facet.configuration.settings.compilerArguments?.pluginClasspaths ?: return false
|
||||
if (pluginClasspath.none(KotlinSerializationImportHandler::isPluginJarPath)) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun runIfEnabledOn(clazz: ClassDescriptor, body: () -> Unit) { getIfEnabledOn<Unit>(clazz, body) }
|
||||
fun <T> getIfEnabledOn(clazz: ClassDescriptor, body: () -> T): T? {
|
||||
return if (isEnabledIn(clazz.module)) body() else null
|
||||
}
|
||||
|
||||
fun runIfEnabledOn(clazz: ClassDescriptor, body: () -> Unit) { getIfEnabledOn<Unit>(clazz, body) }
|
||||
|
||||
fun runIfEnabledIn(moduleDescriptor: ModuleDescriptor, block: () -> Unit) { if (isEnabledIn(moduleDescriptor)) block() }
|
||||
Reference in New Issue
Block a user