[K/N] Add ObjCName annotation (#4815)

This commit is contained in:
Rick Clephas
2022-07-23 18:58:06 +02:00
committed by GitHub
parent edf9e05b13
commit 5a5e6ad8cd
22 changed files with 1372 additions and 78 deletions
+179
View File
@@ -0,0 +1,179 @@
// FILE: kotlin.kt
package kotlin.native
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.PROPERTY,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
public annotation class ObjCName(val name: String = "", val swiftName: String = "", val exact: Boolean = false)
// FILE: test.kt
@ObjCName("ObjCClass", "SwiftClass")
open class KotlinClass {
@ObjCName("objCProperty")
open var kotlinProperty: Int = 0
@ObjCName(swiftName = "swiftFunction")
open fun @receiver:ObjCName("objCReceiver") Int.kotlinFunction(
@ObjCName("objCParam") kotlinParam: Int
): Int = this + kotlinParam
}
@ObjCName("ObjCSubClass", "SwiftSubClass")
class KotlinSubClass: KotlinClass() {
<!INAPPLICABLE_OBJC_NAME!>@ObjCName("objCProperty")<!>
override var kotlinProperty: Int = 1
<!INAPPLICABLE_OBJC_NAME!>@ObjCName(swiftName = "swiftFunction")<!>
override fun <!INAPPLICABLE_OBJC_NAME!>@receiver:ObjCName("objCReceiver")<!> Int.kotlinFunction(
<!INAPPLICABLE_OBJC_NAME!>@ObjCName("objCParam")<!> kotlinParam: Int
): Int = this + kotlinParam * 2
}
<!INVALID_OBJC_NAME!>@ObjCName()<!>
val invalidObjCName: Int = 0
<!INVALID_OBJC_NAME_CHARS!>@ObjCName("validName", "invalid.name")<!>
val invalidCharactersObjCNameA: Int = 0
<!INVALID_OBJC_NAME_CHARS!>@ObjCName("invalid.name", "validName")<!>
val invalidCharactersObjCNameB: Int = 0
<!INVALID_OBJC_NAME_FIRST_CHAR!>@ObjCName("validName1", "1validName")<!>
val invalidFirstCharacterObjCNameA: Int = 0
<!INVALID_OBJC_NAME_FIRST_CHAR!>@ObjCName("1validName", "validName1")<!>
val invalidFirstCharacterObjCNameB: Int = 0
<!MISSING_EXACT_OBJC_NAME!>@ObjCName(swiftName = "SwiftMissingExactName", exact = true)<!>
class MissingExactName
interface KotlinInterfaceA {
@ObjCName("objCPropertyA", "swiftPropertyA")
var kotlinPropertyA: Int
@ObjCName("objCPropertyB", "swiftPropertyB")
var kotlinPropertyB: Int
@ObjCName("objCPropertyB")
var kotlinPropertyC: Int
@ObjCName(swiftName ="swiftPropertyB")
var kotlinPropertyD: Int
var kotlinPropertyE: Int
var kotlinPropertyF: Int
@ObjCName("objCFunctionA", "swiftFunctionA")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionA(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionB", "swiftFunctionB")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionB(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionC", "swiftFunctionC")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionC(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionD", "swiftFunctionD")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionD(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionE", "swiftFunctionE")
fun Int.kotlinFunctionE(@ObjCName("objCParam", "swiftParam") kotlinParam: Int): Int
}
interface KotlinInterfaceB {
@ObjCName("objCPropertyA", "swiftPropertyA")
var kotlinPropertyA: Int
@ObjCName("objCPropertyBB", "swiftPropertyB")
var kotlinPropertyB: Int
@ObjCName(swiftName ="swiftPropertyC")
var kotlinPropertyC: Int
@ObjCName("objCPropertyD")
var kotlinPropertyD: Int
@ObjCName("objCPropertyE")
var kotlinPropertyE: Int
var kotlinPropertyF: Int
@ObjCName("objCFunctionA", "swiftFunctionA")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionA(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionBB", "swiftFunctionB")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionB(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionC", "swiftFunctionC")
fun @receiver:ObjCName("objCReceiverC", "swiftReceiver") Int.kotlinFunctionC(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
@ObjCName("objCFunctionD", "swiftFunctionD")
fun @receiver:ObjCName("objCReceiver", "swiftReceiver") Int.kotlinFunctionD(
@ObjCName("objCParamD", "swiftParam") kotlinParam: Int
): Int
fun @receiver:ObjCName("objCFunctionE", "swiftFunctionE") Int.kotlinFunctionE(
@ObjCName("objCParam", "swiftParam") kotlinParam: Int
): Int
}
class KotlinOverrideClass: KotlinInterfaceA, KotlinInterfaceB {
override var kotlinPropertyA: Int = 0
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override var kotlinPropertyB: Int = 0<!>
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override var kotlinPropertyC: Int = 0<!>
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override var kotlinPropertyD: Int = 0<!>
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override var kotlinPropertyE: Int = 0<!>
override var kotlinPropertyF: Int = 0
override fun Int.kotlinFunctionA(kotlinParam: Int): Int = this + kotlinParam
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override fun Int.kotlinFunctionB(kotlinParam: Int): Int = this + kotlinParam<!>
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override fun Int.kotlinFunctionC(kotlinParam: Int): Int = this + kotlinParam<!>
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override fun Int.kotlinFunctionD(kotlinParam: Int): Int = this + kotlinParam<!>
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>override fun Int.kotlinFunctionE(kotlinParam: Int): Int = this + kotlinParam<!>
}
@ObjCName("ObjCExactChecks", exact = true)
class ExactChecks {
<!INAPPLICABLE_EXACT_OBJC_NAME!>@ObjCName("objCProperty", exact = true)<!>
var property: Int = 0
<!INAPPLICABLE_EXACT_OBJC_NAME!>@ObjCName("objCFunction", exact = true)<!>
fun <!INAPPLICABLE_EXACT_OBJC_NAME!>@receiver:ObjCName("objCReceiver", exact = true)<!> Int.function(
<!INAPPLICABLE_EXACT_OBJC_NAME!>@ObjCName("objCParam", exact = true)<!> param: Int
): Int = this * param
}
@ObjCName("ObjCEnumExactChecks", exact = true)
enum class EnumExactChecks {
<!INAPPLICABLE_EXACT_OBJC_NAME!>@ObjCName("objCEntryOne", exact = true)<!>
ENTRY_ONE,
@ObjCName("objCEntryTwo")
ENTRY_TWO
}
open class Base {
@ObjCName("foo1")
open fun foo() {}
}
interface I {
@ObjCName("foo2")
fun foo()
}
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>open class Derived : Base(), I<!>
open class Derived2 : Derived() {
override fun foo() {}
}
private const val exact = false
private const val objcName = "nonLiteralArgsObjC"
@ObjCName(
<!NON_LITERAL_OBJC_NAME_ARG!>objcName<!>,
<!NON_LITERAL_OBJC_NAME_ARG!>"nonLiteralArgs" + "Swift"<!>,
<!NON_LITERAL_OBJC_NAME_ARG!>exact<!>
)
val nonLiteralArgs: Int = 0
@ObjCName("invalidArgsObjC", <!CONSTANT_EXPECTED_TYPE_MISMATCH!>false<!>, <!TYPE_MISMATCH!>"not a boolean"<!>)
val invalidArgs: Int = 0
+163
View File
@@ -0,0 +1,163 @@
package
private const val exact: kotlin.Boolean = false
@kotlin.native.ObjCName(exact = "not a boolean", name = "invalidArgsObjC", swiftName = false) public val invalidArgs: kotlin.Int = 0
@kotlin.native.ObjCName(name = "validName", swiftName = "invalid.name") public val invalidCharactersObjCNameA: kotlin.Int = 0
@kotlin.native.ObjCName(name = "invalid.name", swiftName = "validName") public val invalidCharactersObjCNameB: kotlin.Int = 0
@kotlin.native.ObjCName(name = "validName1", swiftName = "1validName") public val invalidFirstCharacterObjCNameA: kotlin.Int = 0
@kotlin.native.ObjCName(name = "1validName", swiftName = "validName1") public val invalidFirstCharacterObjCNameB: kotlin.Int = 0
@kotlin.native.ObjCName public val invalidObjCName: kotlin.Int = 0
@kotlin.native.ObjCName(exact = false, name = "nonLiteralArgsObjC", swiftName = "nonLiteralArgsSwift") public val nonLiteralArgs: kotlin.Int = 0
private const val objcName: kotlin.String = "nonLiteralArgsObjC"
public open class Base {
public constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.native.ObjCName(name = "foo1") public open fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class Derived : Base, I {
public constructor Derived()
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.native.ObjCName(name = "foo1") public open override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class Derived2 : Derived {
public constructor Derived2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.native.ObjCName(exact = true, name = "ObjCEnumExactChecks") public final enum class EnumExactChecks : kotlin.Enum<EnumExactChecks> {
@kotlin.native.ObjCName(exact = true, name = "objCEntryOne") enum entry ENTRY_ONE
@kotlin.native.ObjCName(name = "objCEntryTwo") enum entry ENTRY_TWO
private constructor EnumExactChecks()
@kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: EnumExactChecks): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): EnumExactChecks
public final /*synthesized*/ fun values(): kotlin.Array<EnumExactChecks>
}
@kotlin.native.ObjCName(exact = true, name = "ObjCExactChecks") public final class ExactChecks {
public constructor ExactChecks()
@kotlin.native.ObjCName(exact = true, name = "objCProperty") public final var property: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@kotlin.native.ObjCName(exact = true, name = "objCFunction") public final fun @receiver:kotlin.native.ObjCName(exact = true, name = "objCReceiver") kotlin.Int.function(/*0*/ @kotlin.native.ObjCName(exact = true, name = "objCParam") param: kotlin.Int): kotlin.Int
}
public interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.native.ObjCName(name = "foo2") public abstract fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.native.ObjCName(name = "ObjCClass", swiftName = "SwiftClass") public open class KotlinClass {
public constructor KotlinClass()
@kotlin.native.ObjCName(name = "objCProperty") public open var kotlinProperty: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@kotlin.native.ObjCName(swiftName = "swiftFunction") public open fun @receiver:kotlin.native.ObjCName(name = "objCReceiver") kotlin.Int.kotlinFunction(/*0*/ @kotlin.native.ObjCName(name = "objCParam") kotlinParam: kotlin.Int): kotlin.Int
}
public interface KotlinInterfaceA {
@kotlin.native.ObjCName(name = "objCPropertyA", swiftName = "swiftPropertyA") public abstract var kotlinPropertyA: kotlin.Int
@kotlin.native.ObjCName(name = "objCPropertyB", swiftName = "swiftPropertyB") public abstract var kotlinPropertyB: kotlin.Int
@kotlin.native.ObjCName(name = "objCPropertyB") public abstract var kotlinPropertyC: kotlin.Int
@kotlin.native.ObjCName(swiftName = "swiftPropertyB") public abstract var kotlinPropertyD: kotlin.Int
public abstract var kotlinPropertyE: kotlin.Int
public abstract var kotlinPropertyF: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@kotlin.native.ObjCName(name = "objCFunctionA", swiftName = "swiftFunctionA") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionA(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionB", swiftName = "swiftFunctionB") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionB(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionC", swiftName = "swiftFunctionC") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionC(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionD", swiftName = "swiftFunctionD") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionD(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionE", swiftName = "swiftFunctionE") public abstract fun kotlin.Int.kotlinFunctionE(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
}
public interface KotlinInterfaceB {
@kotlin.native.ObjCName(name = "objCPropertyA", swiftName = "swiftPropertyA") public abstract var kotlinPropertyA: kotlin.Int
@kotlin.native.ObjCName(name = "objCPropertyBB", swiftName = "swiftPropertyB") public abstract var kotlinPropertyB: kotlin.Int
@kotlin.native.ObjCName(swiftName = "swiftPropertyC") public abstract var kotlinPropertyC: kotlin.Int
@kotlin.native.ObjCName(name = "objCPropertyD") public abstract var kotlinPropertyD: kotlin.Int
@kotlin.native.ObjCName(name = "objCPropertyE") public abstract var kotlinPropertyE: kotlin.Int
public abstract var kotlinPropertyF: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@kotlin.native.ObjCName(name = "objCFunctionA", swiftName = "swiftFunctionA") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionA(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionBB", swiftName = "swiftFunctionB") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionB(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionC", swiftName = "swiftFunctionC") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiverC", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionC(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
@kotlin.native.ObjCName(name = "objCFunctionD", swiftName = "swiftFunctionD") public abstract fun @receiver:kotlin.native.ObjCName(name = "objCReceiver", swiftName = "swiftReceiver") kotlin.Int.kotlinFunctionD(/*0*/ @kotlin.native.ObjCName(name = "objCParamD", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
public abstract fun @receiver:kotlin.native.ObjCName(name = "objCFunctionE", swiftName = "swiftFunctionE") kotlin.Int.kotlinFunctionE(/*0*/ @kotlin.native.ObjCName(name = "objCParam", swiftName = "swiftParam") kotlinParam: kotlin.Int): kotlin.Int
}
public final class KotlinOverrideClass : KotlinInterfaceA, KotlinInterfaceB {
public constructor KotlinOverrideClass()
public open override /*2*/ var kotlinPropertyA: kotlin.Int
public open override /*2*/ var kotlinPropertyB: kotlin.Int
public open override /*2*/ var kotlinPropertyC: kotlin.Int
public open override /*2*/ var kotlinPropertyD: kotlin.Int
public open override /*2*/ var kotlinPropertyE: kotlin.Int
public open override /*2*/ var kotlinPropertyF: kotlin.Int
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
public open override /*2*/ fun kotlin.Int.kotlinFunctionA(/*0*/ kotlinParam: kotlin.Int): kotlin.Int
public open override /*2*/ fun kotlin.Int.kotlinFunctionB(/*0*/ kotlinParam: kotlin.Int): kotlin.Int
public open override /*2*/ fun kotlin.Int.kotlinFunctionC(/*0*/ kotlinParam: kotlin.Int): kotlin.Int
public open override /*2*/ fun kotlin.Int.kotlinFunctionD(/*0*/ kotlinParam: kotlin.Int): kotlin.Int
public open override /*2*/ fun kotlin.Int.kotlinFunctionE(/*0*/ kotlinParam: kotlin.Int): kotlin.Int
}
@kotlin.native.ObjCName(name = "ObjCSubClass", swiftName = "SwiftSubClass") public final class KotlinSubClass : KotlinClass {
public constructor KotlinSubClass()
@kotlin.native.ObjCName(name = "objCProperty") public open override /*1*/ var kotlinProperty: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@kotlin.native.ObjCName(swiftName = "swiftFunction") public open override /*1*/ fun @receiver:kotlin.native.ObjCName(name = "objCReceiver") kotlin.Int.kotlinFunction(/*0*/ @kotlin.native.ObjCName(name = "objCParam") kotlinParam: kotlin.Int): kotlin.Int
}
@kotlin.native.ObjCName(exact = true, swiftName = "SwiftMissingExactName") public final class MissingExactName {
public constructor MissingExactName()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
package kotlin {
package kotlin.native {
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.MustBeDocumented public final annotation class ObjCName : kotlin.Annotation {
public constructor ObjCName(/*0*/ name: kotlin.String = ..., /*1*/ swiftName: kotlin.String = ..., /*2*/ exact: kotlin.Boolean = ...)
public final val exact: kotlin.Boolean
public final val name: kotlin.String
public final val swiftName: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
}
@@ -30,6 +30,12 @@ public class DiagnosticsNativeTestGenerated extends AbstractDiagnosticsNativeTes
runTest("compiler/testData/diagnostics/nativeTests/identifiers.kt");
}
@Test
@TestMetadata("objCName.kt")
public void testObjCName() throws Exception {
runTest("compiler/testData/diagnostics/nativeTests/objCName.kt");
}
@Test
@TestMetadata("sharedImmutable.kt")
public void testSharedImmutable() throws Exception {
@@ -37,4 +37,5 @@ object KonanFqNames {
val gcUnsafeCall = FqName("kotlin.native.internal.GCUnsafeCall")
val eagerInitialization = FqName("kotlin.native.EagerInitialization")
val noReorderFields = FqName("kotlin.native.internal.NoReorderFields")
val objCName = FqName("kotlin.native.ObjCName")
}
@@ -387,9 +387,10 @@ internal class ObjCExportTranslatorImpl(
descriptor.enumEntries.forEach {
val entryName = namer.getEnumEntrySelector(it)
val swiftName = namer.getEnumEntrySwiftName(it)
add {
ObjCProperty(entryName, it, type, listOf("class", "readonly"),
declarationAttributes = listOf(swiftNameAttribute(entryName)))
declarationAttributes = listOf(swiftNameAttribute(swiftName)))
}
}
@@ -589,7 +590,8 @@ internal class ObjCExportTranslatorImpl(
val getterBridge = mapper.bridgeMethod(baseProperty.getter!!)
val type = mapReturnType(getterBridge.returnBridge, property.getter!!, objCExportScope)
val name = namer.getPropertyName(baseProperty)
val propertyName = namer.getPropertyName(baseProperty)
val name = propertyName.objCName
val attributes = mutableListOf<String>()
@@ -611,7 +613,7 @@ internal class ObjCExportTranslatorImpl(
val getterSelector = getSelector(baseProperty.getter!!)
val getterName: String? = if (getterSelector != name) getterSelector else null
val declarationAttributes = mutableListOf(swiftNameAttribute(name))
val declarationAttributes = mutableListOf(swiftNameAttribute(propertyName.swiftName))
declarationAttributes.addIfNotNull(mapper.getDeprecation(property)?.toDeprecationAttribute())
val visibilityComments = visibilityComments(property.visibility, "property")
@@ -804,7 +806,7 @@ internal class ObjCExportTranslatorImpl(
}
}
private val mustBeDocumentedAnnotationsStopList = setOf(StandardNames.FqNames.deprecated)
private val mustBeDocumentedAnnotationsStopList = setOf(StandardNames.FqNames.deprecated, KonanFqNames.objCName)
private fun mustBeDocumentedAnnotations(annotations: Annotations): List<String> {
return annotations.mapNotNull { it ->
it.annotationClass?.let { annotationClass ->
@@ -1404,8 +1406,11 @@ internal fun ClassDescriptor.needCompanionObjectProperty(namer: ObjCExportNamer,
val companionObject = companionObjectDescriptor
if (companionObject == null || !mapper.shouldBeExposed(companionObject)) return false
if (kind == ClassKind.ENUM_CLASS && enumEntries.any { namer.getEnumEntrySelector(it) == ObjCExportNamer.companionObjectPropertyName })
return false // 'companion' property would clash with enum entry, don't generate it.
if (kind == ClassKind.ENUM_CLASS && enumEntries.any {
namer.getEnumEntrySelector(it) == ObjCExportNamer.companionObjectPropertyName ||
namer.getEnumEntrySwiftName(it) == ObjCExportNamer.companionObjectPropertyName
}
) return false // 'companion' property would clash with enum entry, don't generate it.
return true
}
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.backend.common.serialization.findSourceFile
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.UnitSuspendFunctionObjCExport
import org.jetbrains.kotlin.backend.konan.cKeywords
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
@@ -24,10 +24,13 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal interface ObjCExportNameTranslator {
fun getFileClassName(file: KtFile): ObjCExportNamer.ClassOrProtocolName
@@ -43,6 +46,7 @@ internal interface ObjCExportNameTranslator {
interface ObjCExportNamer {
data class ClassOrProtocolName(val swiftName: String, val objCName: String, val binaryName: String = objCName)
data class PropertyName(val swiftName: String, val objCName: String)
interface Configuration {
val topLevelNamePrefix: String
@@ -56,9 +60,10 @@ interface ObjCExportNamer {
fun getClassOrProtocolName(descriptor: ClassDescriptor): ClassOrProtocolName
fun getSelector(method: FunctionDescriptor): String
fun getSwiftName(method: FunctionDescriptor): String
fun getPropertyName(property: PropertyDescriptor): String
fun getPropertyName(property: PropertyDescriptor): PropertyName
fun getObjectInstanceSelector(descriptor: ClassDescriptor): String
fun getEnumEntrySelector(descriptor: ClassDescriptor): String
fun getEnumEntrySwiftName(descriptor: ClassDescriptor): String
fun getEnumValuesSelector(descriptor: FunctionDescriptor): String
fun getTypeParameterName(typeParameterDescriptor: TypeParameterDescriptor): String
@@ -98,7 +103,7 @@ fun createNamer(
// Note: this class duplicates some of ObjCExportNamerImpl logic,
// but operates on different representation.
internal open class ObjCExportNameTranslatorImpl(
configuration: ObjCExportNamer.Configuration
private val configuration: ObjCExportNamer.Configuration
) : ObjCExportNameTranslator {
private val helper = ObjCExportNamingHelper(configuration.topLevelNamePrefix, configuration.objcGenerics)
@@ -109,30 +114,43 @@ internal open class ObjCExportNameTranslatorImpl(
override fun getCategoryName(file: KtFile): String =
helper.translateFileName(file)
override fun getClassOrProtocolName(
ktClassOrObject: KtClassOrObject
): ObjCExportNamer.ClassOrProtocolName = helper.swiftClassNameToObjC(
getClassOrProtocolSwiftName(ktClassOrObject)
)
override fun getClassOrProtocolName(ktClassOrObject: KtClassOrObject): ObjCExportNamer.ClassOrProtocolName =
ObjCExportNamer.ClassOrProtocolName(
swiftName = getClassOrProtocolAsSwiftName(ktClassOrObject, true),
objCName = buildString {
getClassOrProtocolAsSwiftName(ktClassOrObject, false).split('.').forEachIndexed { index, part ->
append(if (index == 0) part else part.replaceFirstChar(Char::uppercaseChar))
}
}
)
private fun getClassOrProtocolSwiftName(
ktClassOrObject: KtClassOrObject
private fun getClassOrProtocolAsSwiftName(
ktClassOrObject: KtClassOrObject,
forSwift: Boolean
): String = buildString {
val outerClass = ktClassOrObject.getStrictParentOfType<KtClassOrObject>()
if (outerClass != null) {
appendNameWithContainer(ktClassOrObject, outerClass)
val objCName = ktClassOrObject.getObjCName()
if (objCName.isExact) {
append(objCName.asIdentifier(forSwift))
} else {
append(ktClassOrObject.name!!.toIdentifier())
val outerClass = ktClassOrObject.getStrictParentOfType<KtClassOrObject>()
if (outerClass != null) {
appendNameWithContainer(ktClassOrObject, objCName, outerClass, forSwift)
} else {
if (!forSwift) append(configuration.topLevelNamePrefix)
append(objCName.asIdentifier(forSwift))
}
}
}
private fun StringBuilder.appendNameWithContainer(
ktClassOrObject: KtClassOrObject,
outerClass: KtClassOrObject
objCName: ObjCName,
outerClass: KtClassOrObject,
forSwift: Boolean
) = helper.appendNameWithContainer(
this,
ktClassOrObject, ktClassOrObject.name!!.toIdentifier(),
outerClass, getClassOrProtocolSwiftName(outerClass),
ktClassOrObject, objCName.asIdentifier(forSwift),
outerClass, getClassOrProtocolAsSwiftName(outerClass, forSwift),
object : ObjCExportNamingHelper.ClassInfoProvider<KtClassOrObject> {
override fun hasGenerics(clazz: KtClassOrObject): Boolean =
clazz.typeParametersWithOuter.count() != 0
@@ -162,14 +180,6 @@ private class ObjCExportNamingHelper(
return ObjCExportNamer.ClassOrProtocolName(swiftName = baseName, objCName = "$topLevelNamePrefix$baseName")
}
fun swiftClassNameToObjC(swiftName: String): ObjCExportNamer.ClassOrProtocolName =
ObjCExportNamer.ClassOrProtocolName(swiftName, buildString {
append(topLevelNamePrefix)
swiftName.split('.').forEachIndexed { index, part ->
append(if (index == 0) part else part.replaceFirstChar(Char::uppercaseChar))
}
})
fun getFileClassName(file: KtFile): ObjCExportNamer.ClassOrProtocolName =
getFileClassName(file.name)
@@ -324,13 +334,16 @@ internal class ObjCExportNamerImpl(
// Note: this condition is correct but can be too strict.
}
private val propertyNames = object : Mapping<PropertyDescriptor, String>() {
private inner class PropertyNameMapping : Mapping<PropertyDescriptor, String>() {
override fun reserved(name: String) = name in Reserved.propertyNames
override fun conflict(first: PropertyDescriptor, second: PropertyDescriptor): Boolean =
!mapper.canHaveSameName(first, second)
}
private val objCPropertyNames = PropertyNameMapping()
private val swiftPropertyNames = PropertyNameMapping()
private open inner class GlobalNameMapping<in T : Any, N> : Mapping<T, N>() {
final override fun conflict(first: T, second: T): Boolean = true
}
@@ -362,11 +375,14 @@ internal class ObjCExportNamerImpl(
override fun conflict(first: ClassDescriptor, second: ClassDescriptor) = false
}
private val enumClassSelectors = object : ClassSelectorNameMapping<DeclarationDescriptor>() {
private inner class EnumNameMapping : ClassSelectorNameMapping<DeclarationDescriptor>() {
override fun conflict(first: DeclarationDescriptor, second: DeclarationDescriptor) =
first.containingDeclaration == second.containingDeclaration
}
private val enumClassSelectors = EnumNameMapping()
private val enumClassSwiftNames = EnumNameMapping()
override fun getFileClassName(file: SourceFile): ObjCExportNamer.ClassOrProtocolName {
val candidate by lazy {
val fileName = when (file) {
@@ -401,23 +417,29 @@ internal class ObjCExportNamerImpl(
descriptor: ClassDescriptor
): String = swiftClassAndProtocolNames.getOrPut(descriptor) {
StringBuilder().apply {
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor) {
appendNameWithContainer(descriptor, containingDeclaration)
} else if (containingDeclaration is PackageFragmentDescriptor) {
appendTopLevelClassBaseName(descriptor)
val objCName = descriptor.getObjCName()
if (objCName.isExact) {
append(objCName.asIdentifier(true))
} else {
error("unexpected class parent: $containingDeclaration")
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor) {
appendSwiftNameWithContainer(descriptor, objCName, containingDeclaration)
} else if (containingDeclaration is PackageFragmentDescriptor) {
appendTopLevelClassBaseName(descriptor, objCName, true)
} else {
error("unexpected class parent: $containingDeclaration")
}
}
}.mangledBySuffixUnderscores()
}
private fun StringBuilder.appendNameWithContainer(
private fun StringBuilder.appendSwiftNameWithContainer(
clazz: ClassDescriptor,
objCName: ObjCName,
containingClass: ClassDescriptor
) = helper.appendNameWithContainer(
this,
clazz, clazz.name.asString().toIdentifier(),
clazz, objCName.asIdentifier(true),
containingClass, getClassOrProtocolSwiftName(containingClass),
object : ObjCExportNamingHelper.ClassInfoProvider<ClassDescriptor> {
override fun hasGenerics(clazz: ClassDescriptor): Boolean =
@@ -431,25 +453,29 @@ internal class ObjCExportNamerImpl(
val objCMapping = if (descriptor.isInterface) objCProtocolNames else objCClassNames
return objCMapping.getOrPut(descriptor) {
StringBuilder().apply {
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor) {
append(getClassOrProtocolObjCName(containingDeclaration))
.append(descriptor.name.asString().toIdentifier().replaceFirstChar(Char::uppercaseChar))
} else if (containingDeclaration is PackageFragmentDescriptor) {
append(topLevelNamePrefix).appendTopLevelClassBaseName(descriptor)
val objCName = descriptor.getObjCName()
if (objCName.isExact) {
append(objCName.asIdentifier(false))
} else {
error("unexpected class parent: $containingDeclaration")
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor) {
append(getClassOrProtocolObjCName(containingDeclaration))
.append(objCName.asIdentifier(false).replaceFirstChar(Char::uppercaseChar))
} else if (containingDeclaration is PackageFragmentDescriptor) {
append(topLevelNamePrefix).appendTopLevelClassBaseName(descriptor, objCName, false)
} else {
error("unexpected class parent: $containingDeclaration")
}
}
}.mangledBySuffixUnderscores()
}
}
private fun StringBuilder.appendTopLevelClassBaseName(descriptor: ClassDescriptor) = apply {
private fun StringBuilder.appendTopLevelClassBaseName(descriptor: ClassDescriptor, objCName: ObjCName, forSwift: Boolean) = apply {
configuration.getAdditionalPrefix(descriptor.module)?.let {
append(it)
}
append(descriptor.name.asString().toIdentifier())
append(objCName.asIdentifier(forSwift))
}
override fun getSelector(method: FunctionDescriptor): String = methodSelectors.getOrPut(method) {
@@ -465,12 +491,12 @@ internal class ObjCExportNamerImpl(
parameters.forEachIndexed { index, (bridge, it) ->
val name = when (bridge) {
is MethodBridgeValueParameter.Mapped -> when {
it is ReceiverParameterDescriptor -> ""
it is ReceiverParameterDescriptor -> it.getObjCName().asIdentifier(false) { "" }
method is PropertySetterDescriptor -> when (parameters.size) {
1 -> ""
else -> "value"
}
else -> it!!.name.asString().toIdentifier()
else -> it!!.getObjCName().asIdentifier(false)
}
MethodBridgeValueParameter.ErrorOutParameter -> "error"
is MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
@@ -479,11 +505,8 @@ internal class ObjCExportNamerImpl(
if (index == 0) {
append(when {
bridge is MethodBridgeValueParameter.ErrorOutParameter -> "AndReturn"
bridge is MethodBridgeValueParameter.SuspendCompletion -> "With"
method is ConstructorDescriptor -> "With"
else -> ""
})
append(name.replaceFirstChar(Char::uppercaseChar))
@@ -518,12 +541,12 @@ internal class ObjCExportNamerImpl(
parameters@ for ((bridge, it) in parameters) {
val label = when (bridge) {
is MethodBridgeValueParameter.Mapped -> when {
it is ReceiverParameterDescriptor -> "_"
it is ReceiverParameterDescriptor -> it.getObjCName().asIdentifier(true) { "_" }
method is PropertySetterDescriptor -> when (parameters.size) {
1 -> "_"
else -> "value"
}
else -> it!!.name.asString().toIdentifier()
else -> it!!.getObjCName().asIdentifier(true)
}
MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters
is MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
@@ -549,38 +572,57 @@ internal class ObjCExportNamerImpl(
}
}
override fun getPropertyName(property: PropertyDescriptor): String = propertyNames.getOrPut(property) {
override fun getPropertyName(property: PropertyDescriptor): ObjCExportNamer.PropertyName {
assert(mapper.isBaseProperty(property))
assert(mapper.isObjCProperty(property))
StringBuilder().apply {
append(property.name.asString().toIdentifier())
}.mangledSequence {
append('_')
val objCName = property.getObjCName()
fun PropertyNameMapping.getOrPut(forSwift: Boolean) = getOrPut(property) {
StringBuilder().apply {
append(objCName.asIdentifier(forSwift))
}.mangledSequence {
append('_')
}
}
return ObjCExportNamer.PropertyName(
swiftName = swiftPropertyNames.getOrPut(true),
objCName = objCPropertyNames.getOrPut(false)
)
}
override fun getObjectInstanceSelector(descriptor: ClassDescriptor): String {
assert(descriptor.kind == ClassKind.OBJECT)
return objectInstanceSelectors.getOrPut(descriptor) {
val name = descriptor.name.asString().replaceFirstChar(Char::lowercaseChar).toIdentifier().mangleIfSpecialFamily("get")
val name = descriptor.getObjCName().asString(false)
.replaceFirstChar(Char::lowercaseChar).toIdentifier().mangleIfSpecialFamily("get")
StringBuilder(name).mangledBySuffixUnderscores()
}
}
private fun ClassDescriptor.getEnumEntryName(forSwift: Boolean): Sequence<String> {
val name = getObjCName().asIdentifier(forSwift) {
// FOO_BAR_BAZ -> fooBarBaz:
it.split('_').mapIndexed { index, s ->
val lower = s.lowercase()
if (index == 0) lower else lower.replaceFirstChar(Char::uppercaseChar)
}.joinToString("").toIdentifier()
}.mangleIfSpecialFamily("the")
return StringBuilder(name).mangledBySuffixUnderscores()
}
override fun getEnumEntrySelector(descriptor: ClassDescriptor): String {
assert(descriptor.kind == ClassKind.ENUM_ENTRY)
return enumClassSelectors.getOrPut(descriptor) {
// FOO_BAR_BAZ -> fooBarBaz:
val name = descriptor.name.asString().split('_').mapIndexed { index, s ->
val lower = s.lowercase()
if (index == 0) lower else lower.replaceFirstChar(Char::uppercaseChar)
}.joinToString("").toIdentifier().mangleIfSpecialFamily("the")
descriptor.getEnumEntryName(false)
}
}
StringBuilder(name).mangledBySuffixUnderscores()
override fun getEnumEntrySwiftName(descriptor: ClassDescriptor): String {
assert(descriptor.kind == ClassKind.ENUM_ENTRY)
return enumClassSwiftNames.getOrPut(descriptor) {
descriptor.getEnumEntryName(true)
}
}
@@ -677,10 +719,12 @@ internal class ObjCExportNamerImpl(
}
val candidate = when (this) {
is PropertyGetterDescriptor -> this.correspondingProperty.name.asString()
is PropertySetterDescriptor -> "set${this.correspondingProperty.name.asString().replaceFirstChar(kotlin.Char::uppercaseChar)}"
else -> this.name.asString()
}.toIdentifier()
is PropertyGetterDescriptor -> this.correspondingProperty.getObjCName().asIdentifier(forSwift)
is PropertySetterDescriptor -> "set${
this.correspondingProperty.getObjCName().asString(forSwift).replaceFirstChar(kotlin.Char::uppercaseChar)
}".toIdentifier()
else -> this.getObjCName().asIdentifier(forSwift)
}
return candidate.mangleIfSpecialFamily("do")
}
@@ -902,6 +946,86 @@ private fun ObjCExportMapper.canHaveSameName(first: PropertyDescriptor, second:
return bridgePropertyType(first) == bridgePropertyType(second)
}
private class ObjCName(
private val kotlinName: String,
private val objCName: String?,
private val swiftName: String?,
val isExact: Boolean
) {
// TODO: Prevent mangling when objCName or swiftName is provided
fun asString(forSwift: Boolean): String = swiftName.takeIf { forSwift } ?: objCName ?: kotlinName
fun asIdentifier(forSwift: Boolean, default: (String) -> String = { it.toIdentifier() }): String =
swiftName.takeIf { forSwift } ?: objCName ?: default(kotlinName)
}
private fun DeclarationDescriptor.getObjCName(): ObjCName {
var objCName: String? = null
var swiftName: String? = null
var isExact = false
annotations.findAnnotation(KonanFqNames.objCName)?.let { annotation ->
objCName = annotation.argumentValue("name")?.value?.cast()
swiftName = annotation.argumentValue("swiftName")?.value?.cast()
isExact = annotation.argumentValue("exact")?.value?.cast() ?: false
}
return ObjCName(name.asString(), objCName, swiftName, isExact)
}
private fun <T> T.upcast(): T = this
private fun CallableDescriptor.getObjCName(): ObjCName =
overriddenDescriptors.firstOrNull()?.getObjCName() ?: upcast<DeclarationDescriptor>().getObjCName()
private fun ParameterDescriptor.getObjCName(): ObjCName {
val callableDescriptor = containingDeclaration as? CallableDescriptor ?: return upcast<CallableDescriptor>().getObjCName()
fun CallableDescriptor.getBase(): CallableDescriptor = overriddenDescriptors.firstOrNull()?.getBase() ?: this
val baseCallableDescriptor = callableDescriptor.getBase()
if (callableDescriptor.extensionReceiverParameter == this) {
return baseCallableDescriptor.extensionReceiverParameter!!.upcast<CallableDescriptor>().getObjCName()
}
val parameterIndex = callableDescriptor.valueParameters.indexOf(this)
if (parameterIndex != -1) {
return baseCallableDescriptor.valueParameters[parameterIndex].upcast<CallableDescriptor>().getObjCName()
}
error("Unexpected parameter: $this")
}
private val objCNameShortName = KonanFqNames.objCName.shortName().asString()
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"
@@ -1212,6 +1212,132 @@ __attribute__((swift_name("NoAutoreleaseKt")))
+ (void)useIntArrayArray:(KtKotlinIntArray *)array __attribute__((swift_name("useIntArray(array:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC1A")))
@interface KtObjCNameC1A : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (NSString *)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameAKt")))
@interface KtObjCNameAKt : KtBase
+ (NSString *)withUserId:(NSString *)userId __attribute__((swift_name("with(userId:)")));
+ (BOOL)supportsFeatures:(BOOL)features __attribute__((swift_name("supports(_:)")));
+ (NSString *)scanForPeripheralsWithServices:(int32_t)serviceUUIDs options:(NSString *)options __attribute__((swift_name("scanForPeripherals(withServices:options:)")));
+ (NSString *)registerForConnectionEventsWithOptions:(NSString *)options __attribute__((swift_name("registerForConnectionEvents(options:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC1B")))
@interface KtObjCNameC1B : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (NSString *)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("MySwiftArray")))
@interface KtMyObjCArray : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)indexOfObject:(int32_t)element __attribute__((swift_name("index(of:)")));
@property (readonly) int32_t count __attribute__((swift_name("count")));
@end
__attribute__((swift_name("ObjCNameI1")))
@protocol KtObjCNameI1
@required
- (int32_t)someOtherFunctionReceiver:(int32_t)receiver otherParam:(int32_t)param __attribute__((swift_name("someOtherFunction(receiver:otherParam:)")));
@property (readonly) int32_t someOtherValue __attribute__((swift_name("someOtherValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC2")))
@interface KtObjCNameC2 : KtBase <KtObjCNameI1>
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)someOtherFunctionReceiver:(int32_t)receiver otherParam:(int32_t)param __attribute__((swift_name("someOtherFunction(receiver:otherParam:)")));
@property int32_t someOtherValue __attribute__((swift_name("someOtherValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC2.SwiftNestedClass")))
@interface KtObjCNameC2ObjCNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftExactNestedClass")))
@interface ObjCExactNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC3")))
@interface ObjCNameC3 : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC3.SwiftNestedClass")))
@interface ObjCNameC3ObjCNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC4")))
@interface KtObjCNameC4 : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)fooObjCReceiver:(int32_t)receiver objCParam:(int32_t)param __attribute__((swift_name("foo(objCReceiver:objCParam:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftObject")))
@interface KtObjCNameObjCObject : KtBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)objCNameObjCObject __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) KtObjCNameObjCObject *shared __attribute__((swift_name("shared")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftEnum")))
@interface KtObjCNameObjCEnum : KtKotlinEnum<KtObjCNameObjCEnum *>
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
@property (class, readonly) KtObjCNameObjCEnum *objcOne __attribute__((swift_name("swiftOne")));
@property (class, readonly) KtObjCNameObjCEnum *objcTwo __attribute__((swift_name("companion")));
@property (class, readonly) KtObjCNameObjCEnum *objcThree __attribute__((swift_name("swiftThree")));
+ (KtKotlinArray<KtObjCNameObjCEnum *> *)values __attribute__((swift_name("values()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftEnum.Companion")))
@interface KtObjCNameObjCEnumCompanion : KtBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)companion __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) KtObjCNameObjCEnumCompanion *shared __attribute__((swift_name("shared")));
- (int32_t)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameBKt")))
@interface KtObjCNameBKt : KtBase
+ (int32_t)getSomeValueOf:(id<KtObjCNameI1>)receiver __attribute__((swift_name("getSomeValue(of:)")));
@end
__attribute__((swift_name("OverrideKotlinMethods2")))
@protocol KtOverrideKotlinMethods2
@required
@@ -1147,6 +1147,132 @@ __attribute__((swift_name("NoAutoreleaseKt")))
+ (void)useIntArrayArray:(KtKotlinIntArray *)array __attribute__((swift_name("useIntArray(array:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC1A")))
@interface KtObjCNameC1A : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (NSString *)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameAKt")))
@interface KtObjCNameAKt : KtBase
+ (NSString *)withUserId:(NSString *)userId __attribute__((swift_name("with(userId:)")));
+ (BOOL)supportsFeatures:(BOOL)features __attribute__((swift_name("supports(_:)")));
+ (NSString *)scanForPeripheralsWithServices:(int32_t)serviceUUIDs options:(NSString *)options __attribute__((swift_name("scanForPeripherals(withServices:options:)")));
+ (NSString *)registerForConnectionEventsWithOptions:(NSString *)options __attribute__((swift_name("registerForConnectionEvents(options:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC1B")))
@interface KtObjCNameC1B : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (NSString *)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("MySwiftArray")))
@interface KtMyObjCArray : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)indexOfObject:(int32_t)element __attribute__((swift_name("index(of:)")));
@property (readonly) int32_t count __attribute__((swift_name("count")));
@end
__attribute__((swift_name("ObjCNameI1")))
@protocol KtObjCNameI1
@required
- (int32_t)someOtherFunctionReceiver:(int32_t)receiver otherParam:(int32_t)param __attribute__((swift_name("someOtherFunction(receiver:otherParam:)")));
@property (readonly) int32_t someOtherValue __attribute__((swift_name("someOtherValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC2")))
@interface KtObjCNameC2 : KtBase <KtObjCNameI1>
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)someOtherFunctionReceiver:(int32_t)receiver otherParam:(int32_t)param __attribute__((swift_name("someOtherFunction(receiver:otherParam:)")));
@property int32_t someOtherValue __attribute__((swift_name("someOtherValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC2.SwiftNestedClass")))
@interface KtObjCNameC2ObjCNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftExactNestedClass")))
@interface ObjCExactNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC3")))
@interface ObjCNameC3 : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC3.SwiftNestedClass")))
@interface ObjCNameC3ObjCNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC4")))
@interface KtObjCNameC4 : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)fooObjCReceiver:(int32_t)receiver objCParam:(int32_t)param __attribute__((swift_name("foo(objCReceiver:objCParam:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftObject")))
@interface KtObjCNameObjCObject : KtBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)objCNameObjCObject __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) KtObjCNameObjCObject *shared __attribute__((swift_name("shared")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftEnum")))
@interface KtObjCNameObjCEnum : KtKotlinEnum<KtObjCNameObjCEnum *>
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
@property (class, readonly) KtObjCNameObjCEnum *objcOne __attribute__((swift_name("swiftOne")));
@property (class, readonly) KtObjCNameObjCEnum *objcTwo __attribute__((swift_name("companion")));
@property (class, readonly) KtObjCNameObjCEnum *objcThree __attribute__((swift_name("swiftThree")));
+ (KtKotlinArray<KtObjCNameObjCEnum *> *)values __attribute__((swift_name("values()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftEnum.Companion")))
@interface KtObjCNameObjCEnumCompanion : KtBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)companion __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) KtObjCNameObjCEnumCompanion *shared __attribute__((swift_name("shared")));
- (int32_t)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameBKt")))
@interface KtObjCNameBKt : KtBase
+ (int32_t)getSomeValueOf:(id<KtObjCNameI1>)receiver __attribute__((swift_name("getSomeValue(of:)")));
@end
__attribute__((swift_name("OverrideKotlinMethods2")))
@protocol KtOverrideKotlinMethods2
@required
@@ -1147,6 +1147,132 @@ __attribute__((swift_name("NoAutoreleaseKt")))
+ (void)useIntArrayArray:(KtKotlinIntArray *)array __attribute__((swift_name("useIntArray(array:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC1A")))
@interface KtObjCNameC1A : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (NSString *)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameAKt")))
@interface KtObjCNameAKt : KtBase
+ (NSString *)withUserId:(NSString *)userId __attribute__((swift_name("with(userId:)")));
+ (BOOL)supportsFeatures:(BOOL)features __attribute__((swift_name("supports(_:)")));
+ (NSString *)scanForPeripheralsWithServices:(int32_t)serviceUUIDs options:(NSString *)options __attribute__((swift_name("scanForPeripherals(withServices:options:)")));
+ (NSString *)registerForConnectionEventsWithOptions:(NSString *)options __attribute__((swift_name("registerForConnectionEvents(options:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC1B")))
@interface KtObjCNameC1B : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (NSString *)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("MySwiftArray")))
@interface KtMyObjCArray : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)indexOfObject:(int32_t)element __attribute__((swift_name("index(of:)")));
@property (readonly) int32_t count __attribute__((swift_name("count")));
@end
__attribute__((swift_name("ObjCNameI1")))
@protocol KtObjCNameI1
@required
- (int32_t)someOtherFunctionReceiver:(int32_t)receiver otherParam:(int32_t)param __attribute__((swift_name("someOtherFunction(receiver:otherParam:)")));
@property (readonly) int32_t someOtherValue __attribute__((swift_name("someOtherValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC2")))
@interface KtObjCNameC2 : KtBase <KtObjCNameI1>
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)someOtherFunctionReceiver:(int32_t)receiver otherParam:(int32_t)param __attribute__((swift_name("someOtherFunction(receiver:otherParam:)")));
@property int32_t someOtherValue __attribute__((swift_name("someOtherValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC2.SwiftNestedClass")))
@interface KtObjCNameC2ObjCNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftExactNestedClass")))
@interface ObjCExactNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC3")))
@interface ObjCNameC3 : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("SwiftNameC3.SwiftNestedClass")))
@interface ObjCNameC3ObjCNestedClass : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property int32_t nestedValue __attribute__((swift_name("nestedValue")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameC4")))
@interface KtObjCNameC4 : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (int32_t)fooObjCReceiver:(int32_t)receiver objCParam:(int32_t)param __attribute__((swift_name("foo(objCReceiver:objCParam:)")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftObject")))
@interface KtObjCNameObjCObject : KtBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)objCNameObjCObject __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) KtObjCNameObjCObject *shared __attribute__((swift_name("shared")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftEnum")))
@interface KtObjCNameObjCEnum : KtKotlinEnum
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
@property (class, readonly) KtObjCNameObjCEnum *objcOne __attribute__((swift_name("swiftOne")));
@property (class, readonly) KtObjCNameObjCEnum *objcTwo __attribute__((swift_name("companion")));
@property (class, readonly) KtObjCNameObjCEnum *objcThree __attribute__((swift_name("swiftThree")));
+ (KtKotlinArray *)values __attribute__((swift_name("values()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameSwiftEnum.Companion")))
@interface KtObjCNameObjCEnumCompanion : KtBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)companion __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) KtObjCNameObjCEnumCompanion *shared __attribute__((swift_name("shared")));
- (int32_t)foo __attribute__((swift_name("foo()")));
@end
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ObjCNameBKt")))
@interface KtObjCNameBKt : KtBase
+ (int32_t)getSomeValueOf:(id<KtObjCNameI1>)receiver __attribute__((swift_name("getSomeValue(of:)")));
@end
__attribute__((swift_name("OverrideKotlinMethods2")))
@protocol KtOverrideKotlinMethods2
@required
@@ -0,0 +1,78 @@
import Kt
private func testObjCNameClassNames() throws {
try assertEquals(actual: ObjCNameC1A().foo(), expected: "a")
try assertEquals(actual: ObjCNameC1B().foo(), expected: "b")
}
private func testObjCNameFunctionName() throws {
try assertEquals(actual: ObjCNameAKt.with(userId: "abc"), expected: "abc")
}
private func testObjCNameParameterNames() throws {
try assertEquals(actual: ObjCNameAKt.supports(true), expected: true)
try assertEquals(actual: ObjCNameAKt.scanForPeripherals(withServices: 123, options: "abc"), expected: "123 abc")
try assertEquals(actual: ObjCNameAKt.registerForConnectionEvents(options: "abc"), expected: "abc")
}
private func testObjCNameReceiverName() throws {
let object = SwiftNameC2()
try assertEquals(actual: ObjCNameBKt.getSomeValue(of: object), expected: 0)
}
private func testObjCNameMySwiftArray() throws {
let array = MySwiftArray()
try assertEquals(actual: array.count, expected: 0)
try assertEquals(actual: array.index(of: 1), expected: 1)
}
private func testObjCNameOverrides() throws {
let object = SwiftNameC2()
try assertEquals(actual: object.someOtherValue, expected: 0)
object.someOtherValue = 1
try assertEquals(actual: object.someOtherValue, expected: 1)
try assertEquals(actual: object.someOtherFunction(receiver: 2, otherParam: 4), expected: 8)
try assertEquals(actual: ObjCNameC4().foo(objCReceiver: 3, objCParam: 5), expected: 15)
}
private func testObjCNameNestedClass() throws {
let object = SwiftNameC2.SwiftNestedClass()
try assertEquals(actual: object.nestedValue, expected: 1)
object.nestedValue = 2
try assertEquals(actual: object.nestedValue, expected: 2)
}
private func testObjCNameExact() throws {
try assertEquals(actual: SwiftExactNestedClass().nestedValue, expected: 1)
try assertEquals(actual: SwiftNameC3.SwiftNestedClass().nestedValue, expected: 2)
}
private func testObjCNameObject() throws {
try assertEquals(actual: ObjCNameSwiftObject.shared, expected: ObjCNameSwiftObject())
}
private func testObjCNameEnum() throws {
let enumValues = ObjCNameSwiftEnum.values()
try assertEquals(actual: enumValues.size, expected: 3)
try assertSame(actual: enumValues.get(index: 0) as AnyObject, expected: ObjCNameSwiftEnum.swiftOne)
try assertSame(actual: enumValues.get(index: 1) as AnyObject, expected: ObjCNameSwiftEnum.companion)
try assertSame(actual: enumValues.get(index: 2) as AnyObject, expected: ObjCNameSwiftEnum.swiftThree)
try assertEquals(actual: ObjCNameSwiftEnum.Companion.shared.foo(), expected: 0)
}
class ObjCNameTests : SimpleTestProvider {
override init() {
super.init()
test("TestObjCNameClassNames", testObjCNameClassNames)
test("TestObjCNameFunctionName", testObjCNameFunctionName)
test("TestObjCNameParameterNames", testObjCNameParameterNames)
test("TestObjCNameReceiverName", testObjCNameReceiverName)
test("TestObjCNameMySwiftArray", testObjCNameMySwiftArray)
test("TestObjCNameOverrides", testObjCNameOverrides)
test("TestObjCNameNestedClass", testObjCNameNestedClass)
test("TestObjCNameExact", testObjCNameExact)
test("TestObjCNameObject", testObjCNameObject)
test("TestObjCNameEnum", testObjCNameEnum)
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2022 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.
*/
@file:OptIn(ExperimentalObjCName::class)
package objCNameA
import kotlin.experimental.ExperimentalObjCName
// https://youtrack.jetbrains.com/issue/KT-50767
@ObjCName("ObjCNameC1A")
class ObjCNameC1 {
fun foo(): String = "a"
}
// https://youtrack.jetbrains.com/issue/KT-48076
@ObjCName("with")
fun withUserId(userId: String): String = userId
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/3240586-supports
fun supports(@ObjCName(swiftName = "_") features: Boolean): Boolean = features
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/1518986-scanforperipherals
fun scanForPeripherals(@ObjCName("withServices") serviceUUIDs: Int, options: String): String = "$serviceUUIDs $options"
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/3174844-registerforconnectionevents
fun registerForConnectionEvents(@ObjCName("withOptions", "options") options: String): String = "$options"
@@ -0,0 +1,84 @@
/*
* Copyright 2010-2022 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.
*/
@file:OptIn(ExperimentalObjCName::class)
package objCNameB
import kotlin.experimental.ExperimentalObjCName
// https://youtrack.jetbrains.com/issue/KT-50767
@ObjCName("ObjCNameC1B")
class ObjCNameC1 {
fun foo(): String = "b"
}
@ObjCName("MyObjCArray", "MySwiftArray")
class MyKotlinArray {
// https://developer.apple.com/documentation/foundation/nsarray/1409982-count
@ObjCName("count")
val size: Int = 0
// https://developer.apple.com/documentation/foundation/nsarray/1417076-index
@ObjCName(swiftName = "index")
fun indexOf(@ObjCName("object", "of") element: Int): Int = element
}
interface ObjCNameI1 {
@ObjCName("someOtherValue")
val someValue: Int
@ObjCName("someOtherFunction")
fun @receiver:ObjCName("receiver") Int.someFunction(@ObjCName("otherParam") param: Int): Int
}
fun @receiver:ObjCName("of") ObjCNameI1.getSomeValue(): Int = someValue
@ObjCName(swiftName = "SwiftNameC2")
class ObjCNameC2: ObjCNameI1 {
@ObjCName("ObjCNestedClass", "SwiftNestedClass")
class NestedClass {
var nestedValue: Int = 1
}
@ObjCName("ObjCExactNestedClass", "SwiftExactNestedClass", true)
class ExactNestedClass {
var nestedValue: Int = 1
}
override var someValue: Int = 0
override fun Int.someFunction(param: Int): Int = this * param
}
@ObjCName("ObjCNameC3", "SwiftNameC3", true)
class ObjCNameC3 {
@ObjCName("ObjCNestedClass", "SwiftNestedClass")
class NestedClass {
var nestedValue: Int = 2
}
}
private interface ObjCNameI2 {
fun @receiver:ObjCName("objCReceiver") Int.foo(@ObjCName("objCParam") param: Int): Int
}
class ObjCNameC4: ObjCNameI2 {
override fun Int.foo(param: Int): Int = this * param
}
@ObjCName("ObjCNameObjCObject", "ObjCNameSwiftObject")
object ObjCNameKotlinObject
@ObjCName("ObjCNameObjCEnum", "ObjCNameSwiftEnum")
enum class ObjCNameKotlinEnum {
@ObjCName("objcOne", "swiftOne")
KOTLIN_ONE,
@ObjCName("objcTwo", "companion")
kotlinTwo,
@ObjCName("objcThree", "swiftThree")
KotlinThree;
companion object {
fun foo(): Int = 0
}
}
@@ -5,6 +5,7 @@
package kotlin.native
import kotlin.experimental.ExperimentalObjCName
import kotlin.reflect.KClass
/**
@@ -83,3 +84,19 @@ public annotation class EagerInitialization
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
public actual annotation class CName(actual val externName: String = "", actual val shortName: String = "")
/**
* Instructs the Kotlin compiler to use a custom Objective-C and/or Swift name for this class, property, parameter or function.
* @param exact specifies if the name of a class should be interpreted as the exact name.
* E.g. the compiler won't add a top level prefix or the outer class names to exact names.
*/
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.PROPERTY,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
@ExperimentalObjCName
public actual annotation class ObjCName(actual val name: String = "", actual val swiftName: String = "", actual val exact: Boolean = false)
@@ -30,6 +30,14 @@ public inline infix fun kotlin.Byte.xor(other: kotlin.Byte): kotlin.Byte
@kotlin.internal.InlineOnly
public inline infix fun kotlin.Short.xor(other: kotlin.Short): kotlin.Short
@kotlin.RequiresOptIn
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS})
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
@kotlin.annotation.MustBeDocumented
public final annotation class ExperimentalObjCName : kotlin.Annotation {
public constructor ExperimentalObjCName()
}
@kotlin.RequiresOptIn(level = Level.ERROR)
@kotlin.annotation.MustBeDocumented
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
@@ -30,6 +30,14 @@ public inline infix fun kotlin.Byte.xor(other: kotlin.Byte): kotlin.Byte
@kotlin.internal.InlineOnly
public inline infix fun kotlin.Short.xor(other: kotlin.Short): kotlin.Short
@kotlin.RequiresOptIn
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS})
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
@kotlin.annotation.MustBeDocumented
public final annotation class ExperimentalObjCName : kotlin.Annotation {
public constructor ExperimentalObjCName()
}
@kotlin.RequiresOptIn(level = Level.ERROR)
@kotlin.annotation.MustBeDocumented
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
@@ -5,6 +5,8 @@
package kotlin.native
import kotlin.experimental.ExperimentalObjCName
/**
* Makes top level function available from C/C++ code with the given name.
*
@@ -46,3 +48,20 @@ public expect annotation class CName(val externName: String = "", val shortName:
@Retention(AnnotationRetention.BINARY)
@OptionalExpectation
expect annotation class FreezingIsDeprecated
/**
* Instructs the Kotlin compiler to use a custom Objective-C and/or Swift name for this class, property, parameter or function.
* @param exact specifies if the name of a class should be interpreted as the exact name.
* E.g. the compiler won't add a top level prefix or the outer class names to exact names.
*/
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.PROPERTY,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
@OptionalExpectation
@ExperimentalObjCName
public expect annotation class ObjCName(val name: String = "", val swiftName: String = "", val exact: Boolean = false)
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2022 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 kotlin.experimental
/**
* This annotation marks the experimental [ObjCName][kotlin.native.ObjCName] annotation.
*/
@RequiresOptIn
@Target(AnnotationTarget.ANNOTATION_CLASS)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
public annotation class ExperimentalObjCName
@@ -3122,6 +3122,9 @@ public final class kotlin/enums/EnumEntriesKt {
public static final fun enumEntries (Lkotlin/jvm/functions/Function0;)Lkotlin/enums/EnumEntries;
}
public abstract interface annotation class kotlin/experimental/ExperimentalObjCName : java/lang/annotation/Annotation {
}
public abstract interface annotation class kotlin/experimental/ExperimentalTypeInference : java/lang/annotation/Annotation {
}
@@ -38,7 +38,22 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
"@ThreadLocal is applicable only to property with backing field, to property with delegation or to objects"
)
put(ErrorsNative.INAPPLICABLE_THREAD_LOCAL_TOP_LEVEL, "@ThreadLocal is applicable only to top level declarations")
put(ErrorsNative.INVALID_CHARACTERS_NATIVE, "Name {0}", CommonRenderers.STRING);
put(ErrorsNative.INVALID_CHARACTERS_NATIVE, "Name {0}", CommonRenderers.STRING)
put(ErrorsNative.INAPPLICABLE_OBJC_NAME, "@ObjCName is not applicable on overrides")
put(ErrorsNative.INVALID_OBJC_NAME, "@ObjCName should have a name and/or swiftName")
put(ErrorsNative.INVALID_OBJC_NAME_CHARS, "@ObjCName contains illegal characters: {0}", CommonRenderers.STRING)
put(
ErrorsNative.INVALID_OBJC_NAME_FIRST_CHAR, "@ObjCName contains illegal first characters: {0}",
CommonRenderers.STRING
)
put(
ErrorsNative.INCOMPATIBLE_OBJC_NAME_OVERRIDE, "Member \"{0}\" inherits inconsistent @ObjCName from {1}",
Renderers.NAME,
CommonRenderers.commaSeparated(Renderers.NAME)
)
put(ErrorsNative.INAPPLICABLE_EXACT_OBJC_NAME, "Exact @ObjCName is only applicable to classes, objects and interfaces")
put(ErrorsNative.MISSING_EXACT_OBJC_NAME, "Exact @ObjCName is required to have an ObjC name")
put(ErrorsNative.NON_LITERAL_OBJC_NAME_ARG, "@ObjCName accepts only literal string and boolean values")
}
}
@@ -36,6 +36,22 @@ object ErrorsNative {
val VARIABLE_IN_ENUM = DiagnosticFactory0.create<KtElement>(Severity.INFO)
@JvmField
val INVALID_CHARACTERS_NATIVE = DiagnosticFactoryForDeprecation1.create<PsiElement, String>(LanguageFeature.ProhibitInvalidCharsInNativeIdentifiers)
@JvmField
val INAPPLICABLE_OBJC_NAME = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
@JvmField
val INVALID_OBJC_NAME = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
@JvmField
val INVALID_OBJC_NAME_CHARS = DiagnosticFactory1.create<KtElement, String>(Severity.ERROR)
@JvmField
val INVALID_OBJC_NAME_FIRST_CHAR = DiagnosticFactory1.create<KtElement, String>(Severity.ERROR)
@JvmField
val INCOMPATIBLE_OBJC_NAME_OVERRIDE = DiagnosticFactory2.create<KtElement, DeclarationDescriptor, Collection<DeclarationDescriptor>>(Severity.ERROR)
@JvmField
val INAPPLICABLE_EXACT_OBJC_NAME = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
@JvmField
val MISSING_EXACT_OBJC_NAME = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
@JvmField
val NON_LITERAL_OBJC_NAME_ARG = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
init {
Errors.Initializer.initializeFactoryNames(ErrorsNative::class.java)
@@ -0,0 +1,145 @@
/*
* Copyright 2010-2022 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.resolve.konan.diagnostics
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object NativeObjCNameChecker : DeclarationChecker {
private val objCNameFqName = FqName("kotlin.native.ObjCName")
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
checkDeclaration(declaration, descriptor, context)
checkOverrides(declaration, descriptor, context)
checkFakeOverrides(declaration, descriptor, context)
}
private fun checkDeclaration(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val objCNames = descriptor.getObjCNames().filterNotNull()
if (objCNames.isEmpty()) return
if (descriptor is CallableMemberDescriptor && descriptor.overriddenDescriptors.isNotEmpty()) {
objCNames.forEach {
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it.annotation) ?: declaration
context.trace.report(ErrorsNative.INAPPLICABLE_OBJC_NAME.on(reportLocation))
}
}
objCNames.forEach { checkObjCName(it, declaration, descriptor, context) }
}
// We only allow valid ObjC identifiers (even for Swift names)
private val validFirstChars = ('A'..'Z').toSet() + ('a'..'z').toSet() + '_'
private val validChars = validFirstChars + ('0'..'9').toSet()
private fun checkObjCName(
objCName: ObjCName,
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
context: DeclarationCheckerContext
) {
val annotationSource = DescriptorToSourceUtils.getSourceFromAnnotation(objCName.annotation)
annotationSource?.valueArguments?.forEach {
// We don't support constant references since that would require resolution in ObjCExportLazy
val expression = it.getArgumentExpression() ?: return@forEach
if (expression is KtConstantExpression || expression is KtStringTemplateExpression ||
(it is KtValueArgument && it.stringTemplateExpression != null)
) return@forEach
context.trace.report(ErrorsNative.NON_LITERAL_OBJC_NAME_ARG.on(expression))
}
val reportLocation = annotationSource ?: declaration
if (objCName.name == null && objCName.swiftName == null) {
context.trace.report(ErrorsNative.INVALID_OBJC_NAME.on(reportLocation))
}
val invalidNameFirstChar = objCName.name?.firstOrNull()?.takeUnless(validFirstChars::contains)
val invalidSwiftNameFirstChar = objCName.swiftName?.firstOrNull()?.takeUnless(validFirstChars::contains)
val invalidFirstChars = setOfNotNull(invalidNameFirstChar, invalidSwiftNameFirstChar)
if (invalidFirstChars.isNotEmpty()) {
context.trace.report(ErrorsNative.INVALID_OBJC_NAME_FIRST_CHAR.on(reportLocation, invalidFirstChars.joinToString("")))
}
val invalidNameChars = objCName.name?.toSet()?.subtract(validChars) ?: emptySet()
val invalidSwiftNameChars = objCName.swiftName?.toSet()?.subtract(validChars) ?: emptySet()
val invalidChars = invalidNameChars + invalidSwiftNameChars
if (invalidChars.isNotEmpty()) {
context.trace.report(ErrorsNative.INVALID_OBJC_NAME_CHARS.on(reportLocation, invalidChars.joinToString("")))
}
if (objCName.exact && (descriptor !is ClassDescriptor || descriptor.kind == ClassKind.ENUM_ENTRY)) {
context.trace.report(ErrorsNative.INAPPLICABLE_EXACT_OBJC_NAME.on(reportLocation))
}
if (objCName.exact && objCName.name == null) {
context.trace.report(ErrorsNative.MISSING_EXACT_OBJC_NAME.on(reportLocation))
}
}
private fun checkOverrides(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is CallableMemberDescriptor || descriptor.overriddenDescriptors.isEmpty()) return
val objCNames = descriptor.overriddenDescriptors.map { it.getFirstBaseDescriptor().getObjCNames() }
if (!objCNames.allNamesEquals()) {
val containingDeclarations = descriptor.overriddenDescriptors.map { it.containingDeclaration }
context.trace.report(ErrorsNative.INCOMPATIBLE_OBJC_NAME_OVERRIDE.on(declaration, descriptor, containingDeclarations))
}
}
private fun checkFakeOverrides(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is ClassDescriptor) return
descriptor.defaultType.memberScope
.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.ALL_NAME_FILTER)
.forEach {
if (it !is CallableMemberDescriptor || it.kind.isReal) return@forEach
checkOverrides(declaration, it, context)
}
}
private fun CallableMemberDescriptor.getFirstBaseDescriptor(): CallableMemberDescriptor =
if (overriddenDescriptors.isEmpty()) this else overriddenDescriptors.first().getFirstBaseDescriptor()
private class ObjCName(
val annotation: AnnotationDescriptor
) {
val name: String? = annotation.argumentValue("name")?.value?.safeAs<String>()?.takeIf { it.isNotBlank() }
val swiftName: String? = annotation.argumentValue("swiftName")?.value?.safeAs<String>()?.takeIf { it.isNotBlank() }
val exact: Boolean = annotation.argumentValue("exact")?.value?.safeAs<Boolean>() ?: false
override fun equals(other: Any?): Boolean =
other is ObjCName && name == other.name && swiftName == other.swiftName && exact == other.exact
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + swiftName.hashCode()
result = 31 * result + exact.hashCode()
return result
}
}
private fun DeclarationDescriptor.getObjCName(): ObjCName? = annotations.findAnnotation(objCNameFqName)?.let(::ObjCName)
private fun DeclarationDescriptor.getObjCNames(): List<ObjCName?> = when (this) {
is FunctionDescriptor -> buildList {
add(getObjCName())
add(extensionReceiverParameter?.getObjCName())
valueParameters.forEach { add(it.getObjCName()) }
}
else -> listOf(getObjCName())
}
private fun List<List<ObjCName?>>.allNamesEquals(): Boolean {
val first = this[0]
for (i in 1 until size) {
if (first != this[i]) return false
}
return true
}
}
@@ -25,7 +25,8 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
),
additionalDeclarationCheckers = listOf(
NativeThrowsChecker, NativeSharedImmutableChecker,
NativeTopLevelSingletonChecker, NativeThreadLocalChecker
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
NativeObjCNameChecker
)
) {
override fun configureModuleComponents(container: StorageComponentContainer) {