[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
|
||||
get() = if (isConstructor && isArray) {
|
||||
get() = if (isArrayConstructor) {
|
||||
MethodBridgeReceiver.Factory
|
||||
} else if (isTopLevel) {
|
||||
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
|
||||
|
||||
if (isArray) {
|
||||
if (isArrayConstructor) {
|
||||
return MethodBridge.ReturnValue.Instance.FactoryResult
|
||||
} else if (isConstructor) {
|
||||
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.objcexport.Predefined.anyMethodSelectors
|
||||
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.psi.KtFile
|
||||
|
||||
internal val KtCallableSymbol.isConstructor: Boolean
|
||||
get() = this is KtConstructorSymbol
|
||||
|
||||
internal val KtCallableSymbol.isArray: Boolean
|
||||
get() = false //TODO: temp k2 workaround
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
fun KtFunctionSymbol.translateToObjCMethod(
|
||||
): ObjCMethod? {
|
||||
@@ -31,7 +29,6 @@ fun KtFunctionSymbol.translateToObjCMethod(
|
||||
return buildObjCMethod()
|
||||
}
|
||||
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
fun KtFileSymbol.getObjCFileClassOrProtocolName(): ObjCExportFileName? {
|
||||
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)".
|
||||
}
|
||||
|
||||
if (this.isConstructor && !isArray) { // TODO: check methodBridge instead.
|
||||
if (this.isConstructor && !isArrayConstructor) { // TODO: check methodBridge instead.
|
||||
attributes += "objc_designated_initializer"
|
||||
}
|
||||
|
||||
@@ -239,7 +236,7 @@ context(KtAnalysisSession, KtObjCExportSession)
|
||||
private fun KtFunctionLikeSymbol.getMangledName(forSwift: Boolean): String {
|
||||
|
||||
if (this.isConstructor) {
|
||||
return if (isArray && !forSwift) "array" else "init"
|
||||
return if (isArrayConstructor && !forSwift) "array" else "init"
|
||||
}
|
||||
|
||||
val candidate = when (this) {
|
||||
@@ -292,21 +289,9 @@ private fun String.startsWithWords(words: String) = this.startsWith(words) &&
|
||||
fun MethodBridge.valueParametersAssociated(
|
||||
function: KtFunctionLikeSymbol,
|
||||
): List<Pair<MethodBridgeValueParameter, KtValueParameterSymbol?>> {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
val allParameters = function.valueParameters
|
||||
if (allParameters.isEmpty()) return emptyList()
|
||||
|
||||
|
||||
return this.valueParameters.mapIndexed { index, valueParameterBridge ->
|
||||
when (valueParameterBridge) {
|
||||
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