Add synthetic constructors to class member scope, so they won't fly 'in the air' in the backends

This is required mainly for Native compiler since it wont't work correctly on descriptors that are not present in the class.
This commit is contained in:
Leonid Startsev
2019-04-03 14:31:47 +03:00
parent 406896eaf0
commit 6bec6e6905
16 changed files with 187 additions and 110 deletions
@@ -130,6 +130,8 @@ public class ConstructorCodegen {
ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper); ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
KtSecondaryConstructor constructor = (KtSecondaryConstructor) descriptorToDeclaration(constructorDescriptor); KtSecondaryConstructor constructor = (KtSecondaryConstructor) descriptorToDeclaration(constructorDescriptor);
// Synthetic constructors don't have corresponding declarations
if (constructor == null) return;
functionCodegen.generateMethod( functionCodegen.generateMethod(
JvmDeclarationOriginKt.OtherOrigin(constructor, constructorDescriptor), JvmDeclarationOriginKt.OtherOrigin(constructor, constructorDescriptor),
@@ -44,6 +44,7 @@ class SyntheticClassOrObjectDescriptor(
outerScope: LexicalScope, outerScope: LexicalScope,
private val modality: Modality, private val modality: Modality,
private val visibility: Visibility, private val visibility: Visibility,
override val annotations: Annotations,
constructorVisibility: Visibility, constructorVisibility: Visibility,
private val kind: ClassKind, private val kind: ClassKind,
private val isCompanionObject: Boolean private val isCompanionObject: Boolean
@@ -71,8 +72,6 @@ class SyntheticClassOrObjectDescriptor(
this.typeParameters = typeParameters this.typeParameters = typeParameters
} }
override val annotations: Annotations get() = Annotations.EMPTY
override fun getModality() = modality override fun getModality() = modality
override fun getVisibility() = visibility override fun getVisibility() = visibility
override fun getKind() = kind override fun getKind() = kind
@@ -17,10 +17,7 @@
package org.jetbrains.kotlin.resolve.extensions package org.jetbrains.kotlin.resolve.extensions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
@@ -113,6 +110,22 @@ interface SyntheticResolveExtension {
) )
} }
} }
override fun generateSyntheticSecondaryConstructors(
thisDescriptor: ClassDescriptor,
bindingContext: BindingContext,
result: MutableCollection<ClassConstructorDescriptor>
) {
instances.forEach {
withLinkageErrorLogger(it) {
generateSyntheticSecondaryConstructors(
thisDescriptor,
bindingContext,
result
)
}
}
}
} }
} }
} }
@@ -160,4 +173,11 @@ interface SyntheticResolveExtension {
result: MutableSet<PropertyDescriptor> result: MutableSet<PropertyDescriptor>
) { ) {
} }
fun generateSyntheticSecondaryConstructors(
thisDescriptor: ClassDescriptor,
bindingContext: BindingContext,
result: MutableCollection<ClassConstructorDescriptor>
) {
}
} }
@@ -444,7 +444,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
/* parentClassOrObject= */ classOrObject, /* parentClassOrObject= */ classOrObject,
this, syntheticCompanionName, getSource(), this, syntheticCompanionName, getSource(),
/* outerScope= */ getOuterScope(), /* outerScope= */ getOuterScope(),
Modality.FINAL, PUBLIC, PRIVATE, ClassKind.OBJECT, true); Modality.FINAL, PUBLIC, Annotations.Companion.getEMPTY(), PRIVATE, ClassKind.OBJECT, true);
companionDescriptor.initialize(); companionDescriptor.initialize();
return companionDescriptor; return companionDescriptor;
} }
@@ -415,7 +415,18 @@ open class LazyClassMemberScope(
} }
private val secondaryConstructors: NotNullLazyValue<Collection<ClassConstructorDescriptor>> = private val secondaryConstructors: NotNullLazyValue<Collection<ClassConstructorDescriptor>> =
c.storageManager.createLazyValue { resolveSecondaryConstructors() } c.storageManager.createLazyValue { doGetConstructors() }
private fun doGetConstructors(): Collection<ClassConstructorDescriptor> {
val result = mutableListOf<ClassConstructorDescriptor>()
result.addAll(resolveSecondaryConstructors())
addSyntheticSecondaryConstructors(result)
return result
}
private fun addSyntheticSecondaryConstructors(result: MutableCollection<ClassConstructorDescriptor>) {
c.syntheticResolveExtension.generateSyntheticSecondaryConstructors(thisDescriptor, trace.bindingContext, result)
}
fun getConstructors(): Collection<ClassConstructorDescriptor> { fun getConstructors(): Collection<ClassConstructorDescriptor> {
val result = secondaryConstructors() val result = secondaryConstructors()
@@ -20,10 +20,8 @@ import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.classSerializer
import org.jetbrains.kotlinx.serialization.compiler.resolve.isAbstractSerializableClass
abstract class SerializableCodegen( abstract class SerializableCodegen(
protected val serializableDescriptor: ClassDescriptor, protected val serializableDescriptor: ClassDescriptor,
@@ -39,7 +37,7 @@ abstract class SerializableCodegen(
private fun generateSyntheticInternalConstructor() { private fun generateSyntheticInternalConstructor() {
val serializerDescriptor = serializableDescriptor.classSerializer ?: return val serializerDescriptor = serializableDescriptor.classSerializer ?: return
if (isAbstractSerializableClass(serializableDescriptor) || SerializerCodegen.getSyntheticLoadMember(serializerDescriptor) != null) { if (isAbstractSerializableClass(serializableDescriptor) || SerializerCodegen.getSyntheticLoadMember(serializerDescriptor) != null) {
val constrDesc = KSerializerDescriptorResolver.createLoadConstructorDescriptor(serializableDescriptor, bindingContext) val constrDesc = serializableDescriptor.secondaryConstructors.find(ClassConstructorDescriptor::isSerializationCtor) ?: return
generateInternalConstructor(constrDesc) generateInternalConstructor(constrDesc)
} }
} }
@@ -57,4 +55,4 @@ abstract class SerializableCodegen(
protected open fun generateWriteSelfMethod(methodDescriptor: FunctionDescriptor) { protected open fun generateWriteSelfMethod(methodDescriptor: FunctionDescriptor) {
} }
} }
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers
abstract class SerializerCodegen( abstract class SerializerCodegen(
protected val serializerDescriptor: ClassDescriptor, protected val serializerDescriptor: ClassDescriptor,
@@ -18,9 +18,12 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -77,6 +80,7 @@ interface IrBuilderExtension {
fun IrClass.contributeConstructor( fun IrClass.contributeConstructor(
descriptor: ClassConstructorDescriptor, descriptor: ClassConstructorDescriptor,
fromStubs: Boolean = false, fromStubs: Boolean = false,
overwriteValueParameters: Boolean = false,
bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit
) { ) {
val c = if (!fromStubs) compilerContext.localSymbolTable.declareConstructor( val c = if (!fromStubs) compilerContext.localSymbolTable.declareConstructor(
@@ -87,7 +91,7 @@ interface IrBuilderExtension {
) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner ) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner
c.parent = this c.parent = this
c.returnType = descriptor.returnType.toIrType() c.returnType = descriptor.returnType.toIrType()
if (!fromStubs) c.createParameterDeclarations(receiver = null) if (!fromStubs || overwriteValueParameters) c.createParameterDeclarations(receiver = null, overwriteValueParameters = overwriteValueParameters)
if (c.typeParameters.isEmpty()) { if (c.typeParameters.isEmpty()) {
c.copyTypeParamsFromDescriptor() c.copyTypeParamsFromDescriptor()
} }
@@ -346,7 +350,7 @@ interface IrBuilderExtension {
} }
} }
fun IrFunction.createParameterDeclarations(receiver: IrValueParameter?) { fun IrFunction.createParameterDeclarations(receiver: IrValueParameter?, overwriteValueParameters: Boolean = false) {
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl( fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
this@createParameterDeclarations.startOffset, this@createParameterDeclarations.endOffset, this@createParameterDeclarations.startOffset, this@createParameterDeclarations.endOffset,
SERIALIZABLE_PLUGIN_ORIGIN, SERIALIZABLE_PLUGIN_ORIGIN,
@@ -360,8 +364,11 @@ interface IrBuilderExtension {
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter() dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter()
extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter() extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter()
assert(valueParameters.isEmpty()) if (!overwriteValueParameters)
descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() } assert(valueParameters.isEmpty())
else
valueParameters.clear()
valueParameters.addAll(descriptor.valueParameters.map { it.irValueParameter() })
assert(typeParameters.isEmpty()) assert(typeParameters.isEmpty())
copyTypeParamsFromDescriptor() copyTypeParamsFromDescriptor()
@@ -524,7 +531,7 @@ interface IrBuilderExtension {
val serializable = getSerializableClassDescriptorBySerializer(serializerClass) val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) { val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
requireNotNull( requireNotNull(
KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializerClass) findSerializerConstructorForTypeArgumentsSerializers(serializerClass)
) { "Generated serializer does not have constructor with required number of arguments" } ) { "Generated serializer does not have constructor with required number of arguments" }
.let { compilerContext.externalSymbols.referenceConstructor(it) } .let { compilerContext.externalSymbols.referenceConstructor(it) }
} else { } else {
@@ -537,5 +544,5 @@ interface IrBuilderExtension {
} }
fun IrClass.serializableSyntheticConstructor(): IrConstructorSymbol = fun IrClass.serializableSyntheticConstructor(): IrConstructorSymbol =
this.constructors.single { it.origin == SERIALIZABLE_PLUGIN_ORIGIN }.symbol this.constructors.single { it.descriptor.isSerializationCtor() }.symbol
} }
@@ -58,7 +58,7 @@ class SerializableCompanionIrGenerator(
} }
else -> { else -> {
val desc = requireNotNull( val desc = requireNotNull(
KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializer) findSerializerConstructorForTypeArgumentsSerializers(serializer)
) { "Generated serializer does not have constructor with required number of arguments" } ) { "Generated serializer does not have constructor with required number of arguments" }
val ctor = compilerContext.externalSymbols.referenceConstructor(desc) val ctor = compilerContext.externalSymbols.referenceConstructor(desc)
val typeArgs = getter.typeParameters.map { it.defaultType } val typeArgs = getter.typeParameters.map { it.defaultType }
@@ -38,7 +38,7 @@ class SerializableIrGenerator(
get() = _table get() = _table
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) = override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) =
irClass.contributeConstructor(constructorDescriptor) { ctor -> irClass.contributeConstructor(constructorDescriptor, fromStubs = true, overwriteValueParameters = true) { ctor ->
val transformFieldInitializer = buildInitializersRemapping(irClass) val transformFieldInitializer = buildInitializersRemapping(irClass)
// Missing field exception parts // Missing field exception parts
@@ -158,7 +158,7 @@ internal fun SerializerJsTranslator.serializerInstance(
val serializable = getSerializableClassDescriptorBySerializer(serializerClass) val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
val ref = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) { val ref = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
val desc = requireNotNull( val desc = requireNotNull(
KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializerClass) findSerializerConstructorForTypeArgumentsSerializers(serializerClass)
) { "Generated serializer does not have constructor with required number of arguments" } ) { "Generated serializer does not have constructor with required number of arguments" }
if (!desc.isPrimary) if (!desc.isPrimary)
JsInvocation(context.getInnerReference(desc), args) JsInvocation(context.getInnerReference(desc), args)
@@ -46,7 +46,7 @@ class SerializableCompanionJsTranslator(
val args = jsFun.parameters.map { JsNameRef(it.name) } val args = jsFun.parameters.map { JsNameRef(it.name) }
val ref = context.getInnerNameForDescriptor( val ref = context.getInnerNameForDescriptor(
requireNotNull( requireNotNull(
KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializer) findSerializerConstructorForTypeArgumentsSerializers(serializer)
) { "Generated serializer does not have constructor with required number of arguments" }) ) { "Generated serializer does not have constructor with required number of arguments" })
JsInvocation(ref.makeRef(), args) JsInvocation(ref.makeRef(), args)
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlinx.serialization.compiler.extensions package org.jetbrains.kotlinx.serialization.compiler.extensions
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
@@ -69,6 +70,16 @@ open class SerializationResolveExtension : SyntheticResolveExtension {
KSerializerDescriptorResolver.addSerializerSupertypes(thisDescriptor, supertypes) KSerializerDescriptorResolver.addSerializerSupertypes(thisDescriptor, supertypes)
} }
override fun generateSyntheticSecondaryConstructors(
thisDescriptor: ClassDescriptor,
bindingContext: BindingContext,
result: MutableCollection<ClassConstructorDescriptor>
) {
if (thisDescriptor.isInternalSerializable) {
result.add(KSerializerDescriptorResolver.createLoadConstructorDescriptor(thisDescriptor, bindingContext))
}
}
override fun generateSyntheticMethods( override fun generateSyntheticMethods(
thisDescriptor: ClassDescriptor, thisDescriptor: ClassDescriptor,
name: Name, name: Name,
@@ -18,13 +18,9 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
@@ -37,7 +33,6 @@ 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
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName
internal fun isAllowedToHaveAutoGeneratedSerializerMethods( internal fun isAllowedToHaveAutoGeneratedSerializerMethods(
classDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor,
@@ -219,59 +214,3 @@ internal fun ClassDescriptor.checkLoadMethodParameters(parameters: List<ValuePar
internal fun ClassDescriptor.checkLoadMethodResult(type: KotlinType): Boolean = internal fun ClassDescriptor.checkLoadMethodResult(type: KotlinType): Boolean =
getSerializableClassDescriptorBySerializer(this)?.defaultType == type getSerializableClassDescriptorBySerializer(this)?.defaultType == type
// ----------------
inline fun <reified R> Annotations.findAnnotationConstantValue(annotationFqName: FqName, property: String): R? =
findAnnotation(annotationFqName)?.let { annotation ->
annotation.allValueArguments.entries.singleOrNull { it.key.asString() == property }?.value?.value
} as? R
internal fun Annotations.findAnnotationKotlinTypeValue(
annotationFqName: FqName,
moduleForResolve: ModuleDescriptor,
property: String
): KotlinType? =
findAnnotation(annotationFqName)?.let { annotation ->
val maybeKClass = annotation.allValueArguments.entries.singleOrNull { it.key.asString() == property }?.value as? KClassValue
maybeKClass?.getArgumentType(moduleForResolve)
}
// Search utils
internal fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(packageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME))!!
internal fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
getFromPackage(SerializationPackages.internalPackageFqName, classSimpleName)
internal fun ModuleDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
getFromPackage(SerializationPackages.packageFqName, classSimpleName)
private fun ModuleDescriptor.getFromPackage(packageFqName: FqName, classSimpleName: String) = requireNotNull(
findClassAcrossModuleDependencies(
ClassId(
packageFqName,
Name.identifier(classSimpleName)
)
)
) { "Can't locate class $classSimpleName from package $packageFqName" }
internal fun ClassDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
requireNotNull(module.findClassAcrossModuleDependencies(ClassId(packageFqName, Name.identifier(classSimpleName)))) {"Can't locate class $classSimpleName"}
internal fun ClassDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
module.getClassFromInternalSerializationPackage(classSimpleName)
fun ClassDescriptor.toSimpleType(nullable: Boolean = true) = KotlinTypeFactory.simpleType(Annotations.EMPTY, this.typeConstructor, emptyList(), nullable)
internal fun Annotated.annotationsWithArguments(): List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
annotations.asSequence()
.filter { it.type.toClassDescriptor?.isSerialInfoAnnotation == true }
.filterIsInstance<LazyAnnotationDescriptor>()
.mapNotNull { annDesc ->
annDesc.type.toClassDescriptor?.let {
Triple(it, annDesc.annotationEntry.valueArguments, it.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty())
}
}
.toList()
@@ -18,8 +18,10 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.createDeprecatedAnnotation
import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -47,6 +49,10 @@ import java.util.*
object KSerializerDescriptorResolver { object KSerializerDescriptorResolver {
private fun createDeprecatedHiddenAnnotation(module: ModuleDescriptor): AnnotationDescriptor {
return module.builtIns.createDeprecatedAnnotation("This synthesized declaration should not be used directly", level = "HIDDEN")
}
fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean { fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean {
return thisDescriptor.name == IMPL_NAME return thisDescriptor.name == IMPL_NAME
&& thisDescriptor.containingDeclaration is LazyClassDescriptor && thisDescriptor.containingDeclaration is LazyClassDescriptor
@@ -92,6 +98,7 @@ object KSerializerDescriptorResolver {
scope, scope,
Modality.FINAL, Modality.FINAL,
Visibilities.PUBLIC, Visibilities.PUBLIC,
Annotations.create(listOf(createDeprecatedHiddenAnnotation(interfaceDesc.module))),
primaryCtorVisibility, primaryCtorVisibility,
ClassKind.CLASS, ClassKind.CLASS,
false false
@@ -114,7 +121,9 @@ object KSerializerDescriptorResolver {
thisDeclaration, thisDeclaration,
thisDescriptor, SERIALIZER_CLASS_NAME, thisDescriptor.source, thisDescriptor, SERIALIZER_CLASS_NAME, thisDescriptor.source,
scope, scope,
Modality.FINAL, Visibilities.PUBLIC, Visibilities.PRIVATE, Modality.FINAL, Visibilities.PUBLIC,
Annotations.create(listOf(createDeprecatedHiddenAnnotation(thisDescriptor.module))),
Visibilities.PRIVATE,
serializerKind, false serializerKind, false
) )
val typeParameters: List<TypeParameterDescriptor> = val typeParameters: List<TypeParameterDescriptor> =
@@ -276,9 +285,9 @@ object KSerializerDescriptorResolver {
val functionDescriptor = ClassConstructorDescriptorImpl.createSynthesized( val functionDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
classDescriptor, classDescriptor,
Annotations.EMPTY, Annotations.create(listOf(createDeprecatedHiddenAnnotation(classDescriptor.module))),
false, false,
classDescriptor.source SourceElement.NO_SOURCE
) )
val markerDesc = classDescriptor.getKSerializerConstructorMarker() val markerDesc = classDescriptor.getKSerializerConstructorMarker()
@@ -314,29 +323,13 @@ object KSerializerDescriptorResolver {
functionDescriptor.initialize( functionDescriptor.initialize(
consParams, consParams,
Visibilities.PUBLIC Visibilities.INTERNAL
) )
functionDescriptor.returnType = classDescriptor.defaultType functionDescriptor.returnType = classDescriptor.defaultType
return functionDescriptor return functionDescriptor
} }
// finds constructor (KSerializer<T0>, KSerializer<T1>...) on a KSerializer<T<T0, T1...>>
fun findSerializerConstructorForTypeArgumentsSerializers(
serializerDescriptor: ClassDescriptor,
onlyIfSynthetic: Boolean = false
): ClassConstructorDescriptor? {
val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializerDescriptor)?.arguments
?: throw AssertionError("Serializer does not implement KSerializer??")
val typeParamsCount = serializableImplementationTypeArguments.size
if (typeParamsCount == 0) return null //don't need it
val ctor = serializerDescriptor.constructors.find { ctor ->
ctor.valueParameters.size == typeParamsCount && ctor.valueParameters.all { isKSerializer(it.type) }
}
return if (!onlyIfSynthetic) ctor else ctor?.takeIf { it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED }
}
private fun createTypedSerializerConstructorDescriptor( private fun createTypedSerializerConstructorDescriptor(
classDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor,
serializableDescriptor: ClassDescriptor, serializableDescriptor: ClassDescriptor,
@@ -344,7 +337,7 @@ object KSerializerDescriptorResolver {
): ClassConstructorDescriptor { ): ClassConstructorDescriptor {
val constrDesc = ClassConstructorDescriptorImpl.createSynthesized( val constrDesc = ClassConstructorDescriptorImpl.createSynthesized(
classDescriptor, classDescriptor,
Annotations.EMPTY, Annotations.create(listOf(createDeprecatedHiddenAnnotation(classDescriptor.module))),
false, false,
classDescriptor.source classDescriptor.source
) )
@@ -437,8 +430,8 @@ object KSerializerDescriptorResolver {
private fun KotlinType.makeNullableIfNotPrimitive() = private fun KotlinType.makeNullableIfNotPrimitive() =
if (KotlinBuiltIns.isPrimitiveType(this)) this if (KotlinBuiltIns.isPrimitiveType(this)) this
else this.makeNullable() else this.makeNullable()
fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): FunctionDescriptor { fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): FunctionDescriptor {
val jvmStaticClass = thisClass.module.findClassAcrossModuleDependencies( val jvmStaticClass = thisClass.module.findClassAcrossModuleDependencies(
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. 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.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.constants.KClassValue
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
internal fun ClassConstructorDescriptor.isSerializationCtor(): Boolean =
kind == CallableMemberDescriptor.Kind.SYNTHESIZED && valueParameters.lastOrNull()?.name == SerialEntityNames.dummyParamName
// finds constructor (KSerializer<T0>, KSerializer<T1>...) on a KSerializer<T<T0, T1...>>
internal fun findSerializerConstructorForTypeArgumentsSerializers(
serializerDescriptor: ClassDescriptor,
onlyIfSynthetic: Boolean = false
): ClassConstructorDescriptor? {
val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializerDescriptor)?.arguments
?: throw AssertionError("Serializer does not implement KSerializer??")
val typeParamsCount = serializableImplementationTypeArguments.size
if (typeParamsCount == 0) return null //don't need it
val ctor = serializerDescriptor.constructors.find { ctor ->
ctor.valueParameters.size == typeParamsCount && ctor.valueParameters.all { isKSerializer(it.type) }
}
return if (!onlyIfSynthetic) ctor else ctor?.takeIf { it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED }
}
inline fun <reified R> Annotations.findAnnotationConstantValue(annotationFqName: FqName, property: String): R? =
findAnnotation(annotationFqName)?.let { annotation ->
annotation.allValueArguments.entries.singleOrNull { it.key.asString() == property }?.value?.value
} as? R
internal fun Annotations.findAnnotationKotlinTypeValue(
annotationFqName: FqName,
moduleForResolve: ModuleDescriptor,
property: String
): KotlinType? =
findAnnotation(annotationFqName)?.let { annotation ->
val maybeKClass = annotation.allValueArguments.entries.singleOrNull { it.key.asString() == property }?.value as? KClassValue
maybeKClass?.getArgumentType(moduleForResolve)
}
internal fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(SerializationPackages.packageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME))!!
internal fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
getFromPackage(SerializationPackages.internalPackageFqName, classSimpleName)
internal fun ModuleDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
getFromPackage(SerializationPackages.packageFqName, classSimpleName)
private fun ModuleDescriptor.getFromPackage(packageFqName: FqName, classSimpleName: String) = requireNotNull(
findClassAcrossModuleDependencies(
ClassId(
packageFqName,
Name.identifier(classSimpleName)
)
)
) { "Can't locate class $classSimpleName from package $packageFqName" }
internal fun ClassDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
requireNotNull(
module.findClassAcrossModuleDependencies(
ClassId(
SerializationPackages.packageFqName,
Name.identifier(classSimpleName)
)
)
) { "Can't locate class $classSimpleName" }
internal fun ClassDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
module.getClassFromInternalSerializationPackage(classSimpleName)
fun ClassDescriptor.toSimpleType(nullable: Boolean = true) =
KotlinTypeFactory.simpleType(Annotations.EMPTY, this.typeConstructor, emptyList(), nullable)
internal fun Annotated.annotationsWithArguments(): List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
annotations.asSequence()
.filter { it.type.toClassDescriptor?.isSerialInfoAnnotation == true }
.filterIsInstance<LazyAnnotationDescriptor>()
.mapNotNull { annDesc ->
annDesc.type.toClassDescriptor?.let {
Triple(it, annDesc.annotationEntry.valueArguments, it.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty())
}
}
.toList()