From 6bec6e69057e9cb1b5ceeb2931d7c805a2f97ac9 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Wed, 3 Apr 2019 14:31:47 +0300 Subject: [PATCH] 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. --- .../kotlin/codegen/ConstructorCodegen.java | 2 + .../SyntheticClassOrObjectDescriptor.kt | 3 +- .../extensions/SyntheticResolveExtension.kt | 28 +++++- .../lazy/descriptors/LazyClassDescriptor.java | 2 +- .../lazy/descriptors/LazyClassMemberScope.kt | 13 ++- .../backend/common/SerializableCodegen.kt | 10 +- .../backend/common/SerializerCodegen.kt | 1 - .../compiler/backend/ir/GeneratorHelpers.kt | 21 ++-- .../ir/SerializableCompanionIrGenerator.kt | 2 +- .../backend/ir/SerializableIrGenerator.kt | 2 +- .../compiler/backend/js/JsCodegenUtil.kt | 2 +- .../js/SerializableCompanionJsTranslator.kt | 2 +- .../SerializationResolveExtension.kt | 11 +++ .../compiler/resolve/KSerializationUtil.kt | 61 ------------ .../resolve/KSerializerDescriptorResolver.kt | 39 +++----- .../compiler/resolve/SearchUtils.kt | 98 +++++++++++++++++++ 16 files changed, 187 insertions(+), 110 deletions(-) create mode 100644 plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ConstructorCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ConstructorCodegen.java index a46c4455e6a..8e53656771d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ConstructorCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ConstructorCodegen.java @@ -130,6 +130,8 @@ public class ConstructorCodegen { ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper); KtSecondaryConstructor constructor = (KtSecondaryConstructor) descriptorToDeclaration(constructorDescriptor); + // Synthetic constructors don't have corresponding declarations + if (constructor == null) return; functionCodegen.generateMethod( JvmDeclarationOriginKt.OtherOrigin(constructor, constructorDescriptor), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt index 7d61d67ddc1..dd20f2e8001 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt @@ -44,6 +44,7 @@ class SyntheticClassOrObjectDescriptor( outerScope: LexicalScope, private val modality: Modality, private val visibility: Visibility, + override val annotations: Annotations, constructorVisibility: Visibility, private val kind: ClassKind, private val isCompanionObject: Boolean @@ -71,8 +72,6 @@ class SyntheticClassOrObjectDescriptor( this.typeParameters = typeParameters } - override val annotations: Annotations get() = Annotations.EMPTY - override fun getModality() = modality override fun getVisibility() = visibility override fun getKind() = kind diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt index cf81ccb1a4f..c60958e919d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt @@ -17,10 +17,7 @@ package org.jetbrains.kotlin.resolve.extensions import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.BindingContext @@ -113,6 +110,22 @@ interface SyntheticResolveExtension { ) } } + + override fun generateSyntheticSecondaryConstructors( + thisDescriptor: ClassDescriptor, + bindingContext: BindingContext, + result: MutableCollection + ) { + instances.forEach { + withLinkageErrorLogger(it) { + generateSyntheticSecondaryConstructors( + thisDescriptor, + bindingContext, + result + ) + } + } + } } } } @@ -160,4 +173,11 @@ interface SyntheticResolveExtension { result: MutableSet ) { } + + fun generateSyntheticSecondaryConstructors( + thisDescriptor: ClassDescriptor, + bindingContext: BindingContext, + result: MutableCollection + ) { + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 72f06fa749d..06513e7087f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -444,7 +444,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes /* parentClassOrObject= */ classOrObject, this, syntheticCompanionName, getSource(), /* outerScope= */ getOuterScope(), - Modality.FINAL, PUBLIC, PRIVATE, ClassKind.OBJECT, true); + Modality.FINAL, PUBLIC, Annotations.Companion.getEMPTY(), PRIVATE, ClassKind.OBJECT, true); companionDescriptor.initialize(); return companionDescriptor; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt index 226742d6566..3d0fe63e311 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt @@ -415,7 +415,18 @@ open class LazyClassMemberScope( } private val secondaryConstructors: NotNullLazyValue> = - c.storageManager.createLazyValue { resolveSecondaryConstructors() } + c.storageManager.createLazyValue { doGetConstructors() } + + private fun doGetConstructors(): Collection { + val result = mutableListOf() + result.addAll(resolveSecondaryConstructors()) + addSyntheticSecondaryConstructors(result) + return result + } + + private fun addSyntheticSecondaryConstructors(result: MutableCollection) { + c.syntheticResolveExtension.generateSyntheticSecondaryConstructors(thisDescriptor, trace.bindingContext, result) + } fun getConstructors(): Collection { val result = secondaryConstructors() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt index d6334ea2ccb..13839ad2086 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt @@ -20,10 +20,8 @@ import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver -import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperties -import org.jetbrains.kotlinx.serialization.compiler.resolve.classSerializer -import org.jetbrains.kotlinx.serialization.compiler.resolve.isAbstractSerializableClass +import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors +import org.jetbrains.kotlinx.serialization.compiler.resolve.* abstract class SerializableCodegen( protected val serializableDescriptor: ClassDescriptor, @@ -39,7 +37,7 @@ abstract class SerializableCodegen( private fun generateSyntheticInternalConstructor() { val serializerDescriptor = serializableDescriptor.classSerializer ?: return if (isAbstractSerializableClass(serializableDescriptor) || SerializerCodegen.getSyntheticLoadMember(serializerDescriptor) != null) { - val constrDesc = KSerializerDescriptorResolver.createLoadConstructorDescriptor(serializableDescriptor, bindingContext) + val constrDesc = serializableDescriptor.secondaryConstructors.find(ClassConstructorDescriptor::isSerializationCtor) ?: return generateInternalConstructor(constrDesc) } } @@ -57,4 +55,4 @@ abstract class SerializableCodegen( protected open fun generateWriteSelfMethod(methodDescriptor: FunctionDescriptor) { } -} \ No newline at end of file +} 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 96dee484593..b3546c1b472 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 @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlinx.serialization.compiler.resolve.* -import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers abstract class SerializerCodegen( protected val serializerDescriptor: ClassDescriptor, diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index c85008e47eb..f09d819f765 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -18,9 +18,12 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* 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.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.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.name.ClassId @@ -77,6 +80,7 @@ interface IrBuilderExtension { fun IrClass.contributeConstructor( descriptor: ClassConstructorDescriptor, fromStubs: Boolean = false, + overwriteValueParameters: Boolean = false, bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit ) { val c = if (!fromStubs) compilerContext.localSymbolTable.declareConstructor( @@ -87,7 +91,7 @@ interface IrBuilderExtension { ) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner c.parent = this c.returnType = descriptor.returnType.toIrType() - if (!fromStubs) c.createParameterDeclarations(receiver = null) + if (!fromStubs || overwriteValueParameters) c.createParameterDeclarations(receiver = null, overwriteValueParameters = overwriteValueParameters) if (c.typeParameters.isEmpty()) { 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( this@createParameterDeclarations.startOffset, this@createParameterDeclarations.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, @@ -360,8 +364,11 @@ interface IrBuilderExtension { dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter() extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter() - assert(valueParameters.isEmpty()) - descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() } + if (!overwriteValueParameters) + assert(valueParameters.isEmpty()) + else + valueParameters.clear() + valueParameters.addAll(descriptor.valueParameters.map { it.irValueParameter() }) assert(typeParameters.isEmpty()) copyTypeParamsFromDescriptor() @@ -524,7 +531,7 @@ interface IrBuilderExtension { val serializable = getSerializableClassDescriptorBySerializer(serializerClass) val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) { requireNotNull( - KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializerClass) + findSerializerConstructorForTypeArgumentsSerializers(serializerClass) ) { "Generated serializer does not have constructor with required number of arguments" } .let { compilerContext.externalSymbols.referenceConstructor(it) } } else { @@ -537,5 +544,5 @@ interface IrBuilderExtension { } fun IrClass.serializableSyntheticConstructor(): IrConstructorSymbol = - this.constructors.single { it.origin == SERIALIZABLE_PLUGIN_ORIGIN }.symbol + this.constructors.single { it.descriptor.isSerializationCtor() }.symbol } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt index e85c65b562f..2fd98978173 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt @@ -58,7 +58,7 @@ class SerializableCompanionIrGenerator( } else -> { val desc = requireNotNull( - KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializer) + findSerializerConstructorForTypeArgumentsSerializers(serializer) ) { "Generated serializer does not have constructor with required number of arguments" } val ctor = compilerContext.externalSymbols.referenceConstructor(desc) val typeArgs = getter.typeParameters.map { it.defaultType } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt index ef2f3becf2d..1869159bcd1 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt @@ -38,7 +38,7 @@ class SerializableIrGenerator( get() = _table override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) = - irClass.contributeConstructor(constructorDescriptor) { ctor -> + irClass.contributeConstructor(constructorDescriptor, fromStubs = true, overwriteValueParameters = true) { ctor -> val transformFieldInitializer = buildInitializersRemapping(irClass) // Missing field exception parts diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt index d9792eaa8a9..d99452959ee 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/JsCodegenUtil.kt @@ -158,7 +158,7 @@ internal fun SerializerJsTranslator.serializerInstance( val serializable = getSerializableClassDescriptorBySerializer(serializerClass) val ref = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) { val desc = requireNotNull( - KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializerClass) + findSerializerConstructorForTypeArgumentsSerializers(serializerClass) ) { "Generated serializer does not have constructor with required number of arguments" } if (!desc.isPrimary) JsInvocation(context.getInnerReference(desc), args) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableCompanionJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableCompanionJsTranslator.kt index e5283d0f10d..7459e809c5d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableCompanionJsTranslator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableCompanionJsTranslator.kt @@ -46,7 +46,7 @@ class SerializableCompanionJsTranslator( val args = jsFun.parameters.map { JsNameRef(it.name) } val ref = context.getInnerNameForDescriptor( requireNotNull( - KSerializerDescriptorResolver.findSerializerConstructorForTypeArgumentsSerializers(serializer) + findSerializerConstructorForTypeArgumentsSerializers(serializer) ) { "Generated serializer does not have constructor with required number of arguments" }) JsInvocation(ref.makeRef(), args) } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt index ec5cb42b7f6..553c5fe1d1a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlinx.serialization.compiler.extensions +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor @@ -69,6 +70,16 @@ open class SerializationResolveExtension : SyntheticResolveExtension { KSerializerDescriptorResolver.addSerializerSupertypes(thisDescriptor, supertypes) } + override fun generateSyntheticSecondaryConstructors( + thisDescriptor: ClassDescriptor, + bindingContext: BindingContext, + result: MutableCollection + ) { + if (thisDescriptor.isInternalSerializable) { + result.add(KSerializerDescriptorResolver.createLoadConstructorDescriptor(thisDescriptor, bindingContext)) + } + } + override fun generateSyntheticMethods( thisDescriptor: ClassDescriptor, name: Name, 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 971c03f1efc..2e782af7bed 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,13 +18,9 @@ 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.constants.KClassValue import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.module 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.resolve.SerialEntityNames.KSERIALIZER_CLASS import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName -import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName internal fun isAllowedToHaveAutoGeneratedSerializerMethods( classDescriptor: ClassDescriptor, @@ -219,59 +214,3 @@ internal fun ClassDescriptor.checkLoadMethodParameters(parameters: List 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, List>> = - annotations.asSequence() - .filter { it.type.toClassDescriptor?.isSerialInfoAnnotation == 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/KSerializerDescriptorResolver.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt index e9890e93f32..f4166779043 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt @@ -18,8 +18,10 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve import org.jetbrains.kotlin.builtins.KotlinBuiltIns 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.Annotations +import org.jetbrains.kotlin.descriptors.annotations.createDeprecatedAnnotation import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.ClassId @@ -47,6 +49,10 @@ import java.util.* 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 { return thisDescriptor.name == IMPL_NAME && thisDescriptor.containingDeclaration is LazyClassDescriptor @@ -92,6 +98,7 @@ object KSerializerDescriptorResolver { scope, Modality.FINAL, Visibilities.PUBLIC, + Annotations.create(listOf(createDeprecatedHiddenAnnotation(interfaceDesc.module))), primaryCtorVisibility, ClassKind.CLASS, false @@ -114,7 +121,9 @@ object KSerializerDescriptorResolver { thisDeclaration, thisDescriptor, SERIALIZER_CLASS_NAME, thisDescriptor.source, scope, - Modality.FINAL, Visibilities.PUBLIC, Visibilities.PRIVATE, + Modality.FINAL, Visibilities.PUBLIC, + Annotations.create(listOf(createDeprecatedHiddenAnnotation(thisDescriptor.module))), + Visibilities.PRIVATE, serializerKind, false ) val typeParameters: List = @@ -276,9 +285,9 @@ object KSerializerDescriptorResolver { val functionDescriptor = ClassConstructorDescriptorImpl.createSynthesized( classDescriptor, - Annotations.EMPTY, + Annotations.create(listOf(createDeprecatedHiddenAnnotation(classDescriptor.module))), false, - classDescriptor.source + SourceElement.NO_SOURCE ) val markerDesc = classDescriptor.getKSerializerConstructorMarker() @@ -314,29 +323,13 @@ object KSerializerDescriptorResolver { functionDescriptor.initialize( consParams, - Visibilities.PUBLIC + Visibilities.INTERNAL ) functionDescriptor.returnType = classDescriptor.defaultType return functionDescriptor } - // finds constructor (KSerializer, KSerializer...) on a KSerializer> - 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( classDescriptor: ClassDescriptor, serializableDescriptor: ClassDescriptor, @@ -344,7 +337,7 @@ object KSerializerDescriptorResolver { ): ClassConstructorDescriptor { val constrDesc = ClassConstructorDescriptorImpl.createSynthesized( classDescriptor, - Annotations.EMPTY, + Annotations.create(listOf(createDeprecatedHiddenAnnotation(classDescriptor.module))), false, classDescriptor.source ) @@ -437,8 +430,8 @@ object KSerializerDescriptorResolver { private fun KotlinType.makeNullableIfNotPrimitive() = - if (KotlinBuiltIns.isPrimitiveType(this)) this - else this.makeNullable() + if (KotlinBuiltIns.isPrimitiveType(this)) this + else this.makeNullable() fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): FunctionDescriptor { val jvmStaticClass = thisClass.module.findClassAcrossModuleDependencies( diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt new file mode 100644 index 00000000000..4dc008087b2 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt @@ -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, KSerializer...) on a KSerializer> +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 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, List>> = + annotations.asSequence() + .filter { it.type.toClassDescriptor?.isSerialInfoAnnotation == true } + .filterIsInstance() + .mapNotNull { annDesc -> + annDesc.type.toClassDescriptor?.let { + Triple(it, annDesc.annotationEntry.valueArguments, it.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty()) + } + } + .toList()