Add initial support for -Xobjc-generics to ObjCExportLazy

This commit is contained in:
Svyatoslav Scherbina
2020-01-20 14:26:09 +03:00
committed by SvyatoslavScherbina
parent 64ddfee214
commit d3d3b3aa77
2 changed files with 32 additions and 16 deletions
@@ -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<String> = if (configuration.objcGenerics) {
ktClassOrObject.typeParametersWithOuter
.map { nameTranslator.getTypeParameterName(it) }
.toList()
} else {
emptyList()
}
private fun translateTopLevels(file: KtFile): List<ObjCInterface> {
val extensions =
mutableMapOf<ClassDescriptor, MutableList<KtCallableDeclaration>>()
@@ -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() }
@@ -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<TypeParameterDescriptor, String>()
private val typeParameterNameClassOverrides = mutableMapOf<ClassDescriptor, MutableSet<String>>()
fun reserved(name: String): Boolean {
return name in reservedNames
}
fun getOrPut(element: TypeParameterDescriptor, nameCandidates: () -> Sequence<String>): 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<String> {
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<in T : Any, N>() {