From d3d3b3aa772cc88e076ddeaaae5d52ab8c78e929 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Mon, 20 Jan 2020 14:26:09 +0300 Subject: [PATCH] Add initial support for -Xobjc-generics to ObjCExportLazy --- .../konan/objcexport/ObjCExportLazy.kt | 18 ++++++++--- .../konan/objcexport/ObjCExportNamer.kt | 30 +++++++++++-------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt index 6cde40dc803..4f3d47f4dcd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt @@ -18,9 +18,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier -import org.jetbrains.kotlin.psi.psiUtil.modalityModifier -import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierTypeOrDefault +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.DescriptorResolver @@ -140,12 +138,20 @@ internal class ObjCExportLazyImpl( LazyObjCInterfaceImpl(name, attributes, - generics = if (configuration.objcGenerics) TODO() else emptyList(), + generics = translateGenerics(ktClassOrObject), psi = ktClassOrObject, lazy = this) } } + private fun translateGenerics(ktClassOrObject: KtClassOrObject): List = if (configuration.objcGenerics) { + ktClassOrObject.typeParametersWithOuter + .map { nameTranslator.getTypeParameterName(it) } + .toList() + } else { + emptyList() + } + private fun translateTopLevels(file: KtFile): List { val extensions = mutableMapOf>() @@ -437,3 +443,7 @@ private val KtCallableDeclaration.isSuspend: Boolean internal val KtPureClassOrObject.isInterface: Boolean get() = this is KtClass && this.isInterface() + +internal val KtClassOrObject.typeParametersWithOuter + get() = generateSequence(this, { if (it is KtClass && it.isInner()) it.containingClassOrObject else null }) + .flatMap { it.typeParameters.asSequence() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt index fa128a6bee5..9cac75750d0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt @@ -29,6 +29,8 @@ internal interface ObjCExportNameTranslator { fun getClassOrProtocolName( ktClassOrObject: KtClassOrObject ): ObjCExportNamer.ClassOrProtocolName + + fun getTypeParameterName(ktTypeParameter: KtTypeParameter): String } interface ObjCExportNamer { @@ -130,6 +132,11 @@ internal open class ObjCExportNameTranslatorImpl( append(ownName) } } + + override fun getTypeParameterName(ktTypeParameter: KtTypeParameter): String = buildString { + append(ktTypeParameter.name!!.toIdentifier()) + while (helper.isTypeParameterNameReserved(this.toString())) append('_') + } } private class ObjCExportNamingHelper( @@ -161,6 +168,12 @@ private class ObjCExportNamingHelper( "Type" -> "${name}_" // See https://github.com/JetBrains/kotlin-native/issues/3167 else -> name } + + fun isTypeParameterNameReserved(name: String): Boolean = name in reservedTypeParameterNames + + private val reservedTypeParameterNames = setOf("id", "NSObject", "NSArray", "NSCopying", "NSNumber", "NSInteger", + "NSUInteger", "NSString", "NSSet", "NSDictionary", "NSMutableArray", "int", "unsigned", "short", + "char", "long", "float", "double", "int32_t", "int64_t", "int16_t", "int8_t", "unichar") } internal class ObjCExportNamerImpl( @@ -613,10 +626,6 @@ internal class ObjCExportNamerImpl( private val elementToName = mutableMapOf() private val typeParameterNameClassOverrides = mutableMapOf>() - fun reserved(name: String): Boolean { - return name in reservedNames - } - fun getOrPut(element: TypeParameterDescriptor, nameCandidates: () -> Sequence): String { getIfAssigned(element)?.let { return it } @@ -632,7 +641,7 @@ internal class ObjCExportNamerImpl( private fun tryAssign(element: TypeParameterDescriptor, name: String): Boolean { if (element in elementToName) error(element) - if (reserved(name)) return false + if (helper.isTypeParameterNameReserved(name)) return false if (!validName(element, name)) return false @@ -644,28 +653,25 @@ internal class ObjCExportNamerImpl( private fun assignName(element: TypeParameterDescriptor, name: String) { if (!local) { elementToName[element] = name + classNameSet(element).add(name) } - classNameSet(element).add(name) } private fun validName(element: TypeParameterDescriptor, name: String): Boolean { assert(element.containingDeclaration is ClassDescriptor) - val nameSet = classNameSet(element) - return !objCClassNames.nameExists(name) && !objCProtocolNames.nameExists(name) && name !in nameSet + return !objCClassNames.nameExists(name) && !objCProtocolNames.nameExists(name) && + (local || name !in classNameSet(element)) } private fun classNameSet(element: TypeParameterDescriptor): MutableSet { + require(!local) return typeParameterNameClassOverrides.getOrPut(element.containingDeclaration as ClassDescriptor) { mutableSetOf() } } private fun getIfAssigned(element: TypeParameterDescriptor): String? = elementToName[element] - - private val reservedNames = setOf("id", "NSObject", "NSArray", "NSCopying", "NSNumber", "NSInteger", - "NSUInteger", "NSString", "NSSet", "NSDictionary", "NSMutableArray", "int", "unsigned", "short", - "char", "long", "float", "double", "int32_t", "int64_t", "int16_t", "int8_t", "unichar") } private abstract inner class Mapping() {