[K/N][Tests] Migrate framework and objcexport tests
^KT-61259
This commit is contained in:
committed by
Space Team
parent
f00a145dd7
commit
025771460c
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
public abstract class AbstractBase(val y: Int) {
|
||||
abstract val x: Int
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import Foundation
|
||||
import AbstractInstantiation
|
||||
|
||||
func testInstantiate() throws {
|
||||
// this is failure test, it shouldn't work
|
||||
let base = AbstractBase(y: 5)
|
||||
}
|
||||
|
||||
class AbstractInstantiationTests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
providers.append(self)
|
||||
tests = [
|
||||
TestCase(name: "testInstantiate", method: withAutorelease(testInstantiate))
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package lib
|
||||
|
||||
fun lib() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
fun main() {}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
language=Objective-C
|
||||
---
|
||||
struct ForwardDeclaredStruct;
|
||||
@class ForwardDeclaredClass;
|
||||
@protocol ForwardDeclaredProtocol;
|
||||
|
||||
struct ForwardDeclaredStruct* sameStruct(struct ForwardDeclaredStruct* ptr) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ForwardDeclaredClass* sameClass(ForwardDeclaredClass* obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
id<ForwardDeclaredProtocol> sameProtocol(id<ForwardDeclaredProtocol> obj) {
|
||||
return obj;
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
import forwardDeclarations.*
|
||||
import cnames.structs.ForwardDeclaredStruct
|
||||
import objcnames.classes.ForwardDeclaredClass
|
||||
import objcnames.protocols.ForwardDeclaredProtocolProtocol
|
||||
import kotlinx.cinterop.CPointer
|
||||
|
||||
fun sameForwardDeclaredStruct(ptr: CPointer<ForwardDeclaredStruct>?): CPointer<ForwardDeclaredStruct>? = sameStruct(ptr)
|
||||
fun sameForwardDeclaredClass(obj: ForwardDeclaredClass?): ForwardDeclaredClass? = sameClass(obj)
|
||||
fun sameForwardDeclaredProtocol(obj: ForwardDeclaredProtocolProtocol?): ForwardDeclaredProtocolProtocol? = sameProtocol(obj)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import ForwardDeclarations
|
||||
|
||||
private func test1() throws {
|
||||
let ptr = UnsafeMutableRawPointer(bitPattern: 0x1234)
|
||||
try assertEquals(actual: ForwardDeclarationsKt.sameForwardDeclaredStruct(ptr: ptr), expected: ptr)
|
||||
|
||||
// We can't actually test this, because Swift can't import neither types nor functions due to
|
||||
// "interface/protocol '...' is incomplete":
|
||||
//
|
||||
// let classObj: ForwardDeclaredClass? = nil
|
||||
// try assertNil(LibKt.sameForwardDeclaredClass(obj: classObj))
|
||||
//
|
||||
// let protocolObj: ForwardDeclaredProtocol? = nil
|
||||
// try assertNil(LibKt.sameForwardDeclaredProtocol(obj: protocolObj))
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class ForwardDeclarationsTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
language = Objective-C
|
||||
headers = Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h
|
||||
headerFilter = gh3343.h Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h
|
||||
@@ -0,0 +1,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NSString* foo1(int x) {
|
||||
return [NSString stringWithFormat:@"%d", x];
|
||||
}
|
||||
|
||||
NSArray* foo2(int x) {
|
||||
NSValue* xx = @(x);
|
||||
NSString* s = @"zzz";
|
||||
return [NSArray arrayWithObjects: xx, s, nil];
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
import kotlinx.cinterop.*
|
||||
import gh3343.*
|
||||
import kotlin.native.ref.*
|
||||
|
||||
fun run(): List<Any?> {
|
||||
val result = mutableListOf<Any?>()
|
||||
result.add(foo1(42))
|
||||
val list = foo2(117)
|
||||
if (list != null) {
|
||||
result.add(list.size)
|
||||
for (x in list)
|
||||
result.add(x)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import Foundation
|
||||
import Gh3343
|
||||
|
||||
func testGh3343() throws {
|
||||
let list = Gh3343Kt.run()
|
||||
try assertEquals(actual: list[0] as? String, expected: "42")
|
||||
try assertEquals(actual: list[1] as? Int, expected: 2)
|
||||
try assertEquals(actual: list[2] as? Int, expected: 117)
|
||||
try assertEquals(actual: list[3] as? String, expected: "zzz")
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class Gh3343Tests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
providers.append(self)
|
||||
tests = [
|
||||
TestCase(name: "Gh3343", method: withAutorelease(testGh3343)),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class)
|
||||
|
||||
import kotlin.native.Platform
|
||||
|
||||
// The following 2 singletons are unused. However, since we are generating ObjC bindings for them,
|
||||
// they should be marked as used, so that the code generator emits their deinitialization.
|
||||
|
||||
object A {
|
||||
fun foo() = 1
|
||||
}
|
||||
|
||||
class B {
|
||||
companion object {
|
||||
fun foo() = 2
|
||||
}
|
||||
}
|
||||
|
||||
fun enableMemoryChecker() {
|
||||
Platform.isMemoryLeakCheckerActive = true
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import Kt42397
|
||||
|
||||
class Results {
|
||||
var aFoo: Int32 = 0
|
||||
var bFoo: Int32 = 0
|
||||
}
|
||||
|
||||
func runTestKt42397(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
|
||||
autoreleasepool {
|
||||
Kt42397Kt.enableMemoryChecker()
|
||||
let results = pointer.bindMemory(to: Results.self, capacity: 1).pointee
|
||||
results.aFoo = A().foo()
|
||||
results.bFoo = B.Companion().foo()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testKt42397() throws {
|
||||
let results = Results()
|
||||
let resultsPtr = UnsafeMutablePointer<Results>.allocate(capacity: 1)
|
||||
resultsPtr.initialize(to: results)
|
||||
var thread: pthread_t? = nil
|
||||
let result = pthread_create(&thread, nil, runTestKt42397, resultsPtr)
|
||||
try assertEquals(actual: result, expected: 0)
|
||||
pthread_join(thread!, nil)
|
||||
|
||||
try assertEquals(actual: results.aFoo, expected: 1)
|
||||
try assertEquals(actual: results.bFoo, expected: 2)
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class Kt42397Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Kt42397", testKt42397)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
enum E {
|
||||
A, B, C
|
||||
};
|
||||
|
||||
struct S {
|
||||
int i;
|
||||
float f;
|
||||
};
|
||||
|
||||
struct S globalS = { .i = 3, .f = 3.14f };
|
||||
|
||||
enum E createEnum() {
|
||||
return A;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
import kt43517.*
|
||||
|
||||
fun produceEnum(): E =
|
||||
createEnum()
|
||||
|
||||
fun compareEnums(e1: E, e2: E): Boolean =
|
||||
e1 == e2
|
||||
|
||||
fun getFirstField(s: S): Int =
|
||||
s.i
|
||||
|
||||
fun getGlobalS(): S =
|
||||
globalS
|
||||
@@ -0,0 +1,24 @@
|
||||
import Foundation
|
||||
import Kt43517
|
||||
|
||||
func testKt43517() throws {
|
||||
try assertEquals(
|
||||
actual: Kt43517Kt.compareEnums(e1: Kt43517Kt.produceEnum(), e2: Kt43517Kt.produceEnum()),
|
||||
expected: true
|
||||
)
|
||||
try assertEquals(
|
||||
actual: Kt43517Kt.getFirstField(s: Kt43517Kt.getGlobalS()),
|
||||
expected: 3
|
||||
)
|
||||
}
|
||||
|
||||
class Kt43517Tests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
providers.append(self)
|
||||
tests = [
|
||||
TestCase(name: "Kt43517", method: withAutorelease(testKt43517)),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
enum class SimpleEnum {
|
||||
ONE,
|
||||
TWO
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import Kt56233
|
||||
|
||||
func threadRoutine(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
|
||||
autoreleasepool {
|
||||
let f = pointer.bindMemory(to: (() -> ()).self, capacity: 1).pointee
|
||||
f()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func launchThreads(
|
||||
_ f: @convention(c) () -> (),
|
||||
threadCount: Int = 4
|
||||
) throws {
|
||||
var threads: [pthread_t] = []
|
||||
for _ in 0..<threadCount {
|
||||
let fPtr = UnsafeMutablePointer<() -> ()>.allocate(capacity: 1)
|
||||
fPtr.initialize(to: f)
|
||||
var thread: pthread_t? = nil
|
||||
let result = pthread_create(&thread, nil, threadRoutine, fPtr)
|
||||
try assertEquals(actual: result, expected: 0)
|
||||
threads.append(thread!)
|
||||
}
|
||||
for thread in threads {
|
||||
pthread_join(thread, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func kt56233() {
|
||||
#if AGGRESSIVE_GC
|
||||
let count = 50_000
|
||||
#else
|
||||
let count = 50_000_000
|
||||
#endif
|
||||
// Stress testing for race conditions.
|
||||
for _ in 0..<count {
|
||||
_ = Kt56233.SimpleEnum.two.ordinal
|
||||
}
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class Kt56233Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Kt56233", { try launchThreads(kt56233) })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
interface Foo {
|
||||
fun bar(): String?
|
||||
}
|
||||
|
||||
internal class FooImplUnused : Foo {
|
||||
override fun bar(): String? = null
|
||||
}
|
||||
|
||||
fun foobar(foo: Foo): Boolean {
|
||||
val s = foo.bar()
|
||||
if (s == null)
|
||||
return false
|
||||
return s == "zzz"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import Foundation
|
||||
import Kt57791
|
||||
|
||||
class FooImpl : Foo {
|
||||
func bar() -> String? { "zzz" }
|
||||
}
|
||||
|
||||
func testKt57791() throws {
|
||||
try assertTrue(Kt57791Kt.foobar(foo: FooImpl()))
|
||||
}
|
||||
|
||||
class Kt57791Tests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
providers.append(self)
|
||||
tests = [
|
||||
TestCase(name: "Kt57791", method: withAutorelease(testKt57791)),
|
||||
]
|
||||
}
|
||||
}
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
enum TestError : Error {
|
||||
case assertFailed(String)
|
||||
case failure
|
||||
case testsFailed([String])
|
||||
}
|
||||
|
||||
// ---------------- Assertions ----------------
|
||||
|
||||
private func throwAssertFailed(message: String, file: String, line: Int) throws -> Never {
|
||||
throw TestError.assertFailed("\(file):\(line): \(message)")
|
||||
}
|
||||
|
||||
func assertEquals<T: Equatable>(actual: T, expected: T,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line) throws {
|
||||
if (actual != expected) {
|
||||
try throwAssertFailed(message: message + " Expected value: \(expected), but got: \(actual)",
|
||||
file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func assertSame(actual: AnyObject?, expected: AnyObject?,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line) throws {
|
||||
if (actual !== expected) {
|
||||
try throwAssertFailed(message: message + " Expected value: \(expected), but got: \(actual)",
|
||||
file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func assertEquals<T: Equatable>(actual: [T], expected: [T],
|
||||
_ message: String = "Assertion failed: arrays not equal",
|
||||
file: String = #file, line: Int = #line) throws {
|
||||
try assertEquals(actual: actual.count, expected: expected.count, "Size differs", file: file, line: line)
|
||||
try assertTrue(actual.elementsEqual(expected), "Arrays elements are not equal", file: file, line: line)
|
||||
}
|
||||
|
||||
func assertTrue(_ value: Bool,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line) throws {
|
||||
if (value != true) {
|
||||
try throwAssertFailed(message: message + " Expected value to be TRUE, but got: \(value)",
|
||||
file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func assertFalse(_ value: Bool,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line) throws {
|
||||
if (value != false) {
|
||||
try throwAssertFailed(message: message + " Expected value to be FALSE, but got: \(value)",
|
||||
file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func assertNil(_ value: Any?,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line) throws {
|
||||
if (value != nil) {
|
||||
try throwAssertFailed(message: message + " Expected value to be nil, but got: \(value!)",
|
||||
file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func fail(_ message: String = "Should not reach here", file: String = #file, line: Int = #line) throws -> Never {
|
||||
try throwAssertFailed(message: message, file: file, line: line)
|
||||
}
|
||||
|
||||
func assertFailsWith<T : Error>(_ errorType: T.Type,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line,
|
||||
block: () throws -> Void) throws {
|
||||
do {
|
||||
try block()
|
||||
} catch let error {
|
||||
if error is T { return }
|
||||
try throwAssertFailed(message: message + " Expected error \(errorType), got \(error)",
|
||||
file: file, line: line)
|
||||
}
|
||||
|
||||
try throwAssertFailed(message: message + " Expected error \(errorType), but finished successfully",
|
||||
file: file, line: line)
|
||||
}
|
||||
|
||||
func assertFailsWithKotlin<T>(_ exceptionType: T.Type,
|
||||
_ message: String = "Assertion failed:",
|
||||
file: String = #file, line: Int = #line,
|
||||
block: () throws -> Void) throws {
|
||||
do {
|
||||
try block()
|
||||
} catch let error {
|
||||
let kotlinException = error.kotlinException
|
||||
if kotlinException is T { return }
|
||||
let got = kotlinException ?? error
|
||||
try throwAssertFailed(message: message + " Expected Kotlin exception \(exceptionType), got \(got)",
|
||||
file: file, line: line)
|
||||
}
|
||||
|
||||
try throwAssertFailed(message: message + " Expected Kotlin exception \(exceptionType), but finished successfully",
|
||||
file: file, line: line)
|
||||
}
|
||||
|
||||
|
||||
// ---------------- Utils --------------------
|
||||
|
||||
func withAutorelease( _ method: @escaping () throws -> Void) -> () throws -> Void {
|
||||
return { () throws -> Void in
|
||||
try autoreleasepool { try method() }
|
||||
}
|
||||
}
|
||||
|
||||
extension Error {
|
||||
var kotlinException: Any? {
|
||||
get {
|
||||
return (self as NSError).userInfo["KotlinException"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Execution ----------------
|
||||
|
||||
private final class Statistics : CustomStringConvertible {
|
||||
var passed: [String] = []
|
||||
var failed: [String] = []
|
||||
|
||||
var description: String {
|
||||
return """
|
||||
---- RESULTS:
|
||||
PASSED: \(passed.count)
|
||||
FAILED: \(failed.count)
|
||||
"""
|
||||
}
|
||||
|
||||
static let instance = Statistics()
|
||||
|
||||
static func getInstance() -> Statistics {
|
||||
return instance
|
||||
}
|
||||
|
||||
func start(_ name: String) {
|
||||
print("---- Starting test: \(name)")
|
||||
}
|
||||
|
||||
func passed(_ name: String) {
|
||||
print("---- PASSED test: \(name)")
|
||||
passed.append(name)
|
||||
}
|
||||
|
||||
func failed(_ name: String, error: Error) {
|
||||
print("---- FAILED test: \(name) with error: \(error)")
|
||||
failed.append(name)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* TestCase represents a single test
|
||||
*/
|
||||
struct TestCase {
|
||||
let name: String
|
||||
let method: () throws -> Void
|
||||
|
||||
init(name: String, method: @escaping () throws -> Void) {
|
||||
self.name = name
|
||||
self.method = method
|
||||
}
|
||||
|
||||
func run() {
|
||||
let stats = Statistics.getInstance()
|
||||
stats.start(name)
|
||||
do {
|
||||
try method()
|
||||
stats.passed(name)
|
||||
} catch {
|
||||
stats.failed(name, error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol TestProvider {
|
||||
var tests: [TestCase] { get }
|
||||
}
|
||||
|
||||
class SimpleTestProvider : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
providers.append(self)
|
||||
}
|
||||
|
||||
func test(_ name: String, _ method: @escaping () throws -> Void) {
|
||||
tests.append(TestCase(name: name, method: withAutorelease(method)))
|
||||
}
|
||||
}
|
||||
|
||||
var providers: [TestProvider] = []
|
||||
|
||||
private func execute(tests: [TestCase]) {
|
||||
for test in tests {
|
||||
test.run()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point of the test
|
||||
*/
|
||||
private func main() {
|
||||
// Generated method that instantiates test providers.
|
||||
registerProviders()
|
||||
|
||||
let stats = Statistics.getInstance()
|
||||
for pr in providers {
|
||||
let name = String(describing: type(of: pr))
|
||||
print("-- \(name) started")
|
||||
execute(tests: pr.tests)
|
||||
print("-- \(name) finished")
|
||||
}
|
||||
print(stats)
|
||||
|
||||
let failed = stats.failed
|
||||
if !failed.isEmpty {
|
||||
print()
|
||||
print("Tests failed:")
|
||||
for testName in failed {
|
||||
print(":: \(testName)")
|
||||
}
|
||||
abort()
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package multiple
|
||||
|
||||
interface I1 {
|
||||
fun getFortyTwo(): Int
|
||||
}
|
||||
|
||||
class I1Impl : I1 {
|
||||
override fun getFortyTwo(): Int = 42
|
||||
}
|
||||
|
||||
fun getI1() = object : I1 {
|
||||
override fun getFortyTwo(): Int = 42
|
||||
}
|
||||
|
||||
class C
|
||||
|
||||
fun getUnit(): Unit? = Unit
|
||||
|
||||
/*
|
||||
// Disabled for now to avoid depending on platform libs.
|
||||
fun getAnonymousObject() = object : platform.darwin.NSObject() {}
|
||||
class NamedObject : platform.darwin.NSObject()
|
||||
fun getNamedObject() = NamedObject()
|
||||
*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package multiple
|
||||
|
||||
val name = "first"
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package multiple
|
||||
|
||||
interface I2 {
|
||||
fun getFortyTwo(): Int
|
||||
}
|
||||
|
||||
fun getFortyTwoFrom(i2: I2): Int = i2.getFortyTwo()
|
||||
|
||||
fun getI2() = object : I2 {
|
||||
override fun getFortyTwo(): Int = 42
|
||||
}
|
||||
|
||||
class C
|
||||
|
||||
fun isUnit(obj: Any?): Boolean = (obj === Unit)
|
||||
|
||||
/*
|
||||
// Disabled for now to avoid depending on platform libs.
|
||||
fun getAnonymousObject() = object : platform.darwin.NSObject() {}
|
||||
class NamedObject : platform.darwin.NSObject()
|
||||
fun getNamedObject() = NamedObject()
|
||||
*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package multiple
|
||||
|
||||
val name = "second"
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 First
|
||||
import Second
|
||||
|
||||
func testClashingNames() throws {
|
||||
try assertEquals(actual: "first", expected: First.TestKt.name)
|
||||
try assertEquals(actual: "second", expected: Second.TestKt.name)
|
||||
|
||||
let c1 = First.C()
|
||||
let c2 = Second.C()
|
||||
try assertTrue(type(of: c1) == First.C.self)
|
||||
try assertTrue(type(of: c2) == Second.C.self)
|
||||
try assertTrue(First.C.self != Second.C.self)
|
||||
try assertTrue(objc_getClass(class_getName(First.C.self)) as AnyObject === First.C.self)
|
||||
try assertTrue(objc_getClass(class_getName(Second.C.self)) as AnyObject === Second.C.self)
|
||||
}
|
||||
|
||||
extension I1Impl : I2 {}
|
||||
|
||||
func testInteraction() throws {
|
||||
try assertEquals(actual: SecondKt.getFortyTwoFrom(i2: I1Impl()), expected: 42)
|
||||
}
|
||||
|
||||
func testIsolation1() throws {
|
||||
try assertFalse(SecondKt.isUnit(obj: FirstKt.getUnit()))
|
||||
|
||||
// Ensure frameworks don't share the same runtime (state):
|
||||
try assertFalse(First.RuntimeState().consumeChange())
|
||||
try assertFalse(Second.RuntimeState().consumeChange())
|
||||
Second.RuntimeState().produceChange()
|
||||
try assertFalse(First.RuntimeState().consumeChange())
|
||||
try assertTrue(Second.RuntimeState().consumeChange())
|
||||
}
|
||||
|
||||
func testIsolation2() throws {
|
||||
try assertEquals(actual: FirstKt.getI1().getFortyTwo(), expected: 42)
|
||||
try assertEquals(actual: SecondKt.getI2().getFortyTwo(), expected: 42)
|
||||
}
|
||||
|
||||
func testIsolation3() throws {
|
||||
#if false // Disabled for now to avoid depending on platform libs.
|
||||
FirstKt.getAnonymousObject()
|
||||
SecondKt.getAnonymousObject()
|
||||
FirstKt.getNamedObject()
|
||||
SecondKt.getNamedObject()
|
||||
#endif
|
||||
}
|
||||
|
||||
// https://youtrack.jetbrains.com/issue/KT-34261
|
||||
// When First and Second are static frameworks with caches, this test fails due to bad cache isolation:
|
||||
// Caches included into both frameworks have 'ktypew' globals (with same name, hidden visibility and common linkage)
|
||||
// for writable part of this "unexposed stdlib class" TypeInfo.
|
||||
// ld ignores hidden visibility and merges common globals, so two independent frameworks happen to share
|
||||
// the same global instead of two different globals. Things go wrong at runtime then: this writable TypeInfo part
|
||||
// is used to store Obj-C class for this Kotlin class. So after the first object is obtained in Swift, both TypeInfos
|
||||
// have its class, and the second object is wrong then.
|
||||
func testIsolation4() throws {
|
||||
let obj1: Any = First.SharedKt.getUnexposedStdlibClassInstance()
|
||||
try assertTrue(obj1 is First.KotlinBase)
|
||||
try assertFalse(obj1 is Second.KotlinBase)
|
||||
|
||||
let obj2: Any = Second.SharedKt.getUnexposedStdlibClassInstance()
|
||||
try assertFalse(obj2 is First.KotlinBase)
|
||||
try assertTrue(obj2 is Second.KotlinBase)
|
||||
}
|
||||
|
||||
class MultipleTests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
tests = [
|
||||
TestCase(name: "TestClashingNames", method: withAutorelease(testClashingNames)),
|
||||
TestCase(name: "TestInteraction", method: withAutorelease(testInteraction)),
|
||||
TestCase(name: "TestIsolation1", method: withAutorelease(testIsolation1)),
|
||||
TestCase(name: "TestIsolation2", method: withAutorelease(testIsolation2)),
|
||||
TestCase(name: "TestIsolation3", method: withAutorelease(testIsolation3)),
|
||||
TestCase(name: "TestIsolation4", method: withAutorelease(testIsolation4)),
|
||||
]
|
||||
providers.append(self)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
@file:OptIn(ObsoleteWorkersApi::class)
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
object RuntimeState {
|
||||
fun produceChange() {
|
||||
Worker.current.executeAfter {}
|
||||
}
|
||||
|
||||
fun consumeChange(): Boolean {
|
||||
return Worker.current.processQueue()
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this assumes that IntRange class is not exposed by the enclosing framework.
|
||||
fun getUnexposedStdlibClassInstance(): Any = 0..2
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||
|
||||
package coroutines
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
import kotlin.native.concurrent.isFrozen
|
||||
import kotlin.native.internal.ObjCErrorException
|
||||
import kotlin.test.*
|
||||
import kotlin.reflect.*
|
||||
|
||||
class CoroutineException : Throwable()
|
||||
|
||||
suspend fun suspendFun() = 42
|
||||
suspend fun unitSuspendFun() = Unit
|
||||
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
suspend fun suspendFun(result: Any?, doSuspend: Boolean, doThrow: Boolean): Any? {
|
||||
if (doSuspend) {
|
||||
suspendCoroutineUninterceptedOrReturn<Unit> {
|
||||
it.resume(Unit)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
if (doThrow) throw CoroutineException()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
suspend fun unitSuspendFun(doSuspend: Boolean, doThrow: Boolean) {
|
||||
if (doSuspend) {
|
||||
suspendCoroutineUninterceptedOrReturn<Unit> {
|
||||
it.resume(Unit)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
if (doThrow) throw CoroutineException()
|
||||
}
|
||||
|
||||
class ContinuationHolder<T> {
|
||||
internal var continuation: Continuation<T>? = null
|
||||
|
||||
fun resume(value: T) {
|
||||
continuation!!.resume(value)
|
||||
continuation = null
|
||||
}
|
||||
|
||||
fun resumeWithException(exception: Throwable) {
|
||||
continuation!!.resumeWithException(exception)
|
||||
continuation = null
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
suspend fun suspendFunAsync(result: Any?, continuationHolder: ContinuationHolder<Any?>): Any? =
|
||||
suspendCoroutineUninterceptedOrReturn<Any?> {
|
||||
continuationHolder.continuation = it
|
||||
COROUTINE_SUSPENDED
|
||||
} ?: result
|
||||
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
suspend fun unitSuspendFunAsync(continuationHolder: ContinuationHolder<Unit>): Unit =
|
||||
suspendCoroutineUninterceptedOrReturn<Unit> {
|
||||
continuationHolder.continuation = it
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
fun throwException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
|
||||
interface SuspendFun {
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
suspend fun suspendFun(doYield: Boolean, doThrow: Boolean): Int
|
||||
}
|
||||
|
||||
class ResultHolder<T> {
|
||||
var completed: Int = 0
|
||||
var result: T? = null
|
||||
var exception: Throwable? = null
|
||||
|
||||
internal fun complete(result: Result<T>) {
|
||||
this.result = result.getOrNull()
|
||||
this.exception = result.exceptionOrNull()
|
||||
this.completed += 1
|
||||
}
|
||||
}
|
||||
|
||||
private class ResultHolderCompletion<T>(val resultHolder: ResultHolder<T>) : Continuation<T> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resumeWith(result: Result<T>) {
|
||||
resultHolder.complete(result)
|
||||
}
|
||||
}
|
||||
|
||||
fun callSuspendFun(suspendFun: SuspendFun, doYield: Boolean, doThrow: Boolean, resultHolder: ResultHolder<Int>) {
|
||||
suspend { suspendFun.suspendFun(doYield = doYield, doThrow = doThrow) }
|
||||
.startCoroutine(ResultHolderCompletion(resultHolder))
|
||||
}
|
||||
|
||||
@Throws(CoroutineException::class, CancellationException::class)
|
||||
suspend fun callSuspendFun2(suspendFun: SuspendFun, doYield: Boolean, doThrow: Boolean): Int {
|
||||
return suspendFun.suspendFun(doYield = doYield, doThrow = doThrow)
|
||||
}
|
||||
|
||||
interface SuspendBridge<T> {
|
||||
suspend fun int(value: T): Int
|
||||
suspend fun intAsAny(value: T): Any?
|
||||
|
||||
suspend fun unit(value: T): Unit
|
||||
suspend fun unitAsAny(value: T): Any?
|
||||
suspend fun nullableUnit(value: T): Unit?
|
||||
|
||||
@Throws(Throwable::class) suspend fun nothing(value: T): Nothing
|
||||
@Throws(Throwable::class) suspend fun nothingAsInt(value: T): Int
|
||||
@Throws(Throwable::class) suspend fun nothingAsAny(value: T): Any?
|
||||
@Throws(Throwable::class) suspend fun nothingAsUnit(value: T): Unit
|
||||
}
|
||||
|
||||
abstract class AbstractSuspendBridge : SuspendBridge<Int> {
|
||||
override suspend fun intAsAny(value: Int): Int = TODO()
|
||||
|
||||
override suspend fun unit(value: Int): Unit = TODO()
|
||||
override suspend fun unitAsAny(value: Int): Unit = TODO()
|
||||
override suspend fun nullableUnit(value: Int): Unit? = TODO()
|
||||
|
||||
override suspend fun nothingAsInt(value: Int): Nothing = TODO()
|
||||
override suspend fun nothingAsAny(value: Int): Nothing = TODO()
|
||||
override suspend fun nothingAsUnit(value: Int): Nothing = TODO()
|
||||
}
|
||||
|
||||
private suspend fun callSuspendBridgeImpl(bridge: SuspendBridge<Int>) {
|
||||
assertEquals(1, bridge.intAsAny(1))
|
||||
|
||||
assertSame(Unit, bridge.unit(2))
|
||||
assertSame(Unit, bridge.unitAsAny(3))
|
||||
assertSame(Unit, bridge.nullableUnit(4))
|
||||
|
||||
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(5) }
|
||||
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(6) }
|
||||
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(7) }
|
||||
}
|
||||
|
||||
private suspend fun callAbstractSuspendBridgeImpl(bridge: AbstractSuspendBridge) {
|
||||
assertEquals(8, bridge.intAsAny(8))
|
||||
|
||||
assertSame(Unit, bridge.unit(9))
|
||||
assertSame(Unit, bridge.unitAsAny(10))
|
||||
assertSame(Unit, bridge.nullableUnit(11))
|
||||
|
||||
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(12) }
|
||||
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(13) }
|
||||
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(14) }
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun callSuspendBridge(bridge: AbstractSuspendBridge, resultHolder: ResultHolder<Unit>) {
|
||||
suspend {
|
||||
callSuspendBridgeImpl(bridge)
|
||||
callAbstractSuspendBridgeImpl(bridge)
|
||||
}.startCoroutine(ResultHolderCompletion(resultHolder))
|
||||
}
|
||||
|
||||
suspend fun throwCancellationException(): Unit {
|
||||
val exception = CancellationException("coroutine is cancelled")
|
||||
|
||||
// Note: frontend checker hardcodes fq names of CancellationException super classes (see NativeThrowsChecker).
|
||||
// This is our best effort to keep that list in sync with actual stdlib code:
|
||||
assertTrue(exception is kotlin.Throwable)
|
||||
assertTrue(exception is kotlin.Exception)
|
||||
assertTrue(exception is kotlin.RuntimeException)
|
||||
assertTrue(exception is kotlin.IllegalStateException)
|
||||
assertTrue(exception is kotlin.coroutines.cancellation.CancellationException)
|
||||
|
||||
throw exception
|
||||
}
|
||||
|
||||
abstract class ThrowCancellationException {
|
||||
internal abstract suspend fun throwCancellationException()
|
||||
}
|
||||
|
||||
class ThrowCancellationExceptionImpl : ThrowCancellationException() {
|
||||
public override suspend fun throwCancellationException() {
|
||||
throw CancellationException()
|
||||
}
|
||||
}
|
||||
|
||||
class suspendFunctionChild0: suspend () -> String {
|
||||
override suspend fun invoke(): String = "child 0"
|
||||
}
|
||||
|
||||
class suspendFunctionChild1: suspend (String) -> String {
|
||||
override suspend fun invoke(s: String): String = "$s 1"
|
||||
}
|
||||
|
||||
fun getSuspendLambda0(): suspend () -> String = { "lambda 0" }
|
||||
|
||||
private suspend fun suspendCallableReference0Target(): String = "callable reference 0"
|
||||
fun getSuspendCallableReference0(): suspend () -> String = ::suspendCallableReference0Target
|
||||
|
||||
fun getSuspendChild0() = suspendFunctionChild0()
|
||||
|
||||
fun getSuspendLambda1(): suspend (String) -> String = { "$it 1" }
|
||||
|
||||
private suspend fun suspendCallableReference1Target(str: String): String = "$str 1"
|
||||
fun getSuspendCallableReference1(): suspend (String) -> String = ::suspendCallableReference1Target
|
||||
fun getSuspendChild1() = suspendFunctionChild1()
|
||||
|
||||
|
||||
suspend fun invoke1(block: suspend (Any?) -> Any?, argument: Any?): Any? = block(argument)
|
||||
|
||||
fun getKSuspendCallableReference0(): KSuspendFunction0<String> = ::suspendCallableReference0Target
|
||||
fun getKSuspendCallableReference1(): KSuspendFunction1<String, String> = ::suspendCallableReference1Target
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun startCoroutineUninterceptedOrReturn(fn: suspend () -> Any?, resultHolder: ResultHolder<Any?>) =
|
||||
fn.startCoroutineUninterceptedOrReturn(ResultHolderCompletion(resultHolder))
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun startCoroutineUninterceptedOrReturn(fn: suspend Any?.() -> Any?, receiver: Any?, resultHolder: ResultHolder<Any?>) =
|
||||
fn.startCoroutineUninterceptedOrReturn(receiver, ResultHolderCompletion(resultHolder))
|
||||
|
||||
@Throws(Throwable::class)
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
fun startCoroutineUninterceptedOrReturn(fn: suspend Any?.(Any?) -> Any?, receiver: Any?, param: Any?, resultHolder: ResultHolder<Any?>) =
|
||||
fn.startCoroutineUninterceptedOrReturn(receiver, param, ResultHolderCompletion(resultHolder))
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun createCoroutineUninterceptedAndResume(fn: suspend () -> Any?, resultHolder: ResultHolder<Any?>) =
|
||||
fn.createCoroutine(ResultHolderCompletion(resultHolder)).resume(Unit)
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun createCoroutineUninterceptedAndResume(fn: suspend Any?.() -> Any?, receiver: Any?, resultHolder: ResultHolder<Any?>) =
|
||||
fn.createCoroutine(receiver, ResultHolderCompletion(resultHolder)).resume(Unit)
|
||||
|
||||
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||
fun gc() = kotlin.native.runtime.GC.collect()
|
||||
@@ -0,0 +1,741 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
private func testCallSimple() throws {
|
||||
var result: KotlinInt? = nil
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
CoroutinesKt.suspendFun { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertEquals(actual: result, expected: 42)
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
private func testUnitCallSimple() throws {
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
var result: KotlinUnit? = nil
|
||||
#endif
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
CoroutinesKt.unitSuspendFun { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result
|
||||
error = _error
|
||||
}
|
||||
#else
|
||||
CoroutinesKt.unitSuspendFun { _error in
|
||||
completionCalled += 1
|
||||
error = _error
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
try assertSame(actual: result, expected: KotlinUnit.shared)
|
||||
#endif
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
private func testUnitCallNonMainDispatcher() throws {
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
var result: KotlinUnit? = nil
|
||||
#endif
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
let group = DispatchGroup()
|
||||
|
||||
#if ALLOW_SUSPEND_ANY_THREAD
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
DispatchQueue.global().async(group: group) {
|
||||
CoroutinesKt.unitSuspendFun { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result
|
||||
error = _error
|
||||
}
|
||||
}
|
||||
#else
|
||||
DispatchQueue.global().async(group: group) {
|
||||
CoroutinesKt.unitSuspendFun { _error in
|
||||
completionCalled += 1
|
||||
error = _error
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ALLOW_SUSPEND_ANY_THREAD
|
||||
group.wait()
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private func testCallSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
|
||||
class C {}
|
||||
let expectedResult = C()
|
||||
|
||||
var completionCalled = 0
|
||||
var result: AnyObject? = nil
|
||||
var error: Error? = nil
|
||||
|
||||
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as AnyObject?
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
if doThrow {
|
||||
try assertNil(result)
|
||||
try assertTrue(error?.kotlinException is CoroutineException)
|
||||
} else {
|
||||
try assertSame(actual: result, expected: expectedResult)
|
||||
try assertNil(error)
|
||||
}
|
||||
}
|
||||
|
||||
private func testCallUnitSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
|
||||
var completionCalled = 0
|
||||
var result: AnyObject? = nil
|
||||
var error: Error? = nil
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
CoroutinesKt.unitSuspendFun(doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as AnyObject?
|
||||
error = _error
|
||||
}
|
||||
#else
|
||||
CoroutinesKt.unitSuspendFun(doSuspend: doSuspend, doThrow: doThrow) { _error in
|
||||
completionCalled += 1
|
||||
error = _error
|
||||
}
|
||||
#endif
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
if doThrow {
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
try assertNil(result)
|
||||
#endif
|
||||
try assertTrue(error?.kotlinException is CoroutineException)
|
||||
} else {
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
try assertSame(actual: result, expected: KotlinUnit.shared)
|
||||
#endif
|
||||
try assertNil(error)
|
||||
}
|
||||
}
|
||||
|
||||
private class WeakRefHolder {
|
||||
weak var value: AnyObject? = nil
|
||||
}
|
||||
|
||||
#if NO_GENERICS
|
||||
typealias AnyContinuationHolder = ContinuationHolder
|
||||
#else
|
||||
typealias AnyContinuationHolder = ContinuationHolder<AnyObject>
|
||||
#endif
|
||||
|
||||
// This code is extracted to a function just to ensure that all local variables get released at the end.
|
||||
private func callSuspendFunAsync(
|
||||
weakRefToObjectCapturedByCompletion: WeakRefHolder,
|
||||
continuationHolder: AnyContinuationHolder,
|
||||
completionHandler: @escaping (Any?, Error?) -> Void
|
||||
) throws {
|
||||
class C {}
|
||||
let capturedByCompletion = C()
|
||||
weakRefToObjectCapturedByCompletion.value = capturedByCompletion
|
||||
|
||||
CoroutinesKt.suspendFunAsync(result: nil, continuationHolder: continuationHolder) { _result, _error in
|
||||
try! assertSame(actual: capturedByCompletion, expected: weakRefToObjectCapturedByCompletion.value)
|
||||
completionHandler(_result, _error)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSuspendFuncAsync(doThrow: Bool) throws {
|
||||
var completionCalled = 0
|
||||
var result: AnyObject? = nil
|
||||
var error: Error? = nil
|
||||
|
||||
let continuationHolder = AnyContinuationHolder()
|
||||
|
||||
let weakRefToObjectCapturedByCompletion = WeakRefHolder()
|
||||
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
|
||||
try autoreleasepool {
|
||||
try callSuspendFunAsync(
|
||||
weakRefToObjectCapturedByCompletion: weakRefToObjectCapturedByCompletion,
|
||||
continuationHolder: continuationHolder
|
||||
) { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as AnyObject?
|
||||
error = _error
|
||||
}
|
||||
}
|
||||
CoroutinesKt.gc()
|
||||
// This assert checks that suspendFunAsync retains the completion handler:
|
||||
try assertFalse(weakRefToObjectCapturedByCompletion.value === nil)
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 0)
|
||||
|
||||
if doThrow {
|
||||
let exception = CoroutineException()
|
||||
continuationHolder.resumeWithException(exception: exception)
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
try assertNil(result)
|
||||
try assertSame(actual: error?.kotlinException as AnyObject?, expected: exception)
|
||||
} else {
|
||||
class C {}
|
||||
let expectedResult = C()
|
||||
continuationHolder.resume(value: expectedResult)
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
try assertSame(actual: result, expected: expectedResult)
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
#if !NOOP_GC
|
||||
CoroutinesKt.gc()
|
||||
// This assert checks that the completion handler gets properly released after all:
|
||||
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NO_GENERICS
|
||||
typealias UnitContinuationHolder = ContinuationHolder
|
||||
#else
|
||||
typealias UnitContinuationHolder = ContinuationHolder<KotlinUnit>
|
||||
#endif
|
||||
|
||||
// This code is extracted to a function just to ensure that all local variables get released at the end.
|
||||
private func callUnitSuspendFunAsync(
|
||||
weakRefToObjectCapturedByCompletion: WeakRefHolder,
|
||||
continuationHolder: UnitContinuationHolder,
|
||||
completionHandler: @escaping (Error?) -> Void
|
||||
) throws {
|
||||
class C {}
|
||||
let capturedByCompletion = C()
|
||||
weakRefToObjectCapturedByCompletion.value = capturedByCompletion
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
CoroutinesKt.unitSuspendFunAsync(continuationHolder: continuationHolder) { _result, _error in
|
||||
try! assertSame(actual: capturedByCompletion, expected: weakRefToObjectCapturedByCompletion.value)
|
||||
completionHandler(_error)
|
||||
}
|
||||
#else
|
||||
CoroutinesKt.unitSuspendFunAsync(continuationHolder: continuationHolder) { _error in
|
||||
try! assertSame(actual: capturedByCompletion, expected: weakRefToObjectCapturedByCompletion.value)
|
||||
completionHandler(_error)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private func testUnitSuspendFuncAsync(doThrow: Bool) throws {
|
||||
var completionCalled = 0
|
||||
var error: Error? = nil
|
||||
|
||||
let continuationHolder = UnitContinuationHolder()
|
||||
|
||||
let weakRefToObjectCapturedByCompletion = WeakRefHolder()
|
||||
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
|
||||
try autoreleasepool {
|
||||
try callUnitSuspendFunAsync(
|
||||
weakRefToObjectCapturedByCompletion: weakRefToObjectCapturedByCompletion,
|
||||
continuationHolder: continuationHolder
|
||||
) { _error in
|
||||
completionCalled += 1
|
||||
error = _error
|
||||
}
|
||||
}
|
||||
CoroutinesKt.gc()
|
||||
// This assert checks that unitSuspendFunAsync retains the completion handler:
|
||||
try assertFalse(weakRefToObjectCapturedByCompletion.value === nil)
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 0)
|
||||
|
||||
if doThrow {
|
||||
let exception = CoroutineException()
|
||||
continuationHolder.resumeWithException(exception: exception)
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
try assertSame(actual: error?.kotlinException as AnyObject?, expected: exception)
|
||||
} else {
|
||||
continuationHolder.resume(value: KotlinUnit.shared)
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
#if !NOOP_GC
|
||||
CoroutinesKt.gc()
|
||||
// This assert checks that the completion handler gets properly released after all:
|
||||
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
|
||||
#endif
|
||||
}
|
||||
|
||||
private func testCall() throws {
|
||||
try testCallSuspendFun(doSuspend: true, doThrow: false)
|
||||
try testCallSuspendFun(doSuspend: false, doThrow: false)
|
||||
try testCallSuspendFun(doSuspend: true, doThrow: true)
|
||||
try testCallSuspendFun(doSuspend: false, doThrow: true)
|
||||
|
||||
try testCallUnitSuspendFun(doSuspend: true, doThrow: false)
|
||||
try testCallUnitSuspendFun(doSuspend: false, doThrow: false)
|
||||
try testCallUnitSuspendFun(doSuspend: true, doThrow: true)
|
||||
try testCallUnitSuspendFun(doSuspend: false, doThrow: true)
|
||||
|
||||
try testSuspendFuncAsync(doThrow: false)
|
||||
try testSuspendFuncAsync(doThrow: true)
|
||||
|
||||
try testUnitSuspendFuncAsync(doThrow: false)
|
||||
try testUnitSuspendFuncAsync(doThrow: true)
|
||||
}
|
||||
|
||||
private func testCallSuspendFunChain(doSuspend: Bool, doThrow: Bool) throws {
|
||||
class C {}
|
||||
let expectedResult = C()
|
||||
|
||||
var completionCalled = 0
|
||||
var result: AnyObject? = nil
|
||||
var error: Error? = nil
|
||||
|
||||
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _resultOuter, _errorOuter in
|
||||
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as AnyObject?
|
||||
error = _error
|
||||
}
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
if doThrow {
|
||||
try assertNil(result)
|
||||
try assertTrue(error?.kotlinException is CoroutineException)
|
||||
} else {
|
||||
try assertSame(actual: result, expected: expectedResult)
|
||||
try assertNil(error)
|
||||
}
|
||||
}
|
||||
|
||||
private func testCallChain() throws {
|
||||
try testCallSuspendFunChain(doSuspend: true, doThrow: false)
|
||||
try testCallSuspendFunChain(doSuspend: false, doThrow: false)
|
||||
try testCallSuspendFunChain(doSuspend: true, doThrow: true)
|
||||
try testCallSuspendFunChain(doSuspend: false, doThrow: true)
|
||||
}
|
||||
|
||||
private class SuspendFunImpl : SuspendFun {
|
||||
class E : Error {}
|
||||
|
||||
var completion: (() -> Void)? = nil
|
||||
|
||||
func suspendFun(doYield: Bool, doThrow: Bool, completionHandler: @escaping (KotlinInt?, Error?) -> Void) {
|
||||
func callCompletion() {
|
||||
if doThrow {
|
||||
completionHandler(nil, E())
|
||||
} else {
|
||||
completionHandler(17, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if doYield {
|
||||
self.completion = callCompletion
|
||||
} else {
|
||||
callCompletion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func testSuspendFunImpl(doYield: Bool, doThrow: Bool) throws {
|
||||
#if NO_GENERICS
|
||||
let resultHolder = ResultHolder()
|
||||
#else
|
||||
let resultHolder = ResultHolder<KotlinInt>()
|
||||
#endif
|
||||
|
||||
let impl = SuspendFunImpl()
|
||||
|
||||
CoroutinesKt.callSuspendFun(
|
||||
suspendFun: impl,
|
||||
doYield: doYield,
|
||||
doThrow: doThrow,
|
||||
resultHolder: resultHolder
|
||||
)
|
||||
|
||||
if doYield {
|
||||
try assertEquals(actual: resultHolder.completed, expected: 0)
|
||||
guard let completion = impl.completion else { try fail() }
|
||||
completion()
|
||||
}
|
||||
|
||||
try assertEquals(actual: resultHolder.completed, expected: 1)
|
||||
|
||||
if doThrow {
|
||||
try assertNil(resultHolder.result)
|
||||
if let e = resultHolder.exception {
|
||||
try assertFailsWith(SuspendFunImpl.E.self) { try CoroutinesKt.throwException(exception: e) }
|
||||
} else {
|
||||
try fail()
|
||||
}
|
||||
} else {
|
||||
try assertEquals(actual: resultHolder.result as! Int, expected: 17)
|
||||
try assertNil(resultHolder.exception)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSuspendFunImpl2(doYield: Bool, doThrow: Bool) throws {
|
||||
let impl = SuspendFunImpl()
|
||||
|
||||
var completionCalled = 0
|
||||
var result: KotlinInt? = nil
|
||||
var error: Error? = nil
|
||||
|
||||
CoroutinesKt.callSuspendFun2(suspendFun: impl, doYield: doYield, doThrow: doThrow) { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result
|
||||
error = _error
|
||||
}
|
||||
|
||||
if doYield {
|
||||
try assertEquals(actual: completionCalled, expected: 0)
|
||||
guard let completion = impl.completion else { try fail() }
|
||||
completion()
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
|
||||
if doThrow {
|
||||
try assertNil(result)
|
||||
try assertTrue(error is SuspendFunImpl.E)
|
||||
} else {
|
||||
try assertEquals(actual: result, expected: 17)
|
||||
try assertNil(error)
|
||||
}
|
||||
}
|
||||
|
||||
private func testOverride() throws {
|
||||
try testSuspendFunImpl(doYield: false, doThrow: false)
|
||||
try testSuspendFunImpl(doYield: false, doThrow: true)
|
||||
try testSuspendFunImpl(doYield: true, doThrow: false)
|
||||
try testSuspendFunImpl(doYield: true, doThrow: true)
|
||||
|
||||
try testSuspendFunImpl2(doYield: false, doThrow: false)
|
||||
try testSuspendFunImpl2(doYield: false, doThrow: true)
|
||||
try testSuspendFunImpl2(doYield: true, doThrow: false)
|
||||
try testSuspendFunImpl2(doYield: true, doThrow: true)
|
||||
}
|
||||
|
||||
private class SwiftSuspendBridge : AbstractSuspendBridge {
|
||||
class E : Error {}
|
||||
|
||||
override func intAsAny(value: KotlinInt, completionHandler: @escaping (KotlinInt?, Error?) -> Void) {
|
||||
completionHandler(value, nil)
|
||||
}
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
override func unit(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
|
||||
completionHandler(KotlinUnit(), nil)
|
||||
}
|
||||
#else
|
||||
override func unit(value: KotlinInt, completionHandler: @escaping (Error?) -> Void) {
|
||||
completionHandler(nil)
|
||||
}
|
||||
#endif
|
||||
|
||||
override func unitAsAny(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
|
||||
completionHandler(KotlinUnit(), nil)
|
||||
}
|
||||
|
||||
override func nullableUnit(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
|
||||
completionHandler(KotlinUnit(), nil)
|
||||
}
|
||||
|
||||
override func nothingAsInt(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
|
||||
completionHandler(nil, E())
|
||||
}
|
||||
|
||||
override func nothingAsAny(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
|
||||
completionHandler(nil, E())
|
||||
}
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
|
||||
completionHandler(nil, E())
|
||||
}
|
||||
#else
|
||||
override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (Error?) -> Void) {
|
||||
completionHandler(E())
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private func testBridges() throws {
|
||||
#if NO_GENERICS
|
||||
let resultHolder = ResultHolder()
|
||||
#else
|
||||
let resultHolder = ResultHolder<KotlinUnit>()
|
||||
#endif
|
||||
try CoroutinesKt.callSuspendBridge(bridge: SwiftSuspendBridge(), resultHolder: resultHolder)
|
||||
|
||||
try assertEquals(actual: resultHolder.completed, expected: 1)
|
||||
try assertNil(resultHolder.exception)
|
||||
try assertSame(actual: resultHolder.result as AnyObject, expected: KotlinUnit())
|
||||
}
|
||||
|
||||
private func testImplicitThrows1() throws {
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
var result: KotlinUnit? = nil
|
||||
|
||||
CoroutinesKt.throwCancellationException { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertNil(result)
|
||||
#else
|
||||
CoroutinesKt.throwCancellationException { _error in
|
||||
completionCalled += 1
|
||||
error = _error
|
||||
}
|
||||
#endif
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertTrue(error?.kotlinException is KotlinCancellationException)
|
||||
}
|
||||
|
||||
private func testImplicitThrows2() throws {
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
|
||||
var result: KotlinUnit? = nil
|
||||
|
||||
ThrowCancellationExceptionImpl().throwCancellationException { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertNil(result)
|
||||
#else
|
||||
ThrowCancellationExceptionImpl().throwCancellationException { _error in
|
||||
completionCalled += 1
|
||||
error = _error
|
||||
}
|
||||
#endif
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertTrue(error?.kotlinException is KotlinCancellationException)
|
||||
}
|
||||
|
||||
private func testSuspendFunctionType0(f: KotlinSuspendFunction0, expectedResult: String) throws {
|
||||
try assertTrue((f as AnyObject) is KotlinSuspendFunction0)
|
||||
|
||||
var result: String? = nil
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
f.invoke { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as? String
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertEquals(actual: result, expected: expectedResult)
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
private func testSuspendFunctionType1(f: KotlinSuspendFunction1) throws {
|
||||
try assertTrue((f as AnyObject) is KotlinSuspendFunction1)
|
||||
|
||||
var result: String? = nil
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
f.invoke(p1: "suspend function type") { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as? String
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertEquals(actual: result, expected: "suspend function type 1")
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
private func testSuspendFunctionType() throws {
|
||||
try testSuspendFunctionType0(f: CoroutinesKt.getSuspendLambda0(), expectedResult: "lambda 0")
|
||||
try testSuspendFunctionType0(f: CoroutinesKt.getSuspendCallableReference0(), expectedResult: "callable reference 0")
|
||||
try testSuspendFunctionType0(f: CoroutinesKt.getSuspendChild0(), expectedResult: "child 0")
|
||||
try testSuspendFunctionType1(f: CoroutinesKt.getSuspendLambda1())
|
||||
try testSuspendFunctionType1(f: CoroutinesKt.getSuspendCallableReference1())
|
||||
try testSuspendFunctionType1(f: CoroutinesKt.getSuspendChild1())
|
||||
}
|
||||
|
||||
private func testKSuspendFunctionType0(f: KotlinKSuspendFunction0, expectedResult: String) throws {
|
||||
try assertTrue((f as AnyObject) is KotlinKSuspendFunction0)
|
||||
|
||||
var result: String? = nil
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
f.invoke { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as? String
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertEquals(actual: result, expected: expectedResult)
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
private func testKSuspendFunctionType1(f: KotlinKSuspendFunction1) throws {
|
||||
try assertTrue((f as AnyObject) is KotlinKSuspendFunction1)
|
||||
|
||||
var result: String? = nil
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
f.invoke(p1: "suspend function type") { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as? String
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertEquals(actual: result, expected: "suspend function type 1")
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
private func testKSuspendFunctionType() throws {
|
||||
try testKSuspendFunctionType0(f: CoroutinesKt.getKSuspendCallableReference0(), expectedResult: "callable reference 0")
|
||||
try testKSuspendFunctionType1(f: CoroutinesKt.getKSuspendCallableReference1())
|
||||
}
|
||||
|
||||
private func testSuspendFunctionSwiftImpl() throws {
|
||||
var result: String? = nil
|
||||
var error: Error? = nil
|
||||
var completionCalled = 0
|
||||
|
||||
CoroutinesKt.invoke1(block: SuspendFunction1SwiftImpl(), argument: "suspend function") { _result, _error in
|
||||
completionCalled += 1
|
||||
result = _result as? String
|
||||
error = _error
|
||||
}
|
||||
|
||||
try assertEquals(actual: completionCalled, expected: 1)
|
||||
try assertEquals(actual: result, expected: "suspend function Swift")
|
||||
try assertNil(error)
|
||||
}
|
||||
|
||||
#if NO_GENERICS
|
||||
typealias AnyResultHolder = ResultHolder
|
||||
#else
|
||||
typealias AnyResultHolder = ResultHolder<AnyObject>
|
||||
#endif
|
||||
|
||||
private extension AnyResultHolder {
|
||||
func getSuccessfulResult() throws -> Any? {
|
||||
try assertEquals(actual: completed, expected: 1)
|
||||
try assertNil(exception)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// Reported in https://youtrack.jetbrains.com/issue/KT-51043
|
||||
private func testSuspendFunction0SwiftImplStartInKotlin() throws {
|
||||
let resultHolder = AnyResultHolder()
|
||||
try CoroutinesKt.startCoroutineUninterceptedOrReturn(fn: SuspendFunction0SwiftImpl(), resultHolder: resultHolder)
|
||||
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "Swift")
|
||||
}
|
||||
|
||||
private func testSuspendFunction1SwiftImplStartInKotlin() throws {
|
||||
let resultHolder = AnyResultHolder()
|
||||
try CoroutinesKt.startCoroutineUninterceptedOrReturn(fn: SuspendFunction1SwiftImpl(), receiver: "receiver", resultHolder: resultHolder)
|
||||
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "receiver Swift")
|
||||
}
|
||||
|
||||
private func testSuspendFunction2SwiftImplStartInKotlin() throws {
|
||||
let resultHolder = AnyResultHolder()
|
||||
try CoroutinesKt.startCoroutineUninterceptedOrReturn(fn: SuspendFunction2SwiftImpl(), receiver: "receiver", param: "param", resultHolder: resultHolder)
|
||||
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "receiver param Swift")
|
||||
}
|
||||
|
||||
private func testSuspendFunction0SwiftImplCreateInKotlin() throws {
|
||||
let resultHolder = AnyResultHolder()
|
||||
try CoroutinesKt.createCoroutineUninterceptedAndResume(fn: SuspendFunction0SwiftImpl(), resultHolder: resultHolder)
|
||||
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "Swift")
|
||||
}
|
||||
|
||||
private func testSuspendFunction1SwiftImplCreateInKotlin() throws {
|
||||
let resultHolder = AnyResultHolder()
|
||||
try CoroutinesKt.createCoroutineUninterceptedAndResume(fn: SuspendFunction1SwiftImpl(), receiver: "receiver", resultHolder: resultHolder)
|
||||
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "receiver Swift")
|
||||
}
|
||||
|
||||
private class SuspendFunction0SwiftImpl : KotlinSuspendFunction0 {
|
||||
func invoke(completionHandler: (Any?, Error?) -> Void) {
|
||||
completionHandler("Swift", nil)
|
||||
}
|
||||
}
|
||||
|
||||
private class SuspendFunction1SwiftImpl : KotlinSuspendFunction1 {
|
||||
func invoke(p1: Any?, completionHandler: (Any?, Error?) -> Void) {
|
||||
completionHandler("\(p1 ?? "nil") Swift", nil)
|
||||
}
|
||||
}
|
||||
|
||||
private class SuspendFunction2SwiftImpl : KotlinSuspendFunction2 {
|
||||
func invoke(p1: Any?, p2: Any?, completionHandler: (Any?, Error?) -> Void) {
|
||||
completionHandler("\(p1 ?? "nil") \(p2 ?? "nil") Swift", nil)
|
||||
}
|
||||
}
|
||||
|
||||
class CoroutinesTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestCallSimple", testCallSimple)
|
||||
test("TestCallUnitSimple", testUnitCallSimple)
|
||||
test("TestCallFromNonMainDispatcher", testUnitCallNonMainDispatcher)
|
||||
test("TestCall", testCall)
|
||||
test("TestCallChain", testCallChain)
|
||||
test("TestOverride", testOverride)
|
||||
test("TestBridges", testBridges)
|
||||
test("TestImplicitThrows1", testImplicitThrows1)
|
||||
test("TestImplicitThrows2", testImplicitThrows2)
|
||||
test("TestSuspendFunctionType", testSuspendFunctionType)
|
||||
test("TestKSuspendFunctionType", testSuspendFunctionType)
|
||||
test("TestSuspendFunctionSwiftImpl", testSuspendFunctionSwiftImpl)
|
||||
test("TestSuspendFunction0SwiftImplStartInKotlin", testSuspendFunction0SwiftImplStartInKotlin)
|
||||
test("TestSuspendFunction1SwiftImplStartInKotlin", testSuspendFunction1SwiftImplStartInKotlin)
|
||||
test("TestSuspendFunction2SwiftImplStartInKotlin", testSuspendFunction2SwiftImplStartInKotlin)
|
||||
test("TestSuspendFunction0SwiftImplCreateInKotlin", testSuspendFunction0SwiftImplCreateInKotlin)
|
||||
test("TestSuspendFunction1SwiftImplCreateInKotlin", testSuspendFunction1SwiftImplCreateInKotlin)
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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 dataClassComponentMethods
|
||||
|
||||
data class DataClassWithExplicitComponentMethod(val x: Int, val y: Int) {
|
||||
fun component1(arg: Int): Int {
|
||||
return arg + x
|
||||
}
|
||||
}
|
||||
|
||||
interface ComponentInterface {
|
||||
fun component1(): Int
|
||||
}
|
||||
|
||||
data class DataClassWithInheritedComponentMethod(val x: Int) : ComponentInterface
|
||||
|
||||
class RegularClassWithComponentMethods {
|
||||
fun component1() = 3
|
||||
fun component3() = 4
|
||||
}
|
||||
|
||||
fun component1() = 5
|
||||
fun component4() = 6
|
||||
|
||||
data class DataClassWithStrangeNames(val component124: Int, val componentABC: Int) {
|
||||
operator fun component15() = component124
|
||||
fun component16() = component124
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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 Kt
|
||||
|
||||
private func testCustomComponentMethodsAreAccessible() throws {
|
||||
let d = DataClassWithExplicitComponentMethod(x: 1, y: 2)
|
||||
try assertEquals(actual: d.component1(arg: 3), expected: 4)
|
||||
}
|
||||
|
||||
private func testDataClassWithInheritedComponentAreAccessible() throws {
|
||||
let d = DataClassWithInheritedComponentMethod(x: 1)
|
||||
try assertEquals(actual: d.component1(), expected: 1)
|
||||
}
|
||||
|
||||
// Absence of deprecation attributes is checked by comparing "lazy header".
|
||||
private func testRegularComponentMethodsAreAccessible() throws {
|
||||
let r = RegularClassWithComponentMethods()
|
||||
try assertEquals(actual: r.component1(), expected: 3)
|
||||
try assertEquals(actual: r.component3(), expected: 4)
|
||||
}
|
||||
|
||||
private func testTopLevelComponentMethodsAreAccessible() throws {
|
||||
try assertEquals(actual: DataClassComponentMethodsKt.component1(), expected: 5)
|
||||
try assertEquals(actual: DataClassComponentMethodsKt.component4(), expected: 6)
|
||||
}
|
||||
|
||||
private func testComponentExportedOrNot() throws {
|
||||
try assertFalse(class_respondsToSelector(object_getClass(DataClassWithStrangeNames.self), NSSelectorFromString("component1")));
|
||||
try assertFalse(class_respondsToSelector(object_getClass(DataClassWithStrangeNames.self), NSSelectorFromString("component2")));
|
||||
try assertFalse(class_respondsToSelector(object_getClass(DataClassWithStrangeNames.self), NSSelectorFromString("component15")));
|
||||
let r = DataClassWithStrangeNames(component124: 1, componentABC:2)
|
||||
try assertEquals(actual: r.component124, expected: 1)
|
||||
try assertEquals(actual: r.componentABC, expected: 2)
|
||||
try assertEquals(actual: r.component16(), expected: 1)
|
||||
}
|
||||
|
||||
class DataClassComponentMethodsTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
test("testDataClassWithInheritedComponentAreAccessible", testDataClassWithInheritedComponentAreAccessible)
|
||||
test("testCustomComponentMethodsAreAccessible", testCustomComponentMethodsAreAccessible)
|
||||
test("testRegularComponentMethodsAreAccessible", testRegularComponentMethodsAreAccessible)
|
||||
test("testTopLevelComponentMethodsAreAccessible", testTopLevelComponentMethodsAreAccessible)
|
||||
test("testComponentExportedOrNot", testComponentExportedOrNot)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
|
||||
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class)
|
||||
package deallocretain
|
||||
|
||||
open class DeallocRetainBase
|
||||
|
||||
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||
fun garbageCollect() = kotlin.native.runtime.GC.collect()
|
||||
|
||||
fun createWeakReference(value: Any) = kotlin.native.ref.WeakReference(value)
|
||||
|
||||
fun assertNull(value: Any?) {
|
||||
kotlin.test.assertNull(value)
|
||||
}
|
||||
|
||||
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||
fun isExperimentalMM() = kotlin.native.isExperimentalMM()
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
// Note: these tests rely on GC assertions: without the fix and the assertions it won't actually crash.
|
||||
// GC should fire an assertion if it obtains a reference to Kotlin object that is being (or has been) deallocated.
|
||||
|
||||
private func test1() throws {
|
||||
// Attempt to make the state predictable:
|
||||
DeallocRetainKt.garbageCollect()
|
||||
|
||||
DeallocRetain.deallocated = false
|
||||
try assertFalse(DeallocRetain.deallocated)
|
||||
|
||||
try autoreleasepool {
|
||||
let obj = DeallocRetain()
|
||||
try obj.checkWeak()
|
||||
}
|
||||
|
||||
// Runs DeallocRetain.deinit:
|
||||
DeallocRetainKt.garbageCollect()
|
||||
|
||||
try assertTrue(DeallocRetain.deallocated)
|
||||
|
||||
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
|
||||
DeallocRetainKt.garbageCollect()
|
||||
}
|
||||
|
||||
private class DeallocRetain : DeallocRetainBase {
|
||||
static var deallocated = false
|
||||
static var retainObject: DeallocRetain? = nil
|
||||
static weak var weakObject: DeallocRetain? = nil
|
||||
#if NO_GENERICS
|
||||
static var kotlinWeakRef: KotlinWeakReference? = nil
|
||||
#else
|
||||
static var kotlinWeakRef: KotlinWeakReference<AnyObject>? = nil
|
||||
#endif
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
DeallocRetain.weakObject = self
|
||||
DeallocRetain.kotlinWeakRef = DeallocRetainKt.createWeakReference(value: self)
|
||||
}
|
||||
|
||||
func checkWeak() throws {
|
||||
try assertSame(actual: DeallocRetain.weakObject, expected: self)
|
||||
try assertSame(actual: DeallocRetain.kotlinWeakRef!.value as AnyObject, expected: self)
|
||||
}
|
||||
|
||||
deinit {
|
||||
DeallocRetain.retainObject = self
|
||||
DeallocRetain.retainObject = nil
|
||||
|
||||
try! assertNil(DeallocRetain.weakObject)
|
||||
try! assertNil(DeallocRetain.kotlinWeakRef!.value)
|
||||
|
||||
try! assertFalse(DeallocRetain.deallocated)
|
||||
DeallocRetain.deallocated = true
|
||||
}
|
||||
}
|
||||
|
||||
private class DeallocRetainAndAccess : DeallocRetainBase {
|
||||
static var deallocated = false
|
||||
static var retainObject: DeallocRetainAndAccess? = nil
|
||||
|
||||
deinit {
|
||||
DeallocRetainAndAccess.retainObject = self
|
||||
DeallocRetainKt.assertNull(value: DeallocRetainAndAccess.retainObject)
|
||||
DeallocRetainAndAccess.retainObject = nil
|
||||
|
||||
try! assertFalse(DeallocRetainAndAccess.deallocated)
|
||||
DeallocRetainAndAccess.deallocated = true
|
||||
}
|
||||
}
|
||||
|
||||
private func test2() throws {
|
||||
// Attempt to make the state predictable:
|
||||
DeallocRetainKt.garbageCollect()
|
||||
|
||||
DeallocRetainAndAccess.deallocated = false
|
||||
|
||||
autoreleasepool {
|
||||
DeallocRetainAndAccess()
|
||||
}
|
||||
|
||||
// Runs DeallocRetainAndAccess.deinit:
|
||||
DeallocRetainKt.garbageCollect()
|
||||
|
||||
try assertTrue(DeallocRetain.deallocated)
|
||||
|
||||
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
|
||||
DeallocRetainKt.garbageCollect()
|
||||
}
|
||||
|
||||
class DeallocRetainTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
#if !NOOP_GC
|
||||
test("Test1", test1)
|
||||
if (DeallocRetainKt.isExperimentalMM()) {
|
||||
test("Test2", test2)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package enumValues
|
||||
|
||||
import noEnumEntries.*
|
||||
|
||||
enum class EnumLeftRightUpDown {
|
||||
LEFT, RIGHT, UP, DOWN
|
||||
}
|
||||
|
||||
enum class EnumOneTwoThreeValues {
|
||||
ONE, TWO, THREE, VALUES, ENTRIES
|
||||
}
|
||||
|
||||
enum class EnumValuesValues_ {
|
||||
VALUES, VALUES_, ENTRIES, ENTRIES_
|
||||
}
|
||||
|
||||
enum class EmptyEnum {
|
||||
}
|
||||
|
||||
|
||||
fun dceAvoidance() : NoEnumEntriesEnum {
|
||||
return NoEnumEntriesEnum.ONE
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import Kt
|
||||
|
||||
private func testEnumValues() throws {
|
||||
let values = EnumLeftRightUpDown.values()
|
||||
|
||||
try assertEquals(actual: values.size, expected: 4)
|
||||
|
||||
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumLeftRightUpDown.left)
|
||||
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumLeftRightUpDown.right)
|
||||
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumLeftRightUpDown.up)
|
||||
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumLeftRightUpDown.down)
|
||||
}
|
||||
|
||||
private func testEnumValuesMangled() throws {
|
||||
let values = EnumOneTwoThreeValues.values_()
|
||||
|
||||
try assertEquals(actual: values.size, expected: 5)
|
||||
|
||||
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumOneTwoThreeValues.one)
|
||||
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumOneTwoThreeValues.two)
|
||||
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumOneTwoThreeValues.three)
|
||||
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumOneTwoThreeValues.values)
|
||||
try assertSame(actual: values.get(index: 4) as AnyObject, expected: EnumOneTwoThreeValues.entries)
|
||||
}
|
||||
|
||||
private func testEnumValuesMangledTwice() throws {
|
||||
let values = EnumValuesValues_.values__()
|
||||
|
||||
try assertEquals(actual: values.size, expected: 4)
|
||||
|
||||
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumValuesValues_.values)
|
||||
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumValuesValues_.values_)
|
||||
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumValuesValues_.entries)
|
||||
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumValuesValues_.entries_)
|
||||
}
|
||||
|
||||
private func testEnumValuesEmpty() throws {
|
||||
try assertEquals(actual: EmptyEnum.values().size, expected: 0)
|
||||
}
|
||||
|
||||
extension NSObject {
|
||||
|
||||
// convert to dictionary
|
||||
static func toDictionary(from classType: AnyClass) -> [String: Any] {
|
||||
|
||||
var propertiesCount : CUnsignedInt = 0
|
||||
let propertiesInAClass = class_copyMethodList(classType, &propertiesCount)
|
||||
var propertiesDictionary = [String:Any]()
|
||||
|
||||
for i in 0 ..< Int(propertiesCount) {
|
||||
if let property = propertiesInAClass?[i],
|
||||
let strKey = NSString(utf8String: sel_getName(method_getName(property))) as String? {
|
||||
propertiesDictionary[strKey] = value(forKey: strKey)
|
||||
}
|
||||
}
|
||||
return propertiesDictionary
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func testNoEnumEntries() throws {
|
||||
try assertTrue(class_respondsToSelector(object_getClass(EnumLeftRightUpDown.self), NSSelectorFromString("entries")));
|
||||
try assertFalse(class_respondsToSelector(object_getClass(NoEnumEntriesEnum.self), NSSelectorFromString("entries")));
|
||||
}
|
||||
|
||||
private func testEnumEntries() throws {
|
||||
let entries = EnumLeftRightUpDown.entries
|
||||
|
||||
try assertEquals(actual: entries.count, expected: 4)
|
||||
|
||||
try assertSame(actual: entries[0] as AnyObject, expected: EnumLeftRightUpDown.left)
|
||||
try assertSame(actual: entries[1] as AnyObject, expected: EnumLeftRightUpDown.right)
|
||||
try assertSame(actual: entries[2] as AnyObject, expected: EnumLeftRightUpDown.up)
|
||||
try assertSame(actual: entries[3] as AnyObject, expected: EnumLeftRightUpDown.down)
|
||||
}
|
||||
|
||||
private func testEnumEntriesMangled() throws {
|
||||
let entries = EnumOneTwoThreeValues.entries_
|
||||
|
||||
try assertEquals(actual: entries.count, expected: 5)
|
||||
|
||||
try assertSame(actual: entries[0] as AnyObject, expected: EnumOneTwoThreeValues.one)
|
||||
try assertSame(actual: entries[1] as AnyObject, expected: EnumOneTwoThreeValues.two)
|
||||
try assertSame(actual: entries[2] as AnyObject, expected: EnumOneTwoThreeValues.three)
|
||||
try assertSame(actual: entries[3] as AnyObject, expected: EnumOneTwoThreeValues.values)
|
||||
try assertSame(actual: entries[4] as AnyObject, expected: EnumOneTwoThreeValues.entries)
|
||||
}
|
||||
|
||||
private func testEnumEntriesMangledTwice() throws {
|
||||
let entries = EnumValuesValues_.entries__
|
||||
|
||||
try assertEquals(actual: entries.count, expected: 4)
|
||||
|
||||
try assertSame(actual: entries[0] as AnyObject, expected: EnumValuesValues_.values)
|
||||
try assertSame(actual: entries[1] as AnyObject, expected: EnumValuesValues_.values_)
|
||||
try assertSame(actual: entries[2] as AnyObject, expected: EnumValuesValues_.entries)
|
||||
try assertSame(actual: entries[3] as AnyObject, expected: EnumValuesValues_.entries_)
|
||||
}
|
||||
|
||||
private func testEnumEntriesEmpty() throws {
|
||||
try assertEquals(actual: EmptyEnum.entries.count, expected: 0)
|
||||
}
|
||||
|
||||
class EnumValuesTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestEnumValues", testEnumValues)
|
||||
test("TestEnumValuesMangled", testEnumValuesMangled)
|
||||
test("TestEnumValuesMangledTwice", testEnumValuesMangledTwice)
|
||||
test("TestEnumValuesEmpty", testEnumValuesEmpty)
|
||||
test("TestNoEnumEntries", testNoEnumEntries)
|
||||
test("TestEnumEntries", testEnumEntries)
|
||||
test("TestEnumEntriesMangled", testEnumEntriesMangled)
|
||||
test("TestEnumEntriesMangledTwice", testEnumEntriesMangledTwice)
|
||||
test("TestEnumEntriesEmpty", testEnumEntriesEmpty)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+3402
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
package funinterfaces
|
||||
|
||||
fun interface FunInterface {
|
||||
fun run(): Int
|
||||
}
|
||||
|
||||
fun getObject(): FunInterface {
|
||||
return object : FunInterface {
|
||||
override fun run() = 1
|
||||
}
|
||||
}
|
||||
|
||||
fun getLambda(): FunInterface {
|
||||
return FunInterface { 2 }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import Kt
|
||||
|
||||
// Based on https://youtrack.jetbrains.com/issue/KT-44799.
|
||||
private func testSAMConversion() throws {
|
||||
try assertEquals(actual: FunInterfacesKt.getObject().run(), expected: 1)
|
||||
try assertEquals(actual: FunInterfacesKt.getLambda().run(), expected: 2)
|
||||
}
|
||||
|
||||
class FunInterfacesTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestSAMConversion", testSAMConversion)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 functionalTypes
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
typealias AN = Any?
|
||||
|
||||
typealias F2 = (AN, AN) -> AN
|
||||
typealias F5 = (AN, AN, AN, AN, AN) -> AN
|
||||
typealias F6 = (AN, AN, AN, AN, AN, AN,) -> AN
|
||||
typealias F32 = (AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
|
||||
AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
|
||||
AN, AN, AN, AN, AN, AN, AN, AN) -> AN
|
||||
typealias F33 = (AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
|
||||
AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
|
||||
AN, AN, AN, AN, AN, AN, AN, AN, AN) -> AN
|
||||
|
||||
fun callDynType2(list: List<F2>, param: AN) {
|
||||
val fct = list.first()
|
||||
val ret = fct(param, null)
|
||||
assertEquals(param, ret)
|
||||
}
|
||||
|
||||
fun callStaticType2(fct: F2, param: AN) {
|
||||
val ret = fct(param, null)
|
||||
assertEquals(param, ret)
|
||||
}
|
||||
|
||||
fun callDynType32(list: List<F32>, param: AN) {
|
||||
val fct = list.first()
|
||||
val ret = fct(param
|
||||
, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
)
|
||||
assertEquals(param, ret)
|
||||
}
|
||||
|
||||
fun callStaticType32(fct: F32, param: AN) {
|
||||
val ret = fct(param
|
||||
, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
)
|
||||
assertEquals(param, ret)
|
||||
}
|
||||
|
||||
fun callDynType33(list: List<F33>, param: AN) {
|
||||
val fct = list.first()
|
||||
val ret = fct(param
|
||||
, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null, null
|
||||
)
|
||||
assertEquals(param, ret)
|
||||
}
|
||||
|
||||
fun callStaticType33(fct: F33, param: AN) {
|
||||
val ret = fct(param
|
||||
, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null, null
|
||||
)
|
||||
assertEquals(param, ret)
|
||||
}
|
||||
|
||||
abstract class FHolder {
|
||||
abstract val value: Any?
|
||||
}
|
||||
|
||||
// Note: can't provoke dynamic function type conversion using list (as above) or generics
|
||||
// due to Swift <-> Obj-C interop bugs/limitations.
|
||||
// Use covariant return type instead:
|
||||
class F2Holder(override val value: F2) : FHolder()
|
||||
|
||||
fun getDynTypeLambda2(): F2Holder = F2Holder({ p1, _ -> p1 })
|
||||
fun getStaticLambda2(): F2 = { p1, _ -> p1 }
|
||||
|
||||
private fun f2(p1: AN, p2: AN): AN = p1
|
||||
|
||||
fun getDynTypeRef2(): F2Holder = F2Holder(::f2)
|
||||
fun getStaticRef2(): F2 = ::f2
|
||||
|
||||
private fun f32(
|
||||
p1: AN, p2: AN, p3: AN, p4: AN, p5: AN, p6: AN, p7: AN, p8: AN,
|
||||
p9: AN, p10: AN, p11: AN, p12: AN, p13: AN, p14: AN, p15: AN, p16: AN,
|
||||
p17: AN, p18: AN, p19: AN, p20: AN, p21: AN, p22: AN, p23: AN, p24: AN,
|
||||
p25: AN, p26: AN, p27: AN, p28: AN, p29: AN, p30: AN, p31: AN, p32: AN
|
||||
): AN = p1
|
||||
|
||||
private fun f33(
|
||||
p1: AN, p2: AN, p3: AN, p4: AN, p5: AN, p6: AN, p7: AN, p8: AN,
|
||||
p9: AN, p10: AN, p11: AN, p12: AN, p13: AN, p14: AN, p15: AN, p16: AN,
|
||||
p17: AN, p18: AN, p19: AN, p20: AN, p21: AN, p22: AN, p23: AN, p24: AN,
|
||||
p25: AN, p26: AN, p27: AN, p28: AN, p29: AN, p30: AN, p31: AN, p32: AN,
|
||||
p33: AN
|
||||
): AN = p1
|
||||
|
||||
class F32Holder(override val value: F32) : FHolder()
|
||||
|
||||
fun getDynType32(): F32Holder = F32Holder(::f32)
|
||||
fun getStaticType32(): F32 = ::f32
|
||||
|
||||
class F33Holder(override val value: F33) : FHolder()
|
||||
|
||||
fun getDynTypeRef33(): F33Holder = F33Holder(::f33)
|
||||
fun getStaticTypeRef33(): F33 = ::f33
|
||||
|
||||
fun getDynTypeLambda33(): F33Holder = F33Holder(getStaticTypeLambda33())
|
||||
fun getStaticTypeLambda33(): F33 = {
|
||||
p,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _
|
||||
->
|
||||
p
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
private func test1() {
|
||||
FunctionalTypesKt.callStaticType2(fct: foo2, param: "from swift")
|
||||
FunctionalTypesKt.callDynType2(list: [ foo2 ], param: "from swift")
|
||||
|
||||
FunctionalTypesKt.callStaticType2(fct : {a1, _ in return a1 }, param: "from swift block")
|
||||
FunctionalTypesKt.callDynType2(list: [ {a1, _ in return a1 } ], param: "from swift block")
|
||||
|
||||
// 32 params is mapped as regular; block is OK
|
||||
FunctionalTypesKt.callStaticType32(fct : {
|
||||
a1, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _
|
||||
in return a1 }, param: "from swift block")
|
||||
|
||||
FunctionalTypesKt.callDynType32(list : [{
|
||||
a1, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _,
|
||||
_, _, _, _, _, _, _, _
|
||||
in return a1 }], param: "from swift block")
|
||||
|
||||
// 33 params requires explicit implementation of KotlinFunction33
|
||||
FunctionalTypesKt.callStaticType33(fct: foo33, param: "from swift")
|
||||
FunctionalTypesKt.callDynType33(list: [ Foo33() ], param: "from swift")
|
||||
}
|
||||
|
||||
private func test2() throws {
|
||||
try assertEquals(actual: FunctionalTypesKt.getDynTypeLambda2().value("one", nil) as? String, expected: "one")
|
||||
try assertEquals(actual: FunctionalTypesKt.getStaticLambda2()("two", nil) as? String, expected: "two")
|
||||
|
||||
try assertEquals(actual: FunctionalTypesKt.getDynTypeRef2().value("three", nil) as? String, expected: "three")
|
||||
try assertEquals(actual: FunctionalTypesKt.getStaticRef2()("four", nil) as? String, expected: "four")
|
||||
|
||||
// 32 params is mapped as regular; calling result as block is OK
|
||||
try assertEquals(
|
||||
actual: FunctionalTypesKt.getDynType32().value(
|
||||
"five",
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil
|
||||
) as? String,
|
||||
expected: "five"
|
||||
)
|
||||
|
||||
try assertEquals(
|
||||
actual: FunctionalTypesKt.getStaticType32()(
|
||||
"six",
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil
|
||||
) as? String,
|
||||
expected: "six"
|
||||
)
|
||||
|
||||
// 33 params requires explicit invocation of KotlinFunction33.invoke
|
||||
try assertEquals(
|
||||
actual: FunctionalTypesKt.getDynTypeRef33().value.invoke(
|
||||
p1: "seven",
|
||||
p2: nil, p3: nil, p4: nil, p5: nil, p6: nil, p7: nil, p8: nil, p9: nil,
|
||||
p10: nil, p11: nil, p12: nil, p13: nil, p14: nil, p15: nil, p16: nil, p17: nil,
|
||||
p18: nil, p19: nil, p20: nil, p21: nil, p22: nil, p23: nil, p24: nil, p25: nil,
|
||||
p26: nil, p27: nil, p28: nil, p29: nil, p30: nil, p31: nil, p32: nil, p33: nil
|
||||
) as? String,
|
||||
expected: "seven"
|
||||
)
|
||||
|
||||
// static conversion is ok though.
|
||||
try assertEquals(
|
||||
actual: FunctionalTypesKt.getStaticTypeRef33()(
|
||||
"eight",
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil
|
||||
) as? String,
|
||||
expected: "eight"
|
||||
)
|
||||
|
||||
try assertEquals(
|
||||
actual: FunctionalTypesKt.getDynTypeLambda33().value.invoke(
|
||||
p1: "nine",
|
||||
p2: nil, p3: nil, p4: nil, p5: nil, p6: nil, p7: nil, p8: nil, p9: nil,
|
||||
p10: nil, p11: nil, p12: nil, p13: nil, p14: nil, p15: nil, p16: nil, p17: nil,
|
||||
p18: nil, p19: nil, p20: nil, p21: nil, p22: nil, p23: nil, p24: nil, p25: nil,
|
||||
p26: nil, p27: nil, p28: nil, p29: nil, p30: nil, p31: nil, p32: nil, p33: nil
|
||||
) as? String,
|
||||
expected: "nine"
|
||||
)
|
||||
|
||||
try assertEquals(
|
||||
actual: FunctionalTypesKt.getStaticTypeLambda33()(
|
||||
"ten",
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, nil, nil, nil
|
||||
) as? String,
|
||||
expected: "ten"
|
||||
)
|
||||
}
|
||||
|
||||
class FunctionalTypesTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
test("Test2", test2)
|
||||
}
|
||||
}
|
||||
|
||||
private func foo2(a1: Any?, _: Any?) -> Any? {
|
||||
return a1
|
||||
}
|
||||
|
||||
private func foo33(a1: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?,
|
||||
_: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?,
|
||||
_: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?,
|
||||
_: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?
|
||||
) -> Any? {
|
||||
return a1
|
||||
}
|
||||
|
||||
private class Foo33 : KotlinFunction33 {
|
||||
func invoke(p1: Any?, p2: Any?, p3: Any?, p4: Any?, p5: Any?, p6: Any?, p7: Any?, p8: Any?, p9: Any?,
|
||||
p10: Any?, p11: Any?, p12: Any?, p13: Any?, p14: Any?, p15: Any?, p16: Any?, p17: Any?, p18: Any?, p19: Any?,
|
||||
p20: Any?, p21: Any?, p22: Any?, p23: Any?, p24: Any?, p25: Any?, p26: Any?, p27: Any?, p28: Any?, p29: Any?,
|
||||
p30: Any?, p31: Any?, p32: Any?, p33: Any?
|
||||
) -> Any? {
|
||||
return foo33(a1: p1
|
||||
, nil, nil, nil, nil, nil, nil, nil, nil
|
||||
, nil, nil, nil, nil, nil, nil, nil, nil
|
||||
, nil, nil, nil, nil, nil, nil, nil, nil
|
||||
, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 gh4002
|
||||
|
||||
open class GH4002ArgumentBase
|
||||
class GH4002Argument : GH4002ArgumentBase()
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
// See https://github.com/JetBrains/kotlin-native/issues/4002
|
||||
|
||||
class GH4002Base0 : NSObject, NSCoding {
|
||||
required init(coder: NSCoder) { fatalError() }
|
||||
|
||||
func encode(with coder: NSCoder) { fatalError() }
|
||||
}
|
||||
|
||||
class GH4002Base1<T : GH4002ArgumentBase> : GH4002Base0 {}
|
||||
|
||||
@objc(ObjCGH4002)
|
||||
class GH4002 : GH4002Base1<GH4002Argument> {}
|
||||
|
||||
private func test1() throws {
|
||||
try assertEquals(actual: String(cString: class_getName(GH4002.self)), expected: "ObjCGH4002")
|
||||
}
|
||||
|
||||
class Gh4002Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 headerWarnings
|
||||
|
||||
// Note: the test parses the generated header with -Werror to detect warnings.
|
||||
|
||||
class TestIncompatiblePropertyTypeWarning {
|
||||
class Generic<T>(val value: T)
|
||||
|
||||
interface InterfaceWithGenericProperty<T> {
|
||||
val p: Generic<T>
|
||||
}
|
||||
|
||||
class ClassOverridingInterfaceWithGenericProperty(override val p: Generic<String>) : InterfaceWithGenericProperty<String>
|
||||
}
|
||||
|
||||
// https://github.com/JetBrains/kotlin-native/issues/3992
|
||||
class TestGH3992 {
|
||||
abstract class C(open val a: A)
|
||||
|
||||
class D(override val a: B) : C(a)
|
||||
|
||||
abstract class A
|
||||
|
||||
class B : A()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
// Note: the test parses the generated header with -Werror to detect warnings.
|
||||
// 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.
|
||||
|
||||
#if !NO_GENERICS
|
||||
private func testIncompatiblePropertyType() throws {
|
||||
let c = TestIncompatiblePropertyTypeWarning.ClassOverridingInterfaceWithGenericProperty(
|
||||
p: TestIncompatiblePropertyTypeWarningGeneric<NSString>(value: "cba")
|
||||
)
|
||||
|
||||
let pc: TestIncompatiblePropertyTypeWarningGeneric<NSString> = c.p
|
||||
try assertEquals(actual: pc.value, expected: "cba")
|
||||
|
||||
let i: TestIncompatiblePropertyTypeWarningInterfaceWithGenericProperty = c
|
||||
let pi: TestIncompatiblePropertyTypeWarningGeneric<AnyObject> = i.p
|
||||
try assertEquals(actual: pi.value as! String, expected: "cba")
|
||||
}
|
||||
#endif
|
||||
|
||||
private func testGH3992() throws {
|
||||
let d = TestGH3992.D(a: TestGH3992.B())
|
||||
let c: TestGH3992.C = d
|
||||
|
||||
let b: TestGH3992.B = d.a
|
||||
let a: TestGH3992.A = b
|
||||
|
||||
try assertTrue(a is TestGH3992.B)
|
||||
}
|
||||
|
||||
class HeaderWarningsTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
#if !NO_GENERICS
|
||||
test("TestIncompatiblePropertyType", testIncompatiblePropertyType)
|
||||
#endif
|
||||
test("TestGH3992", testGH3992)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package hiddenfromobjc
|
||||
|
||||
import kotlin.experimental.ExperimentalObjCRefinement
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
data class ClassNotAvailableInSwift(val param: String)
|
||||
|
||||
// KT-58839
|
||||
fun ClassNotAvailableInSwift.doSomethingMeaningless(another: ClassNotAvailableInSwift): ClassNotAvailableInSwift {
|
||||
return ClassNotAvailableInSwift(this.param + another.param)
|
||||
}
|
||||
|
||||
fun String.doSomethingMeaningless(another: ClassNotAvailableInSwift): ClassNotAvailableInSwift {
|
||||
return ClassNotAvailableInSwift(this + another.param)
|
||||
}
|
||||
|
||||
// Check that inner and nested classes are hidden if enclosing class is hidden
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
class ParentClass {
|
||||
class NestedClass {
|
||||
class DeeplyNestedClass
|
||||
}
|
||||
|
||||
inner class InnerClass
|
||||
}
|
||||
|
||||
fun useOfUnavailableClass(param: ClassNotAvailableInSwift): ClassNotAvailableInSwift {
|
||||
return ClassNotAvailableInSwift("hi")
|
||||
}
|
||||
|
||||
fun useOfNullableUnavailableClass(param: ClassNotAvailableInSwift?): ClassNotAvailableInSwift? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun produceUnavailable(): ClassNotAvailableInSwift {
|
||||
return ClassNotAvailableInSwift("hi")
|
||||
}
|
||||
|
||||
fun consumeUnavailable(param: ClassNotAvailableInSwift): String {
|
||||
return param.param
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
interface InterfaceNotAvailableInSwift {
|
||||
fun f(): String
|
||||
}
|
||||
|
||||
fun createUnavailableInterface(): InterfaceNotAvailableInSwift {
|
||||
return object : InterfaceNotAvailableInSwift {
|
||||
override fun f(): String = "I'm actually unavailable, call me later."
|
||||
}
|
||||
}
|
||||
|
||||
fun useOfNullableUnavailableInterface(param: InterfaceNotAvailableInSwift?): String? {
|
||||
return param?.f() ?: "null"
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
enum class UnavailableEnum {
|
||||
A, B, C;
|
||||
}
|
||||
|
||||
fun createUnavailableEnum(): UnavailableEnum {
|
||||
return UnavailableEnum.A
|
||||
}
|
||||
|
||||
fun useOfUnavailableEnum(param: UnavailableEnum): String {
|
||||
return param.toString()
|
||||
}
|
||||
|
||||
fun useOfNullableUnavailableEnum(param: UnavailableEnum?): String {
|
||||
return param?.toString() ?: "null"
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
object UnavailableObject {
|
||||
val field: String = "objectField"
|
||||
}
|
||||
|
||||
fun getUnavailableObject(): UnavailableObject {
|
||||
return UnavailableObject
|
||||
}
|
||||
|
||||
fun useOfUnavailableObject(param:UnavailableObject):String {
|
||||
return param.field
|
||||
}
|
||||
|
||||
fun useOfNullableUnavailableObject(param:UnavailableObject?):String? {
|
||||
return param?.field ?: "null"
|
||||
}
|
||||
|
||||
|
||||
sealed class SealedClass {
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
class A : SealedClass()
|
||||
|
||||
class B : SealedClass()
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
object C : SealedClass()
|
||||
}
|
||||
|
||||
fun createSealedClass(): SealedClass {
|
||||
return SealedClass.A()
|
||||
}
|
||||
|
||||
fun useSealedClass(param: SealedClass): String {
|
||||
return when (param) {
|
||||
is SealedClass.A -> "A"
|
||||
is SealedClass.B -> "B"
|
||||
SealedClass.C -> "C"
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : InterfaceNotAvailableInSwift> useUnavailable(a : T): String {
|
||||
return a.f()
|
||||
}
|
||||
|
||||
class WrapperOverUnavailable<T: InterfaceNotAvailableInSwift>(val arg: T)
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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 Kt
|
||||
|
||||
private func testUnavailableEnum() throws {
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfUnavailableEnum(param: HiddenfromobjcKt.createUnavailableEnum()), expected: "A")
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableEnum(param: nil), expected: "null")
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableEnum(param: HiddenfromobjcKt.createUnavailableEnum()), expected: "A")
|
||||
}
|
||||
|
||||
private func testUnavailableObject() throws {
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfUnavailableObject(param: HiddenfromobjcKt.getUnavailableObject()), expected: "objectField")
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableObject(param: HiddenfromobjcKt.getUnavailableObject()), expected: "objectField")
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableObject(param: nil), expected: "null")
|
||||
}
|
||||
|
||||
private func testUnavailableInterface() throws {
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableInterface(
|
||||
param: HiddenfromobjcKt.createUnavailableInterface()),
|
||||
expected: "I'm actually unavailable, call me later."
|
||||
)
|
||||
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableInterface(param: nil), expected: "null")
|
||||
}
|
||||
|
||||
private func testSealedClass() throws {
|
||||
try assertEquals(actual: HiddenfromobjcKt.useSealedClass(param: HiddenfromobjcKt.createSealedClass()), expected: "A")
|
||||
try assertEquals(actual: HiddenfromobjcKt.useSealedClass(param: SealedClass.B()), expected: "B")
|
||||
}
|
||||
|
||||
private func testUnavailableGenerics() throws {
|
||||
try assertEquals(
|
||||
actual: HiddenfromobjcKt.useUnavailable(a: HiddenfromobjcKt.createUnavailableInterface()),
|
||||
expected: "I'm actually unavailable, call me later."
|
||||
)
|
||||
|
||||
let wrapper = WrapperOverUnavailable(arg: HiddenfromobjcKt.createUnavailableInterface() as AnyObject)
|
||||
try assertEquals(
|
||||
actual: HiddenfromobjcKt.useUnavailable(a: wrapper.arg),
|
||||
expected: "I'm actually unavailable, call me later."
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class HiddenfromobjcTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
// Here we check that even if type is erased from Objective-C declarations, we still able to use them properly with proper objects.
|
||||
test("testUnavailableEnum", testUnavailableEnum)
|
||||
test("testUnavailableObject", testUnavailableObject)
|
||||
test("testUnavailableInterface", testUnavailableInterface)
|
||||
test("testSealedClass", testSealedClass)
|
||||
test("testUnavailableGenerics", testUnavailableGenerics)
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
@file:OptIn(kotlin.experimental.ExperimentalObjCName::class)
|
||||
|
||||
package objcNameMangling
|
||||
|
||||
interface InterfaceNameManglingI1 {
|
||||
val clashingProperty: Int
|
||||
|
||||
fun clashingMethod(): Int
|
||||
|
||||
@ObjCName(name = "interfaceClashingMethodWithObjCNameInI1")
|
||||
fun clashingMethodWithObjCNameInI1(): Int
|
||||
|
||||
fun interfaceClashingMethodWithObjCNameInI2(): Int
|
||||
|
||||
@ObjCName(name = "interfaceClashingMethodWithObjCNameInBoth")
|
||||
fun clashingMethodWithObjCNameInBoth(): Int
|
||||
}
|
||||
|
||||
fun i1() = object : InterfaceNameManglingI1 {
|
||||
override val clashingProperty: Int
|
||||
get() = 1
|
||||
|
||||
override fun clashingMethod(): Int = 2
|
||||
|
||||
override fun clashingMethodWithObjCNameInI1(): Int = 3
|
||||
|
||||
override fun interfaceClashingMethodWithObjCNameInI2(): Int = 4
|
||||
|
||||
override fun clashingMethodWithObjCNameInBoth(): Int = 5
|
||||
}
|
||||
|
||||
interface InterfaceNameManglingI2 {
|
||||
val clashingProperty: Any
|
||||
|
||||
fun clashingMethod(): Any
|
||||
|
||||
fun interfaceClashingMethodWithObjCNameInI1(): Any
|
||||
|
||||
@ObjCName(name = "interfaceClashingMethodWithObjCNameInI2")
|
||||
fun clashingMethodWithObjCNameInI2(): Any
|
||||
|
||||
@ObjCName(name = "interfaceClashingMethodWithObjCNameInBoth")
|
||||
fun clashingMethodWithObjCNameInBoth(): Any
|
||||
}
|
||||
|
||||
fun i2() = object : InterfaceNameManglingI2 {
|
||||
override val clashingProperty: Any
|
||||
get() = "one"
|
||||
|
||||
override fun clashingMethod(): Any = "two"
|
||||
|
||||
override fun interfaceClashingMethodWithObjCNameInI1(): Any = "three"
|
||||
|
||||
override fun clashingMethodWithObjCNameInI2(): Any = "four"
|
||||
|
||||
override fun clashingMethodWithObjCNameInBoth(): Any = "five"
|
||||
}
|
||||
|
||||
class InterfaceNameManglingC1 {
|
||||
val clashingProperty: String = "one"
|
||||
|
||||
fun clashingMethod(): String = "two"
|
||||
}
|
||||
|
||||
final class InterfaceNameManglingC2 {
|
||||
val clashingProperty: Int = 1
|
||||
|
||||
fun clashingMethod(): Int = 2
|
||||
}
|
||||
|
||||
fun o1() = InterfaceNameManglingC1()
|
||||
|
||||
fun o2() = InterfaceNameManglingC2()
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import Kt
|
||||
|
||||
private func test1() throws {
|
||||
let i1 = InterfaceMethodNameManglingKt.i1()
|
||||
let i2 = InterfaceMethodNameManglingKt.i2()
|
||||
let o1 = InterfaceMethodNameManglingKt.o1()
|
||||
let o2 = InterfaceMethodNameManglingKt.o2()
|
||||
|
||||
#if DISABLE_MEMBER_NAME_MANGLING || DISABLE_INTERFACE_METHOD_NAME_MANGLING
|
||||
try assertEquals(actual: i1.clashingProperty, expected: 1)
|
||||
try assertEquals(actual: i1.clashingMethod(), expected: 2)
|
||||
try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInI1(), expected: 3)
|
||||
try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInI2(), expected: 4)
|
||||
try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInBoth(), expected: 5)
|
||||
|
||||
try assertEquals(actual: i2.clashingProperty as! String, expected: "one")
|
||||
try assertEquals(actual: i2.clashingMethod() as! String, expected: "two")
|
||||
try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInI1() as! String, expected: "three")
|
||||
try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInI2() as! String, expected: "four")
|
||||
try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInBoth() as! String, expected: "five")
|
||||
|
||||
try assertEquals(actual: o1.clashingProperty, expected: "one")
|
||||
try assertEquals(actual: o1.clashingMethod(), expected: "two")
|
||||
#endif
|
||||
try assertEquals(actual: o2.clashingProperty, expected: 1)
|
||||
try assertEquals(actual: o2.clashingMethod(), expected: 2)
|
||||
}
|
||||
|
||||
class InterfaceMethodNameManglingTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kdocExport
|
||||
|
||||
/**
|
||||
* Summary class [KDocExport].
|
||||
*
|
||||
* @property xyzzy Doc for property xyzzy
|
||||
* @property zzz See below.
|
||||
*/
|
||||
|
||||
// Expected: this comment shall not affect KDoc (i.e. kdoc above is still OK)
|
||||
class KDocExport() {
|
||||
/**
|
||||
* @param xyzzy is documented.
|
||||
*
|
||||
* This is multi-line KDoc. See a blank line above.
|
||||
*/
|
||||
val xyzzy: String = "String example"
|
||||
|
||||
/** Non-primary ctor KDoc: */
|
||||
constructor(name: String) : this() {
|
||||
println(name)
|
||||
}
|
||||
|
||||
/** @property xyzzy KDoc for foo? */
|
||||
val foo = "foo"
|
||||
/** @property foo KDoc for yxxyz? */
|
||||
var yxxyz = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Useless function [whatever]
|
||||
*
|
||||
* This kdoc has some additional formatting.
|
||||
* @param a keep intact and return
|
||||
* @return value of [a]
|
||||
* Check for additional comment (note) below
|
||||
*/
|
||||
@Throws(IllegalArgumentException::class)
|
||||
fun whatever(a:String) = a
|
||||
|
||||
public abstract class SomeClassWithProperty
|
||||
{
|
||||
/**
|
||||
* Returns dispatcher that executes coroutines immediately when it is already in the right context
|
||||
* (e.g. current looper is the same as this handler's looper) without an additional [re-dispatch][CoroutineDispatcher.dispatch].
|
||||
*
|
||||
* Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to [Dispatchers.Unconfined].
|
||||
* The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
|
||||
* The formed event-loop is shared with [Unconfined] and other immediate dispatchers, potentially overlapping tasks between them.
|
||||
*
|
||||
* Example of usage:
|
||||
* ```
|
||||
* suspend fun updateUiElement(val text: String) {
|
||||
* /*
|
||||
* * If it is known that updateUiElement can be invoked both from the Main thread and from other threads,
|
||||
* * `immediate` dispatcher is used as a performance optimization to avoid unnecessary dispatch.
|
||||
* *
|
||||
* * In that case, when `updateUiElement` is invoked from the Main thread, `uiElement.text` will be
|
||||
* * invoked immediately without any dispatching, otherwise, the `Dispatchers.Main` dispatch cycle will be triggered.
|
||||
* */
|
||||
* withContext(Dispatchers.Main.immediate) {
|
||||
* uiElement.text = text
|
||||
* }
|
||||
* // Do context-independent logic such as logging
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Method may throw [UnsupportedOperationException] if immediate dispatching is not supported by current dispatcher,
|
||||
* please refer to specific dispatcher documentation.
|
||||
*
|
||||
* [Dispatchers.Main] supports immediate execution for Android, JavaFx and Swing platforms.
|
||||
*/
|
||||
public abstract val heavyFormattedKDocFoo: SomeClassWithProperty
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 kotlinPrivateOverride
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
// The intention is to test "virtual adapters" machinery of ObjCExport.
|
||||
// This machinery handles the case when exported Kotlin type is subclassed
|
||||
// by a non-exported (e.g. private) Kotlin type, and the instance of the latter is passed to Obj-C.
|
||||
|
||||
interface KotlinPrivateOverrideI1 {
|
||||
fun i123AbstractMethod(): Int
|
||||
fun i1OpenMethod(): Int = -1
|
||||
}
|
||||
|
||||
interface KotlinPrivateOverrideI2 {
|
||||
fun i123AbstractMethod(): Int
|
||||
fun i234AbstractMethod(): Int
|
||||
fun i2AbstractMethod(): Int
|
||||
}
|
||||
|
||||
private interface KotlinPrivateOverridePI1 {
|
||||
fun pi1AbstractMethod(): Int
|
||||
}
|
||||
|
||||
abstract class KotlinPrivateOverrideA1 : KotlinPrivateOverrideI1, KotlinPrivateOverrideI2, KotlinPrivateOverridePI1 {
|
||||
abstract fun a1AbstractMethod(): Int
|
||||
open fun a1OpenMethod(): Int = -2
|
||||
}
|
||||
|
||||
interface KotlinPrivateOverrideI3 {
|
||||
fun i123AbstractMethod(): Int
|
||||
fun i234AbstractMethod(): Int
|
||||
fun i3AbstractMethod(): Int
|
||||
}
|
||||
|
||||
private interface KotlinPrivateOverridePI2 {
|
||||
fun pi2AbstractMethod(): Int
|
||||
}
|
||||
|
||||
private open class KotlinPrivateOverrideP1 : KotlinPrivateOverrideA1(), KotlinPrivateOverrideI3, KotlinPrivateOverridePI2 {
|
||||
override fun i123AbstractMethod(): Int = 1
|
||||
override fun i1OpenMethod(): Int = 2
|
||||
override fun i234AbstractMethod(): Int = 3
|
||||
override fun i2AbstractMethod(): Int = 4
|
||||
override fun pi1AbstractMethod(): Int = 5
|
||||
override fun a1AbstractMethod(): Int = 6
|
||||
override fun a1OpenMethod(): Int = 7
|
||||
override fun i3AbstractMethod(): Int = 8
|
||||
override fun pi2AbstractMethod(): Int = 9
|
||||
}
|
||||
|
||||
fun createP1(): Any = KotlinPrivateOverrideP1()
|
||||
|
||||
interface KotlinPrivateOverrideI4 {
|
||||
fun i234AbstractMethod(): Int
|
||||
fun i4AbstractMethod(): Int
|
||||
}
|
||||
|
||||
private interface KotlinPrivateOverridePI3 {
|
||||
fun pi3AbstractMethod(): Int
|
||||
}
|
||||
|
||||
private class KotlinPrivateOverrideP12 : KotlinPrivateOverrideP1(), KotlinPrivateOverrideI4, KotlinPrivateOverridePI3 {
|
||||
override fun i123AbstractMethod(): Int = 11
|
||||
override fun i1OpenMethod(): Int = 12
|
||||
override fun i234AbstractMethod(): Int = 13
|
||||
override fun i2AbstractMethod(): Int = 14
|
||||
override fun pi1AbstractMethod(): Int = 15
|
||||
override fun a1AbstractMethod(): Int = 16
|
||||
override fun a1OpenMethod(): Int = 17
|
||||
override fun i3AbstractMethod(): Int = 18
|
||||
override fun pi2AbstractMethod(): Int = 19
|
||||
override fun i4AbstractMethod(): Int = 20
|
||||
override fun pi3AbstractMethod(): Int = 21
|
||||
}
|
||||
|
||||
fun createP12(): Any = KotlinPrivateOverrideP12()
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 Kt
|
||||
|
||||
private func testI1Methods(p: Any, base: Int32) throws {
|
||||
guard let i1 = p as? KotlinPrivateOverrideI1 else { try fail() }
|
||||
try assertEquals(actual: i1.i123AbstractMethod(), expected: base + 1)
|
||||
try assertEquals(actual: i1.i1OpenMethod(), expected: base + 2)
|
||||
}
|
||||
|
||||
private func testI2Methods(p: Any, base: Int32) throws {
|
||||
guard let i2 = p as? KotlinPrivateOverrideI2 else { try fail() }
|
||||
try assertEquals(actual: i2.i123AbstractMethod(), expected: base + 1)
|
||||
try assertEquals(actual: i2.i234AbstractMethod(), expected: base + 3)
|
||||
try assertEquals(actual: i2.i2AbstractMethod(), expected: base + 4)
|
||||
}
|
||||
|
||||
private func testA1Methods(p: Any, base: Int32) throws {
|
||||
guard let a1 = p as? KotlinPrivateOverrideA1 else { try fail() }
|
||||
try assertEquals(actual: a1.i123AbstractMethod(), expected: base + 1)
|
||||
try assertEquals(actual: a1.i1OpenMethod(), expected: base + 2)
|
||||
try assertEquals(actual: a1.i234AbstractMethod(), expected: base + 3)
|
||||
try assertEquals(actual: a1.i2AbstractMethod(), expected: base + 4)
|
||||
try assertEquals(actual: a1.a1AbstractMethod(), expected: base + 6)
|
||||
try assertEquals(actual: a1.a1OpenMethod(), expected: base + 7)
|
||||
}
|
||||
|
||||
private func testI3Methods(p: Any, base: Int32) throws {
|
||||
guard let i3 = p as? KotlinPrivateOverrideI3 else { try fail() }
|
||||
try assertEquals(actual: i3.i123AbstractMethod(), expected: base + 1)
|
||||
try assertEquals(actual: i3.i234AbstractMethod(), expected: base + 3)
|
||||
try assertEquals(actual: i3.i3AbstractMethod(), expected: base + 8)
|
||||
}
|
||||
|
||||
private func testI4Methods(p: Any, base: Int32) throws {
|
||||
guard let i4 = p as? KotlinPrivateOverrideI4 else { try fail() }
|
||||
try assertEquals(actual: i4.i234AbstractMethod(), expected: base + 3)
|
||||
try assertEquals(actual: i4.i4AbstractMethod(), expected: base + 10)
|
||||
}
|
||||
|
||||
private func test(p: Any, base: Int32, isI4: Bool) throws {
|
||||
try testI1Methods(p: p, base: base)
|
||||
try testI2Methods(p: p, base: base)
|
||||
try testA1Methods(p: p, base: base)
|
||||
try testI3Methods(p: p, base: base)
|
||||
if isI4 {
|
||||
try testI4Methods(p: p, base: base)
|
||||
}
|
||||
}
|
||||
|
||||
private func test1() throws {
|
||||
try test(p: KotlinPrivateOverrideKt.createP1(), base: 0, isI4: false)
|
||||
try test(p: KotlinPrivateOverrideKt.createP12(), base: 10, isI4: true)
|
||||
}
|
||||
|
||||
|
||||
class KotlinPrivateOverrideTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 kt35940
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
@OptIn(ExperimentalAssociatedObjects::class)
|
||||
@AssociatedObjectKey
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class Associated(val kClass: KClass<*>)
|
||||
|
||||
private interface I1 {
|
||||
val s: String
|
||||
}
|
||||
|
||||
private class I1Impl : I1 {
|
||||
override val s = "zzz"
|
||||
}
|
||||
|
||||
private class C(var i1: I1?)
|
||||
|
||||
private interface I2 {
|
||||
fun bar(c: C)
|
||||
}
|
||||
|
||||
private object I2Impl : I2 {
|
||||
override fun bar(c: C) {
|
||||
c.i1 = I1Impl()
|
||||
}
|
||||
}
|
||||
|
||||
@Associated(I2Impl::class)
|
||||
private class I2ImplHolder
|
||||
|
||||
@OptIn(ExperimentalAssociatedObjects::class)
|
||||
fun testKt35940(): String {
|
||||
val i2 = I2ImplHolder::class.findAssociatedObject<Associated>()!! as I2
|
||||
val c = C(null)
|
||||
i2.bar(c)
|
||||
return c.i1!!.s
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
private func test1() throws {
|
||||
try assertEquals(actual: Kt35940Kt.testKt35940(), expected: "zzz")
|
||||
}
|
||||
|
||||
class Kt35940Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package kt38641
|
||||
|
||||
// See https://youtrack.jetbrains.com/issue/KT-38641.
|
||||
class KT38641 {
|
||||
class IntType {
|
||||
var description = 42
|
||||
}
|
||||
|
||||
class Val {
|
||||
val description = "val"
|
||||
}
|
||||
|
||||
class Var {
|
||||
var description = "var"
|
||||
}
|
||||
|
||||
class TwoProperties {
|
||||
val description = "description"
|
||||
val description_ = "description_"
|
||||
}
|
||||
|
||||
abstract class OverrideVal {
|
||||
abstract val description: String
|
||||
}
|
||||
|
||||
interface OverrideVar {
|
||||
var description: String
|
||||
}
|
||||
}
|
||||
|
||||
fun getOverrideValDescription(impl: KT38641.OverrideVal) = impl.description
|
||||
|
||||
fun getOverrideVarDescription(impl: KT38641.OverrideVar) = impl.description
|
||||
fun setOverrideVarDescription(impl: KT38641.OverrideVar, newValue: String) {
|
||||
impl.description = newValue
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
private func testIntType() throws {
|
||||
let i = KT38641.IntType()
|
||||
|
||||
try assertEquals(actual: i.description_, expected: 42)
|
||||
|
||||
i.description_ = 17
|
||||
try assertEquals(actual: i.description_, expected: 17)
|
||||
}
|
||||
|
||||
private func testVal() throws {
|
||||
try assertEquals(actual: KT38641.Val().description_, expected: "val")
|
||||
}
|
||||
|
||||
private func testVar() throws {
|
||||
let v = KT38641.Var()
|
||||
|
||||
try assertEquals(actual: v.description_, expected: "var")
|
||||
|
||||
v.description_ = "newValue"
|
||||
try assertEquals(actual: v.description_, expected: "newValue")
|
||||
}
|
||||
|
||||
private func testTwoProperties() throws {
|
||||
let t = KT38641.TwoProperties()
|
||||
#if !DISABLE_MEMBER_NAME_MANGLING
|
||||
try assertEquals(actual: t.description_, expected: "description")
|
||||
try assertEquals(actual: t.description__, expected: "description_")
|
||||
#endif
|
||||
}
|
||||
|
||||
private func testOverrideVal() throws {
|
||||
try assertEquals(actual: Kt38641Kt.getOverrideValDescription(impl: KT38641OverrideValImpl()), expected: "description_")
|
||||
}
|
||||
|
||||
class KT38641OverrideValImpl : KT38641.OverrideVal {
|
||||
override var description_: String {
|
||||
get {
|
||||
return "description_"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func testOverrideVar() throws {
|
||||
let impl = KT38641OverrideVarImpl()
|
||||
|
||||
try assertEquals(actual: Kt38641Kt.getOverrideVarDescription(impl: impl), expected: "description_")
|
||||
|
||||
Kt38641Kt.setOverrideVarDescription(impl: impl, newValue: "d")
|
||||
try assertEquals(actual: Kt38641Kt.getOverrideVarDescription(impl: impl), expected: "d")
|
||||
}
|
||||
|
||||
class KT38641OverrideVarImpl : KT38641OverrideVar {
|
||||
var description_: String = "description_"
|
||||
}
|
||||
|
||||
class Kt38641Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestIntType", testIntType)
|
||||
test("TestVal", testVal)
|
||||
test("TestVar", testVar)
|
||||
test("TestTwoProperties", testTwoProperties)
|
||||
test("TestOverrideVal", testOverrideVal)
|
||||
test("TestOverrideVar", testOverrideVar)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// See https://youtrack.jetbrains.com/issue/KT-39206.
|
||||
@Deprecated("Don't call this\nPlease")
|
||||
fun myFunc() = 17
|
||||
|
||||
// See https://youtrack.jetbrains.com/issue/KT-41193.
|
||||
@Deprecated(
|
||||
level = DeprecationLevel.ERROR,
|
||||
message = "This class is deprecated for removal during serialization 1.0 API stabilization.\n" +
|
||||
"For configuring Json instances, the corresponding builder function can be used instead, e.g. instead of" +
|
||||
"'Json(JsonConfiguration.Stable.copy(isLenient = true))' 'Json { isLenient = true }' should be used.\n" +
|
||||
"Instead of storing JsonConfiguration instances of the code, Json instances can be used directly:" +
|
||||
"'Json(MyJsonConfiguration.copy(prettyPrint = true))' can be replaced with 'Json(from = MyApplicationJson) { prettyPrint = true }'"
|
||||
)
|
||||
public open class JsonConfiguration
|
||||
|
||||
@Deprecated("'\"\\@\$(){}\r\n")
|
||||
class MoreTrickyChars
|
||||
@@ -0,0 +1,18 @@
|
||||
import Kt
|
||||
|
||||
private func test1() throws {
|
||||
try assertEquals(actual: Kt39206Kt.myFunc(), expected: 17)
|
||||
}
|
||||
|
||||
private func test2() throws {
|
||||
try assertTrue(MoreTrickyChars() as AnyObject is MoreTrickyChars)
|
||||
}
|
||||
|
||||
class Kt39206Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
test("Test2", test2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 kt41907
|
||||
|
||||
class Ckt41907
|
||||
|
||||
interface Ikt41907 {
|
||||
fun foo(c: Ckt41907)
|
||||
}
|
||||
|
||||
private class Bkt41907 {
|
||||
var c: Ckt41907? = null
|
||||
}
|
||||
|
||||
private val b = Bkt41907()
|
||||
|
||||
fun escapeC(c: Ckt41907) {
|
||||
b.c = c
|
||||
}
|
||||
|
||||
fun testKt41907(o: Ikt41907) {
|
||||
val c = Ckt41907()
|
||||
o.foo(c)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
class Ikt41907Impl : Ikt41907 {
|
||||
func foo(c: Ckt41907) {
|
||||
Kt41907Kt.escapeC(c: c)
|
||||
}
|
||||
}
|
||||
|
||||
private func test1() {
|
||||
Kt41907Kt.testKt41907(o: Ikt41907Impl())
|
||||
}
|
||||
|
||||
class Kt41907Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 kt43599
|
||||
|
||||
// Note: this test relies on two-stage compilation.
|
||||
|
||||
class KT43599 {
|
||||
var memberProperty = "memberProperty"
|
||||
private set
|
||||
}
|
||||
|
||||
var KT43599.extensionProperty
|
||||
get() = "extensionProperty"
|
||||
private set(value) { TODO() }
|
||||
|
||||
var topLevelProperty
|
||||
get() = "topLevelProperty"
|
||||
private set(value) { TODO() }
|
||||
|
||||
lateinit var topLevelLateinitProperty: String
|
||||
private set
|
||||
|
||||
fun setTopLevelLateinitProperty(value: String) {
|
||||
topLevelLateinitProperty = value
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
private func testPropertyWithPrivateSetter() throws {
|
||||
try assertEquals(actual: KT43599().memberProperty, expected: "memberProperty")
|
||||
try assertEquals(actual: KT43599().extensionProperty, expected: "extensionProperty")
|
||||
try assertEquals(actual: Kt43599Kt.topLevelProperty, expected: "topLevelProperty")
|
||||
|
||||
// Checking the reported case too:
|
||||
Kt43599Kt.setTopLevelLateinitProperty(value: "topLevelLateinitProperty")
|
||||
try assertEquals(actual: Kt43599Kt.topLevelLateinitProperty, expected: "topLevelLateinitProperty")
|
||||
}
|
||||
|
||||
class Kt43599Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestPropertyWithPrivateSetter", testPropertyWithPrivateSetter)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
object KT43780TestObject {
|
||||
val x = 5
|
||||
val y = 6
|
||||
val shared = "shared"
|
||||
val Shared = "Shared"
|
||||
}
|
||||
|
||||
class KT43780TestClassWithCompanion {
|
||||
companion object {
|
||||
val z = 7
|
||||
}
|
||||
}
|
||||
|
||||
object Shared {
|
||||
val x = 8
|
||||
}
|
||||
|
||||
class Companion {
|
||||
val t = 10
|
||||
companion object {
|
||||
val x = 9
|
||||
}
|
||||
}
|
||||
|
||||
enum class KT43780Enum {
|
||||
OTHER_ENTRY,
|
||||
COMPANION;
|
||||
|
||||
companion object {
|
||||
val x = 11
|
||||
}
|
||||
}
|
||||
|
||||
class ClassWithInternalCompanion {
|
||||
internal companion object {
|
||||
val x = 12
|
||||
}
|
||||
|
||||
val y = 13
|
||||
}
|
||||
|
||||
class ClassWithPrivateCompanion {
|
||||
private companion object {
|
||||
val x = 14
|
||||
}
|
||||
|
||||
val y = 15
|
||||
}
|
||||
|
||||
// Shouldn't be exported at all:
|
||||
internal class InternalClassWithCompanion {
|
||||
companion object
|
||||
}
|
||||
|
||||
private class PrivateClassWithCompanion {
|
||||
companion object
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import Kt
|
||||
|
||||
private func testObject() throws {
|
||||
let object = KT43780TestObject.shared
|
||||
try assertEquals(actual: object.x, expected: 5)
|
||||
try assertEquals(actual: object.y, expected: 6)
|
||||
try assertEquals(actual: object.shared, expected: "shared")
|
||||
try assertEquals(actual: object.Shared, expected: "Shared")
|
||||
try assertTrue(object === KT43780TestObject())
|
||||
}
|
||||
|
||||
private func testCompanionObject() throws {
|
||||
let object = KT43780TestClassWithCompanion.companion
|
||||
try assertEquals(actual: object.z, expected: 7)
|
||||
try assertTrue(object === KT43780TestClassWithCompanion.Companion())
|
||||
try assertTrue(object === KT43780TestClassWithCompanion.Companion.shared)
|
||||
}
|
||||
|
||||
private func testNameClash() throws {
|
||||
let object = Shared.shared
|
||||
try assertEquals(actual: object.x, expected: 8)
|
||||
try assertTrue(object === Shared())
|
||||
let object2 = Companion.companion
|
||||
try assertEquals(actual: object2.x, expected: 9)
|
||||
try assertTrue(object2 === Companion.Companion())
|
||||
let object3 = Companion()
|
||||
try assertEquals(actual: object3.t, expected: 10)
|
||||
let object4 = Companion()
|
||||
try assertEquals(actual: object4.t, expected: 10)
|
||||
try assertTrue(object3 !== object4)
|
||||
|
||||
let object5 = KT43780Enum.Companion()
|
||||
try assertEquals(actual: object5.x, expected: 11)
|
||||
try assertTrue(object5 === KT43780Enum.Companion())
|
||||
let enumEntry : KT43780Enum = KT43780Enum.companion
|
||||
try assertEquals(actual: enumEntry.name, expected: "COMPANION")
|
||||
try assertEquals(actual: KT43780Enum.otherEntry.name, expected: "OTHER_ENTRY")
|
||||
}
|
||||
|
||||
// Reported as https://youtrack.jetbrains.com/issue/KT-47462
|
||||
private func testUnexposedCompanion() throws {
|
||||
// Just trying to ensure that the classes are accessible:
|
||||
try assertEquals(actual: 13, expected: ClassWithInternalCompanion().y)
|
||||
try assertEquals(actual: 15, expected: ClassWithPrivateCompanion().y)
|
||||
// and this doesn't make the companions accessible as well.
|
||||
}
|
||||
|
||||
|
||||
class Kt43780Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testObject", testObject)
|
||||
test("testCompanionObject", testCompanionObject)
|
||||
test("testNameClash", testNameClash)
|
||||
test("testUnexposedCompanion", testUnexposedCompanion)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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 kt43599
|
||||
|
||||
// Based on https://youtrack.jetbrains.com/issue/KT-46431
|
||||
|
||||
interface Host {
|
||||
val test: String
|
||||
}
|
||||
abstract class AbstractHost : Host
|
||||
|
||||
fun createAbstractHost(): Host {
|
||||
return object : AbstractHost() {
|
||||
override val test: String
|
||||
get() = "1234"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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 Kt
|
||||
|
||||
// Based on https://youtrack.jetbrains.com/issue/KT-46431.
|
||||
|
||||
private func test1() throws {
|
||||
try assertEquals(actual: Kt46431Kt.createAbstractHost().test, expected: "1234")
|
||||
}
|
||||
|
||||
class Kt46431Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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 kt49937
|
||||
|
||||
// Based on https://youtrack.jetbrains.com/issue/KT-49937
|
||||
|
||||
final class KT49937 {
|
||||
override fun toString(): String {
|
||||
return "KT49937"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 Kt
|
||||
|
||||
// Based on https://youtrack.jetbrains.com/issue/KT-49937.
|
||||
|
||||
public extension KT49937 {
|
||||
override var description: String { "KT49937Swift" }
|
||||
}
|
||||
|
||||
private func test1() throws {
|
||||
try assertEquals(actual: KT49937().description, expected: "KT49937Swift")
|
||||
|
||||
let nsObject: NSObject = KT49937()
|
||||
try assertEquals(actual: nsObject.description, expected: "KT49937Swift")
|
||||
}
|
||||
|
||||
class Kt49937Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
@file:MyCustomFileAspect(type = "kt")
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
annotation class MyCustomFileAspect(val type: String = "kt")
|
||||
|
||||
annotation class NoDoc
|
||||
@MustBeDocumented
|
||||
annotation class Foo
|
||||
@MustBeDocumented
|
||||
annotation class BugReport(
|
||||
val assignedTo: String = "[none]",
|
||||
val status: String = "open"
|
||||
)
|
||||
|
||||
@NoDoc
|
||||
@Foo
|
||||
@BugReport(assignedTo = "me", status = "open")
|
||||
interface MyInterface {
|
||||
}
|
||||
|
||||
@NoDoc
|
||||
@Foo
|
||||
@BugReport(assignedTo = "me", status = "open")
|
||||
class Bar {
|
||||
@NoDoc
|
||||
@Foo
|
||||
@Deprecated("warning", level = DeprecationLevel.WARNING)
|
||||
/**
|
||||
* My method
|
||||
* @param nodocParam is one arg
|
||||
* @param fooParam is second arg
|
||||
* @return their sum
|
||||
*/
|
||||
protected suspend fun baz (@NoDoc nodocParam:Int, @Foo @BugReport(assignedTo = "me", status = "fixed") fooParam:Int): Int { return nodocParam + fooParam }
|
||||
|
||||
/** My property
|
||||
***
|
||||
*
|
||||
*/
|
||||
@Foo
|
||||
@BugReport(assignedTo = "me", status = "open")
|
||||
val greeting: String
|
||||
get() {
|
||||
return "Hello World!"
|
||||
}
|
||||
|
||||
// Not a kDoc-formatted comment
|
||||
protected val farewell: String
|
||||
get() { return "Bye bye!" }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kt54119
|
||||
|
||||
class KT54119KotlinKey
|
||||
|
||||
private typealias Foo = KT54119KotlinKey
|
||||
|
||||
fun callContains(set: Set<*>) = set.contains(Foo())
|
||||
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
fun callGetElement(set: Set<*>) = (set as kotlin.native.internal.KonanSet<Any?>).getElement(Foo())
|
||||
|
||||
fun callContainsKey(map: Map<*, *>) = map.containsKey(Foo())
|
||||
|
||||
fun callContainsValue(map: Map<*, *>) = map.containsValue(Foo())
|
||||
|
||||
fun callGet(map: Map<*, *>) = map.get(Foo())
|
||||
|
||||
fun callGetOrThrowConcurrentModification(map: Map<*, *>) = map.hashCode() // calls getOrThrowConcurrentModification under the hood.
|
||||
fun callContainsEntry(map: Map<*, *>) = map.entries.contains(map.entries.first())
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Kt
|
||||
|
||||
// See https://youtrack.jetbrains.com/issue/KT-54119/Native-runtime-assertion-failed-due-to-missing-thread-state-switch
|
||||
|
||||
private func testSetContains() throws {
|
||||
try assertFalse(Kt54119Kt.callContains(set: ["111"]))
|
||||
}
|
||||
|
||||
private func testSetGetElement() throws {
|
||||
try assertNil(Kt54119Kt.callGetElement(set: [222]))
|
||||
}
|
||||
|
||||
private func testMapContainsKey() throws {
|
||||
try assertFalse(Kt54119Kt.callContainsKey(map: ["abc" : "def"]))
|
||||
}
|
||||
|
||||
private func testMapContainsValue() throws {
|
||||
try assertFalse(Kt54119Kt.callContainsValue(map: [KT54119KotlinKey() : 1]))
|
||||
}
|
||||
|
||||
private func testMapGet() throws {
|
||||
try assertNil(Kt54119Kt.callGet(map: [0 : 0]))
|
||||
}
|
||||
|
||||
private func testMapGetOrThrowConcurrentModification() throws {
|
||||
Kt54119Kt.callGetOrThrowConcurrentModification(map: [KT54119KotlinKey() : 2])
|
||||
}
|
||||
|
||||
private func testMapContainsEntry() throws {
|
||||
try assertTrue(Kt54119Kt.callContainsEntry(map: [KT54119KotlinKey() : 3]))
|
||||
}
|
||||
|
||||
class Kt54119Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testSetContains", testSetContains)
|
||||
test("testSetGetElement", testSetGetElement)
|
||||
test("testMapContainsKey", testMapContainsKey)
|
||||
test("testMapContainsValue", testMapContainsValue)
|
||||
test("testMapGet", testMapGet)
|
||||
test("testMapGetOrThrowConcurrentModification", testMapGetOrThrowConcurrentModification)
|
||||
test("testMapContainsEntry", testMapContainsEntry)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import kotlin.sequences.*
|
||||
|
||||
suspend fun SequenceScope<Int>.fill() {
|
||||
yield(1)
|
||||
yield(2)
|
||||
}
|
||||
|
||||
fun getFillFunction() = SequenceScope<Int>::fill
|
||||
|
||||
fun callback(block: suspend SequenceScope<Int>.() -> Unit) : List<Int> {
|
||||
return sequence {
|
||||
block()
|
||||
}.toList()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Kt
|
||||
|
||||
private func testFill() throws {
|
||||
let result = Kt55736Kt.callback(block: Kt55736Kt.getFillFunction())
|
||||
try assertEquals(actual: result.count, expected: 2)
|
||||
try assertEquals(actual: result[0], expected: 1)
|
||||
try assertEquals(actual: result[1], expected: 2)
|
||||
}
|
||||
|
||||
class Kt55736Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testFill", testFill)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
var initialized = 0
|
||||
|
||||
object Kt56521 {
|
||||
init {
|
||||
initialized = 1
|
||||
}
|
||||
}
|
||||
|
||||
fun getKt56521(): Kt56521 {
|
||||
Kt56521
|
||||
return Kt56521
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import Kt
|
||||
|
||||
func testKt56521() throws {
|
||||
let object = Kt56521()
|
||||
try assertTrue(object is Kt56521)
|
||||
try assertEquals(actual: Kt56521Kt.initialized, expected: 1)
|
||||
}
|
||||
|
||||
class Kt56521Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testKt56521", testKt56521)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
interface IKt57373 {
|
||||
val bar: Int
|
||||
}
|
||||
|
||||
class DKt57373(foo: IKt57373) : IKt57373 by foo
|
||||
|
||||
class CKt57373 : IKt57373 {
|
||||
override val bar: Int = 42
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import Kt
|
||||
|
||||
func testKt57373() throws {
|
||||
let impl = CKt57373()
|
||||
let x = DKt57373(foo: impl)
|
||||
try assertEquals(actual: x.bar, expected: 42)
|
||||
}
|
||||
|
||||
class Kt57373Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testKt57373", testKt57373)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kt57791
|
||||
|
||||
abstract class Ckt57791 {
|
||||
abstract fun baz(): Int
|
||||
}
|
||||
|
||||
object Okt57791 : Ckt57791() {
|
||||
override fun baz() = 117
|
||||
}
|
||||
|
||||
class Ckt57791Final : Ckt57791() {
|
||||
override fun baz() = 42
|
||||
}
|
||||
|
||||
interface Foo {
|
||||
fun getCkt57791(): Ckt57791Final
|
||||
}
|
||||
|
||||
fun foobar(f: Boolean, foo: Foo): Boolean {
|
||||
val z = if (f) Okt57791 else foo.getCkt57791()
|
||||
return z.baz() == 42
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import Kt
|
||||
|
||||
class FooImpl : Foo {
|
||||
func getCkt57791() -> Ckt57791Final { return Ckt57791Final() }
|
||||
}
|
||||
|
||||
func testKt57791() throws {
|
||||
try assertTrue(Kt57791Kt.foobar(f: false, foo: FooImpl()))
|
||||
}
|
||||
|
||||
class Kt57791Tests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testKt57791", testKt57791)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 library
|
||||
|
||||
fun readDataFromLibraryClass(input: A): String {
|
||||
return input.data
|
||||
}
|
||||
|
||||
fun readDataFromLibraryInterface(input: I): String {
|
||||
return input.data
|
||||
}
|
||||
|
||||
fun readDataFromLibraryEnum(input: E): String {
|
||||
return input.data
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
func testAccessClassFromLibraryWithShortName() throws {
|
||||
|
||||
let object: MyLibraryA = MyLibraryA(data: "Data from Class")
|
||||
let interface: MyLibraryI = MyLibraryA(data: "Data from Interface")
|
||||
let enumObject: MyLibraryE = MyLibraryE.b
|
||||
|
||||
|
||||
let dataFromClass = LibraryKt.readDataFromLibraryClass(input: object)
|
||||
let dataFromInterface = LibraryKt.readDataFromLibraryInterface(input: interface)
|
||||
let dataFromEnum = LibraryKt.readDataFromLibraryEnum(input: enumObject)
|
||||
|
||||
try assertEquals(actual: dataFromClass, expected: "Data from Class")
|
||||
try assertEquals(actual: dataFromInterface, expected: "Data from Interface")
|
||||
try assertEquals(actual: dataFromEnum, expected: "Enum entry B")
|
||||
}
|
||||
|
||||
class LibraryTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testAccessClassFromLibraryWithShortName", testAccessClassFromLibraryWithShortName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 library
|
||||
|
||||
interface I {
|
||||
val data: String
|
||||
}
|
||||
|
||||
class A(override val data: String): I
|
||||
|
||||
enum class E(val data: String) {
|
||||
A("Enum entry A"),
|
||||
B("Enum entry B"),
|
||||
C("Enum entry C")
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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.
|
||||
*/
|
||||
|
||||
// All classes and methods should be used in tests
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package localEA
|
||||
|
||||
class ArraysConstructor {
|
||||
private val memberArray: IntArray
|
||||
constructor(int1: Int, int2: Int) {
|
||||
memberArray = IntArray(2)
|
||||
set(int1, int2)
|
||||
}
|
||||
fun set(int1: Int, int2: Int) {
|
||||
memberArray[0] = int1
|
||||
memberArray[1] = int2
|
||||
}
|
||||
fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}"
|
||||
}
|
||||
class ArraysDefault {
|
||||
private val memberArray = IntArray(2)
|
||||
constructor(int1: Int, int2: Int) {
|
||||
set(int1, int2)
|
||||
}
|
||||
fun set(int1: Int, int2: Int) {
|
||||
memberArray[0] = int1
|
||||
memberArray[1] = int2
|
||||
}
|
||||
fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}"
|
||||
}
|
||||
class ArraysInitBlock {
|
||||
private val memberArray : IntArray
|
||||
init {
|
||||
memberArray = IntArray(2)
|
||||
}
|
||||
constructor(int1: Int, int2: Int) {
|
||||
set(int1, int2)
|
||||
}
|
||||
fun set(int1: Int, int2: Int) {
|
||||
memberArray[0] = int1
|
||||
memberArray[1] = int2
|
||||
}
|
||||
fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 Kt
|
||||
|
||||
// -------- Tests --------
|
||||
|
||||
func testArraysEscapeAsParameter() throws {
|
||||
let array1 = ArraysConstructor(int1: 1, int2: 2)
|
||||
try assertEquals(actual: array1.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysConstructor.")
|
||||
array1.set(int1: 3, int2: 4)
|
||||
try assertEquals(actual: array1.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysConstructor.")
|
||||
|
||||
let array2 = ArraysDefault(int1: 1, int2: 2)
|
||||
try assertEquals(actual: array2.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysDefault.")
|
||||
array2.set(int1: 3, int2: 4)
|
||||
try assertEquals(actual: array2.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysDefault.")
|
||||
|
||||
let array3 = ArraysInitBlock(int1: 1, int2: 2)
|
||||
try assertEquals(actual: array3.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysInitBlock.")
|
||||
array3.set(int1: 3, int2: 4)
|
||||
try assertEquals(actual: array3.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysInitBlock.")
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class LocalEATests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestArraysEscapeAsParameter", testArraysEscapeAsParameter)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package noAutorelease
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
import kotlin.native.internal.NativePtr
|
||||
import kotlin.native.ref.WeakReference
|
||||
import kotlin.test.*
|
||||
|
||||
@OptIn(kotlin.experimental.ExperimentalNativeApi::class)
|
||||
class KotlinLivenessTracker {
|
||||
val weakRefs = mutableListOf<WeakReference<Any>>()
|
||||
|
||||
fun add(obj: Any?) {
|
||||
assertNotNull(obj)
|
||||
weakRefs += WeakReference(obj)
|
||||
assertFalse(objectsAreDead())
|
||||
}
|
||||
|
||||
fun isEmpty() = weakRefs.isEmpty()
|
||||
fun objectsAreDead() = weakRefs.all { it.value === null }
|
||||
}
|
||||
|
||||
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||
fun gc() = kotlin.native.runtime.GC.collect()
|
||||
|
||||
class KotlinObject
|
||||
|
||||
interface NoAutoreleaseSendHelper {
|
||||
fun sendKotlinObject(kotlinObject: KotlinObject)
|
||||
fun blockReceivingKotlinObject(): (KotlinObject) -> Unit
|
||||
fun sendSwiftObject(swiftObject: Any)
|
||||
fun sendList(list: List<*>)
|
||||
fun sendString(string: String)
|
||||
fun sendNumber(number: Any)
|
||||
fun sendBlock(block: () -> KotlinObject)
|
||||
suspend fun sendCompletion(): Any?
|
||||
}
|
||||
|
||||
interface NoAutoreleaseReceiveHelper {
|
||||
fun receiveKotlinObject(): KotlinObject
|
||||
fun receiveSwiftObject(): Any
|
||||
fun receiveList(): List<*>
|
||||
fun receiveString(): String
|
||||
fun receiveNumber(): Any
|
||||
fun receiveBlock(): () -> KotlinObject
|
||||
}
|
||||
|
||||
class NoAutoreleaseKotlinSendHelper(val kotlinLivenessTracker: KotlinLivenessTracker) : NoAutoreleaseSendHelper {
|
||||
override fun sendKotlinObject(kotlinObject: KotlinObject) = kotlinLivenessTracker.add(kotlinObject)
|
||||
override fun blockReceivingKotlinObject(): (KotlinObject) -> Unit = { kotlinLivenessTracker.add(it) }
|
||||
override fun sendSwiftObject(swiftObject: Any) = kotlinLivenessTracker.add(swiftObject)
|
||||
override fun sendList(list: List<*>) = kotlinLivenessTracker.add(list)
|
||||
override fun sendString(string: String) = kotlinLivenessTracker.add(string)
|
||||
override fun sendNumber(number: Any) = kotlinLivenessTracker.add(number)
|
||||
override fun sendBlock(block: () -> KotlinObject) = kotlinLivenessTracker.add(block)
|
||||
override suspend fun sendCompletion() = suspendCoroutineUninterceptedOrReturn<Any?> { continuation ->
|
||||
kotlinLivenessTracker.add(continuation)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
class NoAutoreleaseKotlinReceiveHelper(val kotlinLivenessTracker: KotlinLivenessTracker) : NoAutoreleaseReceiveHelper {
|
||||
private val kotlinObject = KotlinObject()
|
||||
lateinit var swiftObject: Any
|
||||
private val list = listOf(Any())
|
||||
private val string = Any().toString()
|
||||
private val number = createKotlinNumber()
|
||||
private val block = createLambda(kotlinLivenessTracker)
|
||||
|
||||
override fun receiveKotlinObject(): KotlinObject = kotlinObject.also { kotlinLivenessTracker.add(it) }
|
||||
override fun receiveSwiftObject(): Any = swiftObject.also { kotlinLivenessTracker.add(it) }
|
||||
override fun receiveList(): List<*> = list.also { kotlinLivenessTracker.add(it) }
|
||||
override fun receiveString(): String = string.also { kotlinLivenessTracker.add(it) }
|
||||
override fun receiveNumber(): Any = number.also { kotlinLivenessTracker.add(it) }
|
||||
override fun receiveBlock(): () -> KotlinObject = block.also { kotlinLivenessTracker.add(it) }
|
||||
}
|
||||
|
||||
object NoAutoreleaseSingleton {
|
||||
val x = 1
|
||||
}
|
||||
enum class NoAutoreleaseEnum {
|
||||
ENTRY;
|
||||
|
||||
val x = 2
|
||||
}
|
||||
|
||||
fun callSendKotlinObject(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val kotlinObject = KotlinObject()
|
||||
|
||||
// Repeating twice to cover possible fast paths after caching something for an object.
|
||||
helper.sendKotlinObject(kotlinObject)
|
||||
helper.sendKotlinObject(kotlinObject)
|
||||
tracker.add(kotlinObject)
|
||||
}
|
||||
|
||||
fun sendKotlinObjectToBlock(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val kotlinObject = KotlinObject()
|
||||
|
||||
helper.blockReceivingKotlinObject()(kotlinObject)
|
||||
helper.blockReceivingKotlinObject()(kotlinObject)
|
||||
tracker.add(kotlinObject)
|
||||
}
|
||||
|
||||
fun callSendSwiftObject(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker, swiftObject: Any) {
|
||||
helper.sendSwiftObject(swiftObject)
|
||||
helper.sendSwiftObject(swiftObject)
|
||||
tracker.add(swiftObject)
|
||||
}
|
||||
|
||||
fun callSendList(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val list = listOf(Any())
|
||||
|
||||
helper.sendList(list)
|
||||
helper.sendList(list)
|
||||
tracker.add(list)
|
||||
}
|
||||
|
||||
fun callSendString(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val string = Any().toString()
|
||||
|
||||
helper.sendString(string)
|
||||
helper.sendString(string)
|
||||
tracker.add(string)
|
||||
}
|
||||
|
||||
fun callSendNumber(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val number = createKotlinNumber()
|
||||
|
||||
helper.sendNumber(number)
|
||||
helper.sendNumber(number)
|
||||
tracker.add(number)
|
||||
}
|
||||
|
||||
fun callSendBlock(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val block = createLambda()
|
||||
|
||||
helper.sendBlock(block)
|
||||
helper.sendBlock(block)
|
||||
tracker.add(block)
|
||||
}
|
||||
|
||||
private class EmptyContinuation : Continuation<Any?> {
|
||||
override val context: CoroutineContext = EmptyCoroutineContext
|
||||
override fun resumeWith(result: Result<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
fun callSendCompletion(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
|
||||
val completion = EmptyContinuation()
|
||||
|
||||
suspend {
|
||||
helper.sendCompletion()
|
||||
helper.sendCompletion()
|
||||
}.startCoroutine(completion)
|
||||
|
||||
tracker.add(completion)
|
||||
}
|
||||
|
||||
fun callReceiveKotlinObject(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveKotlinObject())
|
||||
}
|
||||
|
||||
fun callReceiveSwiftObject(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveSwiftObject())
|
||||
}
|
||||
|
||||
fun callReceiveList(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveList())
|
||||
}
|
||||
|
||||
fun callReceiveString(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveString())
|
||||
}
|
||||
|
||||
fun callReceiveNumber(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveNumber())
|
||||
}
|
||||
|
||||
fun callReceiveBlock(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveBlock())
|
||||
}
|
||||
|
||||
fun callReceiveBlockAndCall(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
|
||||
tracker.add(helper.receiveBlock()())
|
||||
}
|
||||
|
||||
fun objc_autoreleasePoolPush() = kotlinx.cinterop.objc_autoreleasePoolPush()
|
||||
fun objc_autoreleasePoolPop(handle: NativePtr) = kotlinx.cinterop.objc_autoreleasePoolPop(handle)
|
||||
|
||||
fun useIntArray(array: IntArray) {} // Just to make IntArray available from Swift.
|
||||
|
||||
private fun createLambda(): () -> KotlinObject {
|
||||
val lambdaResult = KotlinObject()
|
||||
return { lambdaResult } // make it capturing thus dynamic.
|
||||
}
|
||||
|
||||
private fun createLambda(kotlinLivenessTracker: KotlinLivenessTracker): () -> KotlinObject {
|
||||
val lambdaResult = KotlinObject()
|
||||
return {
|
||||
val result = lambdaResult // make it capturing thus dynamic.
|
||||
kotlinLivenessTracker.add(result)
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
private fun createKotlinNumber(): Any = (0.5 + Any().hashCode().toDouble()) // to make it dynamic.
|
||||
@@ -0,0 +1,514 @@
|
||||
import Kt
|
||||
|
||||
private class SwiftLivenessTracker {
|
||||
class SwiftWeakRef {
|
||||
weak var value: AnyObject?
|
||||
}
|
||||
|
||||
var weakRefs: [SwiftWeakRef] = []
|
||||
|
||||
func add(_ obj: AnyObject?) {
|
||||
try! assertTrue(obj != nil)
|
||||
|
||||
let weakRef = SwiftWeakRef()
|
||||
weakRef.value = obj
|
||||
weakRefs.append(weakRef)
|
||||
|
||||
try! assertFalse(objectsAreDead())
|
||||
}
|
||||
|
||||
func isEmpty() -> Bool {
|
||||
return weakRefs.isEmpty
|
||||
}
|
||||
|
||||
func objectsAreDead() -> Bool {
|
||||
for weakRef in weakRefs {
|
||||
if weakRef.value !== nil { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private class NoAutoreleaseSwiftHelper : NoAutoreleaseSendHelper, NoAutoreleaseReceiveHelper {
|
||||
fileprivate var swiftLivenessTracker: SwiftLivenessTracker
|
||||
|
||||
init(swiftLivenessTracker: SwiftLivenessTracker) {
|
||||
self.swiftLivenessTracker = swiftLivenessTracker
|
||||
}
|
||||
|
||||
func sendKotlinObject(kotlinObject: KotlinObject) {
|
||||
swiftLivenessTracker.add(kotlinObject)
|
||||
}
|
||||
|
||||
func blockReceivingKotlinObject() -> (KotlinObject) -> Void {
|
||||
return {
|
||||
self.swiftLivenessTracker.add($0)
|
||||
}
|
||||
}
|
||||
|
||||
func sendSwiftObject(swiftObject: Any) {
|
||||
swiftLivenessTracker.add(swiftObject as AnyObject)
|
||||
}
|
||||
|
||||
func sendList(list: [Any]) {
|
||||
}
|
||||
|
||||
func sendString(string: String) {
|
||||
}
|
||||
|
||||
func sendNumber(number: Any) {
|
||||
swiftLivenessTracker.add(number as AnyObject)
|
||||
}
|
||||
|
||||
func sendBlock(block: @escaping () -> KotlinObject) {
|
||||
}
|
||||
|
||||
func sendCompletion(completionHandler: @escaping (Any?, Error?) -> Void) {
|
||||
completionHandler(nil, nil)
|
||||
}
|
||||
|
||||
let kotlinObject = KotlinObject()
|
||||
let swiftObject = SwiftObject2()
|
||||
let list = createList()
|
||||
let string = createString()
|
||||
let number = createNumber()
|
||||
lazy var block = createBlock(swiftLivenessTracker: swiftLivenessTracker)
|
||||
|
||||
func receiveKotlinObject() -> KotlinObject {
|
||||
let result = kotlinObject
|
||||
swiftLivenessTracker.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func receiveSwiftObject() -> Any {
|
||||
let result = swiftObject
|
||||
swiftLivenessTracker.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func receiveList() -> [Any] {
|
||||
return list
|
||||
}
|
||||
|
||||
func receiveString() -> String {
|
||||
return string
|
||||
}
|
||||
|
||||
func receiveNumber() -> Any {
|
||||
let result = number
|
||||
swiftLivenessTracker.add(result)
|
||||
return number
|
||||
}
|
||||
|
||||
func receiveBlock() -> (() -> KotlinObject) {
|
||||
return block
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestFlags {
|
||||
var trackSwiftLifetime: Bool = true
|
||||
var checkAutorelease: Bool = true
|
||||
|
||||
// When Kotlin refers to a Swift object which refers to a Kotlin object, to reclaim the latter
|
||||
// we have to run the GC twice if experimental MM is enabled:
|
||||
// first GC finds the Kotlin wrapper of the Swift object and releases it during the sweep phase.
|
||||
// The second GC is then able to reclaim the Kotlin object.
|
||||
// This behaviour is different from the legacy MM, which calls objc_release right in the middle of the GC,
|
||||
// so is able to process its outcome during the same GC.
|
||||
var runGCTwice: Bool = false
|
||||
}
|
||||
|
||||
private func testOnce(flags: TestFlags, block: (KotlinLivenessTracker, SwiftLivenessTracker) throws -> Void) throws {
|
||||
try assertAutoreleasepoolNotUsed(flags: flags) { // Note: this assertion will also fail if something in the "test infra" below uses autoreleasepool.
|
||||
let kotlinLivenessTracker = KotlinLivenessTracker()
|
||||
let swiftLivenessTracker = SwiftLivenessTracker()
|
||||
|
||||
try assertTrue(kotlinLivenessTracker.isEmpty())
|
||||
try assertTrue(swiftLivenessTracker.isEmpty())
|
||||
|
||||
try block(kotlinLivenessTracker, swiftLivenessTracker)
|
||||
|
||||
NoAutoreleaseKt.gc()
|
||||
if (flags.runGCTwice) {
|
||||
NoAutoreleaseKt.gc()
|
||||
}
|
||||
|
||||
try assertFalse(kotlinLivenessTracker.isEmpty())
|
||||
if flags.trackSwiftLifetime {
|
||||
try assertFalse(swiftLivenessTracker.isEmpty())
|
||||
} else {
|
||||
// Note: some of the tests don't actually add objects to the swiftLivenessTracker,
|
||||
// because e.g. Swift represents certain Obj-C classes as value types.
|
||||
try assertTrue(swiftLivenessTracker.isEmpty())
|
||||
}
|
||||
|
||||
#if !NOOP_GC
|
||||
// If something has "leaked" to autoreleasepool, one of the assertions below should fail:
|
||||
try assertTrue(kotlinLivenessTracker.objectsAreDead())
|
||||
try assertTrue(swiftLivenessTracker.objectsAreDead())
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private func test(flags: TestFlags, block: (KotlinLivenessTracker, SwiftLivenessTracker) -> Void) throws {
|
||||
for _ in 1...2 {
|
||||
// Repeating twice to cover possible fast paths after caching something for a type.
|
||||
try testOnce(flags: flags, block: block)
|
||||
}
|
||||
}
|
||||
|
||||
private func assertAutoreleasepoolNotUsed(flags: TestFlags = TestFlags(), block: () throws -> Void) throws {
|
||||
let poolBefore = NoAutoreleaseKt.objc_autoreleasePoolPush()
|
||||
NoAutoreleaseKt.objc_autoreleasePoolPop(handle: poolBefore)
|
||||
|
||||
try block()
|
||||
|
||||
let poolAfter = NoAutoreleaseKt.objc_autoreleasePoolPush()
|
||||
NoAutoreleaseKt.objc_autoreleasePoolPop(handle: poolAfter)
|
||||
|
||||
// autoreleasepool machinery is implemented as a stack.
|
||||
// So here we check that stack top after `block()` is the same as before.
|
||||
// Which means that no objects were added to this stack inbetween.
|
||||
if flags.checkAutorelease {
|
||||
try assertEquals(actual: poolAfter, expected: poolBefore)
|
||||
} else {
|
||||
// Just to ensure we disable the hack once it is not needed anymore:
|
||||
try assertFalse(poolAfter == poolBefore)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendToKotlin<T>(
|
||||
_ createObject: () -> T,
|
||||
flags: TestFlags = TestFlags(),
|
||||
sendObject: (NoAutoreleaseKotlinSendHelper, T) -> Void
|
||||
) throws {
|
||||
try test(flags: flags) { kotlinLivenessTracker, swiftLivenessTracker in
|
||||
let helper = NoAutoreleaseKotlinSendHelper(kotlinLivenessTracker: kotlinLivenessTracker)
|
||||
|
||||
let obj = createObject()
|
||||
if flags.trackSwiftLifetime {
|
||||
swiftLivenessTracker.add(obj as AnyObject)
|
||||
}
|
||||
|
||||
// Repeating twice to cover possible fast paths after caching something for an object.
|
||||
sendObject(helper, obj)
|
||||
sendObject(helper, obj)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveFromKotlin<T>(flags: TestFlags = TestFlags(), receiveObject: (NoAutoreleaseKotlinReceiveHelper) -> T) throws {
|
||||
try test(flags: flags) { kotlinLivenessTracker, swiftLivenessTracker in
|
||||
let helper = NoAutoreleaseKotlinReceiveHelper(kotlinLivenessTracker: kotlinLivenessTracker)
|
||||
|
||||
// Repeating twice to cover possible fast paths after caching something for an object.
|
||||
let obj1 = receiveObject(helper)
|
||||
let obj2 = receiveObject(helper)
|
||||
|
||||
if flags.trackSwiftLifetime {
|
||||
swiftLivenessTracker.add(obj1 as AnyObject)
|
||||
swiftLivenessTracker.add(obj2 as AnyObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func testCallToSwift(flags: TestFlags = TestFlags(), callKotlin: (NoAutoreleaseSwiftHelper, KotlinLivenessTracker) -> Void) throws {
|
||||
try test(flags: flags) { kotlinLivenessTracker, swiftLivenessTracker in
|
||||
let helper = NoAutoreleaseSwiftHelper(swiftLivenessTracker: swiftLivenessTracker)
|
||||
|
||||
callKotlin(helper, kotlinLivenessTracker)
|
||||
}
|
||||
}
|
||||
|
||||
private class SwiftObject1 {}
|
||||
private class SwiftObject2 {}
|
||||
private class SwiftObject3 {}
|
||||
private class SwiftObject4 {}
|
||||
|
||||
private func testSendKotlinObjectToKotlin() throws {
|
||||
try testSendToKotlin({ KotlinObject() }) {
|
||||
$0.sendKotlinObject(kotlinObject: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendKotlinObjectToKotlinBlock() throws {
|
||||
try testSendToKotlin({ KotlinObject() }) {
|
||||
$0.blockReceivingKotlinObject()($1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendSwiftObjectToKotlin() throws {
|
||||
try testSendToKotlin({ SwiftObject1() }) {
|
||||
$0.sendSwiftObject(swiftObject: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendListToKotlin() throws {
|
||||
try testSendToKotlin({ createList() }, flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
$0.sendList(list: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendStringToKotlin() throws {
|
||||
try testSendToKotlin({ createString() }, flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
$0.sendString(string: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendNumberToKotlin() throws {
|
||||
try testSendToKotlin({ createNumber() }) {
|
||||
$0.sendNumber(number: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendBlockToKotlin() throws {
|
||||
try testSendToKotlin({ createBlock() }, flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
$0.sendBlock(block: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendCompletionToKotlin() throws {
|
||||
try testSendToKotlin({ createCompletion() }, flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
$0.sendCompletion(completionHandler: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveKotlinObjectFromKotlin() throws {
|
||||
try testReceiveFromKotlin {
|
||||
$0.receiveKotlinObject()
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveSwiftObjectFromKotlin() throws {
|
||||
try testReceiveFromKotlin { (helper: NoAutoreleaseKotlinReceiveHelper) -> Any in
|
||||
helper.swiftObject = SwiftObject3()
|
||||
return helper.receiveSwiftObject()
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveListFromKotlin() throws {
|
||||
// Swift conversion from NSArray to Swift Array uses non-optimized autorelease in the implementation,
|
||||
// So regardless of our efforts, passing List from Kotlin to Swift will use autoreleasepool.
|
||||
// Use `checkAutorelease: false` flag to disable the relevant check.
|
||||
try testReceiveFromKotlin(flags: TestFlags(trackSwiftLifetime: false, checkAutorelease: false)) {
|
||||
$0.receiveList()
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveStringFromKotlin() throws {
|
||||
try testReceiveFromKotlin(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
$0.receiveString()
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveNumberFromKotlin() throws {
|
||||
try testReceiveFromKotlin {
|
||||
$0.receiveNumber()
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveBlockFromKotlin() throws {
|
||||
try testReceiveFromKotlin(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
$0.receiveBlock()
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveBlockFromKotlinAndCall() throws {
|
||||
try testReceiveFromKotlin {
|
||||
$0.receiveBlock()()
|
||||
}
|
||||
}
|
||||
|
||||
private func testCreateKotlinArray() throws {
|
||||
try testReceiveFromKotlin { (helper: NoAutoreleaseKotlinReceiveHelper) -> KotlinIntArray in
|
||||
let array = KotlinIntArray(size: 2)
|
||||
helper.kotlinLivenessTracker.add(obj: array)
|
||||
return array
|
||||
}
|
||||
}
|
||||
|
||||
private func testGetKotlinUnit() throws {
|
||||
try assertAutoreleasepoolNotUsed {
|
||||
try assertSame(actual: KotlinUnit.shared, expected: KotlinUnit.shared)
|
||||
}
|
||||
}
|
||||
|
||||
private func testGetKotlinSingleton() throws {
|
||||
try assertAutoreleasepoolNotUsed {
|
||||
try assertEquals(actual: NoAutoreleaseSingleton.shared.x, expected: 1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testGetKotlinEnumEntry() throws {
|
||||
try assertAutoreleasepoolNotUsed {
|
||||
try assertEquals(actual: NoAutoreleaseEnum.entry.x, expected: 2)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendKotlinObjectToSwift() throws {
|
||||
try testCallToSwift {
|
||||
NoAutoreleaseKt.callSendKotlinObject(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendKotlinObjectToSwiftBlock() throws {
|
||||
try testCallToSwift {
|
||||
NoAutoreleaseKt.sendKotlinObjectToBlock(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendSwiftObjectToSwift() throws {
|
||||
try testCallToSwift {
|
||||
NoAutoreleaseKt.callSendSwiftObject(helper: $0, tracker: $1, swiftObject: SwiftObject4())
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendListToSwift() throws {
|
||||
// Swift conversion from NSArray to Swift Array uses non-optimized autorelease in the implementation,
|
||||
// So regardless of our efforts, passing List from Kotlin to Swift will use autoreleasepool.
|
||||
// Use `checkAutorelease: false` flag to disable the relevant check.
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false, checkAutorelease: false)) {
|
||||
NoAutoreleaseKt.callSendList(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendStringToSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
NoAutoreleaseKt.callSendString(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendNumberToSwift() throws {
|
||||
try testCallToSwift {
|
||||
NoAutoreleaseKt.callSendNumber(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendBlockToSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
NoAutoreleaseKt.callSendBlock(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testSendCompletionToSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
NoAutoreleaseKt.callSendCompletion(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveKotlinObjectFromSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(runGCTwice: true)) {
|
||||
NoAutoreleaseKt.callReceiveKotlinObject(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveSwiftObjectFromSwift() throws {
|
||||
try testCallToSwift {
|
||||
NoAutoreleaseKt.callReceiveSwiftObject(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveListFromSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
NoAutoreleaseKt.callReceiveList(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveStringFromSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
NoAutoreleaseKt.callReceiveString(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveNumberFromSwift() throws {
|
||||
try testCallToSwift {
|
||||
NoAutoreleaseKt.callReceiveNumber(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveBlockFromSwift() throws {
|
||||
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
|
||||
NoAutoreleaseKt.callReceiveBlock(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func testReceiveBlockFromSwiftAndCall() throws {
|
||||
try testCallToSwift(flags: TestFlags(runGCTwice: true)) {
|
||||
NoAutoreleaseKt.callReceiveBlockAndCall(helper: $0, tracker: $1)
|
||||
}
|
||||
}
|
||||
|
||||
private func createList() -> [Any] {
|
||||
return [NSObject()]
|
||||
}
|
||||
|
||||
private func createBlock() -> () -> KotlinObject {
|
||||
let blockResult = KotlinObject()
|
||||
return { return blockResult } // Make capturing thus dynamic.
|
||||
}
|
||||
|
||||
private func createBlock(swiftLivenessTracker: SwiftLivenessTracker) -> () -> KotlinObject {
|
||||
let blockResult = KotlinObject()
|
||||
return {
|
||||
let result = blockResult // Make capturing thus dynamic.
|
||||
swiftLivenessTracker.add(result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private func createCompletion() -> (Any?, Error?) -> Void {
|
||||
return { _, _ in }
|
||||
}
|
||||
|
||||
private func createString() -> String {
|
||||
return NSObject().description // Make it dynamic.
|
||||
}
|
||||
|
||||
private func createNumber() -> NSNumber {
|
||||
return (0.5 + Double(NSObject().hash)) as NSNumber
|
||||
}
|
||||
|
||||
class NoAutoreleaseTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("testSendKotlinObjectToKotlin", testSendKotlinObjectToKotlin)
|
||||
test("testSendKotlinObjectToKotlinBlock", testSendKotlinObjectToKotlinBlock)
|
||||
test("testSendSwiftObjectToKotlin", testSendSwiftObjectToKotlin)
|
||||
test("testSendListToKotlin", testSendListToKotlin)
|
||||
test("testSendStringToKotlin", testSendStringToKotlin)
|
||||
test("testSendNumberToKotlin", testSendNumberToKotlin)
|
||||
test("testSendBlockToKotlin", testSendBlockToKotlin)
|
||||
test("testSendCompletionToKotlin", testSendCompletionToKotlin)
|
||||
|
||||
test("testReceiveKotlinObjectFromKotlin", testReceiveKotlinObjectFromKotlin)
|
||||
test("testReceiveSwiftObjectFromKotlin", testReceiveSwiftObjectFromKotlin)
|
||||
test("testReceiveListFromKotlin", testReceiveListFromKotlin)
|
||||
test("testReceiveStringFromKotlin", testReceiveStringFromKotlin)
|
||||
test("testReceiveNumberFromKotlin", testReceiveNumberFromKotlin)
|
||||
test("testReceiveBlockFromKotlin", testReceiveBlockFromKotlin)
|
||||
test("testReceiveBlockFromKotlinAndCall", testReceiveBlockFromKotlinAndCall)
|
||||
|
||||
test("testCreateKotlinArray", testCreateKotlinArray)
|
||||
|
||||
test("testGetKotlinUnit", testGetKotlinUnit)
|
||||
test("testGetKotlinSingleton", testGetKotlinSingleton)
|
||||
test("testGetKotlinEnumEntry", testGetKotlinEnumEntry)
|
||||
|
||||
test("testSendKotlinObjectToSwift", testSendKotlinObjectToSwift)
|
||||
test("testSendKotlinObjectToSwiftBlock", testSendKotlinObjectToSwiftBlock)
|
||||
test("testSendSwiftObjectToSwift", testSendSwiftObjectToSwift)
|
||||
test("testSendListToSwift", testSendListToSwift)
|
||||
test("testSendStringToSwift", testSendStringToSwift)
|
||||
test("testSendNumberToSwift", testSendNumberToSwift)
|
||||
test("testSendBlockToSwift", testSendBlockToSwift)
|
||||
test("testSendCompletionToSwift", testSendCompletionToSwift)
|
||||
|
||||
test("testReceiveKotlinObjectFromSwift", testReceiveKotlinObjectFromSwift)
|
||||
test("testReceiveSwiftObjectFromSwift", testReceiveSwiftObjectFromSwift)
|
||||
test("testReceiveListFromSwift", testReceiveListFromSwift)
|
||||
test("testReceiveStringFromSwift", testReceiveStringFromSwift)
|
||||
test("testReceiveNumberFromSwift", testReceiveNumberFromSwift)
|
||||
test("testReceiveBlockFromSwift", testReceiveBlockFromSwift)
|
||||
test("testReceiveBlockFromSwiftAndCall", testReceiveBlockFromSwiftAndCall)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package noEnumEntries
|
||||
|
||||
enum class NoEnumEntriesEnum {
|
||||
ONE,
|
||||
TWO,
|
||||
THREE
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import Kt
|
||||
|
||||
private func testObjCNameClassNames() throws {
|
||||
try assertEquals(actual: ObjCNameC1A().foo(), expected: "a")
|
||||
try assertEquals(actual: ObjCNameC1B().foo(), expected: "b")
|
||||
}
|
||||
|
||||
private func testObjCNameFunctionName() throws {
|
||||
try assertEquals(actual: ObjCNameAKt.with(userId: "abc"), expected: "abc")
|
||||
}
|
||||
|
||||
private func testObjCNameParameterNames() throws {
|
||||
try assertEquals(actual: ObjCNameAKt.supports(true), expected: true)
|
||||
try assertEquals(actual: ObjCNameAKt.scanForPeripherals(withServices: 123, options: "abc"), expected: "123 abc")
|
||||
try assertEquals(actual: ObjCNameAKt.registerForConnectionEvents(options: "abc"), expected: "abc")
|
||||
}
|
||||
|
||||
private func testObjCNameReceiverName() throws {
|
||||
let object = SwiftNameC2()
|
||||
try assertEquals(actual: ObjCNameBKt.getSomeValue(of: object), expected: 0)
|
||||
}
|
||||
|
||||
private func testObjCNameMySwiftArray() throws {
|
||||
let array = MySwiftArray()
|
||||
try assertEquals(actual: array.count, expected: 0)
|
||||
try assertEquals(actual: array.index(of: 1), expected: 1)
|
||||
}
|
||||
|
||||
private func testObjCNameOverrides() throws {
|
||||
let object = SwiftNameC2()
|
||||
try assertEquals(actual: object.someOtherValue, expected: 0)
|
||||
object.someOtherValue = 1
|
||||
try assertEquals(actual: object.someOtherValue, expected: 1)
|
||||
try assertEquals(actual: object.someOtherFunction(receiver: 2, otherParam: 4), expected: 8)
|
||||
try assertEquals(actual: ObjCNameC4().foo(objCReceiver: 3, objCParam: 5), expected: 15)
|
||||
}
|
||||
|
||||
private func testObjCNameNestedClass() throws {
|
||||
let object = SwiftNameC2.SwiftNestedClass()
|
||||
try assertEquals(actual: object.nestedValue, expected: 1)
|
||||
object.nestedValue = 2
|
||||
try assertEquals(actual: object.nestedValue, expected: 2)
|
||||
}
|
||||
|
||||
private func testObjCNameExact() throws {
|
||||
try assertEquals(actual: SwiftExactNestedClass().nestedValue, expected: 1)
|
||||
try assertEquals(actual: SwiftNameC3.SwiftNestedClass().nestedValue, expected: 2)
|
||||
}
|
||||
|
||||
private func testObjCNameObject() throws {
|
||||
try assertEquals(actual: ObjCNameSwiftObject.shared, expected: ObjCNameSwiftObject())
|
||||
}
|
||||
|
||||
private func testObjCNameEnum() throws {
|
||||
let enumValues = ObjCNameSwiftEnum.values()
|
||||
try assertEquals(actual: enumValues.size, expected: 3)
|
||||
try assertSame(actual: enumValues.get(index: 0) as AnyObject, expected: ObjCNameSwiftEnum.swiftOne)
|
||||
try assertSame(actual: enumValues.get(index: 1) as AnyObject, expected: ObjCNameSwiftEnum.companion)
|
||||
try assertSame(actual: enumValues.get(index: 2) as AnyObject, expected: ObjCNameSwiftEnum.swiftThree)
|
||||
try assertEquals(actual: ObjCNameSwiftEnum.Companion.shared.foo(), expected: 0)
|
||||
}
|
||||
|
||||
private func testObjCAvoidPreprocessorName() throws {
|
||||
let instance = ObjCAvoidPreprocessorName(time: 42)
|
||||
try assertEquals(actual: instance.time, expected: 42)
|
||||
}
|
||||
|
||||
class ObjCNameTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestObjCNameClassNames", testObjCNameClassNames)
|
||||
test("TestObjCNameFunctionName", testObjCNameFunctionName)
|
||||
test("TestObjCNameParameterNames", testObjCNameParameterNames)
|
||||
test("TestObjCNameReceiverName", testObjCNameReceiverName)
|
||||
test("TestObjCNameMySwiftArray", testObjCNameMySwiftArray)
|
||||
test("TestObjCNameOverrides", testObjCNameOverrides)
|
||||
test("TestObjCNameNestedClass", testObjCNameNestedClass)
|
||||
test("TestObjCNameExact", testObjCNameExact)
|
||||
test("TestObjCNameObject", testObjCNameObject)
|
||||
test("TestObjCNameEnum", testObjCNameEnum)
|
||||
test("TestObjCAvoidPreprocessorName", testObjCAvoidPreprocessorName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalObjCName::class)
|
||||
|
||||
package objCNameA
|
||||
|
||||
import kotlin.experimental.ExperimentalObjCName
|
||||
|
||||
// https://youtrack.jetbrains.com/issue/KT-50767
|
||||
@ObjCName("ObjCNameC1A")
|
||||
class ObjCNameC1 {
|
||||
fun foo(): String = "a"
|
||||
}
|
||||
|
||||
// https://youtrack.jetbrains.com/issue/KT-48076
|
||||
@ObjCName("with")
|
||||
fun withUserId(userId: String): String = userId
|
||||
|
||||
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/3240586-supports
|
||||
fun supports(@ObjCName(swiftName = "_") features: Boolean): Boolean = features
|
||||
|
||||
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/1518986-scanforperipherals
|
||||
fun scanForPeripherals(@ObjCName("withServices") serviceUUIDs: Int, options: String): String = "$serviceUUIDs $options"
|
||||
|
||||
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/3174844-registerforconnectionevents
|
||||
fun registerForConnectionEvents(@ObjCName("withOptions", "options") options: String): String = "$options"
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalObjCName::class)
|
||||
|
||||
package objCNameB
|
||||
|
||||
import kotlin.experimental.ExperimentalObjCName
|
||||
|
||||
// https://youtrack.jetbrains.com/issue/KT-50767
|
||||
@ObjCName("ObjCNameC1B")
|
||||
class ObjCNameC1 {
|
||||
fun foo(): String = "b"
|
||||
}
|
||||
|
||||
@ObjCName("MyObjCArray", "MySwiftArray")
|
||||
class MyKotlinArray {
|
||||
// https://developer.apple.com/documentation/foundation/nsarray/1409982-count
|
||||
@ObjCName("count")
|
||||
val size: Int = 0
|
||||
// https://developer.apple.com/documentation/foundation/nsarray/1417076-index
|
||||
@ObjCName(swiftName = "index")
|
||||
fun indexOf(@ObjCName("object", "of") element: Int): Int = element
|
||||
}
|
||||
|
||||
interface ObjCNameI1 {
|
||||
@ObjCName("someOtherValue")
|
||||
val someValue: Int
|
||||
@ObjCName("someOtherFunction")
|
||||
fun @receiver:ObjCName("receiver") Int.someFunction(@ObjCName("otherParam") param: Int): Int
|
||||
}
|
||||
|
||||
fun @receiver:ObjCName("of") ObjCNameI1.getSomeValue(): Int = someValue
|
||||
|
||||
@ObjCName(swiftName = "SwiftNameC2")
|
||||
class ObjCNameC2: ObjCNameI1 {
|
||||
@ObjCName("ObjCNestedClass", "SwiftNestedClass")
|
||||
class NestedClass {
|
||||
var nestedValue: Int = 1
|
||||
}
|
||||
|
||||
@ObjCName("ObjCExactNestedClass", "SwiftExactNestedClass", true)
|
||||
class ExactNestedClass {
|
||||
var nestedValue: Int = 1
|
||||
}
|
||||
|
||||
override var someValue: Int = 0
|
||||
override fun Int.someFunction(param: Int): Int = this * param
|
||||
}
|
||||
|
||||
@ObjCName("ObjCNameC3", "SwiftNameC3", true)
|
||||
class ObjCNameC3 {
|
||||
@ObjCName("ObjCNestedClass", "SwiftNestedClass")
|
||||
class NestedClass {
|
||||
var nestedValue: Int = 2
|
||||
}
|
||||
}
|
||||
|
||||
private interface ObjCNameI2 {
|
||||
fun @receiver:ObjCName("objCReceiver") Int.foo(@ObjCName("objCParam") param: Int): Int
|
||||
}
|
||||
|
||||
class ObjCNameC4: ObjCNameI2 {
|
||||
override fun Int.foo(param: Int): Int = this * param
|
||||
}
|
||||
|
||||
@ObjCName("ObjCNameObjCObject", "ObjCNameSwiftObject")
|
||||
object ObjCNameKotlinObject
|
||||
|
||||
@ObjCName("ObjCNameObjCEnum", "ObjCNameSwiftEnum")
|
||||
enum class ObjCNameKotlinEnum {
|
||||
@ObjCName("objcOne", "swiftOne")
|
||||
KOTLIN_ONE,
|
||||
@ObjCName("objcTwo", "companion")
|
||||
kotlinTwo,
|
||||
@ObjCName("objcThree", "swiftThree")
|
||||
KotlinThree;
|
||||
|
||||
companion object {
|
||||
fun foo(): Int = 0
|
||||
}
|
||||
}
|
||||
|
||||
class ObjCAvoidPreprocessorName(@property:ObjCName("time") @ObjCName("time") val __TIME__: Int)
|
||||
@@ -0,0 +1,66 @@
|
||||
package overrideKotlinMethods
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
internal interface OverrideKotlinMethods0<T> {
|
||||
fun one(): T
|
||||
}
|
||||
|
||||
internal interface OverrideKotlinMethods1<T> : OverrideKotlinMethods0<T>
|
||||
|
||||
interface OverrideKotlinMethods2 {
|
||||
fun one(): Int
|
||||
}
|
||||
|
||||
open class OverrideKotlinMethods3 {
|
||||
internal open fun one(): Number = 3
|
||||
}
|
||||
|
||||
open class OverrideKotlinMethods4 : OverrideKotlinMethods3(), OverrideKotlinMethods1<Int>, OverrideKotlinMethods2 {
|
||||
override fun one(): Int = 2
|
||||
}
|
||||
|
||||
interface OverrideKotlinMethods5 {
|
||||
fun one(): Int
|
||||
}
|
||||
|
||||
interface OverrideKotlinMethods6 : OverrideKotlinMethods5
|
||||
|
||||
// Using `Any` because Kotlin forbids internal type in public function signature.
|
||||
@Throws(Throwable::class)
|
||||
fun test0(obj: Any) {
|
||||
val obj0 = obj as OverrideKotlinMethods0<*>
|
||||
assertEquals(1, obj0.one())
|
||||
}
|
||||
|
||||
// Using `Any` because Kotlin forbids internal type in public function signature.
|
||||
@Throws(Throwable::class)
|
||||
fun test1(obj: Any) {
|
||||
val obj1 = obj as OverrideKotlinMethods1<*>
|
||||
assertEquals(1, obj1.one())
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun test2(obj: OverrideKotlinMethods2) {
|
||||
assertEquals(1, obj.one())
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun test3(obj: OverrideKotlinMethods3) {
|
||||
assertEquals(1, obj.one())
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun test4(obj: OverrideKotlinMethods4) {
|
||||
assertEquals(1, obj.one())
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun test5(obj: OverrideKotlinMethods5) {
|
||||
assertEquals(1, obj.one())
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun test6(obj: OverrideKotlinMethods6) {
|
||||
assertEquals(1, obj.one())
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 Kt
|
||||
|
||||
class OverrideKotlinMethodsImpl : OverrideKotlinMethods4, OverrideKotlinMethods6 {
|
||||
override func one() -> Int32 {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
private func test1() throws {
|
||||
let obj = OverrideKotlinMethodsImpl()
|
||||
|
||||
try OverrideKotlinMethodsKt.test0(obj: obj)
|
||||
try OverrideKotlinMethodsKt.test1(obj: obj)
|
||||
try OverrideKotlinMethodsKt.test2(obj: obj)
|
||||
try OverrideKotlinMethodsKt.test3(obj: obj)
|
||||
try OverrideKotlinMethodsKt.test4(obj: obj)
|
||||
try OverrideKotlinMethodsKt.test5(obj: obj)
|
||||
try OverrideKotlinMethodsKt.test6(obj: obj)
|
||||
}
|
||||
|
||||
class OverrideKotlinMethodsTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("Test1", test1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package overrideMethodsOfAny
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun test(obj: Any, other: Any, swift: Boolean) {
|
||||
if (!swift) {
|
||||
// Doesn't work for Swift, see https://youtrack.jetbrains.com/issue/KT-44613.
|
||||
assertEquals(42, obj.hashCode())
|
||||
assertTrue(obj.equals(other))
|
||||
}
|
||||
|
||||
assertTrue(obj.equals(obj))
|
||||
assertFalse(obj.equals(null))
|
||||
assertFalse(obj.equals(Any()))
|
||||
|
||||
assertEquals("toString", obj.toString())
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 Kt
|
||||
|
||||
private class SwiftOverridingMethodsOfAny : Hashable, Equatable, CustomStringConvertible {
|
||||
var hashValue: Int { return 42 }
|
||||
|
||||
static func == (lhs: SwiftOverridingMethodsOfAny, rhs: SwiftOverridingMethodsOfAny) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var description: String { return "toString" }
|
||||
}
|
||||
|
||||
private func testSwift() throws {
|
||||
try OverrideMethodsOfAnyKt.test(obj: SwiftOverridingMethodsOfAny(), other: SwiftOverridingMethodsOfAny(), swift: true)
|
||||
}
|
||||
|
||||
private class ObjCOverridingMethodsOfAny : NSObject {
|
||||
override var hash: Int { return 42 }
|
||||
|
||||
override func isEqual(_ other: Any?) -> Bool {
|
||||
return other is ObjCOverridingMethodsOfAny
|
||||
}
|
||||
|
||||
override var description: String { return "toString" }
|
||||
}
|
||||
|
||||
private func testObjC() throws {
|
||||
try OverrideMethodsOfAnyKt.test(obj: ObjCOverridingMethodsOfAny(), other: ObjCOverridingMethodsOfAny(), swift: false)
|
||||
}
|
||||
|
||||
class OverrideMethodsOfAnyTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestSwift", testSwift)
|
||||
test("TestObjC", testObjC)
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package recursiveGenericArguments
|
||||
|
||||
class RecList<T: List<T>>(val value: T)
|
||||
|
||||
class RecFunc<T : () -> T>(val value: T)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import Kt
|
||||
|
||||
#if !NO_GENERICS
|
||||
private func testRecursiveGenericArguments() throws {
|
||||
try assertTrue(type(of: RecList<NSArray>(value: []).value) == [Any].self)
|
||||
}
|
||||
#endif
|
||||
|
||||
class RecursiveGenericArgumentsTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
#if !NO_GENERICS
|
||||
test("TestRecursiveGenericArguments", testRecursiveGenericArguments)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package refined
|
||||
|
||||
import kotlin.experimental.ExperimentalObjCRefinement
|
||||
|
||||
@ExperimentalObjCRefinement
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@MustBeDocumented
|
||||
@HidesFromObjC
|
||||
annotation class MyHiddenFromObjC
|
||||
|
||||
@ExperimentalObjCRefinement
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@MustBeDocumented
|
||||
@RefinesInSwift
|
||||
annotation class MyShouldRefineInSwift
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
fun foo(): Int = 1
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@ShouldRefineInSwift
|
||||
fun fooRefined(): String = foo().toString()
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@MyHiddenFromObjC
|
||||
fun myFoo(): Int = 2
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@MyShouldRefineInSwift
|
||||
fun myFooRefined(): String = myFoo().toString()
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
val bar: Int = 3
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@ShouldRefineInSwift
|
||||
val barRefined: String get() = bar.toString()
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@MyHiddenFromObjC
|
||||
val myBar: Int = 4
|
||||
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@MyShouldRefineInSwift
|
||||
val myBarRefined: String get() = myBar.toString()
|
||||
|
||||
open class RefinedClassA {
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@HiddenFromObjC
|
||||
open fun foo(): Int = 1
|
||||
@OptIn(ExperimentalObjCRefinement::class)
|
||||
@ShouldRefineInSwift
|
||||
open fun fooRefined(): String = foo().toString()
|
||||
}
|
||||
|
||||
class RefinedClassB: RefinedClassA() {
|
||||
override fun foo(): Int = 2
|
||||
override fun fooRefined(): String {
|
||||
val foo = foo()
|
||||
return "$foo$foo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import Kt
|
||||
|
||||
extension RefinedKt {
|
||||
static func foo() -> Int {
|
||||
return Int(RefinedKt.__fooRefined())! * 2
|
||||
}
|
||||
|
||||
static func myFoo() -> Int {
|
||||
return Int(RefinedKt.__myFooRefined())! * 2
|
||||
}
|
||||
|
||||
static var bar: Int {
|
||||
return Int(RefinedKt.__barRefined)! * 2
|
||||
}
|
||||
|
||||
static var myBar: Int {
|
||||
return Int(RefinedKt.__myBarRefined)! * 2
|
||||
}
|
||||
}
|
||||
|
||||
extension RefinedClassA {
|
||||
func foo() -> Int {
|
||||
return Int(__fooRefined())! * 2
|
||||
}
|
||||
}
|
||||
|
||||
private func testSwiftRefinements() throws {
|
||||
try assertEquals(actual: RefinedKt.foo(), expected: 2)
|
||||
try assertEquals(actual: RefinedKt.bar, expected: 6)
|
||||
}
|
||||
|
||||
private func testMySwiftRefinements() throws {
|
||||
try assertEquals(actual: RefinedKt.myFoo(), expected: 4)
|
||||
try assertEquals(actual: RefinedKt.myBar, expected: 8)
|
||||
}
|
||||
|
||||
private func testInheritedRefinements() throws {
|
||||
try assertEquals(actual: RefinedClassA().foo(), expected: 2)
|
||||
try assertEquals(actual: RefinedClassB().foo(), expected: 44)
|
||||
}
|
||||
|
||||
class RefinedTests : SimpleTestProvider {
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
test("TestSwiftRefinements", testSwiftRefinements)
|
||||
test("TestMySwiftRefinements", testMySwiftRefinements)
|
||||
test("TestInheritedRefinements", testInheritedRefinements)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package sealedClass
|
||||
|
||||
sealed class Person() {
|
||||
data class User(val id: Int) : Person()
|
||||
|
||||
abstract class Worker() {
|
||||
data class Employee(val id: Int) : Worker()
|
||||
data class Contractor(val id: Int) : Worker()
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user