Repository: JetBrains/kotlin
File: kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt (Kotlin)

Code before:

private fun KtClassOrObject.getObjCName(): ObjCName {
    var objCName: String? = null
    var swiftName: String? = null
    var isExact = false
    annotationEntries.firstOrNull {
        it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == objCNameShortName
    }?.let { annotation ->
        fun ValueArgument.getStringValue(): String? {
            val stringTemplateExpression = when (this) {
                is KtValueArgument -> stringTemplateExpression
                else -> getArgumentExpression() as? KtStringTemplateExpression
            } ?: return null
            return (stringTemplateExpression.entries.singleOrNull() as? KtLiteralStringTemplateEntry)?.text
        }

        fun ValueArgument.getBooleanValue(): Boolean =
                (getArgumentExpression() as? KtConstantExpression)?.text?.toBooleanStrictOrNull() ?: false

        val argNames = setOf("name", "swiftName", "exact")
        val processedArgs = mutableSetOf<String>()
        for (argument in annotation.valueArguments) {
            val argName = argument.getArgumentName()?.asName?.asString() ?: (argNames - processedArgs).firstOrNull() ?: break
            when (argName) {
                "name" -> objCName = argument.getStringValue()?.takeIf { it.isNotBlank() }
                "swiftName" -> swiftName = argument.getStringValue()?.takeIf { it.isNotBlank() }
                "exact" -> isExact = argument.getBooleanValue()
            }
            processedArgs.add(argName)
        }
    }
    return ObjCName(name!!, objCName, swiftName, isExact)
}

internal val ModuleDescriptor.objCExportAdditionalNamePrefix: String get() {
    if (this.isNativeStdlib()) return "Kotlin"

    val fullPrefix = when(val module = this.klibModuleOrigin) {
        CurrentKlibModuleOrigin ->
            error("expected deserialized module, got $this (origin = $module)")
        SyntheticModulesOrigin ->
            this.name.asString().let { it.substring(1, it.lastIndex) }
        is DeserializedKlibModuleOrigin ->
            module.library.let { it.shortName ?: it.uniqueName }
    }

    return abbreviate(fullPrefix)
}

internal val Context.objCExportTopLevelNamePrefix: String
    get() = abbreviate(config.fullExportedNamePrefix)

Review comment (suggestion):
> Empty or blank names aren't allowed, they are meant to be interpreted as `null`.

Why?
Aren't blank names valid for Objective-C selector fragments? E.g.
```objective-c
- (void)bar:(int)x :(int)y;
```


Code after:

private fun KtClassOrObject.getObjCName(): ObjCName {
    var objCName: String? = null
    var swiftName: String? = null
    var isExact = false
    annotationEntries.firstOrNull {
        it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == objCNameShortName
    }?.let { annotation ->
        fun ValueArgument.getStringValue(): String? {
            val stringTemplateExpression = when (this) {
                is KtValueArgument -> stringTemplateExpression
                else -> getArgumentExpression() as? KtStringTemplateExpression
            } ?: return null
            return (stringTemplateExpression.entries.singleOrNull() as? KtLiteralStringTemplateEntry)?.text
        }

        fun ValueArgument.getBooleanValue(): Boolean =
                (getArgumentExpression() as? KtConstantExpression)?.text?.toBooleanStrictOrNull() ?: false

        val argNames = setOf("name", "swiftName", "exact")
        val processedArgs = mutableSetOf<String>()
        for (argument in annotation.valueArguments) {
            val argName = argument.getArgumentName()?.asName?.asString() ?: (argNames - processedArgs).firstOrNull() ?: break
            when (argName) {
                "name" -> objCName = argument.getStringValue()
                "swiftName" -> swiftName = argument.getStringValue()
                "exact" -> isExact = argument.getBooleanValue()
            }
            processedArgs.add(argName)
        }
    }
    return ObjCName(name!!, objCName, swiftName, isExact)
}

internal val ModuleDescriptor.objCExportAdditionalNamePrefix: String get() {
    if (this.isNativeStdlib()) return "Kotlin"

    val fullPrefix = when(val module = this.klibModuleOrigin) {
        CurrentKlibModuleOrigin ->
            error("expected deserialized module, got $this (origin = $module)")
        SyntheticModulesOrigin ->
            this.name.asString().let { it.substring(1, it.lastIndex) }
        is DeserializedKlibModuleOrigin ->
            module.library.let { it.shortName ?: it.uniqueName }
    }

    return abbreviate(fullPrefix)
}

internal val Context.objCExportTopLevelNamePrefix: String
    get() = abbreviate(config.fullExportedNamePrefix)