[ObjCExport] ObjCExportStub: Do not retain reference to descriptor
FL-23390 ^KT-64076 Fixed
This commit is contained in:
committed by
Space Team
parent
e97463afb3
commit
3e57265fcb
+24
-19
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
interface ObjCExportTranslator {
|
||||
fun generateBaseDeclarations(): List<ObjCTopLevel<*>>
|
||||
fun generateBaseDeclarations(): List<ObjCTopLevel>
|
||||
fun getClassIfExtension(receiverType: KotlinType): ClassDescriptor?
|
||||
fun translateFile(file: SourceFile, declarations: List<CallableMemberDescriptor>): ObjCInterface
|
||||
fun translateClass(descriptor: ClassDescriptor): ObjCInterface
|
||||
@@ -66,7 +66,7 @@ class ObjCExportTranslatorImpl(
|
||||
|
||||
private val kotlinAnyName = namer.kotlinAnyName
|
||||
|
||||
override fun generateBaseDeclarations(): List<ObjCTopLevel<*>> = buildTopLevel {
|
||||
override fun generateBaseDeclarations(): List<ObjCTopLevel> = buildTopLevel {
|
||||
add {
|
||||
objCInterface(namer.kotlinAnyName, superClass = "NSObject", members = buildMembers {
|
||||
add { ObjCMethod(null, true, ObjCInstanceType, listOf("init"), emptyList(), listOf("unavailable")) }
|
||||
@@ -116,7 +116,7 @@ class ObjCExportTranslatorImpl(
|
||||
genKotlinNumbers()
|
||||
}
|
||||
|
||||
private fun StubBuilder<ObjCTopLevel<*>>.genKotlinNumbers() {
|
||||
private fun StubBuilder<ObjCTopLevel>.genKotlinNumbers() {
|
||||
val members = buildMembers {
|
||||
NSNumberKind.entries.forEach {
|
||||
add { nsNumberFactory(it, listOf("unavailable")) }
|
||||
@@ -240,7 +240,7 @@ class ObjCExportTranslatorImpl(
|
||||
}
|
||||
|
||||
val name = translateClassOrInterfaceName(descriptor)
|
||||
val members: List<Stub<*>> = buildMembers { translateInterfaceMembers(descriptor) }
|
||||
val members: List<ObjCExportStub> = buildMembers { translateInterfaceMembers(descriptor) }
|
||||
val superProtocols: List<String> = descriptor.superProtocols
|
||||
val comment = objCCommentOrNull(mustBeDocumentedAttributeList(descriptor.annotations))
|
||||
|
||||
@@ -315,7 +315,7 @@ class ObjCExportTranslatorImpl(
|
||||
}
|
||||
|
||||
val superProtocols: List<String> = descriptor.superProtocols
|
||||
val members: List<Stub<*>> = buildMembers {
|
||||
val members: List<ObjCExportStub> = buildMembers {
|
||||
val presentConstructors = mutableSetOf<String>()
|
||||
|
||||
descriptor.constructors
|
||||
@@ -510,12 +510,12 @@ class ObjCExportTranslatorImpl(
|
||||
.filter { mapper.shouldBeExposed(it) }
|
||||
.toList()
|
||||
|
||||
private fun StubBuilder<Stub<*>>.translateClassMembers(descriptor: ClassDescriptor, objCExportScope: ObjCExportScope) {
|
||||
private fun StubBuilder<ObjCExportStub>.translateClassMembers(descriptor: ClassDescriptor, objCExportScope: ObjCExportScope) {
|
||||
require(!descriptor.isInterface)
|
||||
translateClassMembers(descriptor.getExposedMembers(), objCExportScope)
|
||||
}
|
||||
|
||||
private fun StubBuilder<Stub<*>>.translateInterfaceMembers(descriptor: ClassDescriptor) {
|
||||
private fun StubBuilder<ObjCExportStub>.translateInterfaceMembers(descriptor: ClassDescriptor) {
|
||||
require(descriptor.isInterface)
|
||||
translateBaseMembers(descriptor.getExposedMembers())
|
||||
}
|
||||
@@ -536,7 +536,7 @@ class ObjCExportTranslatorImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun StubBuilder<Stub<*>>.translateClassMembers(
|
||||
private fun StubBuilder<ObjCExportStub>.translateClassMembers(
|
||||
members: List<CallableMemberDescriptor>,
|
||||
objCExportScope: ObjCExportScope,
|
||||
) {
|
||||
@@ -569,7 +569,7 @@ class ObjCExportTranslatorImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun StubBuilder<Stub<*>>.translateBaseMembers(members: List<CallableMemberDescriptor>) {
|
||||
private fun StubBuilder<ObjCExportStub>.translateBaseMembers(members: List<CallableMemberDescriptor>) {
|
||||
// TODO: add some marks about modality.
|
||||
|
||||
val methods = mutableListOf<FunctionDescriptor>()
|
||||
@@ -593,7 +593,10 @@ class ObjCExportTranslatorImpl(
|
||||
translatePlainMembers(methods, properties, ObjCRootExportScope)
|
||||
}
|
||||
|
||||
private fun StubBuilder<Stub<*>>.translatePlainMembers(members: List<CallableMemberDescriptor>, objCExportScope: ObjCExportScope) {
|
||||
private fun StubBuilder<ObjCExportStub>.translatePlainMembers(
|
||||
members: List<CallableMemberDescriptor>,
|
||||
objCExportScope: ObjCExportScope,
|
||||
) {
|
||||
val methods = mutableListOf<FunctionDescriptor>()
|
||||
val properties = mutableListOf<PropertyDescriptor>()
|
||||
|
||||
@@ -604,7 +607,7 @@ class ObjCExportTranslatorImpl(
|
||||
translatePlainMembers(methods, properties, objCExportScope)
|
||||
}
|
||||
|
||||
private fun StubBuilder<Stub<*>>.translatePlainMembers(
|
||||
private fun StubBuilder<ObjCExportStub>.translatePlainMembers(
|
||||
methods: List<FunctionDescriptor>,
|
||||
properties: List<PropertyDescriptor>,
|
||||
objCExportScope: ObjCExportScope,
|
||||
@@ -804,8 +807,10 @@ class ObjCExportTranslatorImpl(
|
||||
} else emptyList()
|
||||
|
||||
val visibilityComments = visibilityComments(method.visibility, "method")
|
||||
val paramComments = parameters.flatMap { parameter ->
|
||||
parameter.descriptor?.let { mustBeDocumentedParamAttributeList(parameter, descriptor = it) } ?: emptyList()
|
||||
val paramComments = method.valueParameters.flatMap { parameterDescriptor ->
|
||||
parameters.find { parameter -> parameter.origin?.name == parameterDescriptor.name }?.let { parameter ->
|
||||
mustBeDocumentedParamAttributeList(parameter, descriptor = parameterDescriptor)
|
||||
} ?: emptyList()
|
||||
}
|
||||
val annotationsComments = mustBeDocumentedAttributeList(method.annotations)
|
||||
return objCCommentOrNull(annotationsComments + paramComments + throwsComments + visibilityComments)
|
||||
@@ -1118,9 +1123,9 @@ class ObjCExportTranslatorImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun buildTopLevel(block: StubBuilder<ObjCTopLevel<*>>.() -> Unit) = buildStubs(block)
|
||||
private inline fun buildMembers(block: StubBuilder<Stub<*>>.() -> Unit) = buildStubs(block)
|
||||
private inline fun <S : Stub<*>> buildStubs(block: StubBuilder<S>.() -> Unit): List<S> =
|
||||
private inline fun buildTopLevel(block: StubBuilder<ObjCTopLevel>.() -> Unit) = buildStubs(block)
|
||||
private inline fun buildMembers(block: StubBuilder<ObjCExportStub>.() -> Unit) = buildStubs(block)
|
||||
private inline fun <S : ObjCExportStub> buildStubs(block: StubBuilder<S>.() -> Unit): List<S> =
|
||||
StubBuilder<S>(problemCollector).apply(block).build()
|
||||
}
|
||||
|
||||
@@ -1131,7 +1136,7 @@ abstract class ObjCExportHeaderGenerator @InternalKotlinNativeApi constructor(
|
||||
val objcGenerics: Boolean,
|
||||
problemCollector: ObjCExportProblemCollector,
|
||||
) {
|
||||
private val stubs = mutableListOf<Stub<*>>()
|
||||
private val stubs = mutableListOf<ObjCExportStub>()
|
||||
|
||||
private val classForwardDeclarations = linkedSetOf<ObjCClassForwardDeclaration>()
|
||||
private val protocolForwardDeclarations = linkedSetOf<String>()
|
||||
@@ -1419,7 +1424,7 @@ private fun objCInterface(
|
||||
superClass: String? = null,
|
||||
superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
||||
superProtocols: List<String> = emptyList(),
|
||||
members: List<Stub<*>> = emptyList(),
|
||||
members: List<ObjCExportStub> = emptyList(),
|
||||
attributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
): ObjCInterface = ObjCInterfaceImpl(
|
||||
@@ -1439,7 +1444,7 @@ private fun objCProtocol(
|
||||
name: ObjCExportNamer.ClassOrProtocolName,
|
||||
descriptor: ClassDescriptor,
|
||||
superProtocols: List<String>,
|
||||
members: List<Stub<*>>,
|
||||
members: List<ObjCExportStub>,
|
||||
attributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
): ObjCProtocol = ObjCProtocolImpl(
|
||||
|
||||
+32
-41
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.backend.konan.InternalKotlinNativeApi
|
||||
import org.jetbrains.kotlin.backend.konan.UnitSuspendFunctionObjCExport
|
||||
@@ -54,9 +53,9 @@ interface ObjCExportLazy {
|
||||
get() = false
|
||||
}
|
||||
|
||||
fun generateBase(): List<ObjCTopLevel<*>>
|
||||
fun generateBase(): List<ObjCTopLevel>
|
||||
|
||||
fun translate(file: KtFile): List<ObjCTopLevel<*>>
|
||||
fun translate(file: KtFile): List<ObjCTopLevel>
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
@@ -113,11 +112,11 @@ class ObjCExportLazyImpl(
|
||||
|
||||
override fun generateBase() = translator.generateBaseDeclarations()
|
||||
|
||||
override fun translate(file: KtFile): List<ObjCTopLevel<*>> =
|
||||
override fun translate(file: KtFile): List<ObjCTopLevel> =
|
||||
translateClasses(file) + translateTopLevels(file)
|
||||
|
||||
private fun translateClasses(container: KtDeclarationContainer): List<ObjCClass<*>> {
|
||||
val result = mutableListOf<ObjCClass<*>>()
|
||||
private fun translateClasses(container: KtDeclarationContainer): List<ObjCClass> {
|
||||
val result = mutableListOf<ObjCClass>()
|
||||
container.declarations.forEach { declaration ->
|
||||
// Supposed to be true if ObjCExportMapper.shouldBeVisible is true.
|
||||
if (declaration is KtClassOrObject && declaration.isPublic && declaration !is KtEnumEntry
|
||||
@@ -136,7 +135,7 @@ class ObjCExportLazyImpl(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun translateClass(ktClassOrObject: KtClassOrObject): ObjCClass<*> {
|
||||
private fun translateClass(ktClassOrObject: KtClassOrObject): ObjCClass {
|
||||
val name = nameTranslator.getClassOrProtocolName(ktClassOrObject)
|
||||
|
||||
// Note: some attributes may be missing (e.g. "unavailable" for unexposed classes).
|
||||
@@ -324,13 +323,12 @@ class ObjCExportLazyImpl(
|
||||
|
||||
private class LazyObjCProtocolImpl(
|
||||
name: ObjCExportNamer.ClassOrProtocolName,
|
||||
override val psi: KtClassOrObject,
|
||||
private val psi: KtClassOrObject,
|
||||
private val lazy: ObjCExportLazyImpl,
|
||||
) : LazyObjCProtocol(name) {
|
||||
override val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
|
||||
private val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
|
||||
|
||||
override val isValid: Boolean
|
||||
get() = lazy.isValid
|
||||
override val origin: ObjCExportStubOrigin? by lazy { ObjCExportStubOrigin(descriptor) }
|
||||
|
||||
override fun computeRealStub(): ObjCProtocol = lazy.translator.translateInterface(descriptor)
|
||||
}
|
||||
@@ -339,13 +337,12 @@ class ObjCExportLazyImpl(
|
||||
name: ObjCExportNamer.ClassOrProtocolName,
|
||||
attributes: List<String>,
|
||||
generics: List<ObjCGenericTypeDeclaration>,
|
||||
override val psi: KtClassOrObject,
|
||||
private 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) }
|
||||
private val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) }
|
||||
|
||||
override val isValid: Boolean
|
||||
get() = lazy.isValid
|
||||
override val origin: ObjCExportStubOrigin? by lazy { ObjCExportStubOrigin(descriptor) }
|
||||
|
||||
override fun computeRealStub(): ObjCInterface = lazy.translator.translateClass(descriptor)
|
||||
}
|
||||
@@ -356,14 +353,8 @@ class ObjCExportLazyImpl(
|
||||
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 isValid: Boolean
|
||||
get() = lazy.isValid
|
||||
|
||||
override val psi: PsiElement?
|
||||
get() = null
|
||||
override val origin: Nothing? = null
|
||||
|
||||
override fun computeRealStub(): ObjCInterface = lazy.translator.translateFile(
|
||||
PsiSourceFile(file),
|
||||
@@ -382,14 +373,8 @@ class ObjCExportLazyImpl(
|
||||
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 isValid: Boolean
|
||||
get() = lazy.isValid
|
||||
|
||||
override val psi: PsiElement?
|
||||
get() = null
|
||||
override val origin: ObjCExportStubOrigin? = ObjCExportStubOrigin(classDescriptor)
|
||||
|
||||
override fun computeRealStub(): ObjCInterface = lazy.translator.translateExtensions(
|
||||
classDescriptor,
|
||||
@@ -400,27 +385,25 @@ class ObjCExportLazyImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class LazyObjCInterface : ObjCInterface {
|
||||
private abstract class LazyObjCInterface(
|
||||
override val name: String,
|
||||
override val generics: List<ObjCGenericTypeDeclaration>,
|
||||
override val categoryName: String?,
|
||||
override val attributes: List<String>,
|
||||
) : ObjCInterface() {
|
||||
|
||||
constructor(
|
||||
name: ObjCExportNamer.ClassOrProtocolName,
|
||||
generics: List<ObjCGenericTypeDeclaration>,
|
||||
categoryName: String?,
|
||||
attributes: List<String>,
|
||||
) : super(name.objCName, generics, categoryName, attributes + name.toNameAttributes())
|
||||
|
||||
constructor(
|
||||
name: String,
|
||||
generics: List<ObjCGenericTypeDeclaration>,
|
||||
categoryName: String,
|
||||
attributes: List<String>,
|
||||
) : super(name, generics, categoryName, attributes)
|
||||
) : this(name.objCName, generics, categoryName, attributes + name.toNameAttributes())
|
||||
|
||||
protected abstract fun computeRealStub(): ObjCInterface
|
||||
|
||||
private val realStub by lazy { computeRealStub() }
|
||||
|
||||
override val members: List<Stub<*>>
|
||||
override val members: List<ObjCExportStub>
|
||||
get() = realStub.members
|
||||
|
||||
override val superProtocols: List<String>
|
||||
@@ -431,17 +414,25 @@ private abstract class LazyObjCInterface : ObjCInterface {
|
||||
|
||||
override val superClassGenerics: List<ObjCNonNullReferenceType>
|
||||
get() = realStub.superClassGenerics
|
||||
|
||||
final override val comment: Nothing? = null
|
||||
}
|
||||
|
||||
private abstract class LazyObjCProtocol(
|
||||
name: ObjCExportNamer.ClassOrProtocolName,
|
||||
) : ObjCProtocol(name.objCName, name.toNameAttributes()) {
|
||||
) : ObjCProtocol() {
|
||||
|
||||
override val name: String = name.objCName
|
||||
|
||||
override val comment: Nothing? = null
|
||||
|
||||
override val attributes: List<String> = name.toNameAttributes()
|
||||
|
||||
protected abstract fun computeRealStub(): ObjCProtocol
|
||||
|
||||
private val realStub by lazy { computeRealStub() }
|
||||
|
||||
override val members: List<Stub<*>>
|
||||
override val members: List<ObjCExportStub>
|
||||
get() = realStub.members
|
||||
|
||||
override val superProtocols: List<String>
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.common.serialization.extractSerializedKdocString
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.findKDocString
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.descriptors.DeserializedDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
|
||||
fun ObjCExportStubOrigin(descriptor: DeclarationDescriptor?): ObjCExportStubOrigin? {
|
||||
if (descriptor == null) return null
|
||||
|
||||
if (descriptor is DeclarationDescriptorWithSource) {
|
||||
return ObjCExportStubOrigin.Source(descriptor.name, descriptor.findKDocString(), (descriptor.source as? PsiSourceElement)?.psi)
|
||||
}
|
||||
|
||||
assert(descriptor is DeserializedDescriptor) { "Expected '$descriptor' to implement ${DeserializedDescriptor::class.simpleName}" }
|
||||
return ObjCExportStubOrigin.Binary(descriptor.name, descriptor.extractSerializedKdocString())
|
||||
}
|
||||
|
||||
sealed class ObjCExportStubOrigin {
|
||||
|
||||
/**
|
||||
* The original 'Kotlin' name of the entity that is associated with this stub
|
||||
*/
|
||||
abstract val name: Name?
|
||||
|
||||
/**
|
||||
* The original 'Kotlin documentation' of the associated with this stub
|
||||
*/
|
||||
abstract val kdoc: String?
|
||||
|
||||
/**
|
||||
* The stub was produced from Kotlin sources
|
||||
*/
|
||||
data class Source(override val name: Name?, override val kdoc: String?, val psi: PsiElement?) : ObjCExportStubOrigin()
|
||||
|
||||
/**
|
||||
* The stub was produced from a compiled binary (e.g. when translating a dependency inside fleet).
|
||||
* Note: On CLI invocations, the ObjC export will only operate on binaries.
|
||||
*/
|
||||
data class Binary(override val name: Name?, override val kdoc: String?) : ObjCExportStubOrigin()
|
||||
}
|
||||
+1
-1
@@ -8,5 +8,5 @@ package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
data class ObjCExportedStubs(
|
||||
val classForwardDeclarations: Set<ObjCClassForwardDeclaration>,
|
||||
val protocolForwardDeclarations: Set<String>,
|
||||
val stubs: List<Stub<*>>,
|
||||
val stubs: List<ObjCExportStub>,
|
||||
)
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
|
||||
internal class StubBuilder<S : Stub<*>>(private val problemCollector: ObjCExportProblemCollector) {
|
||||
internal class StubBuilder<S : ObjCExportStub>(private val problemCollector: ObjCExportProblemCollector) {
|
||||
private val children = mutableListOf<S>()
|
||||
|
||||
inline fun add(provider: () -> S) {
|
||||
|
||||
+5
-16
@@ -5,14 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.extractSerializedKdocString
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.findKDocString
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
|
||||
object StubRenderer {
|
||||
fun render(stub: Stub<*>): List<String> = render(stub, false)
|
||||
fun render(stub: ObjCExportStub): List<String> = render(stub, false)
|
||||
|
||||
private fun findPositionToInsertGeneratedCommentLine(kDoc: List<String>, generatedCommentLine: String): Int {
|
||||
val generatedWords = generatedCommentLine.trim().split(" ").map { it.trim() }
|
||||
@@ -27,7 +21,7 @@ object StubRenderer {
|
||||
return kDoc.size
|
||||
}
|
||||
|
||||
internal fun render(stub: Stub<*>, shouldExportKDoc: Boolean): List<String> = collect {
|
||||
internal fun render(stub: ObjCExportStub, shouldExportKDoc: Boolean): List<String> = collect {
|
||||
stub.run {
|
||||
val (kDocEnding, commentBlockEnding) = if (comment?.contentLines == null) {
|
||||
Pair("*/", null) // Close kDoc with `*/`, and print nothing after empty comment
|
||||
@@ -35,7 +29,7 @@ object StubRenderer {
|
||||
Pair("", "*/") // Don't terminate kDoc, though close comment block with `*/`
|
||||
}
|
||||
val kDoc = if (shouldExportKDoc) {
|
||||
descriptor?.extractKDocString()?.let {
|
||||
origin?.kdoc?.let {
|
||||
if (it.startsWith("/**") && it.endsWith("*/")) {
|
||||
// Nested comment is allowed inside of preformatted ``` block in kdoc but not in ObjC
|
||||
val kdocClean = "/**${it.substring(3, it.length - 2).replace("*/", "**").replace("/*", "**")}$kDocEnding"
|
||||
@@ -182,7 +176,7 @@ object StubRenderer {
|
||||
appendSuperProtocols(this@renderProtocolHeader)
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendSuperProtocols(clazz: ObjCClass<ClassDescriptor>) {
|
||||
private fun StringBuilder.appendSuperProtocols(clazz: ObjCClass) {
|
||||
val protocols = clazz.superProtocols
|
||||
if (protocols.isNotEmpty()) {
|
||||
protocols.joinTo(this, separator = ", ", prefix = " <", postfix = ">")
|
||||
@@ -215,7 +209,7 @@ object StubRenderer {
|
||||
appendSuperProtocols(this@renderInterfaceHeader)
|
||||
}
|
||||
|
||||
private fun Collector.renderMembers(clazz: ObjCClass<*>, shouldExportKDoc: Boolean) {
|
||||
private fun Collector.renderMembers(clazz: ObjCClass, shouldExportKDoc: Boolean) {
|
||||
clazz.members.forEach {
|
||||
+render(it, shouldExportKDoc)
|
||||
}
|
||||
@@ -248,8 +242,3 @@ fun formatGenerics(buffer: Appendable, generics: List<Any>) {
|
||||
generics.joinTo(buffer, separator = ", ", prefix = "<", postfix = ">")
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.extractKDocString(): String? {
|
||||
return (this as? DeclarationDescriptorWithSource)?.findKDocString()
|
||||
?: extractSerializedKdocString()
|
||||
}
|
||||
|
||||
+170
-69
@@ -3,15 +3,63 @@
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
@file:JvmName("ObjCExportStubKt")
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
|
||||
@Deprecated("Use 'ObjCExportStub' instead", replaceWith = ReplaceWith("ObjCExportStub"))
|
||||
@Suppress("unused")
|
||||
typealias Stub<@Suppress("UNUSED_TYPEALIAS_PARAMETER") T> = ObjCExportStub
|
||||
|
||||
sealed interface ObjCExportStub {
|
||||
/**
|
||||
* The ObjC name of this entity;
|
||||
* Note: The original 'Kotlin Name' can be found in [origin]
|
||||
*/
|
||||
val name: String
|
||||
|
||||
val comment: ObjCComment?
|
||||
|
||||
|
||||
/**
|
||||
* Leaves breadcrumbs, minimal information, about the origin of this stub.
|
||||
* A [origin] can either be
|
||||
* - [ObjCExportStubOrigin.Source] indicating that the stub was produced from Source Code (happens inside the IDE)
|
||||
* - [ObjCExportStubOrigin.Binary] indicating that the stub was produced by deserializing a klib (Note: CLI only works in this mode)
|
||||
* - null: Indicating that we not provide information about the origin of this stub. This can happen e.g.
|
||||
* if the stub is just synthetically created by this tool.
|
||||
*/
|
||||
val origin: ObjCExportStubOrigin?
|
||||
}
|
||||
|
||||
val ObjCExportStub.psiOrNull
|
||||
get() = when (val origin = origin) {
|
||||
is ObjCExportStubOrigin.Source -> origin.psi
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
abstract class ObjCTopLevel : ObjCExportStub
|
||||
|
||||
sealed class ObjCClass : ObjCTopLevel() {
|
||||
abstract val attributes: List<String>
|
||||
abstract val superProtocols: List<String>
|
||||
abstract val members: List<ObjCExportStub>
|
||||
}
|
||||
|
||||
abstract class ObjCProtocol : ObjCClass()
|
||||
|
||||
abstract class ObjCInterface : ObjCClass() {
|
||||
abstract val categoryName: String?
|
||||
abstract val generics: List<ObjCGenericTypeDeclaration>
|
||||
abstract val superClass: String?
|
||||
abstract val superClassGenerics: List<ObjCNonNullReferenceType>
|
||||
}
|
||||
|
||||
class ObjCComment(val contentLines: List<String>) {
|
||||
constructor(vararg contentLines: String) : this(contentLines.toList())
|
||||
@@ -22,93 +70,146 @@ data class ObjCClassForwardDeclaration(
|
||||
val typeDeclarations: List<ObjCGenericTypeDeclaration> = emptyList(),
|
||||
)
|
||||
|
||||
abstract class Stub<out D : DeclarationDescriptor>(val name: String, val comment: ObjCComment? = null) {
|
||||
abstract val descriptor: D?
|
||||
open val psi: PsiElement?
|
||||
get() = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
|
||||
open val isValid: Boolean
|
||||
get() = descriptor?.module?.isValid ?: true
|
||||
}
|
||||
|
||||
abstract class ObjCTopLevel<out D : DeclarationDescriptor>(name: String, comment: ObjCComment? = null) : Stub<D>(name, comment)
|
||||
|
||||
abstract class ObjCClass<out D : DeclarationDescriptor>(
|
||||
name: String,
|
||||
val attributes: List<String>,
|
||||
comment: ObjCComment? = null,
|
||||
) : ObjCTopLevel<D>(name, comment) {
|
||||
abstract val superProtocols: List<String>
|
||||
abstract val members: List<Stub<*>>
|
||||
}
|
||||
|
||||
abstract class ObjCProtocol(
|
||||
name: String,
|
||||
attributes: List<String>,
|
||||
comment: ObjCComment? = null,
|
||||
) : ObjCClass<ClassDescriptor>(name, attributes, comment)
|
||||
|
||||
class ObjCProtocolImpl(
|
||||
name: String,
|
||||
override val descriptor: ClassDescriptor,
|
||||
override val name: String,
|
||||
override val comment: ObjCComment?,
|
||||
override val origin: ObjCExportStubOrigin?,
|
||||
override val attributes: List<String>,
|
||||
override val superProtocols: List<String>,
|
||||
override val members: List<Stub<*>>,
|
||||
attributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
) : ObjCProtocol(name, attributes, comment)
|
||||
|
||||
abstract class ObjCInterface(
|
||||
name: String,
|
||||
val generics: List<ObjCGenericTypeDeclaration>,
|
||||
val categoryName: String?,
|
||||
attributes: List<String>,
|
||||
comment: ObjCComment? = null,
|
||||
) : ObjCClass<ClassDescriptor>(name, attributes, comment) {
|
||||
abstract val superClass: String?
|
||||
abstract val superClassGenerics: List<ObjCNonNullReferenceType>
|
||||
override val members: List<ObjCExportStub>,
|
||||
) : ObjCProtocol() {
|
||||
constructor(
|
||||
name: String,
|
||||
descriptor: ClassDescriptor,
|
||||
superProtocols: List<String>,
|
||||
members: List<ObjCExportStub>,
|
||||
attributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
) : this(
|
||||
name = name,
|
||||
comment = comment,
|
||||
origin = ObjCExportStubOrigin(descriptor),
|
||||
attributes = attributes,
|
||||
superProtocols = superProtocols,
|
||||
members = members
|
||||
)
|
||||
}
|
||||
|
||||
class ObjCInterfaceImpl(
|
||||
name: String,
|
||||
generics: List<ObjCGenericTypeDeclaration> = emptyList(),
|
||||
override val descriptor: ClassDescriptor? = null,
|
||||
override val superClass: String? = null,
|
||||
override val superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
||||
override val superProtocols: List<String> = emptyList(),
|
||||
categoryName: String? = null,
|
||||
override val members: List<Stub<*>> = emptyList(),
|
||||
attributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
) : ObjCInterface(name, generics, categoryName, attributes, comment)
|
||||
override val name: String,
|
||||
override val comment: ObjCComment?,
|
||||
override val origin: ObjCExportStubOrigin?,
|
||||
override val attributes: List<String>,
|
||||
override val superProtocols: List<String>,
|
||||
override val members: List<ObjCExportStub>,
|
||||
override val categoryName: String?,
|
||||
override val generics: List<ObjCGenericTypeDeclaration>,
|
||||
override val superClass: String?,
|
||||
override val superClassGenerics: List<ObjCNonNullReferenceType>,
|
||||
) : ObjCInterface() {
|
||||
constructor(
|
||||
name: String,
|
||||
generics: List<ObjCGenericTypeDeclaration> = emptyList(),
|
||||
descriptor: ClassDescriptor? = null,
|
||||
superClass: String? = null,
|
||||
superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
||||
superProtocols: List<String> = emptyList(),
|
||||
categoryName: String? = null,
|
||||
members: List<ObjCExportStub> = emptyList(),
|
||||
attributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
) : this(
|
||||
name = name,
|
||||
comment = comment,
|
||||
origin = ObjCExportStubOrigin(descriptor),
|
||||
attributes = attributes,
|
||||
superProtocols = superProtocols,
|
||||
members = members,
|
||||
categoryName = categoryName,
|
||||
generics = generics,
|
||||
superClass = superClass,
|
||||
superClassGenerics = superClassGenerics
|
||||
)
|
||||
}
|
||||
|
||||
class ObjCMethod(
|
||||
override val descriptor: DeclarationDescriptor?,
|
||||
override val comment: ObjCComment?,
|
||||
override val origin: ObjCExportStubOrigin?,
|
||||
val isInstanceMethod: Boolean,
|
||||
val returnType: ObjCType,
|
||||
val selectors: List<String>,
|
||||
val parameters: List<ObjCParameter>,
|
||||
val attributes: List<String>,
|
||||
comment: ObjCComment? = null,
|
||||
) : Stub<DeclarationDescriptor>(buildMethodName(selectors, parameters), comment)
|
||||
) : ObjCExportStub {
|
||||
constructor(
|
||||
descriptor: DeclarationDescriptor?,
|
||||
isInstanceMethod: Boolean,
|
||||
returnType: ObjCType,
|
||||
selectors: List<String>,
|
||||
parameters: List<ObjCParameter>,
|
||||
attributes: List<String>,
|
||||
comment: ObjCComment? = null,
|
||||
) : this(
|
||||
comment = comment,
|
||||
origin = ObjCExportStubOrigin(descriptor),
|
||||
isInstanceMethod = isInstanceMethod,
|
||||
returnType = returnType,
|
||||
selectors = selectors,
|
||||
parameters = parameters,
|
||||
attributes = attributes
|
||||
)
|
||||
|
||||
class ObjCParameter(
|
||||
name: String,
|
||||
override val descriptor: ParameterDescriptor?,
|
||||
override val name: String = buildMethodName(selectors, parameters)
|
||||
}
|
||||
|
||||
class ObjCParameter private constructor(
|
||||
override val name: String,
|
||||
override val origin: ObjCExportStubOrigin?,
|
||||
val type: ObjCType,
|
||||
) : Stub<ParameterDescriptor>(name)
|
||||
) : ObjCExportStub {
|
||||
|
||||
constructor(
|
||||
name: String,
|
||||
descriptor: ParameterDescriptor?,
|
||||
type: ObjCType,
|
||||
) : this(
|
||||
name = name,
|
||||
origin = ObjCExportStubOrigin(descriptor),
|
||||
type = type
|
||||
)
|
||||
|
||||
override val comment: Nothing? = null
|
||||
}
|
||||
|
||||
class ObjCProperty(
|
||||
name: String,
|
||||
override val descriptor: DeclarationDescriptorWithSource?,
|
||||
override val name: String,
|
||||
override val comment: ObjCComment?,
|
||||
override val origin: ObjCExportStubOrigin?,
|
||||
val type: ObjCType,
|
||||
val propertyAttributes: List<String>,
|
||||
val setterName: String? = null,
|
||||
val getterName: String? = null,
|
||||
val declarationAttributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
) : Stub<DeclarationDescriptorWithSource>(name, comment) {
|
||||
|
||||
@Deprecated("", ReplaceWith("this.propertyAttributes"), DeprecationLevel.WARNING)
|
||||
val attributes: List<String> get() = propertyAttributes
|
||||
) : ObjCExportStub {
|
||||
constructor(
|
||||
name: String,
|
||||
descriptor: DeclarationDescriptorWithSource?,
|
||||
type: ObjCType,
|
||||
propertyAttributes: List<String>,
|
||||
setterName: String? = null,
|
||||
getterName: String? = null,
|
||||
declarationAttributes: List<String> = emptyList(),
|
||||
comment: ObjCComment? = null,
|
||||
) : this(
|
||||
name = name,
|
||||
comment = comment,
|
||||
origin = ObjCExportStubOrigin(descriptor),
|
||||
type = type,
|
||||
propertyAttributes = propertyAttributes,
|
||||
setterName = setterName,
|
||||
getterName = getterName,
|
||||
declarationAttributes = declarationAttributes
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildMethodName(selectors: List<String>, parameters: List<ObjCParameter>): String =
|
||||
|
||||
Reference in New Issue
Block a user