diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCParameters.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCParameters.kt index a7059220367..c206dc3791f 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCParameters.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCParameters.kt @@ -1,12 +1,15 @@ package org.jetbrains.kotlin.objcexport import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.components.buildClassType import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySetterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol import org.jetbrains.kotlin.backend.konan.cKeywords import org.jetbrains.kotlin.backend.konan.objcexport.* +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.psi.KtParameter context(KtAnalysisSession, KtObjCExportSession) internal fun KtFunctionLikeSymbol.translateToObjCParameters(baseMethodBridge: MethodBridge): List { @@ -41,8 +44,15 @@ internal fun KtFunctionLikeSymbol.translateToObjCParameters(baseMethodBridge: Me usedNames += uniqueName val type = when (bridge) { - is MethodBridgeValueParameter.Mapped -> - parameter!!.returnType.translateToObjCType(bridge.bridge) + is MethodBridgeValueParameter.Mapped -> { + val returnType = parameter!!.returnType + if (parameter.isVararg) { + //vararg is a special case, [parameter.returnType] is T, we need Array + buildClassType(StandardClassIds.Array) { argument(parameter.returnType) }.translateToObjCType(bridge.bridge) + } else { + returnType.translateToObjCType(bridge.bridge) + } + } MethodBridgeValueParameter.ErrorOutParameter -> ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true) diff --git a/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt index e284747a411..38776b525fa 100644 --- a/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt +++ b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt @@ -307,6 +307,11 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) { doTest(headersTestDataDir.resolve("specialFunctionNames")) } + @Test + fun `test - vararg`() { + doTest(headersTestDataDir.resolve("vararg")) + } + private fun doTest(root: File, configuration: Configuration = Configuration()) { if (!root.isDirectory) fail("Expected ${root.absolutePath} to be directory") val generatedHeaders = generator.generateHeaders(root, configuration).toString() diff --git a/native/objcexport-header-generator/testData/headers/vararg/!vararg.h b/native/objcexport-header-generator/testData/headers/vararg/!vararg.h new file mode 100644 index 00000000000..13407c5dfbd --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/vararg/!vararg.h @@ -0,0 +1,49 @@ +#import +#import +#import +#import +#import +#import +#import + +@class Array; + +@protocol Iterator; + +NS_ASSUME_NONNULL_BEGIN +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wincompatible-property-type" +#pragma clang diagnostic ignored "-Wnullability" + +#pragma push_macro("_Nullable_result") +#if !__has_feature(nullability_nullable_result) +#undef _Nullable_result +#define _Nullable_result _Nullable +#endif + +__attribute__((objc_subclassing_restricted)) +@interface FooKt : Base ++ (void)fooArgs:(Array *)args __attribute__((swift_name("foo(args:)"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface Array : Base ++ (instancetype)arrayWithSize:(int32_t)size init:(T _Nullable (^)(Int *))init __attribute__((swift_name("init(size:init:)"))); ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (T _Nullable)getIndex:(int32_t)index __attribute__((swift_name("get(index:)"))); +- (id)iterator __attribute__((swift_name("iterator()"))); +- (void)setIndex:(int32_t)index value:(T _Nullable)value __attribute__((swift_name("set(index:value:)"))); +@property (readonly) int32_t size __attribute__((swift_name("size"))); +@end + +@protocol Iterator +@required +- (BOOL)hasNext __attribute__((swift_name("hasNext()"))); +- (id _Nullable)next __attribute__((swift_name("next()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/native/objcexport-header-generator/testData/headers/vararg/Foo.kt b/native/objcexport-header-generator/testData/headers/vararg/Foo.kt new file mode 100644 index 00000000000..22aa97ef00c --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/vararg/Foo.kt @@ -0,0 +1 @@ +fun foo(vararg args: String) {} \ No newline at end of file