[ObjCExport] Support nullable type arguments in translating known Collection types
^KT-65167
This commit is contained in:
committed by
Space Team
parent
858af02a24
commit
3111678f8b
+1
-44
@@ -6,7 +6,6 @@ import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.annotationInfos
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.backend.konan.InternalKotlinNativeApi
|
||||
import org.jetbrains.kotlin.backend.konan.KonanFqNames
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||
@@ -14,7 +13,6 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.objcexport.Predefined.anyMethodSelectors
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getFunctionMethodBridge
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getInlineTargetTypeOrNull
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
@@ -327,7 +325,7 @@ fun KtFunctionLikeSymbol.mapReturnType(returnBridge: MethodBridge.ReturnValue):
|
||||
MethodBridge.ReturnValue.Void,
|
||||
-> ObjCVoidType
|
||||
MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger
|
||||
is MethodBridge.ReturnValue.Mapped -> returnType.mapType(returnBridge.bridge)
|
||||
is MethodBridge.ReturnValue.Mapped -> returnType.translateToObjCType(returnBridge.bridge)
|
||||
MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> {
|
||||
val successReturnType = mapReturnType(returnBridge.successBridge)
|
||||
@@ -349,44 +347,3 @@ fun KtFunctionLikeSymbol.mapReturnType(returnBridge: MethodBridge.ReturnValue):
|
||||
-> ObjCInstanceType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.mapType]
|
||||
*/
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
private fun KtType.mapType(typeBridge: TypeBridge): ObjCType {
|
||||
|
||||
//if (!this.isObjCObjectType()) return null //TODO implement isObjCObjectType
|
||||
|
||||
return when (typeBridge) {
|
||||
is ReferenceBridge -> this.translateToObjCReferenceType()
|
||||
is BlockPointerBridge -> this.translateToObjCFunctionType(typeBridge)
|
||||
is ValueTypeBridge -> when (typeBridge.objCValueType) {
|
||||
ObjCValueType.BOOL -> ObjCPrimitiveType.BOOL
|
||||
ObjCValueType.UNICHAR -> ObjCPrimitiveType.unichar
|
||||
ObjCValueType.CHAR -> ObjCPrimitiveType.int8_t
|
||||
ObjCValueType.SHORT -> ObjCPrimitiveType.int16_t
|
||||
ObjCValueType.INT -> ObjCPrimitiveType.int32_t
|
||||
ObjCValueType.LONG_LONG -> ObjCPrimitiveType.int64_t
|
||||
ObjCValueType.UNSIGNED_CHAR -> ObjCPrimitiveType.uint8_t
|
||||
ObjCValueType.UNSIGNED_SHORT -> ObjCPrimitiveType.uint16_t
|
||||
ObjCValueType.UNSIGNED_INT -> ObjCPrimitiveType.uint32_t
|
||||
ObjCValueType.UNSIGNED_LONG_LONG -> ObjCPrimitiveType.uint64_t
|
||||
ObjCValueType.FLOAT -> ObjCPrimitiveType.float
|
||||
ObjCValueType.DOUBLE -> ObjCPrimitiveType.double
|
||||
ObjCValueType.POINTER -> ObjCPointerType(ObjCVoidType, isBinaryRepresentationNullable())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
private fun KtType.isBinaryRepresentationNullable(): Boolean {
|
||||
if (fullyExpandedType.isMarkedNullable) return true
|
||||
|
||||
getInlineTargetTypeOrNull()?.let { inlineTargetType ->
|
||||
if (inlineTargetType.isMarkedNullable) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ internal fun KtFunctionLikeSymbol.translateToObjCParameters(baseMethodBridge: Me
|
||||
|
||||
val type = when (bridge) {
|
||||
is MethodBridgeValueParameter.Mapped ->
|
||||
parameter!!.returnType.translateToObjCReferenceType()
|
||||
parameter!!.returnType.translateToObjCType(bridge.bridge)
|
||||
MethodBridgeValueParameter.ErrorOutParameter ->
|
||||
ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true)
|
||||
|
||||
|
||||
+72
-11
@@ -8,10 +8,53 @@ import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getInlineTargetTypeOrNull
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isError
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.objCErrorType
|
||||
|
||||
|
||||
/**
|
||||
* [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.mapType]
|
||||
*/
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
internal fun KtType.translateToObjCType(typeBridge: TypeBridge): ObjCType {
|
||||
|
||||
//if (!this.isObjCObjectType()) return null //TODO implement isObjCObjectType
|
||||
|
||||
return when (typeBridge) {
|
||||
is ReferenceBridge -> this.translateToObjCReferenceType()
|
||||
is BlockPointerBridge -> this.translateToObjCFunctionType(typeBridge)
|
||||
is ValueTypeBridge -> when (typeBridge.objCValueType) {
|
||||
ObjCValueType.BOOL -> ObjCPrimitiveType.BOOL
|
||||
ObjCValueType.UNICHAR -> ObjCPrimitiveType.unichar
|
||||
ObjCValueType.CHAR -> ObjCPrimitiveType.int8_t
|
||||
ObjCValueType.SHORT -> ObjCPrimitiveType.int16_t
|
||||
ObjCValueType.INT -> ObjCPrimitiveType.int32_t
|
||||
ObjCValueType.LONG_LONG -> ObjCPrimitiveType.int64_t
|
||||
ObjCValueType.UNSIGNED_CHAR -> ObjCPrimitiveType.uint8_t
|
||||
ObjCValueType.UNSIGNED_SHORT -> ObjCPrimitiveType.uint16_t
|
||||
ObjCValueType.UNSIGNED_INT -> ObjCPrimitiveType.uint32_t
|
||||
ObjCValueType.UNSIGNED_LONG_LONG -> ObjCPrimitiveType.uint64_t
|
||||
ObjCValueType.FLOAT -> ObjCPrimitiveType.float
|
||||
ObjCValueType.DOUBLE -> ObjCPrimitiveType.double
|
||||
ObjCValueType.POINTER -> ObjCPointerType(ObjCVoidType, isBinaryRepresentationNullable())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
private fun KtType.isBinaryRepresentationNullable(): Boolean {
|
||||
if (fullyExpandedType.isMarkedNullable) return true
|
||||
|
||||
getInlineTargetTypeOrNull()?.let { inlineTargetType ->
|
||||
if (inlineTargetType.isMarkedNullable) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.mapReferenceType]
|
||||
*/
|
||||
@@ -36,7 +79,7 @@ private fun KtType.mapToReferenceTypeIgnoringNullability(): ObjCNonNullReference
|
||||
return ObjCIdType
|
||||
}
|
||||
|
||||
if (classId in hiddenTypes) {
|
||||
if (classId in hiddenClassIds) {
|
||||
return ObjCIdType
|
||||
}
|
||||
|
||||
@@ -76,18 +119,30 @@ private fun KtType.mapToReferenceTypeIgnoringNullability(): ObjCNonNullReference
|
||||
val typeName = typesMap[classId]
|
||||
?: classId!!.shortClassName.asString().getObjCKotlinStdlibClassOrProtocolName().objCName
|
||||
|
||||
val typeArguments = run {
|
||||
if (this !is KtNonErrorClassType) {
|
||||
return@run listOf<ObjCNonNullReferenceType>()
|
||||
}
|
||||
|
||||
ownTypeArguments.mapNotNull { typeArgument -> typeArgument.type }
|
||||
.map { typeArgumentType -> typeArgumentType.mapToReferenceTypeIgnoringNullability() }
|
||||
}
|
||||
val typeArguments = translateToObjCTypeArguments()
|
||||
|
||||
return ObjCClassType(typeName, typeArguments)
|
||||
}
|
||||
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
private fun KtType.translateToObjCTypeArguments(): List<ObjCNonNullReferenceType> {
|
||||
if (this !is KtNonErrorClassType) return emptyList()
|
||||
|
||||
/* See special casing below */
|
||||
val isKnownCollectionType = classId in collectionClassIds
|
||||
|
||||
return ownTypeArguments.mapNotNull { typeArgument -> typeArgument.type }
|
||||
.map { typeArgumentType ->
|
||||
|
||||
/*
|
||||
Kotlin `null` keys and values are represented as `NSNull` singleton in collections
|
||||
*/
|
||||
if (isKnownCollectionType && typeArgumentType.isMarkedNullable) return@map ObjCIdType
|
||||
typeArgumentType.mapToReferenceTypeIgnoringNullability()
|
||||
}
|
||||
}
|
||||
|
||||
private fun ObjCNonNullReferenceType.withNullabilityOf(kotlinType: KtType): ObjCReferenceType {
|
||||
return if (kotlinType.nullability.isNullable) {
|
||||
ObjCNullableReferenceType(this)
|
||||
@@ -102,7 +157,7 @@ private fun ObjCNonNullReferenceType.withNullabilityOf(kotlinType: KtType): ObjC
|
||||
* Currently contains super types of classes handled by custom type mappers.
|
||||
* Note: can be generated programmatically, but requires stdlib in this case.
|
||||
*/
|
||||
private val hiddenTypes: Set<ClassId> = listOf(
|
||||
private val hiddenClassIds: Set<ClassId> = listOf(
|
||||
"kotlin.Any",
|
||||
"kotlin.CharSequence",
|
||||
"kotlin.Comparable",
|
||||
@@ -112,4 +167,10 @@ private val hiddenTypes: Set<ClassId> = listOf(
|
||||
"kotlin.collections.Iterable",
|
||||
"kotlin.collections.MutableCollection",
|
||||
"kotlin.collections.MutableIterable"
|
||||
).map { ClassId.topLevel(FqName(it)) }.toSet()
|
||||
).map { ClassId.topLevel(FqName(it)) }.toSet()
|
||||
|
||||
private val collectionClassIds = setOf(
|
||||
StandardClassIds.List, StandardClassIds.MutableList,
|
||||
StandardClassIds.Set, StandardClassIds.MutableSet,
|
||||
StandardClassIds.Map, StandardClassIds.MutableMap
|
||||
)
|
||||
Reference in New Issue
Block a user