Extract ObjCExport lazy declarations to named classes (#3489)

Also convert `ObjCPrimitiveType` to a sealed class.
This commit is contained in:
SvyatoslavScherbina
2019-10-24 18:00:47 +03:00
committed by GitHub
parent 7c3e0bb801
commit 5aca1db362
5 changed files with 139 additions and 92 deletions
@@ -729,9 +729,9 @@ internal class ObjCExportTranslatorImpl(
private fun mapReturnType(returnBridge: MethodBridge.ReturnValue, method: FunctionDescriptor, objCExportScope: ObjCExportScope): ObjCType = when (returnBridge) { private fun mapReturnType(returnBridge: MethodBridge.ReturnValue, method: FunctionDescriptor, objCExportScope: ObjCExportScope): ObjCType = when (returnBridge) {
MethodBridge.ReturnValue.Void -> ObjCVoidType MethodBridge.ReturnValue.Void -> ObjCVoidType
MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType("NSUInteger") MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger
is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope) is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope)
MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType("BOOL") MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL
is MethodBridge.ReturnValue.WithError.RefOrNull -> { is MethodBridge.ReturnValue.WithError.RefOrNull -> {
val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope) as? ObjCNonNullReferenceType val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope) as? ObjCNonNullReferenceType
?: error("Function is expected to have non-null return type: $method") ?: error("Function is expected to have non-null return type: $method")
@@ -900,18 +900,18 @@ internal class ObjCExportTranslatorImpl(
is BlockPointerBridge -> mapFunctionType(kotlinType, objCExportScope, typeBridge) is BlockPointerBridge -> mapFunctionType(kotlinType, objCExportScope, typeBridge)
is ValueTypeBridge -> { is ValueTypeBridge -> {
when (typeBridge.objCValueType) { when (typeBridge.objCValueType) {
ObjCValueType.BOOL -> ObjCPrimitiveType("BOOL") ObjCValueType.BOOL -> ObjCPrimitiveType.BOOL
ObjCValueType.UNICHAR -> ObjCPrimitiveType("unichar") ObjCValueType.UNICHAR -> ObjCPrimitiveType.unichar
ObjCValueType.CHAR -> ObjCPrimitiveType("int8_t") ObjCValueType.CHAR -> ObjCPrimitiveType.int8_t
ObjCValueType.SHORT -> ObjCPrimitiveType("int16_t") ObjCValueType.SHORT -> ObjCPrimitiveType.int16_t
ObjCValueType.INT -> ObjCPrimitiveType("int32_t") ObjCValueType.INT -> ObjCPrimitiveType.int32_t
ObjCValueType.LONG_LONG -> ObjCPrimitiveType("int64_t") ObjCValueType.LONG_LONG -> ObjCPrimitiveType.int64_t
ObjCValueType.UNSIGNED_CHAR -> ObjCPrimitiveType("uint8_t") ObjCValueType.UNSIGNED_CHAR -> ObjCPrimitiveType.uint8_t
ObjCValueType.UNSIGNED_SHORT -> ObjCPrimitiveType("uint16_t") ObjCValueType.UNSIGNED_SHORT -> ObjCPrimitiveType.uint16_t
ObjCValueType.UNSIGNED_INT -> ObjCPrimitiveType("uint32_t") ObjCValueType.UNSIGNED_INT -> ObjCPrimitiveType.uint32_t
ObjCValueType.UNSIGNED_LONG_LONG -> ObjCPrimitiveType("uint64_t") ObjCValueType.UNSIGNED_LONG_LONG -> ObjCPrimitiveType.uint64_t
ObjCValueType.FLOAT -> ObjCPrimitiveType("float") ObjCValueType.FLOAT -> ObjCPrimitiveType.float
ObjCValueType.DOUBLE -> ObjCPrimitiveType("double") ObjCValueType.DOUBLE -> ObjCPrimitiveType.double
ObjCValueType.POINTER -> ObjCPointerType(ObjCVoidType, kotlinType.binaryRepresentationIsNullable()) ObjCValueType.POINTER -> ObjCPointerType(ObjCVoidType, kotlinType.binaryRepresentationIsNullable())
} }
// TODO: consider other namings. // TODO: consider other namings.
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.konan.objcexport package org.jetbrains.kotlin.backend.konan.objcexport
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -126,11 +127,7 @@ internal class ObjCExportLazyImpl(
// Note: some attributes may be missing (e.g. "unavailable" for unexposed classes). // Note: some attributes may be missing (e.g. "unavailable" for unexposed classes).
return if (ktClassOrObject.isInterface) { return if (ktClassOrObject.isInterface) {
object : LazyObjCProtocol(name) { LazyObjCProtocolImpl(name, ktClassOrObject, this)
override val descriptor: ClassDescriptor by lazy { resolve(ktClassOrObject) }
override fun computeRealStub(): ObjCProtocol = translator.translateInterface(descriptor)
}
} else { } else {
val isFinal = ktClassOrObject.modalityModifier() == null || val isFinal = ktClassOrObject.modalityModifier() == null ||
ktClassOrObject.hasModifier(KtTokens.FINAL_KEYWORD) ktClassOrObject.hasModifier(KtTokens.FINAL_KEYWORD)
@@ -141,16 +138,11 @@ internal class ObjCExportLazyImpl(
emptyList() emptyList()
} }
object : LazyObjCInterface( LazyObjCInterfaceImpl(name,
name, attributes,
generics = if (configuration.objcGenerics) TODO() else emptyList(), generics = if (configuration.objcGenerics) TODO() else emptyList(),
categoryName = null, psi = ktClassOrObject,
attributes = attributes lazy = this)
) {
override val descriptor: ClassDescriptor by lazy { resolve(ktClassOrObject) }
override fun computeRealStub(): ObjCInterface = translator.translateClass(descriptor)
}
} }
} }
@@ -185,23 +177,7 @@ internal class ObjCExportLazyImpl(
private fun translateFileClass(file: KtFile, declarations: List<KtCallableDeclaration>): ObjCInterface { private fun translateFileClass(file: KtFile, declarations: List<KtCallableDeclaration>): ObjCInterface {
val name = nameTranslator.getFileClassName(file) val name = nameTranslator.getFileClassName(file)
return LazyObjCFileInterface(name, file, declarations, this)
return object : LazyObjCInterface(
name,
generics = emptyList(),
categoryName = null,
attributes = listOf(OBJC_SUBCLASSING_RESTRICTED)
) {
override val descriptor: ClassDescriptor?
get() = null
override fun computeRealStub(): ObjCInterface = translator.translateFile(
PsiSourceFile(file),
declarations.mapNotNull { declaration ->
resolve(declaration).takeIf { mapper.shouldBeExposed(it) }
}
)
}
} }
private fun translateExtensions( private fun translateExtensions(
@@ -217,22 +193,7 @@ internal class ObjCExportLazyImpl(
namer.getClassOrProtocolName(classDescriptor) namer.getClassOrProtocolName(classDescriptor)
} }
return object : LazyObjCInterface( return LazyObjCExtensionInterface(name, nameTranslator.getCategoryName(file), classDescriptor, declarations, this)
name.objCName,
generics = emptyList(),
categoryName = nameTranslator.getCategoryName(file),
attributes = emptyList()
) {
override val descriptor: ClassDescriptor?
get() = null
override fun computeRealStub(): ObjCInterface = translator.translateExtensions(
classDescriptor,
declarations.mapNotNull { declaration ->
resolve(declaration).takeIf { mapper.shouldBeExposed(it) }
}
)
}
} }
private fun resolveDeclaration(ktDeclaration: KtDeclaration): DeclarationDescriptor = private fun resolveDeclaration(ktDeclaration: KtDeclaration): DeclarationDescriptor =
@@ -326,6 +287,71 @@ internal class ObjCExportLazyImpl(
return result return result
} }
private class LazyObjCProtocolImpl(
name: ObjCExportNamer.ClassOrProtocolName,
override val psi: KtClassOrObject,
private val lazy: ObjCExportLazyImpl
) : LazyObjCProtocol(name) {
override val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
override fun computeRealStub(): ObjCProtocol = lazy.translator.translateInterface(descriptor)
}
private class LazyObjCInterfaceImpl(
name: ObjCExportNamer.ClassOrProtocolName,
attributes: List<String>,
generics: List<String>,
override val psi: KtClassOrObject,
private val lazy: ObjCExportLazyImpl
) : LazyObjCInterface(name = name, generics = generics, categoryName = null, attributes = attributes) {
override val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
override fun computeRealStub(): ObjCInterface = lazy.translator.translateClass(descriptor)
}
private class LazyObjCFileInterface(
name: ObjCExportNamer.ClassOrProtocolName,
private val file: KtFile,
private val declarations: List<KtCallableDeclaration>,
private val lazy: ObjCExportLazyImpl
) : LazyObjCInterface(name = name, generics = emptyList(), categoryName = null, attributes = listOf(OBJC_SUBCLASSING_RESTRICTED)) {
override val descriptor: ClassDescriptor?
get() = null
override val psi: PsiElement?
get() = null
override fun computeRealStub(): ObjCInterface = lazy.translator.translateFile(
PsiSourceFile(file),
declarations.mapNotNull { declaration ->
lazy.resolve(declaration).takeIf { descriptor ->
lazy.mapper.shouldBeExposed(descriptor)
}
}
)
}
private class LazyObjCExtensionInterface(
name: ObjCExportNamer.ClassOrProtocolName,
categoryName: String,
private val classDescriptor: ClassDescriptor,
private val declarations: List<KtCallableDeclaration>,
private val lazy: ObjCExportLazyImpl
) : LazyObjCInterface(name = name.objCName, generics = emptyList(), categoryName = categoryName, attributes = emptyList()) {
override val descriptor: ClassDescriptor?
get() = null
override val psi: PsiElement?
get() = null
override fun computeRealStub(): ObjCInterface = lazy.translator.translateExtensions(
classDescriptor,
declarations.mapNotNull { declaration ->
lazy.resolve(declaration).takeIf { lazy.mapper.shouldBeExposed(it) }
}
)
}
} }
private abstract class LazyObjCInterface : ObjCInterface { private abstract class LazyObjCInterface : ObjCInterface {
@@ -320,21 +320,21 @@ internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor)
} }
internal enum class NSNumberKind(val mappedKotlinClassId: ClassId?, val objCType: ObjCType) { internal enum class NSNumberKind(val mappedKotlinClassId: ClassId?, val objCType: ObjCType) {
CHAR(PrimitiveType.BYTE, "char"), CHAR(PrimitiveType.BYTE, ObjCPrimitiveType.char),
UNSIGNED_CHAR(UnsignedType.UBYTE, "unsigned char"), UNSIGNED_CHAR(UnsignedType.UBYTE, ObjCPrimitiveType.unsigned_char),
SHORT(PrimitiveType.SHORT, "short"), SHORT(PrimitiveType.SHORT, ObjCPrimitiveType.short),
UNSIGNED_SHORT(UnsignedType.USHORT, "unsigned short"), UNSIGNED_SHORT(UnsignedType.USHORT, ObjCPrimitiveType.unsigned_short),
INT(PrimitiveType.INT, "int"), INT(PrimitiveType.INT, ObjCPrimitiveType.int),
UNSIGNED_INT(UnsignedType.UINT, "unsigned int"), UNSIGNED_INT(UnsignedType.UINT, ObjCPrimitiveType.unsigned_int),
LONG("long"), LONG(ObjCPrimitiveType.long),
UNSIGNED_LONG("unsigned long"), UNSIGNED_LONG(ObjCPrimitiveType.unsigned_long),
LONG_LONG(PrimitiveType.LONG, "long long"), LONG_LONG(PrimitiveType.LONG, ObjCPrimitiveType.long_long),
UNSIGNED_LONG_LONG(UnsignedType.ULONG, "unsigned long long"), UNSIGNED_LONG_LONG(UnsignedType.ULONG, ObjCPrimitiveType.unsigned_long_long),
FLOAT(PrimitiveType.FLOAT, "float"), FLOAT(PrimitiveType.FLOAT, ObjCPrimitiveType.float),
DOUBLE(PrimitiveType.DOUBLE, "double"), DOUBLE(PrimitiveType.DOUBLE, ObjCPrimitiveType.double),
BOOL(PrimitiveType.BOOLEAN, "BOOL"), BOOL(PrimitiveType.BOOLEAN, ObjCPrimitiveType.BOOL),
INTEGER("NSInteger"), INTEGER(ObjCPrimitiveType.NSInteger),
UNSIGNED_INTEGER("NSUInteger") UNSIGNED_INTEGER(ObjCPrimitiveType.NSUInteger)
; ;
@@ -347,20 +347,15 @@ internal enum class NSNumberKind(val mappedKotlinClassId: ClassId?, val objCType
val initSelector = "initWith${kindName.capitalize()}:" // initWithUnsignedShort: val initSelector = "initWith${kindName.capitalize()}:" // initWithUnsignedShort:
val factorySelector = "numberWith${kindName.capitalize()}:" // numberWithUnsignedShort: val factorySelector = "numberWith${kindName.capitalize()}:" // numberWithUnsignedShort:
constructor(
mappedKotlinClassId: ClassId?,
objCPrimitiveTypeName: String
) : this(mappedKotlinClassId, ObjCPrimitiveType(objCPrimitiveTypeName))
constructor( constructor(
primitiveType: PrimitiveType, primitiveType: PrimitiveType,
objCPrimitiveTypeName: String objCPrimitiveType: ObjCPrimitiveType
) : this(ClassId.topLevel(primitiveType.typeFqName), objCPrimitiveTypeName) ) : this(ClassId.topLevel(primitiveType.typeFqName), objCPrimitiveType)
constructor( constructor(
unsignedType: UnsignedType, unsignedType: UnsignedType,
objCPrimitiveTypeName: String objCPrimitiveType: ObjCPrimitiveType
) : this(unsignedType.classId, objCPrimitiveTypeName) ) : this(unsignedType.classId, objCPrimitiveType)
constructor(objCPrimitiveTypeName: String) : this(null, ObjCPrimitiveType(objCPrimitiveTypeName)) constructor(objCPrimitiveType: ObjCPrimitiveType) : this(null, objCPrimitiveType)
} }
@@ -93,9 +93,34 @@ object ObjCMetaClassType : ObjCNonNullReferenceType() {
override fun render(attrsAndName: String): String = "Class".withAttrsAndName(attrsAndName) override fun render(attrsAndName: String): String = "Class".withAttrsAndName(attrsAndName)
} }
class ObjCPrimitiveType( sealed class ObjCPrimitiveType(
val cName: String val cName: String
) : ObjCType() { ) : ObjCType() {
object NSUInteger : ObjCPrimitiveType("NSUInteger")
object BOOL : ObjCPrimitiveType("BOOL")
object unichar : ObjCPrimitiveType("unichar")
object int8_t : ObjCPrimitiveType("int8_t")
object int16_t : ObjCPrimitiveType("int16_t")
object int32_t : ObjCPrimitiveType("int32_t")
object int64_t : ObjCPrimitiveType("int64_t")
object uint8_t : ObjCPrimitiveType("uint8_t")
object uint16_t : ObjCPrimitiveType("uint16_t")
object uint32_t : ObjCPrimitiveType("uint32_t")
object uint64_t : ObjCPrimitiveType("uint64_t")
object float : ObjCPrimitiveType("float")
object double : ObjCPrimitiveType("double")
object NSInteger : ObjCPrimitiveType("NSInteger")
object char : ObjCPrimitiveType("char")
object unsigned_char: ObjCPrimitiveType("unsigned char")
object unsigned_short: ObjCPrimitiveType("unsigned short")
object int: ObjCPrimitiveType("int")
object unsigned_int: ObjCPrimitiveType("unsigned int")
object long: ObjCPrimitiveType("long")
object unsigned_long: ObjCPrimitiveType("unsigned long")
object long_long: ObjCPrimitiveType("long long")
object unsigned_long_long: ObjCPrimitiveType("unsigned long long")
object short: ObjCPrimitiveType("short")
override fun render(attrsAndName: String) = cName.withAttrsAndName(attrsAndName) override fun render(attrsAndName: String) = cName.withAttrsAndName(attrsAndName)
} }
@@ -5,13 +5,14 @@
package org.jetbrains.kotlin.backend.konan.objcexport package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.descriptors.ClassDescriptor import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
abstract class Stub<out D : DeclarationDescriptor>(val name: String) { abstract class Stub<out D : DeclarationDescriptor>(val name: String) {
abstract val descriptor: D? abstract val descriptor: D?
open val psi: PsiElement?
get() = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
} }
abstract class ObjCTopLevel<out D : DeclarationDescriptor>(name: String) : Stub<D>(name) abstract class ObjCTopLevel<out D : DeclarationDescriptor>(name: String) : Stub<D>(name)