[ObjCExport] Properly detect Array constructors
^KT-65225 Fixed
This commit is contained in:
committed by
Space Team
parent
926c0a9136
commit
c22149c642
+3
-2
@@ -43,8 +43,9 @@ internal fun KtPropertySymbol.getPropertyMethodBridge(): MethodBridge {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context(KtAnalysisSession)
|
||||||
private val KtCallableSymbol.receiverType: MethodBridgeReceiver
|
private val KtCallableSymbol.receiverType: MethodBridgeReceiver
|
||||||
get() = if (isConstructor && isArray) {
|
get() = if (isArrayConstructor) {
|
||||||
MethodBridgeReceiver.Factory
|
MethodBridgeReceiver.Factory
|
||||||
} else if (isTopLevel) {
|
} else if (isTopLevel) {
|
||||||
MethodBridgeReceiver.Static
|
MethodBridgeReceiver.Static
|
||||||
@@ -129,7 +130,7 @@ private fun KtCallableSymbol.bridgeReturnType(): MethodBridge.ReturnValue {
|
|||||||
|
|
||||||
val convertExceptionsToErrors = false // TODO: Add exception handling and return MethodBridge.ReturnValue.WithError.ZeroForError
|
val convertExceptionsToErrors = false // TODO: Add exception handling and return MethodBridge.ReturnValue.WithError.ZeroForError
|
||||||
|
|
||||||
if (isArray) {
|
if (isArrayConstructor) {
|
||||||
return MethodBridge.ReturnValue.Instance.FactoryResult
|
return MethodBridge.ReturnValue.Instance.FactoryResult
|
||||||
} else if (isConstructor) {
|
} else if (isConstructor) {
|
||||||
val result = MethodBridge.ReturnValue.Instance.InitResult
|
val result = MethodBridge.ReturnValue.Instance.InitResult
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.objcexport.analysisApiUtils
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.arrayTypes
|
||||||
|
|
||||||
|
context(KtAnalysisSession)
|
||||||
|
internal val KtCallableSymbol.isArrayConstructor: Boolean
|
||||||
|
get() = this is KtConstructorSymbol && getContainingSymbol()
|
||||||
|
?.let { containingSymbol -> containingSymbol as? KtClassOrObjectSymbol }
|
||||||
|
?.let { classSymbol -> classSymbol.classIdIfNonLocal?.asFqNameString() in arrayTypes } ?: false
|
||||||
+4
-19
@@ -13,15 +13,13 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.name.NameUtils
|
import org.jetbrains.kotlin.name.NameUtils
|
||||||
import org.jetbrains.kotlin.objcexport.Predefined.anyMethodSelectors
|
import org.jetbrains.kotlin.objcexport.Predefined.anyMethodSelectors
|
||||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getFunctionMethodBridge
|
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getFunctionMethodBridge
|
||||||
|
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isArrayConstructor
|
||||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
internal val KtCallableSymbol.isConstructor: Boolean
|
internal val KtCallableSymbol.isConstructor: Boolean
|
||||||
get() = this is KtConstructorSymbol
|
get() = this is KtConstructorSymbol
|
||||||
|
|
||||||
internal val KtCallableSymbol.isArray: Boolean
|
|
||||||
get() = false //TODO: temp k2 workaround
|
|
||||||
|
|
||||||
context(KtAnalysisSession, KtObjCExportSession)
|
context(KtAnalysisSession, KtObjCExportSession)
|
||||||
fun KtFunctionSymbol.translateToObjCMethod(
|
fun KtFunctionSymbol.translateToObjCMethod(
|
||||||
): ObjCMethod? {
|
): ObjCMethod? {
|
||||||
@@ -31,7 +29,6 @@ fun KtFunctionSymbol.translateToObjCMethod(
|
|||||||
return buildObjCMethod()
|
return buildObjCMethod()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
context(KtAnalysisSession, KtObjCExportSession)
|
context(KtAnalysisSession, KtObjCExportSession)
|
||||||
fun KtFileSymbol.getObjCFileClassOrProtocolName(): ObjCExportFileName? {
|
fun KtFileSymbol.getObjCFileClassOrProtocolName(): ObjCExportFileName? {
|
||||||
val ktFile = this.psi as? KtFile ?: return null
|
val ktFile = this.psi as? KtFile ?: return null
|
||||||
@@ -65,7 +62,7 @@ internal fun KtFunctionLikeSymbol.buildObjCMethod(
|
|||||||
attributes += "swift_error(nonnull_error)" // Means "failure <=> (error != nil)".
|
attributes += "swift_error(nonnull_error)" // Means "failure <=> (error != nil)".
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isConstructor && !isArray) { // TODO: check methodBridge instead.
|
if (this.isConstructor && !isArrayConstructor) { // TODO: check methodBridge instead.
|
||||||
attributes += "objc_designated_initializer"
|
attributes += "objc_designated_initializer"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +236,7 @@ context(KtAnalysisSession, KtObjCExportSession)
|
|||||||
private fun KtFunctionLikeSymbol.getMangledName(forSwift: Boolean): String {
|
private fun KtFunctionLikeSymbol.getMangledName(forSwift: Boolean): String {
|
||||||
|
|
||||||
if (this.isConstructor) {
|
if (this.isConstructor) {
|
||||||
return if (isArray && !forSwift) "array" else "init"
|
return if (isArrayConstructor && !forSwift) "array" else "init"
|
||||||
}
|
}
|
||||||
|
|
||||||
val candidate = when (this) {
|
val candidate = when (this) {
|
||||||
@@ -292,21 +289,9 @@ private fun String.startsWithWords(words: String) = this.startsWith(words) &&
|
|||||||
fun MethodBridge.valueParametersAssociated(
|
fun MethodBridge.valueParametersAssociated(
|
||||||
function: KtFunctionLikeSymbol,
|
function: KtFunctionLikeSymbol,
|
||||||
): List<Pair<MethodBridgeValueParameter, KtValueParameterSymbol?>> {
|
): List<Pair<MethodBridgeValueParameter, KtValueParameterSymbol?>> {
|
||||||
|
val allParameters = function.valueParameters
|
||||||
val skipFirstKotlinParameter = when (this.receiver) {
|
|
||||||
MethodBridgeReceiver.Static -> false
|
|
||||||
MethodBridgeReceiver.Instance -> false
|
|
||||||
MethodBridgeReceiver.Factory -> true
|
|
||||||
}
|
|
||||||
|
|
||||||
val allParameters = function.valueParameters.let { valueParameters ->
|
|
||||||
if (skipFirstKotlinParameter) valueParameters.drop(1)
|
|
||||||
else valueParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allParameters.isEmpty()) return emptyList()
|
if (allParameters.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
|
||||||
return this.valueParameters.mapIndexed { index, valueParameterBridge ->
|
return this.valueParameters.mapIndexed { index, valueParameterBridge ->
|
||||||
when (valueParameterBridge) {
|
when (valueParameterBridge) {
|
||||||
is MethodBridgeValueParameter.Mapped -> valueParameterBridge to allParameters[index]
|
is MethodBridgeValueParameter.Mapped -> valueParameterBridge to allParameters[index]
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.objcexport.tests
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analysis.api.analyze
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isArrayConstructor
|
||||||
|
import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis
|
||||||
|
import org.jetbrains.kotlin.objcexport.testUtils.getClassOrFail
|
||||||
|
import org.jetbrains.kotlin.objcexport.testUtils.getFunctionOrFail
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import kotlin.test.assertFalse
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
import kotlin.test.fail
|
||||||
|
|
||||||
|
class IsArrayConstructorTest(
|
||||||
|
private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis,
|
||||||
|
) {
|
||||||
|
@Test
|
||||||
|
fun `test - regular function`() {
|
||||||
|
val file = inlineSourceCodeAnalysis.createKtFile("fun foo() = Unit")
|
||||||
|
analyze(file) {
|
||||||
|
val foo = file.getFunctionOrFail("foo")
|
||||||
|
assertFalse(foo.isArrayConstructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - regular constructor`() {
|
||||||
|
val file = inlineSourceCodeAnalysis.createKtFile("class Foo(val x: Int)")
|
||||||
|
analyze(file) {
|
||||||
|
val foo = file.getClassOrFail("Foo")
|
||||||
|
val constructor = foo.getMemberScope().getConstructors().singleOrNull() ?: fail("No single constructor found")
|
||||||
|
assertFalse(constructor.isArrayConstructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - IntArray constructor`() = doTestForArray(ClassId.fromString("kotlin/IntArray"))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - ByteArray constructor`() = doTestForArray(ClassId.fromString("kotlin/ByteArray"))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - Array - constructor`() = doTestForArray(ClassId.fromString("kotlin/Array"))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - NativePtrArray - constructor`() = doTestForArray(ClassId.fromString("kotlin/native/internal/NativePtrArray"))
|
||||||
|
|
||||||
|
private fun doTestForArray(classId: ClassId) {
|
||||||
|
val file = inlineSourceCodeAnalysis.createKtFile("")
|
||||||
|
analyze(file) {
|
||||||
|
val arraySymbol = getClassOrObjectSymbolByClassId(classId)
|
||||||
|
?: fail("Missing $$classId symbol")
|
||||||
|
|
||||||
|
arraySymbol.getMemberScope().getConstructors()
|
||||||
|
.ifEmpty { fail("No constructors found on $classId") }
|
||||||
|
.forEach { constructor ->
|
||||||
|
assertTrue(
|
||||||
|
constructor.isArrayConstructor,
|
||||||
|
"Expected $classId constructor to be detected as array constructor"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user