From ac1f664a65c17cdd5da980d27841af48f0db35be Mon Sep 17 00:00:00 2001 From: "eugene.levenetc" Date: Fri, 1 Mar 2024 10:38:40 +0100 Subject: [PATCH] [ObjCExport] Add extras to ObjCExportStub for proper @Throws translation KT-66239 --- .../objcexport/extras/objCExportStubExtras.kt | 15 +++++++++++ .../extras/throwsAnnotationClassIds.kt | 25 +++++++++++++++++++ .../objcexport/translateToObjCHeader.kt | 6 +++++ .../objcexport/translateToObjCMethod.kt | 11 +++++--- .../konan/objcexport/ObjCExportLazy.kt | 6 +++++ .../kotlin/backend/konan/objcexport/stubs.kt | 13 ++++++++-- 6 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/objCExportStubExtras.kt create mode 100644 native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/throwsAnnotationClassIds.kt diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/objCExportStubExtras.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/objCExportStubExtras.kt new file mode 100644 index 00000000000..0841285e342 --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/objCExportStubExtras.kt @@ -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) } +} \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/throwsAnnotationClassIds.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/throwsAnnotationClassIds.kt new file mode 100644 index 00000000000..ab94974b89b --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/extras/throwsAnnotationClassIds.kt @@ -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?>() + +/** + * 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? + get() { + extras[throwsAnnotationClassIdsKey]?.let { return it } + return null + } + +context(ObjCExportStubExtrasBuilderContext) +internal var MutableExtras.throwsAnnotationClassIds: List? + get() = this[throwsAnnotationClassIdsKey] + set(value) { + this[throwsAnnotationClassIdsKey] = value + } \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt index dfc54508396..beb3f3a8bea 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt @@ -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) { diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt index eb290edefc8..cb81fcdfa23 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt @@ -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() 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> { val allParameters = function.valueParameters - if (allParameters.isEmpty()) return emptyList() return this.valueParameters.mapIndexed { index, valueParameterBridge -> when (valueParameterBridge) { diff --git a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt index 9282393c4af..b41f9712c5b 100644 --- a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt +++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt @@ -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, 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, 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, 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( diff --git a/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt index 9b8029d76d2..3460fa375f5 100644 --- a/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt +++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt @@ -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, override val superProtocols: List, override val members: List, + override val extras: Extras = emptyExtras(), ) : ObjCProtocol() class ObjCInterfaceImpl( @@ -85,6 +90,7 @@ class ObjCInterfaceImpl( override val generics: List, override val superClass: String?, override val superClassGenerics: List, + override val extras: Extras = emptyExtras(), ) : ObjCInterface() class ObjCMethod( @@ -95,6 +101,7 @@ class ObjCMethod( val selectors: List, val parameters: List, val attributes: List, + 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 = emptyList(), + override val extras: Extras = emptyExtras(), ) : ObjCExportStub private fun buildMethodName(selectors: List, parameters: List): String =