Native: support objcExportReportNameCollisions=true binary option

This binary option makes the compiler emit a warning whenever it mangles
a name emitted by ObjCExport.

^KT-63153 Fixed
This commit is contained in:
Svyatoslav Scherbina
2023-11-03 12:49:22 +01:00
committed by Space Team
parent 656b61b945
commit 8d20d5b16c
12 changed files with 144 additions and 13 deletions
@@ -33,6 +33,8 @@ object BinaryOptions : BinaryOptionRegistry() {
val objcExportIgnoreInterfaceMethodCollisions by booleanOption()
val objcExportReportNameCollisions by booleanOption()
val gc by option<GC>(shortcut = { it.shortcut })
val gcSchedulerType by option<GCSchedulerType>(hideValue = { it.deprecatedWithReplacement != null })
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportLazyImpl
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportProblemCollector
import org.jetbrains.kotlin.backend.konan.objcexport.dumpObjCHeader
import org.jetbrains.kotlin.container.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
@@ -23,7 +24,7 @@ internal fun StorageComponentContainer.initContainer(config: KonanConfig) {
useImpl<ObjCExportLazyImpl>()
useInstance(object : ObjCExportProblemCollector {
override fun reportWarning(text: String) {}
override fun reportWarning(method: FunctionDescriptor, text: String) {}
override fun reportWarning(declaration: DeclarationDescriptor, text: String) {}
override fun reportException(throwable: Throwable) = throw throwable
})
@@ -50,17 +50,23 @@ internal fun produceObjCExportInterface(
val objcGenerics = config.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS)
val disableSwiftMemberNameMangling = config.configuration.getBoolean(BinaryOptions.objcExportDisableSwiftMemberNameMangling)
val ignoreInterfaceMethodCollisions = config.configuration.getBoolean(BinaryOptions.objcExportIgnoreInterfaceMethodCollisions)
val reportNameCollisions = config.configuration.getBoolean(BinaryOptions.objcExportReportNameCollisions)
val problemCollector = ObjCExportHeaderGeneratorImpl.ProblemCollector(context)
val namer = ObjCExportNamerImpl(
moduleDescriptors.toSet(),
moduleDescriptor.builtIns,
mapper,
problemCollector,
topLevelNamePrefix,
local = false,
objcGenerics = objcGenerics,
disableSwiftMemberNameMangling = disableSwiftMemberNameMangling,
ignoreInterfaceMethodCollisions = ignoreInterfaceMethodCollisions,
reportNameCollisions = reportNameCollisions,
)
val headerGenerator = ObjCExportHeaderGeneratorImpl(context, moduleDescriptors, mapper, namer, objcGenerics)
val headerGenerator = ObjCExportHeaderGeneratorImpl(context, moduleDescriptors, mapper, namer, problemCollector, objcGenerics)
headerGenerator.translateModule()
return headerGenerator.buildInterface()
}
@@ -128,6 +134,7 @@ internal class ObjCExport(
setOf(moduleDescriptor),
moduleDescriptor.builtIns,
mapper,
ObjCExportProblemCollector.SILENT,
topLevelNamePrefix,
local = false
)
@@ -42,12 +42,12 @@ interface ObjCExportTranslator {
interface ObjCExportProblemCollector {
fun reportWarning(text: String)
fun reportWarning(method: FunctionDescriptor, text: String)
fun reportWarning(declaration: DeclarationDescriptor, text: String)
fun reportException(throwable: Throwable)
object SILENT : ObjCExportProblemCollector {
override fun reportWarning(text: String) {}
override fun reportWarning(method: FunctionDescriptor, text: String) {}
override fun reportWarning(declaration: DeclarationDescriptor, text: String) {}
override fun reportException(throwable: Throwable) {}
}
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
import org.jetbrains.kotlin.backend.konan.reportCompilationWarning
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -21,20 +22,21 @@ internal class ObjCExportHeaderGeneratorImpl(
moduleDescriptors: List<ModuleDescriptor>,
mapper: ObjCExportMapper,
namer: ObjCExportNamer,
problemCollector: ObjCExportProblemCollector,
objcGenerics: Boolean
) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics, ProblemCollector(context)) {
) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics, problemCollector) {
override val shouldExportKDoc = context.shouldExportKDoc()
private class ProblemCollector(val context: PhaseContext) : ObjCExportProblemCollector {
internal class ProblemCollector(val context: PhaseContext) : ObjCExportProblemCollector {
override fun reportWarning(text: String) {
context.reportCompilationWarning(text)
}
override fun reportWarning(method: FunctionDescriptor, text: String) {
val psi = (method as? DeclarationDescriptorWithSource)?.source?.getPsi()
override fun reportWarning(declaration: DeclarationDescriptor, text: String) {
val psi = (declaration as? DeclarationDescriptorWithSource)?.source?.getPsi()
?: return reportWarning(
"$text\n (at ${DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(method)})"
"$text\n (at ${DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declaration)})"
)
val location = MessageUtil.psiElementToMessageLocation(psi)
@@ -96,7 +96,7 @@ internal class ObjCExportLazyImpl(
private val mapper = ObjCExportMapper(deprecationResolver, local = true, configuration.unitSuspendFunctionExport)
private val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local = true)
private val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, problemCollector, local = true)
private val translator: ObjCExportTranslator = ObjCExportTranslatorImpl(
null,
@@ -58,6 +58,9 @@ interface ObjCExportNamer {
get() = false
val ignoreInterfaceMethodCollisions: Boolean
get() = false
val reportNameCollisions: Boolean
get() = false
}
val topLevelNamePrefix: String
@@ -103,6 +106,7 @@ fun createNamer(
(exportedDependencies + moduleDescriptor).toSet(),
moduleDescriptor.builtIns,
ObjCExportMapper(local = true, unitSuspendFunctionExport = UnitSuspendFunctionObjCExport.DEFAULT),
ObjCExportProblemCollector.SILENT,
topLevelNamePrefix,
local = true
)
@@ -273,6 +277,7 @@ internal class ObjCExportNamerImpl(
private val configuration: ObjCExportNamer.Configuration,
builtIns: KotlinBuiltIns,
private val mapper: ObjCExportMapper,
private val problemCollector: ObjCExportProblemCollector,
private val local: Boolean
) : ObjCExportNamer {
@@ -280,11 +285,13 @@ internal class ObjCExportNamerImpl(
moduleDescriptors: Set<ModuleDescriptor>,
builtIns: KotlinBuiltIns,
mapper: ObjCExportMapper,
problemCollector: ObjCExportProblemCollector,
topLevelNamePrefix: String,
local: Boolean,
objcGenerics: Boolean = false,
disableSwiftMemberNameMangling: Boolean = false,
ignoreInterfaceMethodCollisions: Boolean = false,
reportNameCollisions: Boolean = false,
) : this(
object : ObjCExportNamer.Configuration {
override val topLevelNamePrefix: String
@@ -301,9 +308,13 @@ internal class ObjCExportNamerImpl(
override val ignoreInterfaceMethodCollisions: Boolean
get() = ignoreInterfaceMethodCollisions
override val reportNameCollisions: Boolean
get() = reportNameCollisions
},
builtIns,
mapper,
problemCollector,
local
)
@@ -826,10 +837,21 @@ internal class ObjCExportNamerImpl(
inline fun getOrPut(element: T, nameCandidates: () -> Sequence<N>): N {
getIfAssigned(element)?.let { return it }
var reportedCollision = false
nameCandidates().forEach {
if (tryAssign(element, it)) {
return it
}
if (configuration.reportNameCollisions && !reportedCollision) {
if (element is DeclarationDescriptor) {
problemCollector.reportWarning(element, "name is mangled when generating Objective-C header")
} else {
problemCollector.reportWarning("name \"$it\" is mangled when generating Objective-C header")
}
reportedCollision = true
}
}
error("name candidates run out")
@@ -26,7 +26,7 @@ class ObjcExportHeaderGeneratorMobile internal constructor(
restrictToLocalModules: Boolean = false): ObjCExportHeaderGenerator {
val mapper = ObjCExportMapper(deprecationResolver, local, configuration.unitSuspendFunctionExport)
val namerConfiguration = createNamerConfiguration(configuration)
val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local)
val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, problemCollector, local)
return ObjcExportHeaderGeneratorMobile(
moduleDescriptors,