[CInterop] Fix global property mangling
Do not mangle properties with the same name but with different receivers
This commit is contained in:
committed by
Sergey Bogolepov
parent
ed36f02c26
commit
567210da9c
+18
-11
@@ -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<String> = 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 + "_")
|
||||
private tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, receiver: String?, name: String): String =
|
||||
scope.declareProperty(receiver, name) ?: getTopLevelPropertyDeclarationName(scope, receiver, name + "_")
|
||||
+12
-1
@@ -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) }
|
||||
}.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
|
||||
}
|
||||
+4
-4
@@ -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<VisitingContext, Any?> {
|
||||
@@ -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)
|
||||
|
||||
+2
-2
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user