From 567210da9ceb6f39d35e13b657c646e8fa379669 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Wed, 29 Apr 2020 18:52:24 +0700 Subject: [PATCH] [CInterop] Fix global property mangling Do not mangle properties with the same name but with different receivers --- .../native/interop/gen/KotlinCodeModel.kt | 29 ++++++++++++------- .../native/interop/gen/StubIrExtensions.kt | 13 ++++++++- .../interop/gen/StubIrMetadataEmitter.kt | 8 ++--- .../native/interop/gen/StubIrTextEmitter.kt | 4 +-- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt index 6e1415c0528..2b2b8fbba41 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt @@ -33,7 +33,7 @@ interface KotlinScope { * @return the string to be used as a name in the declaration of the property in current scope, * or `null` if the property with given name can't be declared. */ - fun declareProperty(name: String): String? + fun declareProperty(receiver: String?, name: String): String? val mappingBridgeGenerator: MappingBridgeGenerator } @@ -314,14 +314,16 @@ abstract class KotlinFile( return topLevelName } - override fun declareProperty(name: String): String? = - if (name in declaredProperties || name in namesToBeDeclared || name in importedNameToPkg) { - null - // TODO: using original global name should be preferred to importing the clashed name. - } else { - declaredProperties.add(name) - name - } + override fun declareProperty(receiver: String?, name: String): String? { + val fullName = receiver?.let { "$it.${name}" } ?: name + return if (fullName in declaredProperties || name in namesToBeDeclared || name in importedNameToPkg) { + null + // TODO: using original global name should be preferred to importing the clashed name. + } else { + declaredProperties.add(fullName) + name + } + } fun buildImports(): List = importedNameToPkg.mapNotNull { (name, pkg) -> if (pkg == "kotlin" || pkg == "kotlinx.cinterop") { @@ -334,6 +336,11 @@ abstract class KotlinFile( } +internal fun getTopLevelPropertyDeclarationName(scope: KotlinScope, property: PropertyStub): String { + val receiverName = property.receiverType?.underlyingTypeFqName + return getTopLevelPropertyDeclarationName(scope, receiverName, property.name) +} + // Try to use the provided name. If failed, mangle it with underscore and try again: -internal tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, name: String): String = - scope.declareProperty(name) ?: getTopLevelPropertyDeclarationName(scope, name + "_") \ No newline at end of file +private tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, receiver: String?, name: String): String = + scope.declareProperty(receiver, name) ?: getTopLevelPropertyDeclarationName(scope, receiver, name + "_") \ No newline at end of file diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt index e4988c3dd92..d48a60046c7 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt @@ -86,4 +86,15 @@ fun ConstantStub.determineConstantAnnotationClassifier(): Classifier = when (thi 8 -> "Double" else -> error("Real constant with unexpected size of $size.") } -}.let { Classifier.topLevel(cinteropInternalPackage, "ConstantValue").nested(it) } \ No newline at end of file +}.let { Classifier.topLevel(cinteropInternalPackage, "ConstantValue").nested(it) } + +/** + * Returns the original name of the given type. + */ +val StubType.underlyingTypeFqName: String + get() = when (this) { + is ClassifierStubType -> classifier.fqName + is AbbreviatedType -> underlyingType.underlyingTypeFqName + is FunctionalType -> classifier.fqName + is TypeParameterType -> name + } \ No newline at end of file diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt index d5d590672ae..870c9e0d718 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt @@ -98,11 +98,11 @@ internal class ModuleMetadataEmitter( private fun isTopLevelContainer(container: StubContainer?): Boolean = container == null - private fun getPropertyNameInScope(originalName: String, container: StubContainer?): String = + private fun getPropertyNameInScope(property: PropertyStub, container: StubContainer?): String = if (isTopLevelContainer(container)) { - getTopLevelPropertyDeclarationName(bridgeBuilderResult.kotlinFile, originalName) + getTopLevelPropertyDeclarationName(bridgeBuilderResult.kotlinFile, property) } else { - originalName + property.name } private val visitor = object : StubIrVisitor { @@ -170,7 +170,7 @@ internal class ModuleMetadataEmitter( data.withMappingExtensions { val kind = element.bridgeSupportedKind if (kind != null) { - val name = getPropertyNameInScope(element.name, data.container) + val name = getPropertyNameInScope(element, data.container) KmProperty(element.flags, name, kind.getterFlags, kind.setterFlags).also { km -> element.annotations.mapTo(km.annotations) { it.map() } km.uniqId = data.uniqIds.uniqIdForProperty(element) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt index 1e622892d94..4951f0b354e 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt @@ -30,7 +30,7 @@ class StubIrTextEmitter( get() = context.configuration.pkgName private val StubContainer.isTopLevelContainer: Boolean - get() = this == builderResult.stubs + get() = this == builderResult.stubs || this in builderResult.stubs.simpleContainers /** * The output currently used by the generator. @@ -286,7 +286,7 @@ class StubIrTextEmitter( val modality = "$override${renderMemberModality(element.modality, owner)}" val receiver = if (element.receiverType != null) "${renderStubType(element.receiverType)}." else "" val name = if (owner?.isTopLevelContainer == true) { - getTopLevelPropertyDeclarationName(kotlinFile, element.name).asSimpleName() + getTopLevelPropertyDeclarationName(kotlinFile, element).asSimpleName() } else { element.name.asSimpleName() }