Properly handle extensions to inlined classes when producing framework
See https://github.com/JetBrains/kotlin-native/issues/2120#issuecomment-424262886
This commit is contained in:
committed by
SvyatoslavScherbina
parent
9b2a03b6cd
commit
080ecf0d11
+3
-6
@@ -11,12 +11,10 @@ import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -34,18 +32,17 @@ internal abstract class ObjCExportMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ObjCExportMapper.isRepresentedAsObjCInterface(descriptor: ClassDescriptor): Boolean =
|
||||
!descriptor.isInterface && !isSpecialMapped(descriptor)
|
||||
|
||||
internal fun ObjCExportMapper.getClassIfCategory(descriptor: CallableMemberDescriptor): ClassDescriptor? {
|
||||
if (descriptor.dispatchReceiverParameter != null) return null
|
||||
|
||||
val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return null
|
||||
|
||||
// FIXME: this code must rely on type mapping instead of copying its logic.
|
||||
|
||||
if (extensionReceiverType.isObjCObjectType()) return null
|
||||
|
||||
val erasedClass = extensionReceiverType.getErasedTypeClass()
|
||||
return if (this.isRepresentedAsObjCInterface(erasedClass)) {
|
||||
return if (!erasedClass.isInterface && !erasedClass.isInlined() && !this.isSpecialMapped(erasedClass)) {
|
||||
erasedClass
|
||||
} else {
|
||||
// E.g. receiver is protocol, or some type with custom mapping.
|
||||
|
||||
@@ -132,6 +132,9 @@ fun Any?.toString(): String = this?.toString() ?: "null"
|
||||
|
||||
fun Any?.print() = println(this.toString())
|
||||
|
||||
fun Char.boxChar(): Char? = this
|
||||
fun Char?.isA(): Boolean = (this == 'A')
|
||||
|
||||
// Lambdas
|
||||
val sumLambda = { x: Int, y: Int -> x + y }
|
||||
|
||||
@@ -223,4 +226,13 @@ fun box(ic2: IC2): Any = ic2
|
||||
fun box(ic3: IC3): Any = ic3
|
||||
|
||||
fun concatenateInlineClassValues(ic1: IC1, ic1N: IC1?, ic2: IC2, ic2N: IC2?, ic3: IC3, ic3N: IC3?): String =
|
||||
"${ic1.value} ${ic1N?.value} ${ic2.value} ${ic2N?.value} ${ic3.value} ${ic3N?.value}"
|
||||
"${ic1.value} ${ic1N?.value} ${ic2.value} ${ic2N?.value} ${ic3.value} ${ic3N?.value}"
|
||||
|
||||
fun IC1.getValue1() = this.value
|
||||
fun IC1?.getValueOrNull1() = this?.value
|
||||
|
||||
fun IC2.getValue2() = value
|
||||
fun IC2?.getValueOrNull2() = this?.value
|
||||
|
||||
fun IC3.getValue3() = value
|
||||
fun IC3?.getValueOrNull3() = this?.value
|
||||
|
||||
@@ -314,6 +314,11 @@ func testAnyPrint() throws {
|
||||
print("END")
|
||||
}
|
||||
|
||||
func testCharExtensions() throws {
|
||||
try assertTrue(ValuesKt.isA(ValuesKt.boxChar(65)))
|
||||
try assertFalse(ValuesKt.isA(ValuesKt.boxChar(66)))
|
||||
}
|
||||
|
||||
func testLambda() throws {
|
||||
try assertEquals(actual: ValuesKt.sumLambda(3, 4), expected: 7)
|
||||
}
|
||||
@@ -404,6 +409,15 @@ func testInlineClasses() throws {
|
||||
actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: nil, ic2: ic2, ic2N: nil, ic3: nil, ic3N: nil),
|
||||
expected: "42 null foo null null null"
|
||||
)
|
||||
|
||||
try assertEquals(actual: ValuesKt.getValue1(ic1), expected: 42)
|
||||
try assertEquals(actual: ValuesKt.getValueOrNull1(ic1N) as! Int, expected: 17)
|
||||
|
||||
try assertEquals(actual: ValuesKt.getValue2(ic2), expected: "foo")
|
||||
try assertEquals(actual: ValuesKt.getValueOrNull2(ic2N), expected: "bar")
|
||||
|
||||
try assertEquals(actual: ValuesKt.getValue3(ic3), expected: ic3)
|
||||
try assertEquals(actual: ValuesKt.getValueOrNull3(ic3N), expected: nil)
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
@@ -431,6 +445,7 @@ class ValuesTests : TestProvider {
|
||||
TestCase(name: "TestStringExtension", method: withAutorelease(testStrExtFun)),
|
||||
TestCase(name: "TestAnyToString", method: withAutorelease(testAnyToString)),
|
||||
TestCase(name: "TestAnyPrint", method: withAutorelease(testAnyPrint)),
|
||||
TestCase(name: "TestCharExtensions", method: withAutorelease(testCharExtensions)),
|
||||
TestCase(name: "TestLambda", method: withAutorelease(testLambda)),
|
||||
TestCase(name: "TestInterfaceExtension", method: withAutorelease(testInterfaceExtension)),
|
||||
TestCase(name: "TestClassInstances", method: withAutorelease(testClassInstances)),
|
||||
|
||||
Reference in New Issue
Block a user