Retain typed generics in ObjC export stubs (#4727)
* Add ObjC export test with disabled generics * Retain typed generics in ObjC export stubs * Introduce ObjC variance enum to decouple stubs from Kotlin variance (cherry picked from commit 4d7c78b952a467ca3318c8c49d36b768fdc1ef9c)
This commit is contained in:
+61
-57
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isInterface
|
import org.jetbrains.kotlin.types.typeUtil.isInterface
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
@@ -79,19 +78,23 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
|
|
||||||
// TODO: only if appears
|
// TODO: only if appears
|
||||||
add {
|
add {
|
||||||
|
val generics = listOf("ObjectType")
|
||||||
objCInterface(
|
objCInterface(
|
||||||
namer.mutableSetName,
|
namer.mutableSetName,
|
||||||
generics = listOf("ObjectType"),
|
generics = generics,
|
||||||
superClass = "NSMutableSet<ObjectType>"
|
superClass = "NSMutableSet",
|
||||||
|
superClassGenerics = generics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: only if appears
|
// TODO: only if appears
|
||||||
add {
|
add {
|
||||||
|
val generics = listOf("KeyType", "ObjectType")
|
||||||
objCInterface(
|
objCInterface(
|
||||||
namer.mutableMapName,
|
namer.mutableMapName,
|
||||||
generics = listOf("KeyType", "ObjectType"),
|
generics = generics,
|
||||||
superClass = "NSMutableDictionary<KeyType, ObjectType>"
|
superClass = "NSMutableDictionary",
|
||||||
|
superClassGenerics = generics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,23 +195,14 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun referenceClass(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName {
|
private fun referenceClass(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName {
|
||||||
fun forwardDeclarationObjcClassName(objcGenerics: Boolean, descriptor: ClassDescriptor, namer:ObjCExportNamer): String {
|
|
||||||
val className = translateClassOrInterfaceName(descriptor)
|
|
||||||
val builder = StringBuilder(className.objCName)
|
|
||||||
if (objcGenerics)
|
|
||||||
formatGenerics(builder, descriptor.typeConstructor.parameters.map { typeParameterDescriptor ->
|
|
||||||
"${typeParameterDescriptor.variance.objcDeclaration()}${namer.getTypeParameterName(typeParameterDescriptor)}"
|
|
||||||
})
|
|
||||||
return builder.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(mapper.shouldBeExposed(descriptor)) { "Shouldn't be exposed: $descriptor" }
|
assert(mapper.shouldBeExposed(descriptor)) { "Shouldn't be exposed: $descriptor" }
|
||||||
assert(!descriptor.isInterface)
|
assert(!descriptor.isInterface)
|
||||||
generator?.requireClassOrInterface(descriptor)
|
generator?.requireClassOrInterface(descriptor)
|
||||||
|
|
||||||
return translateClassOrInterfaceName(descriptor).also {
|
return translateClassOrInterfaceName(descriptor).also { className ->
|
||||||
val objcName = forwardDeclarationObjcClassName(objcGenerics, descriptor, namer)
|
val generics = mapTypeConstructorParameters(descriptor)
|
||||||
generator?.referenceClass(objcName)
|
val forwardDeclaration = ObjCClassForwardDeclaration(className.objCName, generics)
|
||||||
|
generator?.referenceClass(forwardDeclaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,14 +290,14 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun superClassGenerics(genericExportScope: ObjCExportScope): List<ObjCNonNullReferenceType> {
|
fun superClassGenerics(genericExportScope: ObjCExportScope): List<ObjCNonNullReferenceType> {
|
||||||
val parentType = computeSuperClassType(descriptor)
|
if (objcGenerics) {
|
||||||
return if(parentType != null) {
|
computeSuperClassType(descriptor)?.let { parentType ->
|
||||||
parentType.arguments.map { typeProjection ->
|
return parentType.arguments.map { typeProjection ->
|
||||||
mapReferenceTypeIgnoringNullability(typeProjection.type, genericExportScope)
|
mapReferenceTypeIgnoringNullability(typeProjection.type, genericExportScope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
}
|
||||||
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val superClass = descriptor.getSuperClassNotAny()
|
val superClass = descriptor.getSuperClassNotAny()
|
||||||
@@ -397,20 +391,8 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
val attributes = if (descriptor.isFinalOrEnum) listOf(OBJC_SUBCLASSING_RESTRICTED) else emptyList()
|
val attributes = if (descriptor.isFinalOrEnum) listOf(OBJC_SUBCLASSING_RESTRICTED) else emptyList()
|
||||||
|
|
||||||
val name = translateClassOrInterfaceName(descriptor)
|
val name = translateClassOrInterfaceName(descriptor)
|
||||||
|
val generics = mapTypeConstructorParameters(descriptor)
|
||||||
val generics = if (objcGenerics) {
|
val superClassGenerics = superClassGenerics(genericExportScope)
|
||||||
descriptor.typeConstructor.parameters.map {
|
|
||||||
"${it.variance.objcDeclaration()}${namer.getTypeParameterName(it)}"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val superClassGenerics = if (objcGenerics) {
|
|
||||||
superClassGenerics(genericExportScope)
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
return objCInterface(
|
return objCInterface(
|
||||||
name,
|
name,
|
||||||
@@ -424,6 +406,15 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mapTypeConstructorParameters(descriptor: ClassDescriptor): List<ObjCGenericTypeParameterDeclaration> {
|
||||||
|
if (objcGenerics) {
|
||||||
|
return descriptor.typeConstructor.parameters.map {
|
||||||
|
ObjCGenericTypeParameterDeclaration(it, namer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildEnumValuesMethod(
|
private fun buildEnumValuesMethod(
|
||||||
enumValues: SimpleFunctionDescriptor,
|
enumValues: SimpleFunctionDescriptor,
|
||||||
genericExportScope: ObjCExportScope
|
genericExportScope: ObjCExportScope
|
||||||
@@ -822,9 +813,9 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(objcGenerics && kotlinType.isTypeParameter()){
|
if(objcGenerics && kotlinType.isTypeParameter()){
|
||||||
val genericTypeDeclaration = objCExportScope.getGenericDeclaration(TypeUtils.getTypeParameterDescriptorOrNull(kotlinType))
|
val genericTypeUsage = objCExportScope.getGenericTypeUsage(TypeUtils.getTypeParameterDescriptorOrNull(kotlinType))
|
||||||
if(genericTypeDeclaration != null)
|
if(genericTypeUsage != null)
|
||||||
return genericTypeDeclaration
|
return genericTypeUsage
|
||||||
}
|
}
|
||||||
|
|
||||||
val classDescriptor = kotlinType.getErasedTypeClass()
|
val classDescriptor = kotlinType.getErasedTypeClass()
|
||||||
@@ -892,7 +883,7 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun foreignClassType(name: String): ObjCClassType {
|
private fun foreignClassType(name: String): ObjCClassType {
|
||||||
generator?.referenceClass(name)
|
generator?.referenceClass(ObjCClassForwardDeclaration(name))
|
||||||
return ObjCClassType(name)
|
return ObjCClassType(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,7 +962,7 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
) {
|
) {
|
||||||
private val stubs = mutableListOf<Stub<*>>()
|
private val stubs = mutableListOf<Stub<*>>()
|
||||||
|
|
||||||
private val classForwardDeclarations = linkedSetOf<String>()
|
private val classForwardDeclarations = linkedSetOf<ObjCClassForwardDeclaration>()
|
||||||
private val protocolForwardDeclarations = linkedSetOf<String>()
|
private val protocolForwardDeclarations = linkedSetOf<String>()
|
||||||
private val extraClassesToTranslate = mutableSetOf<ClassDescriptor>()
|
private val extraClassesToTranslate = mutableSetOf<ClassDescriptor>()
|
||||||
|
|
||||||
@@ -989,7 +980,14 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
add("")
|
add("")
|
||||||
|
|
||||||
if (classForwardDeclarations.isNotEmpty()) {
|
if (classForwardDeclarations.isNotEmpty()) {
|
||||||
add("@class ${classForwardDeclarations.joinToString()};")
|
add("@class ${
|
||||||
|
classForwardDeclarations.joinToString {
|
||||||
|
buildString {
|
||||||
|
append(it.className)
|
||||||
|
formatGenerics(this, it.typeDeclarations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};")
|
||||||
add("")
|
add("")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,8 +1161,8 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun referenceClass(objCName: String) {
|
internal fun referenceClass(forwardDeclaration: ObjCClassForwardDeclaration) {
|
||||||
classForwardDeclarations += objCName
|
classForwardDeclarations += forwardDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun referenceProtocol(objCName: String) {
|
internal fun referenceProtocol(objCName: String) {
|
||||||
@@ -1192,7 +1190,19 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
|||||||
|
|
||||||
private fun objCInterface(
|
private fun objCInterface(
|
||||||
name: ObjCExportNamer.ClassOrProtocolName,
|
name: ObjCExportNamer.ClassOrProtocolName,
|
||||||
generics: List<String> = emptyList(),
|
generics: List<String>,
|
||||||
|
superClass: String,
|
||||||
|
superClassGenerics: List<String>
|
||||||
|
): ObjCInterface = objCInterface(
|
||||||
|
name,
|
||||||
|
generics = generics.map { ObjCGenericTypeRawDeclaration(it) },
|
||||||
|
superClass = superClass,
|
||||||
|
superClassGenerics = superClassGenerics.map { ObjCGenericTypeRawUsage(it) }
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun objCInterface(
|
||||||
|
name: ObjCExportNamer.ClassOrProtocolName,
|
||||||
|
generics: List<ObjCGenericTypeDeclaration> = emptyList(),
|
||||||
descriptor: ClassDescriptor? = null,
|
descriptor: ClassDescriptor? = null,
|
||||||
superClass: String? = null,
|
superClass: String? = null,
|
||||||
superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
||||||
@@ -1234,7 +1244,7 @@ private fun swiftNameAttribute(swiftName: String) = "swift_name(\"$swiftName\")"
|
|||||||
private fun objcRuntimeNameAttribute(name: String) = "objc_runtime_name(\"$name\")"
|
private fun objcRuntimeNameAttribute(name: String) = "objc_runtime_name(\"$name\")"
|
||||||
|
|
||||||
interface ObjCExportScope{
|
interface ObjCExportScope{
|
||||||
fun getGenericDeclaration(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeDeclaration?
|
fun getGenericTypeUsage(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeUsage?
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ObjCClassExportScope constructor(container:DeclarationDescriptor, val namer: ObjCExportNamer): ObjCExportScope {
|
internal class ObjCClassExportScope constructor(container:DeclarationDescriptor, val namer: ObjCExportNamer): ObjCExportScope {
|
||||||
@@ -1244,7 +1254,7 @@ internal class ObjCClassExportScope constructor(container:DeclarationDescriptor,
|
|||||||
emptyList<TypeParameterDescriptor>()
|
emptyList<TypeParameterDescriptor>()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getGenericDeclaration(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeDeclaration? {
|
override fun getGenericTypeUsage(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeUsage? {
|
||||||
val localTypeParam = typeNames.firstOrNull {
|
val localTypeParam = typeNames.firstOrNull {
|
||||||
typeParameterDescriptor != null &&
|
typeParameterDescriptor != null &&
|
||||||
(it == typeParameterDescriptor || (it.isCapturedFromOuterDeclaration && it.original == typeParameterDescriptor))
|
(it == typeParameterDescriptor || (it.isCapturedFromOuterDeclaration && it.original == typeParameterDescriptor))
|
||||||
@@ -1253,19 +1263,13 @@ internal class ObjCClassExportScope constructor(container:DeclarationDescriptor,
|
|||||||
return if(localTypeParam == null) {
|
return if(localTypeParam == null) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
ObjCGenericTypeDeclaration(localTypeParam, namer)
|
ObjCGenericTypeParameterUsage(localTypeParam, namer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object ObjCNoneExportScope: ObjCExportScope{
|
internal object ObjCNoneExportScope: ObjCExportScope{
|
||||||
override fun getGenericDeclaration(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeDeclaration? = null
|
override fun getGenericTypeUsage(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeUsage? = null
|
||||||
}
|
|
||||||
|
|
||||||
internal fun Variance.objcDeclaration():String = when(this){
|
|
||||||
Variance.OUT_VARIANCE -> "__covariant "
|
|
||||||
Variance.IN_VARIANCE -> "__contravariant "
|
|
||||||
else -> ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeSuperClassType(descriptor: ClassDescriptor): KotlinType? = descriptor.typeConstructor.supertypes.filter { !it.isInterface() }.firstOrNull()
|
private fun computeSuperClassType(descriptor: ClassDescriptor): KotlinType? = descriptor.typeConstructor.supertypes.filter { !it.isInterface() }.firstOrNull()
|
||||||
|
|||||||
+10
-5
@@ -150,9 +150,14 @@ internal class ObjCExportLazyImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateGenerics(ktClassOrObject: KtClassOrObject): List<String> = if (configuration.objcGenerics) {
|
private fun translateGenerics(ktClassOrObject: KtClassOrObject): List<ObjCGenericTypeDeclaration> = if (configuration.objcGenerics) {
|
||||||
ktClassOrObject.typeParametersWithOuter
|
ktClassOrObject.typeParametersWithOuter
|
||||||
.map { nameTranslator.getTypeParameterName(it) }
|
.map {
|
||||||
|
ObjCGenericTypeRawDeclaration(
|
||||||
|
nameTranslator.getTypeParameterName(it),
|
||||||
|
ObjCVariance.fromKotlinVariance(it.variance)
|
||||||
|
)
|
||||||
|
}
|
||||||
.toList()
|
.toList()
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
@@ -316,7 +321,7 @@ internal class ObjCExportLazyImpl(
|
|||||||
private class LazyObjCInterfaceImpl(
|
private class LazyObjCInterfaceImpl(
|
||||||
name: ObjCExportNamer.ClassOrProtocolName,
|
name: ObjCExportNamer.ClassOrProtocolName,
|
||||||
attributes: List<String>,
|
attributes: List<String>,
|
||||||
generics: List<String>,
|
generics: List<ObjCGenericTypeDeclaration>,
|
||||||
override val psi: KtClassOrObject,
|
override val psi: KtClassOrObject,
|
||||||
private val lazy: ObjCExportLazyImpl
|
private val lazy: ObjCExportLazyImpl
|
||||||
) : LazyObjCInterface(name = name, generics = generics, categoryName = null, attributes = attributes) {
|
) : LazyObjCInterface(name = name, generics = generics, categoryName = null, attributes = attributes) {
|
||||||
@@ -382,14 +387,14 @@ private abstract class LazyObjCInterface : ObjCInterface {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
name: ObjCExportNamer.ClassOrProtocolName,
|
name: ObjCExportNamer.ClassOrProtocolName,
|
||||||
generics: List<String>,
|
generics: List<ObjCGenericTypeDeclaration>,
|
||||||
categoryName: String?,
|
categoryName: String?,
|
||||||
attributes: List<String>
|
attributes: List<String>
|
||||||
) : super(name.objCName, generics, categoryName, attributes + name.toNameAttributes())
|
) : super(name.objCName, generics, categoryName, attributes + name.toNameAttributes())
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
name: String,
|
name: String,
|
||||||
generics: List<String>,
|
generics: List<ObjCGenericTypeDeclaration>,
|
||||||
categoryName: String,
|
categoryName: String,
|
||||||
attributes: List<String>
|
attributes: List<String>
|
||||||
) : super(name, generics, categoryName, attributes)
|
) : super(name, generics, categoryName, attributes)
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||||
|
|
||||||
data class ObjCExportedStubs(
|
data class ObjCExportedStubs(
|
||||||
val classForwardDeclarations: Set<String>,
|
val classForwardDeclarations: Set<ObjCClassForwardDeclaration>,
|
||||||
val protocolForwardDeclarations: Set<String>,
|
val protocolForwardDeclarations: Set<String>,
|
||||||
val stubs: List<Stub<*>>
|
val stubs: List<Stub<*>>
|
||||||
)
|
)
|
||||||
+2
-2
@@ -159,7 +159,7 @@ object StubRenderer {
|
|||||||
private fun ObjCInterface.renderInterfaceHeader() = buildString {
|
private fun ObjCInterface.renderInterfaceHeader() = buildString {
|
||||||
fun appendSuperClass() {
|
fun appendSuperClass() {
|
||||||
if (superClass != null) append(" : $superClass")
|
if (superClass != null) append(" : $superClass")
|
||||||
formatGenerics(this, superClassGenerics.map { it.render() })
|
formatGenerics(this, superClassGenerics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun appendGenerics() {
|
fun appendGenerics() {
|
||||||
@@ -210,7 +210,7 @@ object StubRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun formatGenerics(buffer: Appendable, generics:List<String>) {
|
fun formatGenerics(buffer: Appendable, generics: List<Any>) {
|
||||||
if (generics.isNotEmpty()) {
|
if (generics.isNotEmpty()) {
|
||||||
generics.joinTo(buffer, separator = ", ", prefix = "<", postfix = ">")
|
generics.joinTo(buffer, separator = ", ", prefix = "<", postfix = ">")
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-12
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
sealed class ObjCType {
|
sealed class ObjCType {
|
||||||
final override fun toString(): String = this.render()
|
final override fun toString(): String = this.render()
|
||||||
@@ -18,7 +19,7 @@ sealed class ObjCType {
|
|||||||
if (attrsAndName.isEmpty()) this else "$this ${attrsAndName.trimStart()}"
|
if (attrsAndName.isEmpty()) this else "$this ${attrsAndName.trimStart()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjCRawType(
|
data class ObjCRawType(
|
||||||
val rawText: String
|
val rawText: String
|
||||||
) : ObjCType() {
|
) : ObjCType() {
|
||||||
override fun render(attrsAndName: String): String = rawText.withAttrsAndName(attrsAndName)
|
override fun render(attrsAndName: String): String = rawText.withAttrsAndName(attrsAndName)
|
||||||
@@ -34,7 +35,7 @@ data class ObjCNullableReferenceType(
|
|||||||
override fun render(attrsAndName: String) = nonNullType.render(" _Nullable".withAttrsAndName(attrsAndName))
|
override fun render(attrsAndName: String) = nonNullType.render(" _Nullable".withAttrsAndName(attrsAndName))
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjCClassType(
|
data class ObjCClassType(
|
||||||
val className: String,
|
val className: String,
|
||||||
val typeArguments: List<ObjCNonNullReferenceType> = emptyList()
|
val typeArguments: List<ObjCNonNullReferenceType> = emptyList()
|
||||||
) : ObjCNonNullReferenceType() {
|
) : ObjCNonNullReferenceType() {
|
||||||
@@ -51,16 +52,24 @@ class ObjCClassType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjCGenericTypeDeclaration(
|
sealed class ObjCGenericTypeUsage: ObjCNonNullReferenceType() {
|
||||||
val typeParameterDescriptor: TypeParameterDescriptor,
|
abstract val typeName: String
|
||||||
val namer: ObjCExportNamer
|
final override fun render(attrsAndName: String): String {
|
||||||
) : ObjCNonNullReferenceType() {
|
return typeName.withAttrsAndName(attrsAndName)
|
||||||
override fun render(attrsAndName: String): String {
|
|
||||||
return namer.getTypeParameterName(typeParameterDescriptor).withAttrsAndName(attrsAndName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjCProtocolType(
|
data class ObjCGenericTypeRawUsage(override val typeName: String) : ObjCGenericTypeUsage()
|
||||||
|
|
||||||
|
data class ObjCGenericTypeParameterUsage(
|
||||||
|
val typeParameterDescriptor: TypeParameterDescriptor,
|
||||||
|
val namer: ObjCExportNamer
|
||||||
|
) : ObjCGenericTypeUsage() {
|
||||||
|
override val typeName: String
|
||||||
|
get() = namer.getTypeParameterName(typeParameterDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ObjCProtocolType(
|
||||||
val protocolName: String
|
val protocolName: String
|
||||||
) : ObjCNonNullReferenceType() {
|
) : ObjCNonNullReferenceType() {
|
||||||
override fun render(attrsAndName: String) = "id<$protocolName>".withAttrsAndName(attrsAndName)
|
override fun render(attrsAndName: String) = "id<$protocolName>".withAttrsAndName(attrsAndName)
|
||||||
@@ -74,7 +83,7 @@ object ObjCInstanceType : ObjCNonNullReferenceType() {
|
|||||||
override fun render(attrsAndName: String): String = "instancetype".withAttrsAndName(attrsAndName)
|
override fun render(attrsAndName: String): String = "instancetype".withAttrsAndName(attrsAndName)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjCBlockPointerType(
|
data class ObjCBlockPointerType(
|
||||||
val returnType: ObjCType,
|
val returnType: ObjCType,
|
||||||
val parameterTypes: List<ObjCReferenceType>
|
val parameterTypes: List<ObjCReferenceType>
|
||||||
) : ObjCNonNullReferenceType() {
|
) : ObjCNonNullReferenceType() {
|
||||||
@@ -124,7 +133,7 @@ sealed class ObjCPrimitiveType(
|
|||||||
override fun render(attrsAndName: String) = cName.withAttrsAndName(attrsAndName)
|
override fun render(attrsAndName: String) = cName.withAttrsAndName(attrsAndName)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjCPointerType(
|
data class ObjCPointerType(
|
||||||
val pointee: ObjCType,
|
val pointee: ObjCType,
|
||||||
val nullable: Boolean = false
|
val nullable: Boolean = false
|
||||||
) : ObjCType() {
|
) : ObjCType() {
|
||||||
@@ -156,6 +165,41 @@ internal enum class ObjCValueType(val encoding: String) {
|
|||||||
POINTER("^v")
|
POINTER("^v")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class ObjCVariance(internal val declaration: String) {
|
||||||
|
INVARIANT(""),
|
||||||
|
COVARIANT("__covariant "),
|
||||||
|
CONTRAVARIANT("__contravariant ");
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromKotlinVariance(variance: Variance): ObjCVariance = when (variance) {
|
||||||
|
Variance.OUT_VARIANCE -> COVARIANT
|
||||||
|
Variance.IN_VARIANCE -> CONTRAVARIANT
|
||||||
|
else -> INVARIANT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class ObjCGenericTypeDeclaration {
|
||||||
|
abstract val typeName: String
|
||||||
|
abstract val variance: ObjCVariance
|
||||||
|
final override fun toString(): String = variance.declaration + typeName
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ObjCGenericTypeRawDeclaration(
|
||||||
|
override val typeName: String,
|
||||||
|
override val variance: ObjCVariance = ObjCVariance.INVARIANT
|
||||||
|
) : ObjCGenericTypeDeclaration()
|
||||||
|
|
||||||
|
data class ObjCGenericTypeParameterDeclaration(
|
||||||
|
val typeParameterDescriptor: TypeParameterDescriptor,
|
||||||
|
val namer: ObjCExportNamer
|
||||||
|
) : ObjCGenericTypeDeclaration() {
|
||||||
|
override val typeName: String
|
||||||
|
get() = namer.getTypeParameterName(typeParameterDescriptor)
|
||||||
|
override val variance: ObjCVariance
|
||||||
|
get() = ObjCVariance.fromKotlinVariance(typeParameterDescriptor.variance)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun ObjCType.makeNullableIfReferenceOrPointer(): ObjCType = when (this) {
|
internal fun ObjCType.makeNullableIfReferenceOrPointer(): ObjCType = when (this) {
|
||||||
is ObjCPointerType -> ObjCPointerType(this.pointee, nullable = true)
|
is ObjCPointerType -> ObjCPointerType(this.pointee, nullable = true)
|
||||||
|
|
||||||
@@ -167,4 +211,4 @@ internal fun ObjCType.makeNullableIfReferenceOrPointer(): ObjCType = when (this)
|
|||||||
internal fun ObjCReferenceType.makeNullable(): ObjCNullableReferenceType = when (this) {
|
internal fun ObjCReferenceType.makeNullable(): ObjCNullableReferenceType = when (this) {
|
||||||
is ObjCNonNullReferenceType -> ObjCNullableReferenceType(this)
|
is ObjCNonNullReferenceType -> ObjCNullableReferenceType(this)
|
||||||
is ObjCNullableReferenceType -> this
|
is ObjCNullableReferenceType -> this
|
||||||
}
|
}
|
||||||
+7
-2
@@ -14,6 +14,11 @@ class ObjCComment(val contentLines: List<String>) {
|
|||||||
constructor(vararg contentLines: String) : this(contentLines.toList())
|
constructor(vararg contentLines: String) : this(contentLines.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class ObjCClassForwardDeclaration(
|
||||||
|
val className: String,
|
||||||
|
val typeDeclarations: List<ObjCGenericTypeDeclaration> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
abstract class Stub<out D : DeclarationDescriptor>(val name: String, val comment: ObjCComment? = null) {
|
abstract class Stub<out D : DeclarationDescriptor>(val name: String, val comment: ObjCComment? = null) {
|
||||||
abstract val descriptor: D?
|
abstract val descriptor: D?
|
||||||
open val psi: PsiElement?
|
open val psi: PsiElement?
|
||||||
@@ -41,7 +46,7 @@ class ObjCProtocolImpl(
|
|||||||
attributes: List<String> = emptyList()) : ObjCProtocol(name, attributes)
|
attributes: List<String> = emptyList()) : ObjCProtocol(name, attributes)
|
||||||
|
|
||||||
abstract class ObjCInterface(name: String,
|
abstract class ObjCInterface(name: String,
|
||||||
val generics: List<String>,
|
val generics: List<ObjCGenericTypeDeclaration>,
|
||||||
val categoryName: String?,
|
val categoryName: String?,
|
||||||
attributes: List<String>) : ObjCClass<ClassDescriptor>(name, attributes) {
|
attributes: List<String>) : ObjCClass<ClassDescriptor>(name, attributes) {
|
||||||
abstract val superClass: String?
|
abstract val superClass: String?
|
||||||
@@ -50,7 +55,7 @@ abstract class ObjCInterface(name: String,
|
|||||||
|
|
||||||
class ObjCInterfaceImpl(
|
class ObjCInterfaceImpl(
|
||||||
name: String,
|
name: String,
|
||||||
generics: List<String> = emptyList(),
|
generics: List<ObjCGenericTypeDeclaration> = emptyList(),
|
||||||
override val descriptor: ClassDescriptor? = null,
|
override val descriptor: ClassDescriptor? = null,
|
||||||
override val superClass: String? = null,
|
override val superClass: String? = null,
|
||||||
override val superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
override val superClassGenerics: List<ObjCNonNullReferenceType> = emptyList(),
|
||||||
|
|||||||
@@ -4730,6 +4730,59 @@ if (isAppleTarget(project)) {
|
|||||||
swiftSources = ['objcexport']
|
swiftSources = ['objcexport']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frameworkTest('testObjCExportNoGenerics') {
|
||||||
|
enabled = !isExperimentalMM // Experimental MM doesn't support ObjC blocks yet.
|
||||||
|
final String frameworkName = 'KtNoGenerics'
|
||||||
|
final String frameworkArtifactName = 'Kt'
|
||||||
|
final String dir = "$testOutputFramework/testObjCExportNoGenerics"
|
||||||
|
final File lazyHeader = file("$dir/$target-lazy.h")
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
final String expectedLazyHeaderName = "expectedLazyNoGenerics.h"
|
||||||
|
final String expectedLazyHeaderDir = file("objcexport/")
|
||||||
|
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
|
||||||
|
|
||||||
|
if (expectedLazyHeader.readLines() != lazyHeader.readLines()) {
|
||||||
|
exec {
|
||||||
|
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
|
||||||
|
ignoreExitValue = true
|
||||||
|
}
|
||||||
|
|
||||||
|
copy {
|
||||||
|
from(lazyHeader)
|
||||||
|
into(expectedLazyHeaderDir)
|
||||||
|
rename { expectedLazyHeaderName }
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def libraryName = frameworkName + "Library"
|
||||||
|
konanArtifacts {
|
||||||
|
library(libraryName, targets: [target.name]) {
|
||||||
|
srcDir "objcexport/library"
|
||||||
|
artifactName "test-library"
|
||||||
|
|
||||||
|
if (!useCustomDist) {
|
||||||
|
dependsOn ":${target.name}CrossDistRuntime", ':distCompiler'
|
||||||
|
}
|
||||||
|
|
||||||
|
extraOpts "-Xshort-module-name=MyLibrary"
|
||||||
|
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
framework(frameworkName) {
|
||||||
|
sources = ['objcexport']
|
||||||
|
artifact = frameworkArtifactName
|
||||||
|
library = libraryName
|
||||||
|
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xno-objc-generics"]
|
||||||
|
}
|
||||||
|
swiftSources = ['objcexport']
|
||||||
|
swiftExtraOpts = [ '-D', 'NO_GENERICS' ]
|
||||||
|
}
|
||||||
|
|
||||||
frameworkTest('testObjCExportStatic') {
|
frameworkTest('testObjCExportStatic') {
|
||||||
enabled = !isExperimentalMM // Experimental MM doesn't support ObjC blocks yet.
|
enabled = !isExperimentalMM // Experimental MM doesn't support ObjC blocks yet.
|
||||||
final String frameworkName = 'KtStatic'
|
final String frameworkName = 'KtStatic'
|
||||||
|
|||||||
@@ -51,7 +51,11 @@ private func testSuspendFuncAsync(doThrow: Bool) throws {
|
|||||||
var result: AnyObject? = nil
|
var result: AnyObject? = nil
|
||||||
var error: Error? = nil
|
var error: Error? = nil
|
||||||
|
|
||||||
|
#if NO_GENERICS
|
||||||
|
let continuationHolder = ContinuationHolder()
|
||||||
|
#else
|
||||||
let continuationHolder = ContinuationHolder<AnyObject>()
|
let continuationHolder = ContinuationHolder<AnyObject>()
|
||||||
|
#endif
|
||||||
|
|
||||||
CoroutinesKt.suspendFunAsync(result: nil, continuationHolder: continuationHolder) { _result, _error in
|
CoroutinesKt.suspendFunAsync(result: nil, continuationHolder: continuationHolder) { _result, _error in
|
||||||
completionCalled += 1
|
completionCalled += 1
|
||||||
@@ -114,7 +118,11 @@ private class SuspendFunImpl : SuspendFun {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func testSuspendFunImpl(doYield: Bool, doThrow: Bool) throws {
|
private func testSuspendFunImpl(doYield: Bool, doThrow: Bool) throws {
|
||||||
|
#if NO_GENERICS
|
||||||
|
let resultHolder = ResultHolder()
|
||||||
|
#else
|
||||||
let resultHolder = ResultHolder<KotlinInt>()
|
let resultHolder = ResultHolder<KotlinInt>()
|
||||||
|
#endif
|
||||||
|
|
||||||
let impl = SuspendFunImpl()
|
let impl = SuspendFunImpl()
|
||||||
|
|
||||||
@@ -141,7 +149,7 @@ private func testSuspendFunImpl(doYield: Bool, doThrow: Bool) throws {
|
|||||||
try fail()
|
try fail()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try assertEquals(actual: resultHolder.result, expected: 17)
|
try assertEquals(actual: resultHolder.result as! Int, expected: 17)
|
||||||
try assertNil(resultHolder.exception)
|
try assertNil(resultHolder.exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,12 +221,16 @@ private class SwiftSuspendBridge : AbstractSuspendBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func testBridges() throws {
|
private func testBridges() throws {
|
||||||
|
#if NO_GENERICS
|
||||||
|
let resultHolder = ResultHolder()
|
||||||
|
#else
|
||||||
let resultHolder = ResultHolder<KotlinUnit>()
|
let resultHolder = ResultHolder<KotlinUnit>()
|
||||||
|
#endif
|
||||||
try CoroutinesKt.callSuspendBridge(bridge: SwiftSuspendBridge(), resultHolder: resultHolder)
|
try CoroutinesKt.callSuspendBridge(bridge: SwiftSuspendBridge(), resultHolder: resultHolder)
|
||||||
|
|
||||||
try assertEquals(actual: resultHolder.completed, expected: 1)
|
try assertEquals(actual: resultHolder.completed, expected: 1)
|
||||||
try assertNil(resultHolder.exception)
|
try assertNil(resultHolder.exception)
|
||||||
try assertSame(actual: resultHolder.result, expected: KotlinUnit())
|
try assertSame(actual: resultHolder.result as AnyObject, expected: KotlinUnit())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func testImplicitThrows1() throws {
|
private func testImplicitThrows1() throws {
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ private class DeallocRetain : DeallocRetainBase {
|
|||||||
static var deallocated = false
|
static var deallocated = false
|
||||||
static var retainObject: DeallocRetain? = nil
|
static var retainObject: DeallocRetain? = nil
|
||||||
static weak var weakObject: DeallocRetain? = nil
|
static weak var weakObject: DeallocRetain? = nil
|
||||||
|
#if NO_GENERICS
|
||||||
|
static var kotlinWeakRef: KotlinWeakReference? = nil
|
||||||
|
#else
|
||||||
static var kotlinWeakRef: KotlinWeakReference<AnyObject>? = nil
|
static var kotlinWeakRef: KotlinWeakReference<AnyObject>? = nil
|
||||||
|
#endif
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
@@ -43,7 +47,7 @@ private class DeallocRetain : DeallocRetainBase {
|
|||||||
|
|
||||||
func checkWeak() throws {
|
func checkWeak() throws {
|
||||||
try assertSame(actual: DeallocRetain.weakObject, expected: self)
|
try assertSame(actual: DeallocRetain.weakObject, expected: self)
|
||||||
try assertSame(actual: DeallocRetain.kotlinWeakRef!.value, expected: self)
|
try assertSame(actual: DeallocRetain.kotlinWeakRef!.value as AnyObject, expected: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ private func testEnumValues() throws {
|
|||||||
|
|
||||||
try assertEquals(actual: values.size, expected: 4)
|
try assertEquals(actual: values.size, expected: 4)
|
||||||
|
|
||||||
try assertSame(actual: values.get(index: 0), expected: EnumLeftRightUpDown.left)
|
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumLeftRightUpDown.left)
|
||||||
try assertSame(actual: values.get(index: 1), expected: EnumLeftRightUpDown.right)
|
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumLeftRightUpDown.right)
|
||||||
try assertSame(actual: values.get(index: 2), expected: EnumLeftRightUpDown.up)
|
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumLeftRightUpDown.up)
|
||||||
try assertSame(actual: values.get(index: 3), expected: EnumLeftRightUpDown.down)
|
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumLeftRightUpDown.down)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func testEnumValuesMangled() throws {
|
private func testEnumValuesMangled() throws {
|
||||||
@@ -16,10 +16,10 @@ private func testEnumValuesMangled() throws {
|
|||||||
|
|
||||||
try assertEquals(actual: values.size, expected: 4)
|
try assertEquals(actual: values.size, expected: 4)
|
||||||
|
|
||||||
try assertSame(actual: values.get(index: 0), expected: EnumOneTwoThreeValues.one)
|
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumOneTwoThreeValues.one)
|
||||||
try assertSame(actual: values.get(index: 1), expected: EnumOneTwoThreeValues.two)
|
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumOneTwoThreeValues.two)
|
||||||
try assertSame(actual: values.get(index: 2), expected: EnumOneTwoThreeValues.three)
|
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumOneTwoThreeValues.three)
|
||||||
try assertSame(actual: values.get(index: 3), expected: EnumOneTwoThreeValues.values)
|
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumOneTwoThreeValues.values)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func testEnumValuesMangledTwice() throws {
|
private func testEnumValuesMangledTwice() throws {
|
||||||
@@ -27,8 +27,8 @@ private func testEnumValuesMangledTwice() throws {
|
|||||||
|
|
||||||
try assertEquals(actual: values.size, expected: 2)
|
try assertEquals(actual: values.size, expected: 2)
|
||||||
|
|
||||||
try assertSame(actual: values.get(index: 0), expected: EnumValuesValues_.values)
|
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumValuesValues_.values)
|
||||||
try assertSame(actual: values.get(index: 1), expected: EnumValuesValues_.values_)
|
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumValuesValues_.values_)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func testEnumValuesEmpty() throws {
|
private func testEnumValuesEmpty() throws {
|
||||||
|
|||||||
@@ -2227,3 +2227,42 @@ __attribute__((swift_name("ValuesKt")))
|
|||||||
@property (class) int32_t gh3525InitCount __attribute__((swift_name("gh3525InitCount")));
|
@property (class) int32_t gh3525InitCount __attribute__((swift_name("gh3525InitCount")));
|
||||||
@end;
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("InvariantSuper")))
|
||||||
|
@interface KtInvariantSuper<T> : 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("Invariant")))
|
||||||
|
@interface KtInvariant<T> : KtInvariantSuper<T>
|
||||||
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("OutVariantSuper")))
|
||||||
|
@interface KtOutVariantSuper<__covariant T> : 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("OutVariant")))
|
||||||
|
@interface KtOutVariant<__covariant T> : KtOutVariantSuper<T>
|
||||||
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("InVariantSuper")))
|
||||||
|
@interface KtInVariantSuper<__contravariant T> : 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("InVariant")))
|
||||||
|
@interface KtInVariant<__contravariant T> : KtInVariantSuper<T>
|
||||||
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@ import Kt
|
|||||||
// It is enough to have just Kotlin declarations at the moment.
|
// It is enough to have just Kotlin declarations at the moment.
|
||||||
// Adding usages for all declarations to avoid any kind of DCE that may appear later.
|
// Adding usages for all declarations to avoid any kind of DCE that may appear later.
|
||||||
|
|
||||||
|
#if !NO_GENERICS
|
||||||
private func testIncompatiblePropertyType() throws {
|
private func testIncompatiblePropertyType() throws {
|
||||||
let c = TestIncompatiblePropertyTypeWarning.ClassOverridingInterfaceWithGenericProperty(
|
let c = TestIncompatiblePropertyTypeWarning.ClassOverridingInterfaceWithGenericProperty(
|
||||||
p: TestIncompatiblePropertyTypeWarningGeneric<NSString>(value: "cba")
|
p: TestIncompatiblePropertyTypeWarningGeneric<NSString>(value: "cba")
|
||||||
@@ -21,6 +22,7 @@ private func testIncompatiblePropertyType() throws {
|
|||||||
let pi: TestIncompatiblePropertyTypeWarningGeneric<AnyObject> = i.p
|
let pi: TestIncompatiblePropertyTypeWarningGeneric<AnyObject> = i.p
|
||||||
try assertEquals(actual: pi.value as! String, expected: "cba")
|
try assertEquals(actual: pi.value as! String, expected: "cba")
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private func testGH3992() throws {
|
private func testGH3992() throws {
|
||||||
let d = TestGH3992.D(a: TestGH3992.B())
|
let d = TestGH3992.D(a: TestGH3992.B())
|
||||||
@@ -36,7 +38,9 @@ class HeaderWarningsTests : SimpleTestProvider {
|
|||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
#if !NO_GENERICS
|
||||||
test("TestIncompatiblePropertyType", testIncompatiblePropertyType)
|
test("TestIncompatiblePropertyType", testIncompatiblePropertyType)
|
||||||
|
#endif
|
||||||
test("TestGH3992", testGH3992)
|
test("TestGH3992", testGH3992)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,11 @@ func testGenericsFoo() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testVararg() throws {
|
func testVararg() throws {
|
||||||
|
#if NO_GENERICS
|
||||||
|
let ktArray = KotlinArray(size: 3, init: { (_) -> NSNumber in return 42 })
|
||||||
|
#else
|
||||||
let ktArray = KotlinArray<AnyObject>(size: 3, init: { (_) -> NSNumber in return 42 })
|
let ktArray = KotlinArray<AnyObject>(size: 3, init: { (_) -> NSNumber in return 42 })
|
||||||
|
#endif
|
||||||
let arr: [Int] = ValuesKt.varargToList(args: ktArray) as! [Int]
|
let arr: [Int] = ValuesKt.varargToList(args: ktArray) as! [Int]
|
||||||
try assertEquals(actual: arr, expected: [42, 42, 42])
|
try assertEquals(actual: arr, expected: [42, 42, 42])
|
||||||
}
|
}
|
||||||
@@ -507,13 +511,21 @@ func testDataClass() throws {
|
|||||||
let s = "2"
|
let s = "2"
|
||||||
let t = "3"
|
let t = "3"
|
||||||
|
|
||||||
|
#if NO_GENERICS
|
||||||
|
let tripleVal = TripleVals(first: f as NSString, second: s as NSString, third: t as NSString)
|
||||||
|
#else
|
||||||
let tripleVal = TripleVals<NSString>(first: f as NSString, second: s as NSString, third: t as NSString)
|
let tripleVal = TripleVals<NSString>(first: f as NSString, second: s as NSString, third: t as NSString)
|
||||||
|
#endif
|
||||||
try assertEquals(actual: tripleVal.first as! String, expected: f, "Data class' value")
|
try assertEquals(actual: tripleVal.first as! String, expected: f, "Data class' value")
|
||||||
try assertEquals(actual: tripleVal.component2() as! String, expected: s, "Data class' component")
|
try assertEquals(actual: tripleVal.component2() as! String, expected: s, "Data class' component")
|
||||||
print(tripleVal)
|
print(tripleVal)
|
||||||
try assertEquals(actual: String(describing: tripleVal), expected: "TripleVals(first=\(f), second=\(s), third=\(t))")
|
try assertEquals(actual: String(describing: tripleVal), expected: "TripleVals(first=\(f), second=\(s), third=\(t))")
|
||||||
|
|
||||||
|
#if NO_GENERICS
|
||||||
|
let tripleVar = TripleVars(first: f as NSString, second: s as NSString, third: t as NSString)
|
||||||
|
#else
|
||||||
let tripleVar = TripleVars<NSString>(first: f as NSString, second: s as NSString, third: t as NSString)
|
let tripleVar = TripleVars<NSString>(first: f as NSString, second: s as NSString, third: t as NSString)
|
||||||
|
#endif
|
||||||
try assertEquals(actual: tripleVar.first as! String, expected: f, "Data class' value")
|
try assertEquals(actual: tripleVar.first as! String, expected: f, "Data class' value")
|
||||||
try assertEquals(actual: tripleVar.component2() as! String, expected: s, "Data class' component")
|
try assertEquals(actual: tripleVar.component2() as! String, expected: s, "Data class' component")
|
||||||
print(tripleVar)
|
print(tripleVar)
|
||||||
@@ -542,7 +554,11 @@ func testInlineClasses() throws {
|
|||||||
let ic1N = ValuesKt.box(ic1: 17)
|
let ic1N = ValuesKt.box(ic1: 17)
|
||||||
let ic2 = "foo"
|
let ic2 = "foo"
|
||||||
let ic2N = "bar"
|
let ic2N = "bar"
|
||||||
|
#if NO_GENERICS
|
||||||
|
let ic3 = TripleVals(first: 1, second: 2, third: 3)
|
||||||
|
#else
|
||||||
let ic3 = TripleVals<NSNumber>(first: 1, second: 2, third: 3)
|
let ic3 = TripleVals<NSNumber>(first: 1, second: 2, third: 3)
|
||||||
|
#endif
|
||||||
let ic3N = ValuesKt.box(ic3: nil)
|
let ic3N = ValuesKt.box(ic3: nil)
|
||||||
|
|
||||||
try assertEquals(
|
try assertEquals(
|
||||||
@@ -609,7 +625,11 @@ func testPureSwiftClasses() throws {
|
|||||||
func testNames() throws {
|
func testNames() throws {
|
||||||
try assertEquals(actual: ValuesKt.PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT, expected: 111)
|
try assertEquals(actual: ValuesKt.PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT, expected: 111)
|
||||||
try assertEquals(actual: Deeply.NestedType().thirtyTwo, expected: 32)
|
try assertEquals(actual: Deeply.NestedType().thirtyTwo, expected: 32)
|
||||||
|
#if NO_GENERICS
|
||||||
|
try assertEquals(actual: WithGenericDeeply.NestedType().thirtyThree, expected: 33)
|
||||||
|
#else
|
||||||
try assertEquals(actual: WithGenericDeeplyNestedType<AnyObject>().thirtyThree, expected: 33)
|
try assertEquals(actual: WithGenericDeeplyNestedType<AnyObject>().thirtyThree, expected: 33)
|
||||||
|
#endif
|
||||||
try assertEquals(actual: CKeywords(float: 1.0, enum : 42, goto: true).goto_, expected: true)
|
try assertEquals(actual: CKeywords(float: 1.0, enum : 42, goto: true).goto_, expected: true)
|
||||||
try assertEquals(actual: TypeOuter.Type_().thirtyFour, expected: 34)
|
try assertEquals(actual: TypeOuter.Type_().thirtyFour, expected: 34)
|
||||||
try assertTrue(String(describing: DeeplyNestedIType.self).hasSuffix("DeeplyNestedIType"))
|
try assertTrue(String(describing: DeeplyNestedIType.self).hasSuffix("DeeplyNestedIType"))
|
||||||
@@ -637,7 +657,11 @@ class TransformIntToLongCallingSuper : TransformIntToLong {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testKotlinOverride() throws {
|
func testKotlinOverride() throws {
|
||||||
|
#if NO_GENERICS
|
||||||
|
try assertEquals(actual: TransformInheritingDefault().map(value: 1) as! Int32, expected: 1)
|
||||||
|
#else
|
||||||
try assertEquals(actual: TransformInheritingDefault<NSNumber>().map(value: 1) as! Int32, expected: 1)
|
try assertEquals(actual: TransformInheritingDefault<NSNumber>().map(value: 1) as! Int32, expected: 1)
|
||||||
|
#endif
|
||||||
try assertEquals(actual: TransformIntToDecimalString().map(value: 2), expected: "2")
|
try assertEquals(actual: TransformIntToDecimalString().map(value: 2), expected: "2")
|
||||||
try assertEquals(actual: TransformIntToDecimalString().map(intValue: 3), expected: "3")
|
try assertEquals(actual: TransformIntToDecimalString().map(intValue: 3), expected: "3")
|
||||||
try assertEquals(actual: ValuesKt.createTransformDecimalStringToInt().map(value: "4") as! Int32, expected: 4)
|
try assertEquals(actual: ValuesKt.createTransformDecimalStringToInt().map(value: "4") as! Int32, expected: 4)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package variance
|
||||||
|
|
||||||
|
sealed class InvariantSuper<T>
|
||||||
|
class Invariant<T> : InvariantSuper<T>()
|
||||||
|
|
||||||
|
sealed class OutVariantSuper<out T>
|
||||||
|
class OutVariant<out T> : OutVariantSuper<T>()
|
||||||
|
|
||||||
|
sealed class InVariantSuper<in T>
|
||||||
|
class InVariant<in T> : InVariantSuper<T>()
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Kt
|
||||||
|
|
||||||
|
// -------- Tests --------
|
||||||
|
|
||||||
|
func testInstantiation() {
|
||||||
|
#if NO_GENERICS
|
||||||
|
Invariant()
|
||||||
|
OutVariant()
|
||||||
|
InVariant()
|
||||||
|
#else
|
||||||
|
Invariant<VarianceTests>()
|
||||||
|
OutVariant<VarianceTests>()
|
||||||
|
InVariant<VarianceTests>()
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------- Execution of the test --------
|
||||||
|
|
||||||
|
class VarianceTests : SimpleTestProvider {
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
test("TestInstantiation", testInstantiation)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,9 @@ open class FrameworkTest : DefaultTask(), KonanTestExecutable {
|
|||||||
@Input
|
@Input
|
||||||
lateinit var swiftSources: List<String>
|
lateinit var swiftSources: List<String>
|
||||||
|
|
||||||
|
@Input
|
||||||
|
var swiftExtraOpts: List<String> = emptyList()
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
lateinit var frameworks: MutableList<Framework>
|
lateinit var frameworks: MutableList<Framework>
|
||||||
|
|
||||||
@@ -159,7 +162,7 @@ open class FrameworkTest : DefaultTask(), KonanTestExecutable {
|
|||||||
"-F", frameworkParentDirPath,
|
"-F", frameworkParentDirPath,
|
||||||
"-Xcc", "-Werror" // To fail compilation on warnings in framework header.
|
"-Xcc", "-Werror" // To fail compilation on warnings in framework header.
|
||||||
)
|
)
|
||||||
compileSwift(project, project.testTarget, sources, options, Paths.get(executable), fullBitcode)
|
compileSwift(project, project.testTarget, sources, options + swiftExtraOpts, Paths.get(executable), fullBitcode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
|
|||||||
Reference in New Issue
Block a user