[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,
|
* @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.
|
* 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
|
val mappingBridgeGenerator: MappingBridgeGenerator
|
||||||
}
|
}
|
||||||
@@ -314,14 +314,16 @@ abstract class KotlinFile(
|
|||||||
return topLevelName
|
return topLevelName
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun declareProperty(name: String): String? =
|
override fun declareProperty(receiver: String?, name: String): String? {
|
||||||
if (name in declaredProperties || name in namesToBeDeclared || name in importedNameToPkg) {
|
val fullName = receiver?.let { "$it.${name}" } ?: name
|
||||||
null
|
return if (fullName in declaredProperties || name in namesToBeDeclared || name in importedNameToPkg) {
|
||||||
// TODO: using original global name should be preferred to importing the clashed name.
|
null
|
||||||
} else {
|
// TODO: using original global name should be preferred to importing the clashed name.
|
||||||
declaredProperties.add(name)
|
} else {
|
||||||
name
|
declaredProperties.add(fullName)
|
||||||
}
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun buildImports(): List<String> = importedNameToPkg.mapNotNull { (name, pkg) ->
|
fun buildImports(): List<String> = importedNameToPkg.mapNotNull { (name, pkg) ->
|
||||||
if (pkg == "kotlin" || pkg == "kotlinx.cinterop") {
|
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:
|
// Try to use the provided name. If failed, mangle it with underscore and try again:
|
||||||
internal tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, name: String): String =
|
private tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, receiver: String?, name: String): String =
|
||||||
scope.declareProperty(name) ?: getTopLevelPropertyDeclarationName(scope, name + "_")
|
scope.declareProperty(receiver, name) ?: getTopLevelPropertyDeclarationName(scope, receiver, name + "_")
|
||||||
+11
@@ -87,3 +87,14 @@ fun ConstantStub.determineConstantAnnotationClassifier(): Classifier = when (thi
|
|||||||
else -> error("Real constant with unexpected size of $size.")
|
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 =
|
private fun isTopLevelContainer(container: StubContainer?): Boolean =
|
||||||
container == null
|
container == null
|
||||||
|
|
||||||
private fun getPropertyNameInScope(originalName: String, container: StubContainer?): String =
|
private fun getPropertyNameInScope(property: PropertyStub, container: StubContainer?): String =
|
||||||
if (isTopLevelContainer(container)) {
|
if (isTopLevelContainer(container)) {
|
||||||
getTopLevelPropertyDeclarationName(bridgeBuilderResult.kotlinFile, originalName)
|
getTopLevelPropertyDeclarationName(bridgeBuilderResult.kotlinFile, property)
|
||||||
} else {
|
} else {
|
||||||
originalName
|
property.name
|
||||||
}
|
}
|
||||||
|
|
||||||
private val visitor = object : StubIrVisitor<VisitingContext, Any?> {
|
private val visitor = object : StubIrVisitor<VisitingContext, Any?> {
|
||||||
@@ -170,7 +170,7 @@ internal class ModuleMetadataEmitter(
|
|||||||
data.withMappingExtensions {
|
data.withMappingExtensions {
|
||||||
val kind = element.bridgeSupportedKind
|
val kind = element.bridgeSupportedKind
|
||||||
if (kind != null) {
|
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 ->
|
KmProperty(element.flags, name, kind.getterFlags, kind.setterFlags).also { km ->
|
||||||
element.annotations.mapTo(km.annotations) { it.map() }
|
element.annotations.mapTo(km.annotations) { it.map() }
|
||||||
km.uniqId = data.uniqIds.uniqIdForProperty(element)
|
km.uniqId = data.uniqIds.uniqIdForProperty(element)
|
||||||
|
|||||||
+2
-2
@@ -30,7 +30,7 @@ class StubIrTextEmitter(
|
|||||||
get() = context.configuration.pkgName
|
get() = context.configuration.pkgName
|
||||||
|
|
||||||
private val StubContainer.isTopLevelContainer: Boolean
|
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.
|
* The output currently used by the generator.
|
||||||
@@ -286,7 +286,7 @@ class StubIrTextEmitter(
|
|||||||
val modality = "$override${renderMemberModality(element.modality, owner)}"
|
val modality = "$override${renderMemberModality(element.modality, owner)}"
|
||||||
val receiver = if (element.receiverType != null) "${renderStubType(element.receiverType)}." else ""
|
val receiver = if (element.receiverType != null) "${renderStubType(element.receiverType)}." else ""
|
||||||
val name = if (owner?.isTopLevelContainer == true) {
|
val name = if (owner?.isTopLevelContainer == true) {
|
||||||
getTopLevelPropertyDeclarationName(kotlinFile, element.name).asSimpleName()
|
getTopLevelPropertyDeclarationName(kotlinFile, element).asSimpleName()
|
||||||
} else {
|
} else {
|
||||||
element.name.asSimpleName()
|
element.name.asSimpleName()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user