Improve naming in produced framework
* Group top-level declarations by file name instead of package name
* Remove main prefix from Swift class names
* Use 'Kotlin' prefix
* Instead of 'Stdlib'
* In Swift names for KotlinMutableSet/Dictionary, KotlinNumber and subclasses
This commit is contained in:
committed by
SvyatoslavScherbina
parent
2f61cf9fa3
commit
da2736337e
+18
-15
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
@@ -149,24 +148,28 @@ internal class ObjCExportCodeGenerator(
|
|||||||
|
|
||||||
internal fun emitRtti(
|
internal fun emitRtti(
|
||||||
generatedClasses: Collection<ClassDescriptor>,
|
generatedClasses: Collection<ClassDescriptor>,
|
||||||
topLevel: Map<FqName, List<CallableMemberDescriptor>>
|
topLevel: Map<SourceFile, List<CallableMemberDescriptor>>
|
||||||
) {
|
) {
|
||||||
val objCTypeAdapters = mutableListOf<ObjCTypeAdapter>()
|
val objCTypeAdapters = mutableListOf<ObjCTypeAdapter>()
|
||||||
|
|
||||||
generatedClasses.forEach {
|
generatedClasses.forEach {
|
||||||
objCTypeAdapters += createTypeAdapter(it)
|
objCTypeAdapters += createTypeAdapter(it)
|
||||||
val className = namer.getClassOrProtocolName(it)
|
|
||||||
val superClass = it.getSuperClassOrAny()
|
|
||||||
val superClassName = namer.getClassOrProtocolName(superClass)
|
|
||||||
|
|
||||||
dataGenerator.emitEmptyClass(className, superClassName)
|
if (!it.isInterface) {
|
||||||
// Note: it is generated only to be visible for linker.
|
val className = namer.getClassOrProtocolName(it).binaryName
|
||||||
// Methods will be added at runtime.
|
val superClass = it.getSuperClassOrAny()
|
||||||
|
val superClassName = namer.getClassOrProtocolName(superClass).binaryName
|
||||||
|
|
||||||
|
dataGenerator.emitEmptyClass(className, superClassName)
|
||||||
|
// Note: it is generated only to be visible for linker.
|
||||||
|
// Methods will be added at runtime.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
topLevel.forEach { fqName, declarations ->
|
topLevel.forEach { sourceFile, declarations ->
|
||||||
objCTypeAdapters += createTypeAdapterForPackage(fqName, declarations)
|
objCTypeAdapters += createTypeAdapterForFileClass(sourceFile, declarations)
|
||||||
dataGenerator.emitEmptyClass(namer.getPackageName(fqName), namer.kotlinAnyName)
|
val name = namer.getFileClassName(sourceFile).binaryName
|
||||||
|
dataGenerator.emitEmptyClass(name, namer.kotlinAnyName.binaryName)
|
||||||
}
|
}
|
||||||
|
|
||||||
NSNumberKind.values().mapNotNull { it.mappedKotlinClassId }.forEach {
|
NSNumberKind.values().mapNotNull { it.mappedKotlinClassId }.forEach {
|
||||||
@@ -831,11 +834,11 @@ private fun ObjCExportCodeGenerator.vtableIndex(descriptor: FunctionDescriptor):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ObjCExportCodeGenerator.createTypeAdapterForPackage(
|
private fun ObjCExportCodeGenerator.createTypeAdapterForFileClass(
|
||||||
fqName: FqName,
|
sourceFile: SourceFile,
|
||||||
declarations: List<CallableMemberDescriptor>
|
declarations: List<CallableMemberDescriptor>
|
||||||
): ObjCExportCodeGenerator.ObjCTypeAdapter {
|
): ObjCExportCodeGenerator.ObjCTypeAdapter {
|
||||||
val name = namer.getPackageName(fqName)
|
val name = namer.getFileClassName(sourceFile).binaryName
|
||||||
|
|
||||||
val adapters = declarations.toMethods().map { createMethodAdapter(it, it) }
|
val adapters = declarations.toMethods().map { createMethodAdapter(it, it) }
|
||||||
|
|
||||||
@@ -934,7 +937,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
|||||||
|
|
||||||
val irClass = context.ir.get(descriptor)
|
val irClass = context.ir.get(descriptor)
|
||||||
val typeInfo = constPointer(codegen.typeInfoValue(irClass))
|
val typeInfo = constPointer(codegen.typeInfoValue(irClass))
|
||||||
val objCName = namer.getClassOrProtocolName(descriptor)
|
val objCName = namer.getClassOrProtocolName(descriptor).binaryName
|
||||||
|
|
||||||
val vtableSize = if (descriptor.kind == ClassKind.INTERFACE) {
|
val vtableSize = if (descriptor.kind == ClassKind.INTERFACE) {
|
||||||
-1
|
-1
|
||||||
|
|||||||
+2
-1
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportCodeGenerato
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -33,7 +34,7 @@ internal class ObjCExport(val codegen: CodeGenerator) {
|
|||||||
|
|
||||||
val objCCodeGenerator: ObjCExportCodeGenerator
|
val objCCodeGenerator: ObjCExportCodeGenerator
|
||||||
val generatedClasses: Set<ClassDescriptor>
|
val generatedClasses: Set<ClassDescriptor>
|
||||||
val topLevelDeclarations: Map<FqName, List<CallableMemberDescriptor>>
|
val topLevelDeclarations: Map<SourceFile, List<CallableMemberDescriptor>>
|
||||||
|
|
||||||
if (context.config.produce == CompilerOutputKind.FRAMEWORK) {
|
if (context.config.produce == CompilerOutputKind.FRAMEWORK) {
|
||||||
val headerGenerator = ObjCExportHeaderGeneratorImpl(context)
|
val headerGenerator = ObjCExportHeaderGeneratorImpl(context)
|
||||||
|
|||||||
+74
-40
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.builtins.UnsignedType
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||||
@@ -43,7 +42,7 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
internal val namer = ObjCExportNamerImpl(moduleDescriptor, builtIns, mapper, topLevelNamePrefix)
|
internal val namer = ObjCExportNamerImpl(moduleDescriptor, builtIns, mapper, topLevelNamePrefix)
|
||||||
|
|
||||||
internal val generatedClasses = mutableSetOf<ClassDescriptor>()
|
internal val generatedClasses = mutableSetOf<ClassDescriptor>()
|
||||||
internal val topLevel = mutableMapOf<FqName, MutableList<CallableMemberDescriptor>>()
|
internal val topLevel = mutableMapOf<SourceFile, MutableList<CallableMemberDescriptor>>()
|
||||||
|
|
||||||
private val mappedToNSNumber: List<ClassDescriptor> = with(builtIns) {
|
private val mappedToNSNumber: List<ClassDescriptor> = with(builtIns) {
|
||||||
val result = mutableListOf(boolean, byte, short, int, long, float, double)
|
val result = mutableListOf(boolean, byte, short, int, long, float, double)
|
||||||
@@ -63,15 +62,15 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
result += CustomTypeMapper.Collection(generator, list, "NSArray")
|
result += CustomTypeMapper.Collection(generator, list, "NSArray")
|
||||||
result += CustomTypeMapper.Collection(generator, mutableList, "NSMutableArray")
|
result += CustomTypeMapper.Collection(generator, mutableList, "NSMutableArray")
|
||||||
result += CustomTypeMapper.Collection(generator, set, "NSSet")
|
result += CustomTypeMapper.Collection(generator, set, "NSSet")
|
||||||
result += CustomTypeMapper.Collection(generator, mutableSet, namer.mutableSetName)
|
result += CustomTypeMapper.Collection(generator, mutableSet, namer.mutableSetName.objCName)
|
||||||
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
|
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
|
||||||
result += CustomTypeMapper.Collection(generator, mutableMap, namer.mutableMapName)
|
result += CustomTypeMapper.Collection(generator, mutableMap, namer.mutableMapName.objCName)
|
||||||
|
|
||||||
NSNumberKind.values().forEach {
|
NSNumberKind.values().forEach {
|
||||||
// TODO: NSNumber seem to have different equality semantics.
|
// TODO: NSNumber seem to have different equality semantics.
|
||||||
if (it.mappedKotlinClassId != null) {
|
if (it.mappedKotlinClassId != null) {
|
||||||
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(it.mappedKotlinClassId)!!
|
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(it.mappedKotlinClassId)!!
|
||||||
result += CustomTypeMapper.Simple(descriptor, namer.numberBoxName(descriptor))
|
result += CustomTypeMapper.Simple(descriptor, namer.numberBoxName(descriptor).objCName)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -99,7 +98,7 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
private val kotlinAnyName = namer.kotlinAnyName
|
private val kotlinAnyName = namer.kotlinAnyName
|
||||||
|
|
||||||
private val stubs = mutableListOf<Stub<*>>()
|
private val stubs = mutableListOf<Stub<*>>()
|
||||||
private val classOrInterfaceToName = mutableMapOf<ClassDescriptor, String>()
|
private val classOrInterfaceToName = mutableMapOf<ClassDescriptor, ObjCExportNamer.ClassOrProtocolName>()
|
||||||
|
|
||||||
private val classForwardDeclarations = mutableSetOf<String>()
|
private val classForwardDeclarations = mutableSetOf<String>()
|
||||||
private val protocolForwardDeclarations = mutableSetOf<String>()
|
private val protocolForwardDeclarations = mutableSetOf<String>()
|
||||||
@@ -107,37 +106,74 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
private val extensions = mutableMapOf<ClassDescriptor, MutableList<CallableMemberDescriptor>>()
|
private val extensions = mutableMapOf<ClassDescriptor, MutableList<CallableMemberDescriptor>>()
|
||||||
private val extraClassesToTranslate = mutableSetOf<ClassDescriptor>()
|
private val extraClassesToTranslate = mutableSetOf<ClassDescriptor>()
|
||||||
|
|
||||||
|
private fun objCInterface(
|
||||||
|
name: ObjCExportNamer.ClassOrProtocolName,
|
||||||
|
generics: List<String> = emptyList(),
|
||||||
|
descriptor: ClassDescriptor? = null,
|
||||||
|
superClass: String? = null,
|
||||||
|
superProtocols: List<String> = emptyList(),
|
||||||
|
categoryName: String? = null,
|
||||||
|
members: List<Stub<*>> = emptyList(),
|
||||||
|
attributes: List<String> = emptyList()
|
||||||
|
): ObjCInterface = ObjCInterface(
|
||||||
|
name.objCName,
|
||||||
|
generics,
|
||||||
|
descriptor,
|
||||||
|
superClass,
|
||||||
|
superProtocols,
|
||||||
|
categoryName,
|
||||||
|
members,
|
||||||
|
attributes + name.toNameAttributes()
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun objCProtocol(
|
||||||
|
name: ObjCExportNamer.ClassOrProtocolName,
|
||||||
|
descriptor: ClassDescriptor,
|
||||||
|
superProtocols: List<String>,
|
||||||
|
members: List<Stub<*>>,
|
||||||
|
attributes: List<String> = emptyList()
|
||||||
|
): ObjCProtocol = ObjCProtocol(
|
||||||
|
name.objCName,
|
||||||
|
descriptor,
|
||||||
|
superProtocols,
|
||||||
|
members,
|
||||||
|
attributes + name.toNameAttributes()
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun ObjCExportNamer.ClassOrProtocolName.toNameAttributes(): List<String> = listOfNotNull(
|
||||||
|
binaryName.takeIf { it != objCName }?.let { objcRuntimeNameAttribute(it) },
|
||||||
|
swiftName.takeIf { it != objCName }?.let { swiftNameAttribute(it) }
|
||||||
|
)
|
||||||
|
|
||||||
fun translateModule(): List<Stub<*>> {
|
fun translateModule(): List<Stub<*>> {
|
||||||
// TODO: make the translation order stable
|
// TODO: make the translation order stable
|
||||||
// to stabilize name mangling.
|
// to stabilize name mangling.
|
||||||
|
|
||||||
stubs.add(ObjCInterface(kotlinAnyName, superClass = "NSObject", members = buildMembers {
|
stubs.add(objCInterface(kotlinAnyName, superClass = "NSObject", members = buildMembers {
|
||||||
+ObjCMethod(null, true, ObjCInstanceType, listOf("init"), emptyList(), listOf("unavailable"))
|
+ObjCMethod(null, true, ObjCInstanceType, listOf("init"), emptyList(), listOf("unavailable"))
|
||||||
+ObjCMethod(null, false, ObjCInstanceType, listOf("new"), emptyList(), listOf("unavailable"))
|
+ObjCMethod(null, false, ObjCInstanceType, listOf("new"), emptyList(), listOf("unavailable"))
|
||||||
+ObjCMethod(null, false, ObjCVoidType, listOf("initialize"), emptyList(), listOf("objc_requires_super"))
|
+ObjCMethod(null, false, ObjCVoidType, listOf("initialize"), emptyList(), listOf("objc_requires_super"))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// TODO: add comment to the header.
|
// TODO: add comment to the header.
|
||||||
stubs.add(ObjCInterface(
|
stubs.add(objCInterface(
|
||||||
kotlinAnyName,
|
kotlinAnyName,
|
||||||
superProtocols = listOf("NSCopying"),
|
superProtocols = listOf("NSCopying"),
|
||||||
categoryName = "${kotlinAnyName}Copying"
|
categoryName = "${kotlinAnyName.objCName}Copying"
|
||||||
))
|
))
|
||||||
|
|
||||||
// TODO: only if appears
|
// TODO: only if appears
|
||||||
stubs.add(ObjCInterface(
|
stubs.add(objCInterface(
|
||||||
namer.mutableSetName,
|
namer.mutableSetName,
|
||||||
generics = listOf("ObjectType"),
|
generics = listOf("ObjectType"),
|
||||||
superClass = "NSMutableSet<ObjectType>",
|
superClass = "NSMutableSet<ObjectType>"
|
||||||
attributes = listOf(objcRuntimeNameAttribute("KotlinMutableSet"))
|
|
||||||
))
|
))
|
||||||
|
|
||||||
// TODO: only if appears
|
// TODO: only if appears
|
||||||
stubs.add(ObjCInterface(
|
stubs.add(objCInterface(
|
||||||
namer.mutableMapName,
|
namer.mutableMapName,
|
||||||
generics = listOf("KeyType", "ObjectType"),
|
generics = listOf("KeyType", "ObjectType"),
|
||||||
superClass = "NSMutableDictionary<KeyType, ObjectType>",
|
superClass = "NSMutableDictionary<KeyType, ObjectType>"
|
||||||
attributes = listOf(objcRuntimeNameAttribute("KotlinMutableDictionary"))
|
|
||||||
))
|
))
|
||||||
|
|
||||||
stubs.add(ObjCInterface("NSError", categoryName = "NSErrorKotlinException", members = buildMembers {
|
stubs.add(ObjCInterface("NSError", categoryName = "NSErrorKotlinException", members = buildMembers {
|
||||||
@@ -158,7 +194,7 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
if (classDescriptor != null) {
|
if (classDescriptor != null) {
|
||||||
extensions.getOrPut(classDescriptor, { mutableListOf() }) += it
|
extensions.getOrPut(classDescriptor, { mutableListOf() }) += it
|
||||||
} else {
|
} else {
|
||||||
topLevel.getOrPut(packageFragment.fqName, { mutableListOf() }) += it
|
topLevel.getOrPut(it.source.containingFile, { mutableListOf() }) += it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,8 +224,8 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
translateExtensions(classDescriptor, declarations)
|
translateExtensions(classDescriptor, declarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
topLevel.forEach { packageFqName, declarations ->
|
topLevel.forEach { sourceFile, declarations ->
|
||||||
translateTopLevel(packageFqName, declarations)
|
translateTopLevel(sourceFile, declarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (extraClassesToTranslate.isNotEmpty()) {
|
while (extraClassesToTranslate.isNotEmpty()) {
|
||||||
@@ -214,11 +250,10 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
+nsNumberInit(it, listOf("unavailable"))
|
+nsNumberInit(it, listOf("unavailable"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stubs.add(ObjCInterface(
|
stubs.add(objCInterface(
|
||||||
namer.kotlinNumberName,
|
namer.kotlinNumberName,
|
||||||
superClass = "NSNumber",
|
superClass = "NSNumber",
|
||||||
members = members,
|
members = members
|
||||||
attributes = listOf(objcRuntimeNameAttribute("KotlinNumber"))
|
|
||||||
))
|
))
|
||||||
|
|
||||||
NSNumberKind.values().forEach {
|
NSNumberKind.values().forEach {
|
||||||
@@ -236,11 +271,10 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
+nsNumberFactory(kind)
|
+nsNumberFactory(kind)
|
||||||
+nsNumberInit(kind)
|
+nsNumberInit(kind)
|
||||||
}
|
}
|
||||||
return ObjCInterface(
|
return objCInterface(
|
||||||
name,
|
name,
|
||||||
superClass = namer.kotlinNumberName,
|
superClass = namer.kotlinNumberName.objCName,
|
||||||
members = members,
|
members = members
|
||||||
attributes = listOf(objcRuntimeNameAttribute("Kotlin${kotlinClassId.shortClassName}"))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,21 +300,21 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateClassName(descriptor: ClassDescriptor): String = classOrInterfaceToName.getOrPut(descriptor) {
|
private fun translateClassName(descriptor: ClassDescriptor) = classOrInterfaceToName.getOrPut(descriptor) {
|
||||||
assert(mapper.shouldBeExposed(descriptor))
|
assert(mapper.shouldBeExposed(descriptor))
|
||||||
val forwardDeclarations = if (descriptor.isInterface) protocolForwardDeclarations else classForwardDeclarations
|
val forwardDeclarations = if (descriptor.isInterface) protocolForwardDeclarations else classForwardDeclarations
|
||||||
|
|
||||||
namer.getClassOrProtocolName(descriptor).also { forwardDeclarations += it }
|
namer.getClassOrProtocolName(descriptor).also { forwardDeclarations += it.objCName }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateInterface(descriptor: ClassDescriptor) {
|
private fun translateInterface(descriptor: ClassDescriptor) {
|
||||||
if (!generatedClasses.add(descriptor)) return
|
if (!generatedClasses.add(descriptor)) return
|
||||||
|
|
||||||
val name: String = translateClassName(descriptor)
|
val name = translateClassName(descriptor)
|
||||||
val members: List<Stub<*>> = buildMembers { translateClassOrInterfaceMembers(descriptor) }
|
val members: List<Stub<*>> = buildMembers { translateClassOrInterfaceMembers(descriptor) }
|
||||||
val superProtocols: List<String> = descriptor.superProtocols
|
val superProtocols: List<String> = descriptor.superProtocols
|
||||||
|
|
||||||
val protocolStub = ObjCProtocol(name, descriptor, superProtocols, members)
|
val protocolStub = objCProtocol(name, descriptor, superProtocols, members)
|
||||||
|
|
||||||
stubs.add(protocolStub)
|
stubs.add(protocolStub)
|
||||||
}
|
}
|
||||||
@@ -292,7 +326,7 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
.filter { mapper.shouldBeExposed(it) }
|
.filter { mapper.shouldBeExposed(it) }
|
||||||
.map {
|
.map {
|
||||||
translateInterface(it)
|
translateInterface(it)
|
||||||
translateClassName(it)
|
translateClassName(it).objCName
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
@@ -303,19 +337,19 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
val members = buildMembers {
|
val members = buildMembers {
|
||||||
translateMembers(declarations)
|
translateMembers(declarations)
|
||||||
}
|
}
|
||||||
stubs.add(ObjCInterface(name, categoryName = "Extensions", members = members))
|
stubs.add(objCInterface(name, categoryName = "Extensions", members = members))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateTopLevel(packageFqName: FqName, declarations: List<CallableMemberDescriptor>) {
|
private fun translateTopLevel(sourceFile: SourceFile, declarations: List<CallableMemberDescriptor>) {
|
||||||
val name = namer.getPackageName(packageFqName)
|
val name = namer.getFileClassName(sourceFile)
|
||||||
|
|
||||||
// TODO: stop inheriting KotlinBase.
|
// TODO: stop inheriting KotlinBase.
|
||||||
val members = buildMembers {
|
val members = buildMembers {
|
||||||
translateMembers(declarations)
|
translateMembers(declarations)
|
||||||
}
|
}
|
||||||
stubs.add(ObjCInterface(
|
stubs.add(objCInterface(
|
||||||
name,
|
name,
|
||||||
superClass = namer.kotlinAnyName,
|
superClass = namer.kotlinAnyName.objCName,
|
||||||
members = members,
|
members = members,
|
||||||
attributes = listOf("objc_subclassing_restricted")
|
attributes = listOf("objc_subclassing_restricted")
|
||||||
))
|
))
|
||||||
@@ -327,7 +361,7 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
val name = translateClassName(descriptor)
|
val name = translateClassName(descriptor)
|
||||||
val superClass = descriptor.getSuperClassNotAny()
|
val superClass = descriptor.getSuperClassNotAny()
|
||||||
|
|
||||||
val superName: String = if (superClass == null) {
|
val superName = if (superClass == null) {
|
||||||
kotlinAnyName
|
kotlinAnyName
|
||||||
} else {
|
} else {
|
||||||
translateClass(superClass)
|
translateClass(superClass)
|
||||||
@@ -404,10 +438,10 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
|
|
||||||
val attributes = if (descriptor.isFinalOrEnum) listOf("objc_subclassing_restricted") else emptyList()
|
val attributes = if (descriptor.isFinalOrEnum) listOf("objc_subclassing_restricted") else emptyList()
|
||||||
|
|
||||||
val interfaceStub = ObjCInterface(
|
val interfaceStub = objCInterface(
|
||||||
name,
|
name,
|
||||||
descriptor = descriptor,
|
descriptor = descriptor,
|
||||||
superClass = superName,
|
superClass = superName.objCName,
|
||||||
superProtocols = superProtocols,
|
superProtocols = superProtocols,
|
||||||
members = members,
|
members = members,
|
||||||
attributes = attributes
|
attributes = attributes
|
||||||
@@ -763,9 +797,9 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
scheduleClassToBeGenerated(classDescriptor)
|
scheduleClassToBeGenerated(classDescriptor)
|
||||||
|
|
||||||
return if (classDescriptor.isInterface) {
|
return if (classDescriptor.isInterface) {
|
||||||
ObjCProtocolType(translateClassName(classDescriptor))
|
ObjCProtocolType(translateClassName(classDescriptor).objCName)
|
||||||
} else {
|
} else {
|
||||||
ObjCClassType(translateClassName(classDescriptor))
|
ObjCClassType(translateClassName(classDescriptor).objCName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+49
-28
@@ -9,14 +9,20 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.konan.isKonanStdlib
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
|
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||||
|
|
||||||
|
|
||||||
interface ObjCExportNamer {
|
interface ObjCExportNamer {
|
||||||
fun getPackageName(fqName: FqName): String
|
data class ClassOrProtocolName(val swiftName: String, val objCName: String, val binaryName: String = objCName)
|
||||||
fun getClassOrProtocolName(descriptor: ClassDescriptor): String
|
|
||||||
|
fun getFileClassName(file: SourceFile): ClassOrProtocolName
|
||||||
|
fun getClassOrProtocolName(descriptor: ClassDescriptor): ClassOrProtocolName
|
||||||
fun getSelector(method: FunctionDescriptor): String
|
fun getSelector(method: FunctionDescriptor): String
|
||||||
fun getSwiftName(method: FunctionDescriptor): String
|
fun getSwiftName(method: FunctionDescriptor): String
|
||||||
fun getPropertyName(property: PropertyDescriptor): String
|
fun getPropertyName(property: PropertyDescriptor): String
|
||||||
@@ -40,15 +46,27 @@ internal class ObjCExportNamerImpl(
|
|||||||
private val topLevelNamePrefix: String = moduleDescriptor.namePrefix
|
private val topLevelNamePrefix: String = moduleDescriptor.namePrefix
|
||||||
) : ObjCExportNamer {
|
) : ObjCExportNamer {
|
||||||
|
|
||||||
val kotlinAnyName = "KotlinBase"
|
private fun String.mangleClassOrProtocolName(): ObjCExportNamer.ClassOrProtocolName =
|
||||||
|
ObjCExportNamer.ClassOrProtocolName(swiftName = this, objCName = "$topLevelNamePrefix${this}")
|
||||||
|
|
||||||
private val commonPackageSegments = moduleDescriptor.guessMainPackage().pathSegments()
|
private fun String.toUnmangledClassOrProtocolName(): ObjCExportNamer.ClassOrProtocolName =
|
||||||
|
ObjCExportNamer.ClassOrProtocolName(swiftName = this, objCName = this)
|
||||||
|
|
||||||
val mutableSetName = "${topLevelNamePrefix}MutableSet"
|
private fun String.toSpecialStandardClassOrProtocolName() = ObjCExportNamer.ClassOrProtocolName(
|
||||||
val mutableMapName = "${topLevelNamePrefix}MutableDictionary"
|
swiftName = "Kotlin$this",
|
||||||
|
objCName = "${topLevelNamePrefix}$this",
|
||||||
|
binaryName = "Kotlin$this"
|
||||||
|
)
|
||||||
|
|
||||||
fun numberBoxName(descriptor: ClassDescriptor): String = "$topLevelNamePrefix${descriptor.name.asString()}"
|
val kotlinAnyName = "KotlinBase".toUnmangledClassOrProtocolName()
|
||||||
val kotlinNumberName = "${topLevelNamePrefix}Number"
|
|
||||||
|
val mutableSetName = "MutableSet".toSpecialStandardClassOrProtocolName()
|
||||||
|
val mutableMapName = "MutableDictionary".toSpecialStandardClassOrProtocolName()
|
||||||
|
|
||||||
|
fun numberBoxName(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName =
|
||||||
|
descriptor.name.asString().toSpecialStandardClassOrProtocolName()
|
||||||
|
|
||||||
|
val kotlinNumberName = "Number".toSpecialStandardClassOrProtocolName()
|
||||||
|
|
||||||
private val methodSelectors = object : Mapping<FunctionDescriptor, String>() {
|
private val methodSelectors = object : Mapping<FunctionDescriptor, String>() {
|
||||||
|
|
||||||
@@ -109,26 +127,26 @@ internal class ObjCExportNamerImpl(
|
|||||||
first.containingDeclaration == second.containingDeclaration
|
first.containingDeclaration == second.containingDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPackageName(fqName: FqName): String = classNames.getOrPut(fqName) {
|
override fun getFileClassName(file: SourceFile): ObjCExportNamer.ClassOrProtocolName = classNames.getOrPut(file) {
|
||||||
StringBuilder().apply {
|
val psiSourceFile = file as? PsiSourceFile ?: error("SourceFile '$file' is not PsiSourceFile")
|
||||||
append(topLevelNamePrefix)
|
val psiFile = psiSourceFile.psiFile
|
||||||
fqName.pathSegments().forEachIndexed { index, segment ->
|
val ktFile = psiFile as? KtFile ?: error("PsiFile '$psiFile' is not KtFile")
|
||||||
if (index < commonPackageSegments.size) {
|
StringBuilder(PackagePartClassUtils.getFilePartShortName(ktFile.name)).mangledSequence { append("_") }
|
||||||
assert(commonPackageSegments[index] == segment)
|
}.mangleClassOrProtocolName()
|
||||||
} else {
|
|
||||||
append(segment.asString().capitalize())
|
private val predefinedClassNames = mapOf(
|
||||||
}
|
builtIns.any to kotlinAnyName,
|
||||||
}
|
builtIns.mutableSet to mutableSetName,
|
||||||
}.mangledSequence { append("_") }
|
builtIns.mutableMap to mutableMapName
|
||||||
}
|
)
|
||||||
|
|
||||||
|
override fun getClassOrProtocolName(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName {
|
||||||
|
predefinedClassNames[descriptor]?.let { return it }
|
||||||
|
|
||||||
override fun getClassOrProtocolName(descriptor: ClassDescriptor): String {
|
|
||||||
val mapping = if (descriptor.isInterface) protocolNames else classNames
|
val mapping = if (descriptor.isInterface) protocolNames else classNames
|
||||||
|
|
||||||
return mapping.getOrPut(descriptor) {
|
return mapping.getOrPut(descriptor) {
|
||||||
StringBuilder().apply {
|
StringBuilder().apply {
|
||||||
append(topLevelNamePrefix)
|
|
||||||
|
|
||||||
if (descriptor.module != moduleDescriptor) {
|
if (descriptor.module != moduleDescriptor) {
|
||||||
append(descriptor.module.namePrefix)
|
append(descriptor.module.namePrefix)
|
||||||
}
|
}
|
||||||
@@ -137,7 +155,7 @@ internal class ObjCExportNamerImpl(
|
|||||||
.toList().reversed()
|
.toList().reversed()
|
||||||
.joinTo(this, "") { it.name.asString().capitalize() }
|
.joinTo(this, "") { it.name.asString().capitalize() }
|
||||||
}.mangledSequence { append("_") }
|
}.mangledSequence { append("_") }
|
||||||
}
|
}.mangleClassOrProtocolName()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSelector(method: FunctionDescriptor): String = methodSelectors.getOrPut(method) {
|
override fun getSelector(method: FunctionDescriptor): String = methodSelectors.getOrPut(method) {
|
||||||
@@ -261,9 +279,10 @@ internal class ObjCExportNamerImpl(
|
|||||||
init {
|
init {
|
||||||
val any = builtIns.any
|
val any = builtIns.any
|
||||||
|
|
||||||
classNames.forceAssign(any, kotlinAnyName)
|
predefinedClassNames.forEach { descriptor, name ->
|
||||||
classNames.forceAssign(builtIns.mutableSet, mutableSetName)
|
// Note: it is a hack.
|
||||||
classNames.forceAssign(builtIns.mutableMap, mutableMapName)
|
classNames.forceAssign(descriptor, name.swiftName)
|
||||||
|
}
|
||||||
|
|
||||||
fun ClassDescriptor.method(name: String) =
|
fun ClassDescriptor.method(name: String) =
|
||||||
this.unsubstitutedMemberScope.getContributedFunctions(
|
this.unsubstitutedMemberScope.getContributedFunctions(
|
||||||
@@ -453,6 +472,8 @@ private fun ObjCExportMapper.canHaveSameName(first: PropertyDescriptor, second:
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal val ModuleDescriptor.namePrefix: String get() {
|
internal val ModuleDescriptor.namePrefix: String get() {
|
||||||
|
if (this.isKonanStdlib()) return "Kotlin"
|
||||||
|
|
||||||
// <fooBar> -> FooBar
|
// <fooBar> -> FooBar
|
||||||
val moduleName = this.name.asString()
|
val moduleName = this.name.asString()
|
||||||
.let { it.substring(1, it.lastIndex) }
|
.let { it.substring(1, it.lastIndex) }
|
||||||
|
|||||||
+3
@@ -12,6 +12,9 @@ object StubRenderer {
|
|||||||
stub.run {
|
stub.run {
|
||||||
when (this) {
|
when (this) {
|
||||||
is ObjCProtocol -> {
|
is ObjCProtocol -> {
|
||||||
|
attributes.forEach {
|
||||||
|
+renderAttribute(it)
|
||||||
|
}
|
||||||
+renderProtocolHeader()
|
+renderProtocolHeader()
|
||||||
+"@required"
|
+"@required"
|
||||||
renderMembers(this)
|
renderMembers(this)
|
||||||
|
|||||||
+5
-3
@@ -15,12 +15,14 @@ open class Stub<out D : DeclarationDescriptor>(val name: String, val descriptor:
|
|||||||
abstract class ObjCClass<out D : DeclarationDescriptor>(name: String,
|
abstract class ObjCClass<out D : DeclarationDescriptor>(name: String,
|
||||||
descriptor: D?,
|
descriptor: D?,
|
||||||
val superProtocols: List<String>,
|
val superProtocols: List<String>,
|
||||||
val members: List<Stub<*>>) : Stub<D>(name, descriptor)
|
val members: List<Stub<*>>,
|
||||||
|
val attributes: List<String>) : Stub<D>(name, descriptor)
|
||||||
|
|
||||||
class ObjCProtocol(name: String,
|
class ObjCProtocol(name: String,
|
||||||
descriptor: ClassDescriptor,
|
descriptor: ClassDescriptor,
|
||||||
superProtocols: List<String>,
|
superProtocols: List<String>,
|
||||||
members: List<Stub<*>>) : ObjCClass<ClassDescriptor>(name, descriptor, superProtocols, members)
|
members: List<Stub<*>>,
|
||||||
|
attributes: List<String> = emptyList()) : ObjCClass<ClassDescriptor>(name, descriptor, superProtocols, members, attributes)
|
||||||
|
|
||||||
class ObjCInterface(name: String,
|
class ObjCInterface(name: String,
|
||||||
val generics: List<String> = emptyList(),
|
val generics: List<String> = emptyList(),
|
||||||
@@ -29,7 +31,7 @@ class ObjCInterface(name: String,
|
|||||||
superProtocols: List<String> = emptyList(),
|
superProtocols: List<String> = emptyList(),
|
||||||
val categoryName: String? = null,
|
val categoryName: String? = null,
|
||||||
members: List<Stub<*>> = emptyList(),
|
members: List<Stub<*>> = emptyList(),
|
||||||
val attributes: List<String> = emptyList()) : ObjCClass<ClassDescriptor>(name, descriptor, superProtocols, members)
|
attributes: List<String> = emptyList()) : ObjCClass<ClassDescriptor>(name, descriptor, superProtocols, members, attributes)
|
||||||
|
|
||||||
class ObjCMethod(descriptor: DeclarationDescriptor?,
|
class ObjCMethod(descriptor: DeclarationDescriptor?,
|
||||||
val isInstanceMethod: Boolean,
|
val isInstanceMethod: Boolean,
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ class StdlibTests : TestProvider {
|
|||||||
*/
|
*/
|
||||||
func testEmptyDictionary() throws {
|
func testEmptyDictionary() throws {
|
||||||
let immutableEmptyDict = [String: Int]()
|
let immutableEmptyDict = [String: Int]()
|
||||||
try assertTrue(Stdlib.isEmpty(map: immutableEmptyDict), "Empty dictionary")
|
try assertTrue(StdlibKt.isEmpty(map: immutableEmptyDict), "Empty dictionary")
|
||||||
let keys = Stdlib.getKeysAsSet(map: immutableEmptyDict)
|
let keys = StdlibKt.getKeysAsSet(map: immutableEmptyDict)
|
||||||
try assertTrue(keys.isEmpty, "Should have empty set")
|
try assertTrue(keys.isEmpty, "Should have empty set")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class StdlibTests : TestProvider {
|
|||||||
* Tests usage of a map with generics.
|
* Tests usage of a map with generics.
|
||||||
*/
|
*/
|
||||||
func testGenericMapUsage() throws {
|
func testGenericMapUsage() throws {
|
||||||
let map = Stdlib.createLinkedMap()
|
let map = StdlibKt.createLinkedMap()
|
||||||
map[1] = "One"
|
map[1] = "One"
|
||||||
map[10] = "Ten"
|
map[10] = "Ten"
|
||||||
map[11] = "Eleven"
|
map[11] = "Eleven"
|
||||||
@@ -82,7 +82,7 @@ class StdlibTests : TestProvider {
|
|||||||
* Checks order of the underlying LinkedHashMap.
|
* Checks order of the underlying LinkedHashMap.
|
||||||
*/
|
*/
|
||||||
func testOrderedMapStored() throws {
|
func testOrderedMapStored() throws {
|
||||||
let pair = Stdlib.createPair()
|
let pair = StdlibKt.createPair()
|
||||||
let map = pair.first as? NSMutableDictionary
|
let map = pair.first as? NSMutableDictionary
|
||||||
|
|
||||||
map?[1] = "One"
|
map?[1] = "One"
|
||||||
@@ -90,7 +90,7 @@ class StdlibTests : TestProvider {
|
|||||||
map?[11] = "Eleven"
|
map?[11] = "Eleven"
|
||||||
map?["10"] = "Ten as string"
|
map?["10"] = "Ten as string"
|
||||||
|
|
||||||
let gen = pair.second as! StdlibGenericExtensionClass
|
let gen = pair.second as! GenericExtensionClass
|
||||||
let value: String? = gen.getFirstValue() as? String
|
let value: String? = gen.getFirstValue() as? String
|
||||||
try assertEquals(actual: value!, expected: "One", "First value of the map")
|
try assertEquals(actual: value!, expected: "One", "First value of the map")
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ class StdlibTests : TestProvider {
|
|||||||
* Tests typed map created in Kotlin.
|
* Tests typed map created in Kotlin.
|
||||||
*/
|
*/
|
||||||
func testTypedMapUsage() throws {
|
func testTypedMapUsage() throws {
|
||||||
let map = Stdlib.createTypedMutableMap()
|
let map = StdlibKt.createTypedMutableMap()
|
||||||
map[1] = "One"
|
map[1] = "One"
|
||||||
map[1.0 as Float] = "Float"
|
map[1.0 as Float] = "Float"
|
||||||
map[11] = "Eleven"
|
map[11] = "Eleven"
|
||||||
@@ -116,11 +116,11 @@ class StdlibTests : TestProvider {
|
|||||||
* Get first element of the collection.
|
* Get first element of the collection.
|
||||||
*/
|
*/
|
||||||
func testFirstElement() throws {
|
func testFirstElement() throws {
|
||||||
let m = Stdlib.createTypedMutableMap()
|
let m = StdlibKt.createTypedMutableMap()
|
||||||
m[10] = "Str"
|
m[10] = "Str"
|
||||||
try assertEquals(actual: Stdlib.getFirstElement(collection: m.allKeys) as! Int, expected: 10, "First key")
|
try assertEquals(actual: StdlibKt.getFirstElement(collection: m.allKeys) as! Int, expected: 10, "First key")
|
||||||
|
|
||||||
try assertEquals(actual: Stdlib.getFirstElement(collection: Stdlib.getKeysAsList(map: m as! Dictionary)) as! Int,
|
try assertEquals(actual: StdlibKt.getFirstElement(collection: StdlibKt.getKeysAsList(map: m as! Dictionary)) as! Int,
|
||||||
expected: 10, "First key from a list")
|
expected: 10, "First key from a list")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,35 +129,35 @@ class StdlibTests : TestProvider {
|
|||||||
*/
|
*/
|
||||||
func testAddDictionary() throws {
|
func testAddDictionary() throws {
|
||||||
let m = [ "ABC": 10, "CDE": 12, "FGH": 3 ]
|
let m = [ "ABC": 10, "CDE": 12, "FGH": 3 ]
|
||||||
Stdlib.addSomeElementsToMap(map: StdlibMutableDictionary(dictionary: m))
|
StdlibKt.addSomeElementsToMap(map: KotlinMutableDictionary(dictionary: m))
|
||||||
for (k, v) in m {
|
for (k, v) in m {
|
||||||
print("MAP: \(k) - \(v)")
|
print("MAP: \(k) - \(v)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var smd = StdlibMutableDictionary<NSString, StdlibInt>()
|
var smd = KotlinMutableDictionary<NSString, KotlinInt>()
|
||||||
smd.setObject(333, forKey: "333" as NSString)
|
smd.setObject(333, forKey: "333" as NSString)
|
||||||
try assertEquals(actual: smd.object(forKey: "333" as NSString) as! Int, expected: 333, "Add element to dict")
|
try assertEquals(actual: smd.object(forKey: "333" as NSString) as! Int, expected: 333, "Add element to dict")
|
||||||
|
|
||||||
Stdlib.addSomeElementsToMap(map: smd)
|
StdlibKt.addSomeElementsToMap(map: smd)
|
||||||
for (k, v) in smd {
|
for (k, v) in smd {
|
||||||
print("MAP: \(k) - \(v)")
|
print("MAP: \(k) - \(v)")
|
||||||
}
|
}
|
||||||
try assertEquals(actual: smd.object(forKey: "XYZ" as NSString) as! Int, expected: 321, "Get element from Kotlin")
|
try assertEquals(actual: smd.object(forKey: "XYZ" as NSString) as! Int, expected: 321, "Get element from Kotlin")
|
||||||
}
|
}
|
||||||
|
|
||||||
func zeroTo(_ n: Int32) -> StdlibStdlibArray { return StdlibStdlibArray(size: n) { $0 } }
|
func zeroTo(_ n: Int32) -> KotlinArray { return KotlinArray(size: n) { $0 } }
|
||||||
|
|
||||||
func testList() throws {
|
func testList() throws {
|
||||||
let elements = zeroTo(5)
|
let elements = zeroTo(5)
|
||||||
elements.set(index: 1, value: nil)
|
elements.set(index: 1, value: nil)
|
||||||
let list = Stdlib.list(elements: elements) as! NSArray
|
let list = StdlibKt.list(elements: elements) as! NSArray
|
||||||
try assertEquals(actual: list.object(at: 2) as! NSNumber, expected: NSNumber(value: 2))
|
try assertEquals(actual: list.object(at: 2) as! NSNumber, expected: NSNumber(value: 2))
|
||||||
try assertEquals(actual: list.object(at: 1) as! NSNull, expected: NSNull())
|
try assertEquals(actual: list.object(at: 1) as! NSNull, expected: NSNull())
|
||||||
try assertEquals(actual: list.count, expected: 5)
|
try assertEquals(actual: list.count, expected: 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMutableList() throws {
|
func testMutableList() throws {
|
||||||
let kotlinList = Stdlib.emptyMutableList() as! NSMutableArray
|
let kotlinList = StdlibKt.emptyMutableList() as! NSMutableArray
|
||||||
let nsList = NSMutableArray()
|
let nsList = NSMutableArray()
|
||||||
|
|
||||||
func apply<T : Equatable>(op: (NSMutableArray)->T) throws {
|
func apply<T : Equatable>(op: (NSMutableArray)->T) throws {
|
||||||
@@ -191,7 +191,7 @@ class StdlibTests : TestProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testMutableSet() throws {
|
func testMutableSet() throws {
|
||||||
let kotlinSet = Stdlib.emptyMutableSet() as! NSMutableSet
|
let kotlinSet = StdlibKt.emptyMutableSet() as! NSMutableSet
|
||||||
let nsSet = NSMutableSet()
|
let nsSet = NSMutableSet()
|
||||||
|
|
||||||
func apply<T : Equatable>(op: (NSMutableSet)->T) throws {
|
func apply<T : Equatable>(op: (NSMutableSet)->T) throws {
|
||||||
@@ -214,10 +214,10 @@ class StdlibTests : TestProvider {
|
|||||||
try applyVoid { $0.add("bar") }
|
try applyVoid { $0.add("bar") }
|
||||||
try applyVoid { $0.remove("baz") }
|
try applyVoid { $0.remove("baz") }
|
||||||
try applyVoid { $0.add("baz") }
|
try applyVoid { $0.add("baz") }
|
||||||
try applyVoid { $0.add(StdlibTripleVals(first: 1, second: 2, third: 3)) }
|
try applyVoid { $0.add(TripleVals(first: 1, second: 2, third: 3)) }
|
||||||
try apply { $0.member(StdlibTripleVals(first: 1, second: 2, third: 3)) as! StdlibTripleVals }
|
try apply { $0.member(TripleVals(first: 1, second: 2, third: 3)) as! TripleVals }
|
||||||
try apply { $0.member(42) == nil }
|
try apply { $0.member(42) == nil }
|
||||||
try applyVoid { $0.remove(StdlibTripleVals(first: 1, second: 2, third: 3)) }
|
try applyVoid { $0.remove(TripleVals(first: 1, second: 2, third: 3)) }
|
||||||
|
|
||||||
let NULL0: Any? = nil
|
let NULL0: Any? = nil
|
||||||
let NULL = NULL0 as Any
|
let NULL = NULL0 as Any
|
||||||
@@ -235,7 +235,7 @@ class StdlibTests : TestProvider {
|
|||||||
|
|
||||||
func testMutableMap() throws {
|
func testMutableMap() throws {
|
||||||
// TODO: test KotlinMutableSet/Dictionary constructors
|
// TODO: test KotlinMutableSet/Dictionary constructors
|
||||||
let kotlinMap = Stdlib.emptyMutableMap() as! NSMutableDictionary
|
let kotlinMap = StdlibKt.emptyMutableMap() as! NSMutableDictionary
|
||||||
let nsMap = NSMutableDictionary()
|
let nsMap = NSMutableDictionary()
|
||||||
|
|
||||||
func apply<T : Equatable>(op: (NSMutableDictionary)->T) throws {
|
func apply<T : Equatable>(op: (NSMutableDictionary)->T) throws {
|
||||||
@@ -257,7 +257,7 @@ class StdlibTests : TestProvider {
|
|||||||
try apply { $0.object(forKey: 42) == nil }
|
try apply { $0.object(forKey: 42) == nil }
|
||||||
try applyVoid { $0.setObject(42, forKey: 42 as NSNumber) }
|
try applyVoid { $0.setObject(42, forKey: 42 as NSNumber) }
|
||||||
try applyVoid { $0.setObject(17, forKey: "foo" as NSString) }
|
try applyVoid { $0.setObject(17, forKey: "foo" as NSString) }
|
||||||
let triple = StdlibTripleVals(first: 3, second: 2, third: 1)
|
let triple = TripleVals(first: 3, second: 2, third: 1)
|
||||||
try applyVoid { $0.setObject("bar", forKey: triple) }
|
try applyVoid { $0.setObject("bar", forKey: triple) }
|
||||||
try applyVoid { $0.removeObject(forKey: 42) }
|
try applyVoid { $0.removeObject(forKey: 42) }
|
||||||
try apply { $0.count }
|
try apply { $0.count }
|
||||||
@@ -312,10 +312,10 @@ class StdlibTests : TestProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSet() throws {
|
func testSet() throws {
|
||||||
let elements = StdlibStdlibArray(size: 2) { index in nil }
|
let elements = KotlinArray(size: 2) { index in nil }
|
||||||
elements.set(index: 0, value: nil)
|
elements.set(index: 0, value: nil)
|
||||||
elements.set(index: 1, value: 42)
|
elements.set(index: 1, value: 42)
|
||||||
let set = Stdlib.set(elements: elements) as! NSSet
|
let set = StdlibKt.set(elements: elements) as! NSSet
|
||||||
try assertEquals(actual: set.count, expected: 2)
|
try assertEquals(actual: set.count, expected: 2)
|
||||||
try assertEquals(actual: set.member(NSNull()) as! NSNull, expected: NSNull())
|
try assertEquals(actual: set.member(NSNull()) as! NSNull, expected: NSNull())
|
||||||
try assertEquals(actual: set.member(42) as! NSNumber, expected: NSNumber(value: 42 as Int32))
|
try assertEquals(actual: set.member(42) as! NSNumber, expected: NSNumber(value: 42 as Int32))
|
||||||
@@ -329,7 +329,7 @@ class StdlibTests : TestProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testMap() throws {
|
func testMap() throws {
|
||||||
let elements = StdlibStdlibArray(size: 6) { index in nil }
|
let elements = KotlinArray(size: 6) { index in nil }
|
||||||
elements.set(index: 0, value: nil)
|
elements.set(index: 0, value: nil)
|
||||||
elements.set(index: 1, value: 42)
|
elements.set(index: 1, value: 42)
|
||||||
elements.set(index: 2, value: "foo")
|
elements.set(index: 2, value: "foo")
|
||||||
@@ -337,7 +337,7 @@ class StdlibTests : TestProvider {
|
|||||||
elements.set(index: 4, value: 42)
|
elements.set(index: 4, value: 42)
|
||||||
elements.set(index: 5, value: nil)
|
elements.set(index: 5, value: nil)
|
||||||
|
|
||||||
let map = Stdlib.map(keysAndValues: elements) as! NSDictionary
|
let map = StdlibKt.map(keysAndValues: elements) as! NSDictionary
|
||||||
try assertEquals(actual: map.count, expected: 3)
|
try assertEquals(actual: map.count, expected: 3)
|
||||||
|
|
||||||
try assertEquals(actual: map.object(forKey: NSNull()) as! NSNumber, expected: NSNumber(value: 42))
|
try assertEquals(actual: map.object(forKey: NSNull()) as! NSNumber, expected: NSNumber(value: 42))
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import Values
|
|||||||
|
|
||||||
func testVals() throws {
|
func testVals() throws {
|
||||||
print("Values from Swift")
|
print("Values from Swift")
|
||||||
let dbl = Values.dbl
|
let dbl = ValuesKt.dbl
|
||||||
let flt = Values.flt
|
let flt = ValuesKt.flt
|
||||||
let int = Values.integer
|
let int = ValuesKt.integer
|
||||||
let long = Values.longInt
|
let long = ValuesKt.longInt
|
||||||
|
|
||||||
print(dbl)
|
print(dbl)
|
||||||
print(flt)
|
print(flt)
|
||||||
@@ -39,9 +39,9 @@ func testVals() throws {
|
|||||||
|
|
||||||
func testVars() throws {
|
func testVars() throws {
|
||||||
print("Variables from Swift")
|
print("Variables from Swift")
|
||||||
var intVar = Values.intVar
|
var intVar = ValuesKt.intVar
|
||||||
var strVar = Values.str
|
var strVar = ValuesKt.str
|
||||||
var strAsId = Values.strAsAny
|
var strAsId = ValuesKt.strAsAny
|
||||||
|
|
||||||
print(intVar)
|
print(intVar)
|
||||||
print(strVar)
|
print(strVar)
|
||||||
@@ -52,133 +52,133 @@ func testVars() throws {
|
|||||||
try assertEquals(actual: strAsId as! String, expected: "Kotlin String as Any")
|
try assertEquals(actual: strAsId as! String, expected: "Kotlin String as Any")
|
||||||
|
|
||||||
strAsId = "Swift str"
|
strAsId = "Swift str"
|
||||||
Values.strAsAny = strAsId
|
ValuesKt.strAsAny = strAsId
|
||||||
print(Values.strAsAny)
|
print(ValuesKt.strAsAny)
|
||||||
try assertEquals(actual: Values.strAsAny as! String, expected: strAsId as! String)
|
try assertEquals(actual: ValuesKt.strAsAny as! String, expected: strAsId as! String)
|
||||||
|
|
||||||
// property with custom getter/setter backed by the Kotlin's var
|
// property with custom getter/setter backed by the Kotlin's var
|
||||||
var intProp : Int32 {
|
var intProp : Int32 {
|
||||||
get {
|
get {
|
||||||
return Values.intVar * 2
|
return ValuesKt.intVar * 2
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
Values.intVar = 123 + value
|
ValuesKt.intVar = 123 + value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
intProp += 10
|
intProp += 10
|
||||||
print(intProp)
|
print(intProp)
|
||||||
print(Values.intVar)
|
print(ValuesKt.intVar)
|
||||||
try assertEquals(actual: Values.intVar * 2, expected: intProp, "Property backed by var")
|
try assertEquals(actual: ValuesKt.intVar * 2, expected: intProp, "Property backed by var")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDoubles() throws {
|
func testDoubles() throws {
|
||||||
print("Doubles in Swift")
|
print("Doubles in Swift")
|
||||||
let minDouble = Values.minDoubleVal as! Double
|
let minDouble = ValuesKt.minDoubleVal as! Double
|
||||||
let maxDouble = Values.maxDoubleVal as! NSNumber
|
let maxDouble = ValuesKt.maxDoubleVal as! NSNumber
|
||||||
|
|
||||||
print(minDouble)
|
print(minDouble)
|
||||||
print(maxDouble)
|
print(maxDouble)
|
||||||
print(Values.nanDoubleVal)
|
print(ValuesKt.nanDoubleVal)
|
||||||
print(Values.nanFloatVal)
|
print(ValuesKt.nanFloatVal)
|
||||||
print(Values.infDoubleVal)
|
print(ValuesKt.infDoubleVal)
|
||||||
print(Values.infFloatVal)
|
print(ValuesKt.infFloatVal)
|
||||||
|
|
||||||
try assertEquals(actual: minDouble, expected: Double.leastNonzeroMagnitude, "Min double")
|
try assertEquals(actual: minDouble, expected: Double.leastNonzeroMagnitude, "Min double")
|
||||||
try assertEquals(actual: maxDouble, expected: Double.greatestFiniteMagnitude as NSNumber, "Max double")
|
try assertEquals(actual: maxDouble, expected: Double.greatestFiniteMagnitude as NSNumber, "Max double")
|
||||||
try assertTrue(Values.nanDoubleVal.isNaN, "NaN double")
|
try assertTrue(ValuesKt.nanDoubleVal.isNaN, "NaN double")
|
||||||
try assertTrue(Values.nanFloatVal.isNaN, "NaN float")
|
try assertTrue(ValuesKt.nanFloatVal.isNaN, "NaN float")
|
||||||
try assertEquals(actual: Values.infDoubleVal, expected: Double.infinity, "Inf double")
|
try assertEquals(actual: ValuesKt.infDoubleVal, expected: Double.infinity, "Inf double")
|
||||||
try assertEquals(actual: Values.infFloatVal, expected: -Float.infinity, "-Inf float")
|
try assertEquals(actual: ValuesKt.infFloatVal, expected: -Float.infinity, "-Inf float")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testNumbers() throws {
|
func testNumbers() throws {
|
||||||
try assertEquals(actual: ValuesBoolean(value: true).boolValue, expected: true)
|
try assertEquals(actual: KotlinBoolean(value: true).boolValue, expected: true)
|
||||||
try assertEquals(actual: ValuesBoolean(value: false).intValue, expected: 0)
|
try assertEquals(actual: KotlinBoolean(value: false).intValue, expected: 0)
|
||||||
try assertEquals(actual: ValuesBoolean(value: true), expected: true)
|
try assertEquals(actual: KotlinBoolean(value: true), expected: true)
|
||||||
try assertFalse(ValuesBoolean(value: false) as! Bool)
|
try assertFalse(KotlinBoolean(value: false) as! Bool)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesByte(value: -1).int8Value, expected: -1)
|
try assertEquals(actual: KotlinByte(value: -1).int8Value, expected: -1)
|
||||||
try assertEquals(actual: ValuesByte(value: -1).int32Value, expected: -1)
|
try assertEquals(actual: KotlinByte(value: -1).int32Value, expected: -1)
|
||||||
try assertEquals(actual: ValuesByte(value: -1).doubleValue, expected: -1.0)
|
try assertEquals(actual: KotlinByte(value: -1).doubleValue, expected: -1.0)
|
||||||
try assertEquals(actual: ValuesByte(value: -1), expected: NSNumber(value: Int64(-1)))
|
try assertEquals(actual: KotlinByte(value: -1), expected: NSNumber(value: Int64(-1)))
|
||||||
try assertFalse(ValuesByte(value: -1) == NSNumber(value: -1.5))
|
try assertFalse(KotlinByte(value: -1) == NSNumber(value: -1.5))
|
||||||
try assertEquals(actual: ValuesByte(value: -1), expected: -1)
|
try assertEquals(actual: KotlinByte(value: -1), expected: -1)
|
||||||
try assertTrue(ValuesByte(value: -1) == -1)
|
try assertTrue(KotlinByte(value: -1) == -1)
|
||||||
try assertFalse(ValuesByte(value: -1) == 1)
|
try assertFalse(KotlinByte(value: -1) == 1)
|
||||||
try assertEquals(actual: ValuesByte(value: -1) as! Int32, expected: -1)
|
try assertEquals(actual: KotlinByte(value: -1) as! Int32, expected: -1)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesShort(value: 111).int16Value, expected: 111)
|
try assertEquals(actual: KotlinShort(value: 111).int16Value, expected: 111)
|
||||||
try assertEquals(actual: ValuesShort(value: -15) as! Int16, expected: -15)
|
try assertEquals(actual: KotlinShort(value: -15) as! Int16, expected: -15)
|
||||||
try assertEquals(actual: ValuesShort(value: 47), expected: 47)
|
try assertEquals(actual: KotlinShort(value: 47), expected: 47)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesInt(value: 99).int32Value, expected: 99)
|
try assertEquals(actual: KotlinInt(value: 99).int32Value, expected: 99)
|
||||||
try assertEquals(actual: ValuesInt(value: -1) as! Int32, expected: -1)
|
try assertEquals(actual: KotlinInt(value: -1) as! Int32, expected: -1)
|
||||||
try assertEquals(actual: ValuesInt(value: 72), expected: 72)
|
try assertEquals(actual: KotlinInt(value: 72), expected: 72)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesLong(value: 65).int64Value, expected: 65)
|
try assertEquals(actual: KotlinLong(value: 65).int64Value, expected: 65)
|
||||||
try assertEquals(actual: ValuesLong(value: 10000000000) as! Int64, expected: 10000000000)
|
try assertEquals(actual: KotlinLong(value: 10000000000) as! Int64, expected: 10000000000)
|
||||||
try assertEquals(actual: ValuesLong(value: 8), expected: 8)
|
try assertEquals(actual: KotlinLong(value: 8), expected: 8)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesUByte(value: 17).uint8Value, expected: 17)
|
try assertEquals(actual: KotlinUByte(value: 17).uint8Value, expected: 17)
|
||||||
try assertEquals(actual: ValuesUByte(value: 42) as! UInt8, expected: 42)
|
try assertEquals(actual: KotlinUByte(value: 42) as! UInt8, expected: 42)
|
||||||
try assertEquals(actual: 88, expected: ValuesUByte(value: 88))
|
try assertEquals(actual: 88, expected: KotlinUByte(value: 88))
|
||||||
|
|
||||||
try assertEquals(actual: ValuesUShort(value: 40000).uint16Value, expected: 40000)
|
try assertEquals(actual: KotlinUShort(value: 40000).uint16Value, expected: 40000)
|
||||||
try assertEquals(actual: ValuesUShort(value: 1) as! UInt16, expected: UInt16(1))
|
try assertEquals(actual: KotlinUShort(value: 1) as! UInt16, expected: UInt16(1))
|
||||||
try assertEquals(actual: ValuesUShort(value: 65000), expected: 65000)
|
try assertEquals(actual: KotlinUShort(value: 65000), expected: 65000)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesUInt(value: 3).uint32Value, expected: 3)
|
try assertEquals(actual: KotlinUInt(value: 3).uint32Value, expected: 3)
|
||||||
try assertEquals(actual: ValuesUInt(value: UInt32.max) as! UInt32, expected: UInt32.max)
|
try assertEquals(actual: KotlinUInt(value: UInt32.max) as! UInt32, expected: UInt32.max)
|
||||||
try assertEquals(actual: ValuesUInt(value: 2), expected: 2)
|
try assertEquals(actual: KotlinUInt(value: 2), expected: 2)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesULong(value: 55).uint64Value, expected: 55)
|
try assertEquals(actual: KotlinULong(value: 55).uint64Value, expected: 55)
|
||||||
try assertEquals(actual: ValuesULong(value: 0) as! UInt64, expected: 0)
|
try assertEquals(actual: KotlinULong(value: 0) as! UInt64, expected: 0)
|
||||||
try assertEquals(actual: ValuesULong(value: 7), expected: 7)
|
try assertEquals(actual: KotlinULong(value: 7), expected: 7)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesFloat(value: 1.0).floatValue, expected: 1.0)
|
try assertEquals(actual: KotlinFloat(value: 1.0).floatValue, expected: 1.0)
|
||||||
try assertEquals(actual: ValuesFloat(value: 22.0) as! Float, expected: 22)
|
try assertEquals(actual: KotlinFloat(value: 22.0) as! Float, expected: 22)
|
||||||
try assertEquals(actual: ValuesFloat(value: 41.0), expected: 41)
|
try assertEquals(actual: KotlinFloat(value: 41.0), expected: 41)
|
||||||
try assertEquals(actual: ValuesFloat(value: -5.5), expected: -5.5)
|
try assertEquals(actual: KotlinFloat(value: -5.5), expected: -5.5)
|
||||||
|
|
||||||
try assertEquals(actual: ValuesDouble(value: 0.5).doubleValue, expected: 0.5)
|
try assertEquals(actual: KotlinDouble(value: 0.5).doubleValue, expected: 0.5)
|
||||||
try assertEquals(actual: ValuesDouble(value: 45.0) as! Double, expected: 45)
|
try assertEquals(actual: KotlinDouble(value: 45.0) as! Double, expected: 45)
|
||||||
try assertEquals(actual: ValuesDouble(value: 89.0), expected: 89)
|
try assertEquals(actual: KotlinDouble(value: 89.0), expected: 89)
|
||||||
try assertEquals(actual: ValuesDouble(value: -3.7), expected: -3.7)
|
try assertEquals(actual: KotlinDouble(value: -3.7), expected: -3.7)
|
||||||
|
|
||||||
Values.ensureEqualBooleans(actual: ValuesBoolean(value: true), expected: true)
|
ValuesKt.ensureEqualBooleans(actual: KotlinBoolean(value: true), expected: true)
|
||||||
Values.ensureEqualBooleans(actual: false, expected: false)
|
ValuesKt.ensureEqualBooleans(actual: false, expected: false)
|
||||||
|
|
||||||
Values.ensureEqualBytes(actual: ValuesByte(value: 42), expected: 42)
|
ValuesKt.ensureEqualBytes(actual: KotlinByte(value: 42), expected: 42)
|
||||||
Values.ensureEqualBytes(actual: -11, expected: -11)
|
ValuesKt.ensureEqualBytes(actual: -11, expected: -11)
|
||||||
|
|
||||||
Values.ensureEqualShorts(actual: ValuesShort(value: 256), expected: 256)
|
ValuesKt.ensureEqualShorts(actual: KotlinShort(value: 256), expected: 256)
|
||||||
Values.ensureEqualShorts(actual: -1, expected: -1)
|
ValuesKt.ensureEqualShorts(actual: -1, expected: -1)
|
||||||
|
|
||||||
Values.ensureEqualInts(actual: ValuesInt(value: 100000), expected: 100000)
|
ValuesKt.ensureEqualInts(actual: KotlinInt(value: 100000), expected: 100000)
|
||||||
Values.ensureEqualInts(actual: -7, expected: -7)
|
ValuesKt.ensureEqualInts(actual: -7, expected: -7)
|
||||||
|
|
||||||
Values.ensureEqualLongs(actual: ValuesLong(value: Int64.max), expected: Int64.max)
|
ValuesKt.ensureEqualLongs(actual: KotlinLong(value: Int64.max), expected: Int64.max)
|
||||||
Values.ensureEqualLongs(actual: 17, expected: 17)
|
ValuesKt.ensureEqualLongs(actual: 17, expected: 17)
|
||||||
|
|
||||||
Values.ensureEqualUBytes(actual: ValuesUByte(value: 6), expected: 6)
|
ValuesKt.ensureEqualUBytes(actual: KotlinUByte(value: 6), expected: 6)
|
||||||
Values.ensureEqualUBytes(actual: 255, expected: 255)
|
ValuesKt.ensureEqualUBytes(actual: 255, expected: 255)
|
||||||
|
|
||||||
Values.ensureEqualUShorts(actual: ValuesUShort(value: 300), expected: 300)
|
ValuesKt.ensureEqualUShorts(actual: KotlinUShort(value: 300), expected: 300)
|
||||||
Values.ensureEqualUShorts(actual: 65535, expected: UInt16.max)
|
ValuesKt.ensureEqualUShorts(actual: 65535, expected: UInt16.max)
|
||||||
|
|
||||||
Values.ensureEqualUInts(actual: ValuesUInt(value: 70000), expected: 70000)
|
ValuesKt.ensureEqualUInts(actual: KotlinUInt(value: 70000), expected: 70000)
|
||||||
Values.ensureEqualUInts(actual: 48, expected: 48)
|
ValuesKt.ensureEqualUInts(actual: 48, expected: 48)
|
||||||
|
|
||||||
Values.ensureEqualULongs(actual: ValuesULong(value: UInt64.max), expected: UInt64.max)
|
ValuesKt.ensureEqualULongs(actual: KotlinULong(value: UInt64.max), expected: UInt64.max)
|
||||||
Values.ensureEqualULongs(actual: 39, expected: 39)
|
ValuesKt.ensureEqualULongs(actual: 39, expected: 39)
|
||||||
|
|
||||||
Values.ensureEqualFloats(actual: ValuesFloat(value: 36.6), expected: 36.6)
|
ValuesKt.ensureEqualFloats(actual: KotlinFloat(value: 36.6), expected: 36.6)
|
||||||
Values.ensureEqualFloats(actual: 49.5, expected: 49.5)
|
ValuesKt.ensureEqualFloats(actual: 49.5, expected: 49.5)
|
||||||
Values.ensureEqualFloats(actual: 18, expected: 18.0)
|
ValuesKt.ensureEqualFloats(actual: 18, expected: 18.0)
|
||||||
|
|
||||||
Values.ensureEqualDoubles(actual: ValuesDouble(value: 12.34), expected: 12.34)
|
ValuesKt.ensureEqualDoubles(actual: KotlinDouble(value: 12.34), expected: 12.34)
|
||||||
Values.ensureEqualDoubles(actual: 56.78, expected: 56.78)
|
ValuesKt.ensureEqualDoubles(actual: 56.78, expected: 56.78)
|
||||||
Values.ensureEqualDoubles(actual: 3, expected: 3)
|
ValuesKt.ensureEqualDoubles(actual: 3, expected: 3)
|
||||||
|
|
||||||
func checkBox<T: Equatable, B : NSObject>(_ value: T, _ boxFunction: (T) -> B?) throws {
|
func checkBox<T: Equatable, B : NSObject>(_ value: T, _ boxFunction: (T) -> B?) throws {
|
||||||
let box = boxFunction(value)!
|
let box = boxFunction(value)!
|
||||||
@@ -188,27 +188,27 @@ func testNumbers() throws {
|
|||||||
try assertTrue(box.isKind(of: B.self))
|
try assertTrue(box.isKind(of: B.self))
|
||||||
}
|
}
|
||||||
|
|
||||||
try checkBox(true, Values.box)
|
try checkBox(true, ValuesKt.box)
|
||||||
try checkBox(Int8(-1), Values.box)
|
try checkBox(Int8(-1), ValuesKt.box)
|
||||||
try checkBox(Int16(-2), Values.box)
|
try checkBox(Int16(-2), ValuesKt.box)
|
||||||
try checkBox(Int32(-3), Values.box)
|
try checkBox(Int32(-3), ValuesKt.box)
|
||||||
try checkBox(Int64(-4), Values.box)
|
try checkBox(Int64(-4), ValuesKt.box)
|
||||||
try checkBox(UInt8(5), Values.box)
|
try checkBox(UInt8(5), ValuesKt.box)
|
||||||
try checkBox(UInt16(6), Values.box)
|
try checkBox(UInt16(6), ValuesKt.box)
|
||||||
try checkBox(UInt32(7), Values.box)
|
try checkBox(UInt32(7), ValuesKt.box)
|
||||||
try checkBox(UInt64(8), Values.box)
|
try checkBox(UInt64(8), ValuesKt.box)
|
||||||
try checkBox(Float(8.7), Values.box)
|
try checkBox(Float(8.7), ValuesKt.box)
|
||||||
try checkBox(Double(9.4), Values.box)
|
try checkBox(Double(9.4), ValuesKt.box)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLists() throws {
|
func testLists() throws {
|
||||||
let numbersList = Values.numbersList
|
let numbersList = ValuesKt.numbersList
|
||||||
let gold = [1, 2, 13]
|
let gold = [1, 2, 13]
|
||||||
for i in 0..<gold.count {
|
for i in 0..<gold.count {
|
||||||
try assertEquals(actual: gold[i], expected: Int(numbersList[i] as! NSNumber), "Numbers list")
|
try assertEquals(actual: gold[i], expected: Int(numbersList[i] as! NSNumber), "Numbers list")
|
||||||
}
|
}
|
||||||
|
|
||||||
let anyList = Values.anyList
|
let anyList = ValuesKt.anyList
|
||||||
for i in anyList {
|
for i in anyList {
|
||||||
print(i)
|
print(i)
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ func testLists() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testLazyVal() throws {
|
func testLazyVal() throws {
|
||||||
let lazyVal = Values.lazyVal
|
let lazyVal = ValuesKt.lazyVal
|
||||||
print(lazyVal)
|
print(lazyVal)
|
||||||
try assertEquals(actual: lazyVal, expected: "Lazily initialized string", "lazy value")
|
try assertEquals(actual: lazyVal, expected: "Lazily initialized string", "lazy value")
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ func testLazyVal() throws {
|
|||||||
let goldenArray = ["Delegated", "global", "array", "property"]
|
let goldenArray = ["Delegated", "global", "array", "property"]
|
||||||
|
|
||||||
func testDelegatedProp() throws {
|
func testDelegatedProp() throws {
|
||||||
let delegatedGlobalArray = Values.delegatedGlobalArray
|
let delegatedGlobalArray = ValuesKt.delegatedGlobalArray
|
||||||
guard Int(delegatedGlobalArray.size) == goldenArray.count else {
|
guard Int(delegatedGlobalArray.size) == goldenArray.count else {
|
||||||
throw TestError.assertFailed("Size differs")
|
throw TestError.assertFailed("Size differs")
|
||||||
}
|
}
|
||||||
@@ -234,7 +234,7 @@ func testDelegatedProp() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testGetterDelegate() throws {
|
func testGetterDelegate() throws {
|
||||||
let delegatedList = Values.delegatedList
|
let delegatedList = ValuesKt.delegatedList
|
||||||
guard delegatedList.count == goldenArray.count else {
|
guard delegatedList.count == goldenArray.count else {
|
||||||
throw TestError.assertFailed("Size differs")
|
throw TestError.assertFailed("Size differs")
|
||||||
}
|
}
|
||||||
@@ -244,16 +244,16 @@ func testGetterDelegate() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testNulls() throws {
|
func testNulls() throws {
|
||||||
let nilVal : Any? = Values.nullVal
|
let nilVal : Any? = ValuesKt.nullVal
|
||||||
try assertTrue(nilVal == nil, "Null value")
|
try assertTrue(nilVal == nil, "Null value")
|
||||||
|
|
||||||
Values.nullVar = nil
|
ValuesKt.nullVar = nil
|
||||||
var nilVar : Any? = Values.nullVar
|
var nilVar : Any? = ValuesKt.nullVar
|
||||||
try assertTrue(nilVar == nil, "Null variable")
|
try assertTrue(nilVar == nil, "Null variable")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAnyVar() throws {
|
func testAnyVar() throws {
|
||||||
let anyVar : Any = Values.anyValue
|
let anyVar : Any = ValuesKt.anyValue
|
||||||
print(anyVar)
|
print(anyVar)
|
||||||
if let str = anyVar as? String {
|
if let str = anyVar as? String {
|
||||||
print(str)
|
print(str)
|
||||||
@@ -264,19 +264,19 @@ func testAnyVar() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testFunctions() throws {
|
func testFunctions() throws {
|
||||||
let _: Any? = Values.emptyFun()
|
let _: Any? = ValuesKt.emptyFun()
|
||||||
|
|
||||||
let str = Values.strFun()
|
let str = ValuesKt.strFun()
|
||||||
try assertEquals(actual: str, expected: "fooStr")
|
try assertEquals(actual: str, expected: "fooStr")
|
||||||
|
|
||||||
try assertEquals(actual: Values.argsFun(i: 10, l: 20, d: 3.5, s: "res") as! String,
|
try assertEquals(actual: ValuesKt.argsFun(i: 10, l: 20, d: 3.5, s: "res") as! String,
|
||||||
expected: "res10203.5")
|
expected: "res10203.5")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFuncType() throws {
|
func testFuncType() throws {
|
||||||
let s = "str"
|
let s = "str"
|
||||||
let fFunc: () -> String = { return s }
|
let fFunc: () -> String = { return s }
|
||||||
try assertEquals(actual: Values.funArgument(foo: fFunc), expected: s, "Using function type arguments failed")
|
try assertEquals(actual: ValuesKt.funArgument(foo: fFunc), expected: s, "Using function type arguments failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGenericsFoo() throws {
|
func testGenericsFoo() throws {
|
||||||
@@ -284,48 +284,48 @@ func testGenericsFoo() throws {
|
|||||||
// wrap lambda to workaround issue with type conversion inability:
|
// wrap lambda to workaround issue with type conversion inability:
|
||||||
// (Int) -> String can't be cast to (Any?) -> Any?
|
// (Int) -> String can't be cast to (Any?) -> Any?
|
||||||
let wrapper = { (t: Any?) -> Any? in return fun(t as! Int) }
|
let wrapper = { (t: Any?) -> Any? in return fun(t as! Int) }
|
||||||
let res = Values.genericFoo(t: 42, foo: wrapper)
|
let res = ValuesKt.genericFoo(t: 42, foo: wrapper)
|
||||||
try assertEquals(actual: res as! String, expected: "S 42")
|
try assertEquals(actual: res as! String, expected: "S 42")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVararg() throws {
|
func testVararg() throws {
|
||||||
let ktArray = ValuesStdlibArray(size: 3, init: { (_) -> Int in return 42 })
|
let ktArray = KotlinArray(size: 3, init: { (_) -> Int in return 42 })
|
||||||
let arr: [Int] = Values.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])
|
||||||
}
|
}
|
||||||
|
|
||||||
func testStrExtFun() throws {
|
func testStrExtFun() throws {
|
||||||
try assertEquals(actual: Values.subExt("String", i: 2), expected: "r")
|
try assertEquals(actual: ValuesKt.subExt("String", i: 2), expected: "r")
|
||||||
try assertEquals(actual: Values.subExt("A", i: 2), expected: "nothing")
|
try assertEquals(actual: ValuesKt.subExt("A", i: 2), expected: "nothing")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAnyToString() throws {
|
func testAnyToString() throws {
|
||||||
try assertEquals(actual: Values.toString(nil), expected: "null")
|
try assertEquals(actual: ValuesKt.toString(nil), expected: "null")
|
||||||
try assertEquals(actual: Values.toString(42), expected: "42")
|
try assertEquals(actual: ValuesKt.toString(42), expected: "42")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAnyPrint() throws {
|
func testAnyPrint() throws {
|
||||||
print("BEGIN")
|
print("BEGIN")
|
||||||
Values.print(nil)
|
ValuesKt.print(nil)
|
||||||
Values.print("Print")
|
ValuesKt.print("Print")
|
||||||
Values.print(123456789)
|
ValuesKt.print(123456789)
|
||||||
Values.print(3.14)
|
ValuesKt.print(3.14)
|
||||||
Values.print([3, 2, 1])
|
ValuesKt.print([3, 2, 1])
|
||||||
print("END")
|
print("END")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLambda() throws {
|
func testLambda() throws {
|
||||||
try assertEquals(actual: Values.sumLambda(3, 4), expected: 7)
|
try assertEquals(actual: ValuesKt.sumLambda(3, 4), expected: 7)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- Tests for classes and interfaces -------
|
// -------- Tests for classes and interfaces -------
|
||||||
class ValIEmptyExt : ValuesI {
|
class ValIEmptyExt : I {
|
||||||
func iFun() -> String {
|
func iFun() -> String {
|
||||||
return "ValIEmptyExt::iFun"
|
return "ValIEmptyExt::iFun"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValIExt : ValuesI {
|
class ValIExt : I {
|
||||||
func iFun() -> String {
|
func iFun() -> String {
|
||||||
return "ValIExt::iFun"
|
return "ValIExt::iFun"
|
||||||
}
|
}
|
||||||
@@ -337,19 +337,19 @@ func testInterfaceExtension() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testClassInstances() throws {
|
func testClassInstances() throws {
|
||||||
try assertEquals(actual: ValuesOpenClassI().iFun(), expected: "OpenClassI::iFun")
|
try assertEquals(actual: OpenClassI().iFun(), expected: "OpenClassI::iFun")
|
||||||
try assertEquals(actual: ValuesDefaultInterfaceExt().iFun(), expected: "I::iFun")
|
try assertEquals(actual: DefaultInterfaceExt().iFun(), expected: "I::iFun")
|
||||||
try assertEquals(actual: ValuesFinalClassExtOpen().iFun(), expected: "FinalClassExtOpen::iFun")
|
try assertEquals(actual: FinalClassExtOpen().iFun(), expected: "FinalClassExtOpen::iFun")
|
||||||
try assertEquals(actual: ValuesMultiExtClass().iFun(), expected: "PI::iFun")
|
try assertEquals(actual: MultiExtClass().iFun(), expected: "PI::iFun")
|
||||||
try assertEquals(actual: ValuesMultiExtClass().piFun() as! Int, expected: 42)
|
try assertEquals(actual: MultiExtClass().piFun() as! Int, expected: 42)
|
||||||
try assertEquals(actual: ValuesConstrClass(i: 1, s: "str", a: "Any").iFun(), expected: "OpenClassI::iFun")
|
try assertEquals(actual: ConstrClass(i: 1, s: "str", a: "Any").iFun(), expected: "OpenClassI::iFun")
|
||||||
try assertEquals(actual: ValuesExtConstrClass(i: 123).iFun(), expected: "ExtConstrClass::iFun::123-String-AnyS")
|
try assertEquals(actual: ExtConstrClass(i: 123).iFun(), expected: "ExtConstrClass::iFun::123-String-AnyS")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEnum() throws {
|
func testEnum() throws {
|
||||||
try assertEquals(actual: Values.passEnum().enumValue, expected: 42)
|
try assertEquals(actual: ValuesKt.passEnum().enumValue, expected: 42)
|
||||||
try assertEquals(actual: Values.passEnum().name, expected: "ANSWER")
|
try assertEquals(actual: ValuesKt.passEnum().name, expected: "ANSWER")
|
||||||
Values.receiveEnum(e: 1)
|
ValuesKt.receiveEnum(e: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDataClass() throws {
|
func testDataClass() throws {
|
||||||
@@ -357,13 +357,13 @@ func testDataClass() throws {
|
|||||||
let s = "2"
|
let s = "2"
|
||||||
let t = "3"
|
let t = "3"
|
||||||
|
|
||||||
let tripleVal = ValuesTripleVals(first: f, second: s, third: t)
|
let tripleVal = TripleVals(first: f, second: s, third: t)
|
||||||
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))")
|
||||||
|
|
||||||
let tripleVar = ValuesTripleVars(first: f, second: s, third: t)
|
let tripleVar = TripleVars(first: f, second: s, third: t)
|
||||||
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)
|
||||||
@@ -377,31 +377,31 @@ func testDataClass() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCompanionObj() throws {
|
func testCompanionObj() throws {
|
||||||
try assertEquals(actual: ValuesWithCompanionAndObjectCompanion().str, expected: "String")
|
try assertEquals(actual: WithCompanionAndObjectCompanion().str, expected: "String")
|
||||||
try assertEquals(actual: Values.getCompanionObject().str, expected: "String")
|
try assertEquals(actual: ValuesKt.getCompanionObject().str, expected: "String")
|
||||||
|
|
||||||
let namedFromCompanion = Values.getCompanionObject().named
|
let namedFromCompanion = ValuesKt.getCompanionObject().named
|
||||||
let named = Values.getNamedObject()
|
let named = ValuesKt.getNamedObject()
|
||||||
try assertTrue(named === namedFromCompanion, "Should be the same Named object")
|
try assertTrue(named === namedFromCompanion, "Should be the same Named object")
|
||||||
|
|
||||||
try assertEquals(actual: Values.getNamedObjectInterface().iFun(), expected: named.iFun(), "Named object's method")
|
try assertEquals(actual: ValuesKt.getNamedObjectInterface().iFun(), expected: named.iFun(), "Named object's method")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInlineClasses() throws {
|
func testInlineClasses() throws {
|
||||||
let ic1: Int32 = 42
|
let ic1: Int32 = 42
|
||||||
let ic1N = Values.box(ic1: 17)
|
let ic1N = ValuesKt.box(ic1: 17)
|
||||||
let ic2 = "foo"
|
let ic2 = "foo"
|
||||||
let ic2N = "bar"
|
let ic2N = "bar"
|
||||||
let ic3 = ValuesTripleVals(first: 1, second: 2, third: 3)
|
let ic3 = TripleVals(first: 1, second: 2, third: 3)
|
||||||
let ic3N = Values.box(ic3: nil)
|
let ic3N = ValuesKt.box(ic3: nil)
|
||||||
|
|
||||||
try assertEquals(
|
try assertEquals(
|
||||||
actual: Values.concatenateInlineClassValues(ic1: ic1, ic1N: ic1N, ic2: ic2, ic2N: ic2N, ic3: ic3, ic3N: ic3N),
|
actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: ic1N, ic2: ic2, ic2N: ic2N, ic3: ic3, ic3N: ic3N),
|
||||||
expected: "42 17 foo bar TripleVals(first=1, second=2, third=3) null"
|
expected: "42 17 foo bar TripleVals(first=1, second=2, third=3) null"
|
||||||
)
|
)
|
||||||
|
|
||||||
try assertEquals(
|
try assertEquals(
|
||||||
actual: Values.concatenateInlineClassValues(ic1: ic1, ic1N: nil, ic2: ic2, ic2N: nil, ic3: nil, ic3N: nil),
|
actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: nil, ic2: ic2, ic2N: nil, ic3: nil, ic3N: nil),
|
||||||
expected: "42 null foo null null null"
|
expected: "42 null foo null null null"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class ViewController: UIViewController, UITextViewDelegate, UICollectionViewData
|
|||||||
@IBOutlet var input: UITextView!
|
@IBOutlet var input: UITextView!
|
||||||
@IBOutlet var numpad: UICollectionView!
|
@IBOutlet var numpad: UICollectionView!
|
||||||
|
|
||||||
private let parser = KAPPartialParser(composer: KAPCalculator(), partialComposer: PartialRenderer())
|
private let parser = PartialParser(composer: Calculator(), partialComposer: PartialRenderer())
|
||||||
|
|
||||||
@IBAction func numpadButtonPressed(_ sender: UIButton) {
|
@IBAction func numpadButtonPressed(_ sender: UIButton) {
|
||||||
let title = sender.currentTitle!
|
let title = sender.currentTitle!
|
||||||
@@ -112,7 +112,7 @@ private extension String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PartialRenderer: NSObject, KAPPartialExpressionComposer {
|
private class PartialRenderer: NSObject, PartialExpressionComposer {
|
||||||
func missing() -> Any {
|
func missing() -> Any {
|
||||||
return "... ".toAttributed()
|
return "... ".toAttributed()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user