Native: add included forward declarations into cinterop klib manifest
This allows the compiler to limit imports from "magic" packages like cnames.structs to forward declarations actually present in dependent cinterop klibs. The manifest already had `exportForwardDeclarations` field, but - it didn't include Objective-C forward declarations (@class, @protocol) - it has a slightly different meaning (the export list enables importing the listed declarations through the interop package of the library, while the include list shouldn't do that), so we better avoid mixing them.
This commit is contained in:
committed by
Space Team
parent
86a29a7b07
commit
322a8a443b
@@ -20,6 +20,7 @@ const val KLIB_PROPERTY_CONTAINS_ERROR_CODE = "contains_error_code"
|
||||
// Native-specific:
|
||||
const val KLIB_PROPERTY_INTEROP = "interop"
|
||||
const val KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS = "exportForwardDeclarations"
|
||||
const val KLIB_PROPERTY_INCLUDED_FORWARD_DECLARATIONS = "includedForwardDeclarations"
|
||||
|
||||
/**
|
||||
* Copy-pasted to `kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt`
|
||||
@@ -104,6 +105,9 @@ val KotlinLibrary.packageFqName: String?
|
||||
val KotlinLibrary.exportForwardDeclarations: List<String>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS, escapeInQuotes = true)
|
||||
|
||||
val KotlinLibrary.includedForwardDeclarations: List<String>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_INCLUDED_FORWARD_DECLARATIONS, escapeInQuotes = true)
|
||||
|
||||
val BaseKotlinLibrary.nativeTargets: List<String>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_NATIVE_TARGETS)
|
||||
|
||||
|
||||
+2
@@ -162,6 +162,8 @@ data class KotlinFunctionType(
|
||||
}
|
||||
|
||||
internal val cnamesStructsPackageName = "cnames.structs"
|
||||
internal val objcnamesClassesPackageName = "objcnames.classes"
|
||||
internal val objcnamesProtocolsPackageName = "objcnames.protocols"
|
||||
|
||||
object KotlinTypes {
|
||||
val independent = Classifier.topLevel("kotlin.native.internal", "Independent")
|
||||
|
||||
+4
-2
@@ -37,8 +37,8 @@ fun DeclarationMapper.getKotlinClassFor(
|
||||
): Classifier {
|
||||
val pkg = if (objCClassOrProtocol.isForwardDeclaration) {
|
||||
when (objCClassOrProtocol) {
|
||||
is ObjCClass -> "objcnames.classes"
|
||||
is ObjCProtocol -> "objcnames.protocols"
|
||||
is ObjCClass -> objcnamesClassesPackageName
|
||||
is ObjCProtocol -> objcnamesProtocolsPackageName
|
||||
}
|
||||
} else {
|
||||
this.getPackageFor(objCClassOrProtocol)
|
||||
@@ -539,6 +539,8 @@ internal tailrec fun ObjCClass.isNSStringOrSubclass(): Boolean = when (this.name
|
||||
|
||||
internal fun ObjCClass.isNSStringSubclass(): Boolean = this.baseClass?.isNSStringOrSubclass() == true
|
||||
|
||||
internal fun ObjCClass.shouldBeIncludedIntoKotlinAPI(): Boolean = !this.isNSStringSubclass()
|
||||
|
||||
private fun objCPointerMirror(declarationMapper: DeclarationMapper, type: ObjCPointer): TypeMirror.ByValue {
|
||||
if (type is ObjCObjectPointer && type.def.isNSStringOrSubclass()) {
|
||||
val valueType = KotlinTypes.string
|
||||
|
||||
+3
-2
@@ -329,8 +329,9 @@ class StubIrBuilder(private val context: StubIrContext) {
|
||||
|
||||
fun build(): StubIrBuilderResult {
|
||||
nativeIndex.objCProtocols.filter { !it.isForwardDeclaration }.forEach { generateStubsForObjCProtocol(it) }
|
||||
nativeIndex.objCClasses.filter { !it.isForwardDeclaration && !it.isNSStringSubclass()} .forEach { generateStubsForObjCClass(it) }
|
||||
nativeIndex.objCCategories.filter { !it.clazz.isNSStringSubclass() }.forEach { generateStubsForObjCCategory(it) }
|
||||
nativeIndex.objCClasses.filter { !it.isForwardDeclaration && it.shouldBeIncludedIntoKotlinAPI() }
|
||||
.forEach { generateStubsForObjCClass(it) }
|
||||
nativeIndex.objCCategories.filter { it.clazz.shouldBeIncludedIntoKotlinAPI() }.forEach { generateStubsForObjCCategory(it) }
|
||||
nativeIndex.structs.forEach { generateStubsForStruct(it) }
|
||||
nativeIndex.enums.forEach { generateStubsForEnum(it) }
|
||||
nativeIndex.functions.filter { it.name !in excludedFunctions }.forEach { generateStubsForFunction(it) }
|
||||
|
||||
+27
-1
@@ -5,6 +5,8 @@
|
||||
package org.jetbrains.kotlin.native.interop.gen
|
||||
|
||||
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||
import org.jetbrains.kotlin.library.KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS
|
||||
import org.jetbrains.kotlin.library.KLIB_PROPERTY_INCLUDED_FORWARD_DECLARATIONS
|
||||
import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode
|
||||
import org.jetbrains.kotlin.native.interop.gen.jvm.InteropConfiguration
|
||||
import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform
|
||||
@@ -93,7 +95,31 @@ class StubIrContext(
|
||||
"$cnamesStructsPackageName.${getKotlinName(it)}"
|
||||
}
|
||||
|
||||
properties["exportForwardDeclarations"] = exportForwardDeclarations.joinToString(" ")
|
||||
// Note: includedForwardDeclarations is somewhat similar to exportForwardDeclarations. But reusing the latter
|
||||
// instead is undesirable: exportForwardDeclarations makes the compiler enable importing the listed declarations
|
||||
// through interop library package. E.g., if `cnames.structs.Foo` is in exportForwardDeclarations of a cinterop
|
||||
// klib bar with package bar, then `import bar.Foo` is valid. This is an arguable feature and a candidate for
|
||||
// deprecation, so enabling it for new declarations instead is undesirable.
|
||||
// That's why, to make the included Obj-C forward declarations known to the compiler, we have to create a new
|
||||
// manifest property for that.
|
||||
val includedForwardDeclarations = mutableListOf<String>()
|
||||
includedForwardDeclarations.addAll(exportForwardDeclarations)
|
||||
|
||||
// TODO: should we add meta classes?
|
||||
nativeIndex.objCClasses
|
||||
.filter { it.isForwardDeclaration && it.shouldBeIncludedIntoKotlinAPI() }
|
||||
.mapTo(includedForwardDeclarations) {
|
||||
"$objcnamesClassesPackageName.${it.kotlinClassName(isMeta = false)}"
|
||||
}
|
||||
|
||||
nativeIndex.objCProtocols
|
||||
.filter { it.isForwardDeclaration }
|
||||
.mapTo(includedForwardDeclarations) {
|
||||
"$objcnamesProtocolsPackageName.${it.kotlinClassName(isMeta = false)}"
|
||||
}
|
||||
|
||||
properties[KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS] = exportForwardDeclarations.joinToString(" ")
|
||||
properties[KLIB_PROPERTY_INCLUDED_FORWARD_DECLARATIONS] = includedForwardDeclarations.joinToString(" ")
|
||||
|
||||
// TODO: consider exporting Objective-C class and protocol forward refs.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user