[K/N] Add ObjCName annotation (#4815)
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -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 {
|
||||
|
||||
+1
@@ -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")
|
||||
}
|
||||
|
||||
+11
-6
@@ -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
|
||||
}
|
||||
|
||||
+194
-70
@@ -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
|
||||
+3
@@ -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 {
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -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)
|
||||
|
||||
+145
@@ -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
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -25,7 +25,8 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
|
||||
),
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeThrowsChecker, NativeSharedImmutableChecker,
|
||||
NativeTopLevelSingletonChecker, NativeThreadLocalChecker
|
||||
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
|
||||
NativeObjCNameChecker
|
||||
)
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
|
||||
Reference in New Issue
Block a user