[ObjCExport] ObjCType: Implement HasExtras instead of HasMutableExtras

... to enforce the immutability concept of this entities.

KT-65891 Fixed
This commit is contained in:
Sebastian Sellmair
2024-02-21 13:37:33 +01:00
committed by Space Team
parent 704379934e
commit 6b6808d87c
9 changed files with 118 additions and 41 deletions
@@ -4,7 +4,8 @@ import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.backend.konan.objcexport.*
import org.jetbrains.kotlin.objcexport.KtObjCExportSession
import org.jetbrains.kotlin.objcexport.extras.withRequiresForwardDeclaration
import org.jetbrains.kotlin.objcexport.extras.objCTypeExtras
import org.jetbrains.kotlin.objcexport.extras.requiresForwardDeclaration
/**
* Traverses stubs and returns true if [objCErrorType] is used as a return, parameter or property type
@@ -45,4 +46,6 @@ internal val errorInterface
superClassGenerics = emptyList()
)
internal val objCErrorType = ObjCClassType(errorClassName).withRequiresForwardDeclaration()
internal val objCErrorType = ObjCClassType(errorClassName, extras = objCTypeExtras {
requiresForwardDeclaration = true
})
@@ -6,8 +6,9 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCClassType
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCProperty
import org.jetbrains.kotlin.backend.konan.objcexport.swiftNameAttribute
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isCompanion
import org.jetbrains.kotlin.objcexport.extras.withOriginClassId
import org.jetbrains.kotlin.objcexport.extras.withRequiresForwardDeclaration
import org.jetbrains.kotlin.objcexport.extras.objCTypeExtras
import org.jetbrains.kotlin.objcexport.extras.originClassId
import org.jetbrains.kotlin.objcexport.extras.requiresForwardDeclaration
/**
* If object class has companion object it needs to have property which returns this companion.
@@ -25,9 +26,10 @@ internal fun KtClassOrObjectSymbol.buildCompanionProperty(): ObjCProperty {
name = propertyName,
comment = null,
origin = null,
type = ObjCClassType(typeName.objCName)
.withRequiresForwardDeclaration()
.withOriginClassId(companion.classIdIfNonLocal),
type = ObjCClassType(typeName.objCName, extras = objCTypeExtras {
requiresForwardDeclaration = true
originClassId = companion.classIdIfNonLocal
}),
propertyAttributes = listOf("class", "readonly"),
getterName = propertyName,
declarationAttributes = listOf(swiftNameAttribute(propertyName))
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2024 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.objcexport.extras
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCType
import org.jetbrains.kotlin.tooling.core.Extras
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
/**
* Acts as scope for discoverable 'builder functions'
* - See [objCTypeExtras] factory function
* - See [MutableExtras.originClassId] as example for declaring a discoverable API for types
* - See [MutableExtras.requiresForwardDeclaration] "="
*/
internal object ObjCTypeExtrasBuilderContext
/**
* Convenience function for building extras for [ObjCType]
*/
internal fun objCTypeExtras(builder: context(ObjCTypeExtrasBuilderContext) MutableExtras.() -> Unit): Extras {
return mutableExtrasOf().also { extras -> builder(ObjCTypeExtrasBuilderContext, extras) }
}
@@ -6,12 +6,13 @@
package org.jetbrains.kotlin.objcexport.extras
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCNullableReferenceType
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCReferenceType
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.extrasKeyOf
private val originClassIdKey = extrasKeyOf<ClassId>()
private val originClassIdKey = extrasKeyOf<ClassId?>()
/**
* Tracks the Kotlin origin associated with [this] [ObjCType].
@@ -30,9 +31,11 @@ internal val ObjCType.originClassId: ClassId?
}
/**
* See [originClassId]
* See [ObjCType.originClassId]
*/
internal fun <T : ObjCReferenceType> T.withOriginClassId(classId: ClassId?): T = also { type ->
if (classId != null) type.extras[originClassIdKey] = classId
else type.extras.remove(originClassIdKey)
}
context(ObjCTypeExtrasBuilderContext)
internal var MutableExtras.originClassId: ClassId?
get() = this[originClassIdKey]
set(value) {
this[originClassIdKey] = value
}
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.objcexport.extras
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCReferenceType
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.extrasKeyOf
import org.jetbrains.kotlin.tooling.core.readWriteProperty
private val requiresForwardDeclarationKey = extrasKeyOf<Boolean>("isForwardDeclaration")
@@ -16,13 +16,16 @@ private val requiresForwardDeclarationKey = extrasKeyOf<Boolean>("isForwardDecla
* - Default value: `false`.
* - Example: All types used in function and method signature are expected to render forward declarations
*/
internal val ObjCReferenceType.requiresForwardDeclaration by requiresForwardDeclarationKey.readWriteProperty.notNull(false)
internal val ObjCReferenceType.requiresForwardDeclaration: Boolean get() = extras[requiresForwardDeclarationKey] ?: false
/**
* ⚠️ Marks [this] [ObjCReferenceType] as 'requires forward declaration' and returns the same instance.
* This method shall be used during the construction of a new type.
* @see ObjCReferenceType.requiresForwardDeclaration
*/
internal fun <T : ObjCReferenceType> T.withRequiresForwardDeclaration(): T = also { type ->
type.extras[requiresForwardDeclarationKey] = true
}
context(ObjCTypeExtrasBuilderContext)
internal var MutableExtras.requiresForwardDeclaration: Boolean
get() = this[requiresForwardDeclarationKey] ?: false
set(value) {
this[requiresForwardDeclarationKey] = value
}
@@ -8,8 +8,9 @@ import org.jetbrains.kotlin.backend.konan.objcexport.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isCompanion
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
import org.jetbrains.kotlin.objcexport.extras.withOriginClassId
import org.jetbrains.kotlin.objcexport.extras.withRequiresForwardDeclaration
import org.jetbrains.kotlin.objcexport.extras.objCTypeExtras
import org.jetbrains.kotlin.objcexport.extras.originClassId
import org.jetbrains.kotlin.objcexport.extras.requiresForwardDeclaration
context(KtAnalysisSession, KtObjCExportSession)
fun KtClassOrObjectSymbol.translateToObjCObject(): ObjCClass? {
@@ -85,8 +86,14 @@ private fun KtClassOrObjectSymbol.getDefaultMembers(): List<ObjCExportStub> {
* See also: [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.mapReferenceType]
*/
context(KtAnalysisSession, KtObjCExportSession)
private fun KtClassOrObjectSymbol.toPropertyType() = ObjCClassType(getObjCClassOrProtocolName().objCName, emptyList(),)
.withRequiresForwardDeclaration().withOriginClassId(classIdIfNonLocal)
private fun KtClassOrObjectSymbol.toPropertyType() = ObjCClassType(
className = getObjCClassOrProtocolName().objCName,
typeArguments = emptyList(),
extras = objCTypeExtras {
requiresForwardDeclaration = true
originClassId = classIdIfNonLocal
}
)
/**
* [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamerImpl.getObjectInstanceSelector]
@@ -21,7 +21,8 @@ import org.jetbrains.kotlin.name.NativeStandardInteropNames.cInteropPackage
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDeclaredSuperInterfaceSymbols
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getSuperClassSymbolNotAny
import org.jetbrains.kotlin.objcexport.analysisApiUtils.objCErrorType
import org.jetbrains.kotlin.objcexport.extras.withRequiresForwardDeclaration
import org.jetbrains.kotlin.objcexport.extras.objCTypeExtras
import org.jetbrains.kotlin.objcexport.extras.requiresForwardDeclaration
/**
* ClassId for 'kotlinx.cinterop.ObjCClass'
@@ -49,13 +50,19 @@ internal fun KtType.translateToObjCObjectType(): ObjCNonNullReferenceType {
context(KtAnalysisSession, KtObjCExportSession)
private fun KtClassOrObjectSymbol.translateToObjCObjectType(): ObjCNonNullReferenceType {
if (isObjCMetaClass()) return ObjCMetaClassType
if (isObjCProtocolClass()) return ObjCClassType("Protocol").withRequiresForwardDeclaration()
if (isObjCProtocolClass()) return ObjCClassType("Protocol", extras = objCTypeExtras {
requiresForwardDeclaration = true
})
if (isExternalObjCClass() || isObjCForwardDeclaration()) {
return if (classKind == KtClassKind.INTERFACE) {
ObjCProtocolType(nameOrAnonymous.asString().removeSuffix("Protocol")).withRequiresForwardDeclaration()
ObjCProtocolType(nameOrAnonymous.asString().removeSuffix("Protocol"), extras = objCTypeExtras {
requiresForwardDeclaration = true
})
} else {
ObjCClassType(nameOrAnonymous.asString()).withRequiresForwardDeclaration()
ObjCClassType(nameOrAnonymous.asString(), extras = objCTypeExtras {
requiresForwardDeclaration = true
})
}
}
@@ -19,8 +19,9 @@ import org.jetbrains.kotlin.objcexport.analysisApiUtils.getInlineTargetTypeOrNul
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isError
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isObjCObjectType
import org.jetbrains.kotlin.objcexport.analysisApiUtils.objCErrorType
import org.jetbrains.kotlin.objcexport.extras.withOriginClassId
import org.jetbrains.kotlin.objcexport.extras.withRequiresForwardDeclaration
import org.jetbrains.kotlin.objcexport.extras.objCTypeExtras
import org.jetbrains.kotlin.objcexport.extras.originClassId
import org.jetbrains.kotlin.objcexport.extras.requiresForwardDeclaration
/**
@@ -106,13 +107,24 @@ internal fun KtType.mapToReferenceTypeIgnoringNullability(): ObjCNonNullReferenc
}
if (fullyExpandedType is KtNonErrorClassType) {
// TODO NOW: create type translation test
return if (classSymbol?.classKind == KtClassKind.INTERFACE) {
ObjCProtocolType(fullyExpandedType.objCTypeName)
ObjCProtocolType(
protocolName = fullyExpandedType.objCTypeName,
extras = objCTypeExtras {
requiresForwardDeclaration = true
originClassId = classId
}
)
} else {
ObjCClassType(fullyExpandedType.objCTypeName, translateTypeArgumentsToObjC())
}.withRequiresForwardDeclaration().withOriginClassId(classId)
ObjCClassType(
className = fullyExpandedType.objCTypeName,
typeArguments = translateTypeArgumentsToObjC(),
extras = objCTypeExtras {
requiresForwardDeclaration = true
originClassId = classId
}
)
}
}
if (fullyExpandedType is KtTypeParameterType) {