[ObjCExport] Add extras to ObjCExportStub for proper @Throws translation

KT-66239
This commit is contained in:
eugene.levenetc
2024-03-01 10:38:40 +01:00
committed by Space Team
parent 42d8db1c52
commit ac1f664a65
6 changed files with 71 additions and 5 deletions
@@ -0,0 +1,15 @@
package org.jetbrains.kotlin.objcexport.extras
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportStub
import org.jetbrains.kotlin.tooling.core.Extras
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
internal object ObjCExportStubExtrasBuilderContext
/**
* Convenience function for building extras for [ObjCExportStub]
*/
internal fun objCExportStubExtras(builder: context(ObjCExportStubExtrasBuilderContext) MutableExtras.() -> Unit): Extras {
return mutableExtrasOf().also { extras -> builder(ObjCExportStubExtrasBuilderContext, extras) }
}
@@ -0,0 +1,25 @@
package org.jetbrains.kotlin.objcexport.extras
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportStub
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.extrasKeyOf
private val throwsAnnotationClassIdsKey = extrasKeyOf<List<ClassId>?>()
/**
* Functions and constructors can have [Throws] annotations which lists exceptions.
* This lists of exceptions needs to be translated and forwarded as dependencies
*/
internal val ObjCExportStub.throwsAnnotationClassIds: List<ClassId>?
get() {
extras[throwsAnnotationClassIdsKey]?.let { return it }
return null
}
context(ObjCExportStubExtrasBuilderContext)
internal var MutableExtras.throwsAnnotationClassIds: List<ClassId>?
get() = this[throwsAnnotationClassIdsKey]
set(value) {
this[throwsAnnotationClassIdsKey] = value
}
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.objcexport.KtObjCExportHeaderGenerator.QueueElement
import org.jetbrains.kotlin.objcexport.analysisApiUtils.*
import org.jetbrains.kotlin.objcexport.extras.originClassId
import org.jetbrains.kotlin.objcexport.extras.requiresForwardDeclaration
import org.jetbrains.kotlin.objcexport.extras.throwsAnnotationClassIds
import org.jetbrains.kotlin.psi.KtFile
@@ -181,6 +182,11 @@ private class KtObjCExportHeaderGenerator {
* and `Array` has to be registered as forward declaration.
*/
private fun enqueueDependencyClasses(stub: ObjCExportStub) {
symbolDeque += stub.closureSequence()
.flatMap { child -> child.throwsAnnotationClassIds.orEmpty() }
.map { QueueElement.Class(it) }
symbolDeque += stub.closureSequence()
.mapNotNull { child ->
when (child) {
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.objcexport.Predefined.anyMethodSelectors
import org.jetbrains.kotlin.objcexport.Predefined.anyMethodSwiftNames
import org.jetbrains.kotlin.objcexport.analysisApiUtils.*
import org.jetbrains.kotlin.objcexport.extras.objCExportStubExtras
import org.jetbrains.kotlin.objcexport.extras.throwsAnnotationClassIds
internal val KtCallableSymbol.isConstructor: Boolean
get() = this is KtConstructorSymbol
@@ -50,7 +52,8 @@ internal fun KtFunctionLikeSymbol.buildObjCMethod(
val swiftName = getSwiftName(bridge)
val attributes = mutableListOf<String>()
val returnBridge = bridge.returnBridge
val comment = this.translateToObjCComment(bridge, parameters)
val comment = translateToObjCComment(bridge, parameters)
val throws = definedThrows.map { it }.toList()
attributes += getSwiftPrivateAttribute() ?: swiftNameAttribute(swiftName)
@@ -81,7 +84,10 @@ internal fun KtFunctionLikeSymbol.buildObjCMethod(
returnType = returnType,
selectors = selectors,
parameters = parameters,
attributes = attributes
attributes = attributes,
extras = objCExportStubExtras {
throwsAnnotationClassIds = throws
}
)
}
@@ -257,7 +263,6 @@ fun MethodBridge.valueParametersAssociated(
function: KtFunctionLikeSymbol,
): List<Pair<MethodBridgeValueParameter, KtValueParameterSymbol?>> {
val allParameters = function.valueParameters
if (allParameters.isEmpty()) return emptyList()
return this.valueParameters.mapIndexed { index, valueParameterBridge ->
when (valueParameterBridge) {
@@ -36,6 +36,8 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.LocalRedeclarationChecker
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.tooling.core.Extras
import org.jetbrains.kotlin.tooling.core.emptyExtras
import org.jetbrains.kotlin.types.error.ErrorUtils
interface ObjCExportLazy {
@@ -325,6 +327,7 @@ class ObjCExportLazyImpl(
name: ObjCExportNamer.ClassOrProtocolName,
private val psi: KtClassOrObject,
private val lazy: ObjCExportLazyImpl,
override val extras: Extras = emptyExtras(),
) : LazyObjCProtocol(name) {
private val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
@@ -339,6 +342,7 @@ class ObjCExportLazyImpl(
generics: List<ObjCGenericTypeDeclaration>,
private val psi: KtClassOrObject,
private val lazy: ObjCExportLazyImpl,
override val extras: Extras = emptyExtras(),
) : LazyObjCInterface(name = name, generics = generics, categoryName = null, attributes = attributes) {
private val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
@@ -352,6 +356,7 @@ class ObjCExportLazyImpl(
private val file: KtFile,
private val declarations: List<KtCallableDeclaration>,
private val lazy: ObjCExportLazyImpl,
override val extras: Extras = emptyExtras(),
) : LazyObjCInterface(name = name, generics = emptyList(), categoryName = null, attributes = listOf(OBJC_SUBCLASSING_RESTRICTED)) {
override val origin: Nothing? = null
@@ -372,6 +377,7 @@ class ObjCExportLazyImpl(
private val classDescriptor: ClassDescriptor,
private val declarations: List<KtCallableDeclaration>,
private val lazy: ObjCExportLazyImpl,
override val extras: Extras = emptyExtras(),
) : LazyObjCInterface(name = name.objCName, generics = emptyList(), categoryName = categoryName, attributes = emptyList()) {
override fun computeRealStub(): ObjCInterface = lazy.translator.translateExtensions(
@@ -7,11 +7,15 @@
package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.tooling.core.Extras
import org.jetbrains.kotlin.tooling.core.HasExtras
import org.jetbrains.kotlin.tooling.core.emptyExtras
@Deprecated("Use 'ObjCExportStub' instead", replaceWith = ReplaceWith("ObjCExportStub"))
@Suppress("unused")
typealias Stub<@Suppress("UNUSED_TYPEALIAS_PARAMETER") T> = ObjCExportStub
sealed interface ObjCExportStub {
sealed interface ObjCExportStub : HasExtras {
/**
* The ObjC name of this entity;
* Note: The original 'Kotlin Name' can be found in [origin]
@@ -72,6 +76,7 @@ class ObjCProtocolImpl(
override val attributes: List<String>,
override val superProtocols: List<String>,
override val members: List<ObjCExportStub>,
override val extras: Extras = emptyExtras(),
) : ObjCProtocol()
class ObjCInterfaceImpl(
@@ -85,6 +90,7 @@ class ObjCInterfaceImpl(
override val generics: List<ObjCGenericTypeDeclaration>,
override val superClass: String?,
override val superClassGenerics: List<ObjCNonNullReferenceType>,
override val extras: Extras = emptyExtras(),
) : ObjCInterface()
class ObjCMethod(
@@ -95,6 +101,7 @@ class ObjCMethod(
val selectors: List<String>,
val parameters: List<ObjCParameter>,
val attributes: List<String>,
override val extras: Extras = emptyExtras(),
) : ObjCExportStub {
override val name: String = buildMethodName(selectors, parameters)
}
@@ -103,7 +110,8 @@ class ObjCParameter(
override val name: String,
override val origin: ObjCExportStubOrigin?,
val type: ObjCType,
val todo: Nothing?
val todo: Nothing?,
override val extras: Extras = emptyExtras(),
) : ObjCExportStub {
override val comment: Nothing? = null
}
@@ -117,6 +125,7 @@ class ObjCProperty(
val setterName: String? = null,
val getterName: String? = null,
val declarationAttributes: List<String> = emptyList(),
override val extras: Extras = emptyExtras(),
) : ObjCExportStub
private fun buildMethodName(selectors: List<String>, parameters: List<ObjCParameter>): String =