Add facility to restrict extra classes in Mobile ObjC Generator (#4498)
- Implement way to restrict extra classes from other modules in Mobile ObjC generator - Split generation into smaller steps - Add API to retrieve stubs and foundation imports
This commit is contained in:
committed by
Stanislav Erokhin
parent
edfdc88d6d
commit
598d0e07e3
+66
-20
@@ -240,7 +240,7 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { mapper.shouldBeExposed(it) }
|
.filter { mapper.shouldBeExposed(it) }
|
||||||
.map {
|
.map {
|
||||||
generator?.generateInterface(it)
|
generator?.generateExtraInterfaceEarly(it)
|
||||||
referenceProtocol(it).objCName
|
referenceProtocol(it).objCName
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
@@ -249,7 +249,7 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
classDescriptor: ClassDescriptor,
|
classDescriptor: ClassDescriptor,
|
||||||
declarations: List<CallableMemberDescriptor>
|
declarations: List<CallableMemberDescriptor>
|
||||||
): ObjCInterface {
|
): ObjCInterface {
|
||||||
generator?.generateClass(classDescriptor)
|
generator?.generateExtraClassEarly(classDescriptor)
|
||||||
|
|
||||||
val name = referenceClass(classDescriptor).objCName
|
val name = referenceClass(classDescriptor).objCName
|
||||||
val members = buildMembers {
|
val members = buildMembers {
|
||||||
@@ -301,7 +301,7 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
val superName = if (superClass == null) {
|
val superName = if (superClass == null) {
|
||||||
kotlinAnyName
|
kotlinAnyName
|
||||||
} else {
|
} else {
|
||||||
generator?.generateClass(superClass)
|
generator?.generateExtraClassEarly(superClass)
|
||||||
referenceClass(superClass)
|
referenceClass(superClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1002,16 +1002,8 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
private val topLevel = mutableMapOf<SourceFile, MutableList<CallableMemberDescriptor>>()
|
private val topLevel = mutableMapOf<SourceFile, MutableList<CallableMemberDescriptor>>()
|
||||||
|
|
||||||
fun build(): List<String> = mutableListOf<String>().apply {
|
fun build(): List<String> = mutableListOf<String>().apply {
|
||||||
add("#import <Foundation/NSArray.h>")
|
addImports(foundationImports)
|
||||||
add("#import <Foundation/NSDictionary.h>")
|
addImports(getAdditionalImports())
|
||||||
add("#import <Foundation/NSError.h>")
|
|
||||||
add("#import <Foundation/NSObject.h>")
|
|
||||||
add("#import <Foundation/NSSet.h>")
|
|
||||||
add("#import <Foundation/NSString.h>")
|
|
||||||
add("#import <Foundation/NSValue.h>")
|
|
||||||
getAdditionalImports().forEach {
|
|
||||||
add("#import <$it>")
|
|
||||||
}
|
|
||||||
add("")
|
add("")
|
||||||
|
|
||||||
if (classForwardDeclarations.isNotEmpty()) {
|
if (classForwardDeclarations.isNotEmpty()) {
|
||||||
@@ -1054,19 +1046,32 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
return ObjCExportedInterface(generatedClasses, extensions, topLevel, headerLines, namer, mapper)
|
return ObjCExportedInterface(generatedClasses, extensions, topLevel, headerLines, namer, mapper)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getExportStubs(): ObjCExportedStubs =
|
||||||
|
ObjCExportedStubs(classForwardDeclarations, protocolForwardDeclarations, stubs)
|
||||||
|
|
||||||
protected abstract fun reportWarning(text: String)
|
protected abstract fun reportWarning(text: String)
|
||||||
|
|
||||||
protected abstract fun reportWarning(method: FunctionDescriptor, text: String)
|
protected abstract fun reportWarning(method: FunctionDescriptor, text: String)
|
||||||
|
|
||||||
protected open fun getAdditionalImports(): List<String> = emptyList()
|
protected open fun getAdditionalImports(): List<String> = emptyList()
|
||||||
|
|
||||||
|
fun translateModule() {
|
||||||
fun translateModule(): List<Stub<*>> {
|
|
||||||
// TODO: make the translation order stable
|
// TODO: make the translation order stable
|
||||||
// to stabilize name mangling.
|
// to stabilize name mangling.
|
||||||
|
translateBaseDeclarations()
|
||||||
|
translateModuleDeclarations()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun translateBaseDeclarations() {
|
||||||
stubs += translator.generateBaseDeclarations()
|
stubs += translator.generateBaseDeclarations()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun translateModuleDeclarations() {
|
||||||
|
translatePackageFragments()
|
||||||
|
translateExtraClasses()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translatePackageFragments() {
|
||||||
val packageFragments = moduleDescriptors.flatMap { it.getPackageFragments() }
|
val packageFragments = moduleDescriptors.flatMap { it.getPackageFragments() }
|
||||||
|
|
||||||
packageFragments.forEach { packageFragment ->
|
packageFragments.forEach { packageFragment ->
|
||||||
@@ -1119,18 +1124,31 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
topLevel.forEach { sourceFile, declarations ->
|
topLevel.forEach { sourceFile, declarations ->
|
||||||
generateFile(sourceFile, declarations)
|
generateFile(sourceFile, declarations)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates additional classes referenced from the module's declarations, such as parameter types, return types,
|
||||||
|
* thrown exception types, and underlying enum types.
|
||||||
|
*
|
||||||
|
* This is required for classes from dependencies to be exported correctly. However, we also currently rely on this
|
||||||
|
* for a few edge cases, such as some inner classes. Sub classes may reject certain descriptors to be translated.
|
||||||
|
* Some referenced descriptors may be translated early for ordering reasons.
|
||||||
|
* @see shouldTranslateExtraClass
|
||||||
|
* @see generateExtraClassEarly
|
||||||
|
* @see generateExtraInterfaceEarly
|
||||||
|
*/
|
||||||
|
private fun translateExtraClasses() {
|
||||||
while (extraClassesToTranslate.isNotEmpty()) {
|
while (extraClassesToTranslate.isNotEmpty()) {
|
||||||
val descriptor = extraClassesToTranslate.first()
|
val descriptor = extraClassesToTranslate.first()
|
||||||
extraClassesToTranslate -= descriptor
|
extraClassesToTranslate -= descriptor
|
||||||
|
|
||||||
|
assert(shouldTranslateExtraClass(descriptor)) { "Shouldn't be queued for translation: $descriptor" }
|
||||||
if (descriptor.isInterface) {
|
if (descriptor.isInterface) {
|
||||||
generateInterface(descriptor)
|
generateInterface(descriptor)
|
||||||
} else {
|
} else {
|
||||||
generateClass(descriptor)
|
generateClass(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stubs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateFile(sourceFile: SourceFile, declarations: List<CallableMemberDescriptor>) {
|
private fun generateFile(sourceFile: SourceFile, declarations: List<CallableMemberDescriptor>) {
|
||||||
@@ -1141,18 +1159,28 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
stubs.add(translator.translateExtensions(classDescriptor, declarations))
|
stubs.add(translator.translateExtensions(classDescriptor, declarations))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun generateClass(descriptor: ClassDescriptor) {
|
protected open fun shouldTranslateExtraClass(descriptor: ClassDescriptor): Boolean = true
|
||||||
|
|
||||||
|
internal fun generateExtraClassEarly(descriptor: ClassDescriptor) {
|
||||||
|
if (shouldTranslateExtraClass(descriptor)) generateClass(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun generateExtraInterfaceEarly(descriptor: ClassDescriptor) {
|
||||||
|
if (shouldTranslateExtraClass(descriptor)) generateInterface(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateClass(descriptor: ClassDescriptor) {
|
||||||
if (!generatedClasses.add(descriptor)) return
|
if (!generatedClasses.add(descriptor)) return
|
||||||
stubs.add(translator.translateClass(descriptor))
|
stubs.add(translator.translateClass(descriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun generateInterface(descriptor: ClassDescriptor) {
|
private fun generateInterface(descriptor: ClassDescriptor) {
|
||||||
if (!generatedClasses.add(descriptor)) return
|
if (!generatedClasses.add(descriptor)) return
|
||||||
stubs.add(translator.translateInterface(descriptor))
|
stubs.add(translator.translateInterface(descriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun requireClassOrInterface(descriptor: ClassDescriptor) {
|
internal fun requireClassOrInterface(descriptor: ClassDescriptor) {
|
||||||
if (descriptor !in generatedClasses) {
|
if (shouldTranslateExtraClass(descriptor) && descriptor !in generatedClasses) {
|
||||||
extraClassesToTranslate += descriptor
|
extraClassesToTranslate += descriptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1164,6 +1192,24 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
internal fun referenceProtocol(objCName: String) {
|
internal fun referenceProtocol(objCName: String) {
|
||||||
protocolForwardDeclarations += objCName
|
protocolForwardDeclarations += objCName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val foundationImports = listOf(
|
||||||
|
"Foundation/NSArray.h",
|
||||||
|
"Foundation/NSDictionary.h",
|
||||||
|
"Foundation/NSError.h",
|
||||||
|
"Foundation/NSObject.h",
|
||||||
|
"Foundation/NSSet.h",
|
||||||
|
"Foundation/NSString.h",
|
||||||
|
"Foundation/NSValue.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun MutableList<String>.addImports(imports: Iterable<String>) {
|
||||||
|
imports.forEach {
|
||||||
|
add("#import <$it>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun objCInterface(
|
private fun objCInterface(
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||||
|
|
||||||
|
data class ObjCExportedStubs(
|
||||||
|
val classForwardDeclarations: Set<String>,
|
||||||
|
val protocolForwardDeclarations: Set<String>,
|
||||||
|
val stubs: List<Stub<*>>
|
||||||
|
)
|
||||||
+16
-9
@@ -1,16 +1,19 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
class ObjcExportHeaderGeneratorMobile internal constructor(
|
class ObjcExportHeaderGeneratorMobile internal constructor(
|
||||||
moduleDescriptors: List<ModuleDescriptor>,
|
moduleDescriptors: List<ModuleDescriptor>,
|
||||||
mapper: ObjCExportMapper,
|
mapper: ObjCExportMapper,
|
||||||
namer: ObjCExportNamer,
|
namer: ObjCExportNamer,
|
||||||
private val warningCollector: ObjCExportWarningCollector,
|
private val warningCollector: ObjCExportWarningCollector,
|
||||||
objcGenerics: Boolean
|
objcGenerics: Boolean,
|
||||||
|
private val restrictToLocalModules: Boolean
|
||||||
) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics) {
|
) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -20,21 +23,26 @@ class ObjcExportHeaderGeneratorMobile internal constructor(
|
|||||||
builtIns: KotlinBuiltIns,
|
builtIns: KotlinBuiltIns,
|
||||||
moduleDescriptors: List<ModuleDescriptor>,
|
moduleDescriptors: List<ModuleDescriptor>,
|
||||||
deprecationResolver: DeprecationResolver? = null,
|
deprecationResolver: DeprecationResolver? = null,
|
||||||
local: Boolean = false): ObjCExportHeaderGenerator {
|
local: Boolean = false,
|
||||||
|
restrictToLocalModules: Boolean = false): ObjCExportHeaderGenerator {
|
||||||
val mapper = ObjCExportMapper(deprecationResolver, local)
|
val mapper = ObjCExportMapper(deprecationResolver, local)
|
||||||
val namerConfiguration = createNamerConfiguration(configuration)
|
val namerConfiguration = createNamerConfiguration(configuration)
|
||||||
val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local)
|
val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local)
|
||||||
|
|
||||||
return ObjcExportHeaderGeneratorMobile(
|
return ObjcExportHeaderGeneratorMobile(
|
||||||
moduleDescriptors,
|
moduleDescriptors,
|
||||||
mapper,
|
mapper,
|
||||||
namer,
|
namer,
|
||||||
warningCollector,
|
warningCollector,
|
||||||
configuration.objcGenerics)
|
configuration.objcGenerics,
|
||||||
|
restrictToLocalModules
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun shouldTranslateExtraClass(descriptor: ClassDescriptor): Boolean =
|
||||||
|
!restrictToLocalModules || descriptor.module in moduleDescriptors
|
||||||
|
|
||||||
override fun reportWarning(text: String) {
|
override fun reportWarning(text: String) {
|
||||||
warningCollector.reportWarning(text)
|
warningCollector.reportWarning(text)
|
||||||
}
|
}
|
||||||
@@ -42,5 +50,4 @@ class ObjcExportHeaderGeneratorMobile internal constructor(
|
|||||||
override fun reportWarning(method: FunctionDescriptor, text: String) {
|
override fun reportWarning(method: FunctionDescriptor, text: String) {
|
||||||
warningCollector.reportWarning(method, text)
|
warningCollector.reportWarning(method, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user