diff --git a/kotlin-native/backend.native/build.gradle b/kotlin-native/backend.native/build.gradle index 727629f2c08..6037a41c93f 100644 --- a/kotlin-native/backend.native/build.gradle +++ b/kotlin-native/backend.native/build.gradle @@ -29,6 +29,12 @@ sourceSets { cli_bc { kotlin.srcDir 'cli.bc/src' } + + test { + kotlin { + srcDir 'functionalTest/src' + } + } } compileCompilerKotlin { @@ -119,7 +125,6 @@ kotlinNativeInterop { } } - configurations { compilerApi { extendsFrom kotlinNativeInterop['llvm'].configuration @@ -182,8 +187,9 @@ dependencies { cli_bcApi sourceSets.compiler.output cli_bcApiElements sourceSets.cli_bc.output -} + testImplementation(project(path: ":compiler:tests-common", configuration: "tests-jar")) +} classes.dependsOn 'compilerClasses', 'cli_bcClasses' @@ -243,3 +249,25 @@ RepoArtifacts.sourcesJar(project) { } RepoArtifacts.javadocJar(project) + +/* +Configure 'test' task + */ + +TasksKt.projectTest(project) +tasks { + test { + dependsOn ':kotlin-native:dist' + systemProperty("org.jetbrains.kotlin.native.home", distDir.canonicalPath) + workingDir(rootProject.projectDir) + } +} + +kotlin { + target { + compilations { + test.associateWith(compiler) + } + } +} + diff --git a/kotlin-native/backend.native/functionalTest/.editorconfig b/kotlin-native/backend.native/functionalTest/.editorconfig new file mode 100644 index 00000000000..93a002809be --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/.editorconfig @@ -0,0 +1,2 @@ +[*] +ij_continuation_indent_size = 4 \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/AbstractObjCExportHeaderGeneratorTest.kt b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/AbstractObjCExportHeaderGeneratorTest.kt new file mode 100644 index 00000000000..f4e58b23c43 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/AbstractObjCExportHeaderGeneratorTest.kt @@ -0,0 +1,39 @@ +/* + * 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 org.jetbrains.kotlin.backend.konan.testUtils + +import com.intellij.openapi.Disposable +import com.intellij.openapi.util.Disposer +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.junit.After +import java.io.File +import kotlin.test.fail + +abstract class AbstractObjCExportHeaderGeneratorTest( + private val generator: ObjCExportHeaderGenerator +) { + + fun interface ObjCExportHeaderGenerator { + fun generateHeaders(disposable: Disposable, root: File): String + } + + private val testRootDisposable = Disposer.newDisposable() + protected val objCExportTestDataDir = testDataDir.resolve("objcexport") + + @After + fun dispose() { + Disposer.dispose(testRootDisposable) + } + + + protected fun doTest(root: File) { + if (!root.isDirectory) fail("Expected ${root.absolutePath} to be directory") + val generatedHeaders = generator.generateHeaders(testRootDisposable, root) + KotlinTestUtils.assertEqualsToFile(root.resolve("!${root.nameWithoutExtension}.h"), generatedHeaders) + } +} + +abstract class AbstractFE10ObjCExportHeaderGeneratorTest : AbstractObjCExportHeaderGeneratorTest(Fe10ObjCExportHeaderGenerator) diff --git a/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt new file mode 100644 index 00000000000..914d2fcb9bd --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt @@ -0,0 +1,174 @@ +/* + * 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 org.jetbrains.kotlin.backend.konan.testUtils + +import com.intellij.openapi.Disposable +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer +import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory +import org.jetbrains.kotlin.backend.konan.KlibFactories +import org.jetbrains.kotlin.backend.konan.KonanConfig +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys.Companion.KONAN_HOME +import org.jetbrains.kotlin.backend.konan.UnitSuspendFunctionObjCExport +import org.jetbrains.kotlin.backend.konan.driver.BasicPhaseContext +import org.jetbrains.kotlin.backend.konan.objcexport.* +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGeneratorImpl +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportMapper +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamerImpl +import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments +import org.jetbrains.kotlin.cli.common.createFlexiblePhaseConfig +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.library.resolveSingleFileKlib +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.CommonPlatforms +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.konan.NativePlatforms +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices +import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices +import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.testFramework.MockProjectEx +import org.jetbrains.kotlin.test.util.KtTestUtil +import java.io.File + +object Fe10ObjCExportHeaderGenerator : AbstractObjCExportHeaderGeneratorTest.ObjCExportHeaderGenerator { + override fun generateHeaders(disposable: Disposable, root: File): String { + val headerGenerator = createObjCExportHeaderGenerator(disposable, root) + headerGenerator.translateModuleDeclarations() + return headerGenerator.build().joinToString(System.lineSeparator()) + } + + private fun createObjCExportHeaderGenerator(disposable: Disposable, root: File): ObjCExportHeaderGenerator { + val compilerConfiguration = createCompilerConfiguration() + + val mapper = ObjCExportMapper( + unitSuspendFunctionExport = UnitSuspendFunctionObjCExport.DEFAULT + ) + + val namer = ObjCExportNamerImpl( + mapper = mapper, + builtIns = DefaultBuiltIns.Instance, + local = false, + problemCollector = ObjCExportProblemCollector.SILENT, + configuration = object : ObjCExportNamer.Configuration { + override val topLevelNamePrefix: String get() = "" + override fun getAdditionalPrefix(module: ModuleDescriptor): String? = null + override val objcGenerics: Boolean = true + } + + ) + + val environment: KotlinCoreEnvironment = KotlinCoreEnvironment.createForTests( + parentDisposable = disposable, + initialConfiguration = compilerConfiguration, + extensionConfigs = EnvironmentConfigFiles.METADATA_CONFIG_FILES + ) + + val phaseContext = BasicPhaseContext( + KonanConfig(environment.project, compilerConfiguration) + ) + + val kotlinFiles = root.walkTopDown().filter { it.isFile }.filter { it.extension == "kt" }.toList() + + return ObjCExportHeaderGeneratorImpl( + context = phaseContext, + moduleDescriptors = listOf(getModuleDescriptor(environment, kotlinFiles)), + mapper = mapper, + namer = namer, + problemCollector = ObjCExportProblemCollector.SILENT, + objcGenerics = true + ) + } + + private fun getModuleDescriptor( + environment: KotlinCoreEnvironment, kotlinFiles: List + ): ModuleDescriptor { + val psiFactory = KtPsiFactory(environment.project) + val kotlinPsiFiles = kotlinFiles.map { file -> psiFactory.createFile(file.name, KtTestUtil.doLoadFile(file)) } + + val analysisResult = CommonResolverForModuleFactory.analyzeFiles( + files = kotlinPsiFiles, + moduleName = Name.special(""), + dependOnBuiltIns = true, + languageVersionSettings = environment.configuration.languageVersionSettings, + targetPlatform = CommonPlatforms.defaultCommonPlatform, + targetEnvironment = CompilerEnvironment, + dependenciesContainer = DependenciesContainerImpl, + ) { content -> + environment.createPackagePartProvider(content.moduleContentScope) + } + + return analysisResult.moduleDescriptor + } + + + private object DependenciesContainerImpl : CommonDependenciesContainer { + override val moduleInfos: List get() = listOf(DefaultBuiltInsModuleInfo, KotlinNativeStdlibModuleInfo) + override val friendModuleInfos: List get() = emptyList() + override val refinesModuleInfos: List get() = emptyList() + override fun registerDependencyForAllModules(moduleInfo: ModuleInfo, descriptorForModule: ModuleDescriptorImpl) = Unit + override fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider? = null + + private val stdlibModuleDescriptor = KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptor( + library = resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File("$konanHomePath/klib/common/stdlib")), + languageVersionSettings = createLanguageVersionSettings(), + builtIns = DefaultBuiltIns.Instance, + storageManager = LockBasedStorageManager.NO_LOCKS, + packageAccessHandler = null + ).also { it.setDependencies(it) } + + override fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor { + if (moduleInfo == DefaultBuiltInsModuleInfo) return DefaultBuiltIns.Instance.builtInsModule + if (moduleInfo == KotlinNativeStdlibModuleInfo) return stdlibModuleDescriptor + error("Unknown module info $moduleInfo") + } + } + + private object DefaultBuiltInsModuleInfo : ModuleInfo { + override val name get() = DefaultBuiltIns.Instance.builtInsModule.name + override fun dependencies() = listOf(this) + override fun dependencyOnBuiltIns() = ModuleInfo.DependencyOnBuiltIns.LAST + override val platform get() = NativePlatforms.unspecifiedNativePlatform + override val analyzerServices get() = NativePlatformAnalyzerServices + } + + private object KotlinNativeStdlibModuleInfo : ModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = NativePlatformAnalyzerServices + override val name: Name = Name.special("") + override val platform: TargetPlatform = NativePlatforms.unspecifiedNativePlatform + override fun dependencies(): List = listOf(this) + } + + private fun createCompilerConfiguration(): CompilerConfiguration { + val configuration = KotlinTestUtils.newConfiguration() + configuration.put(KONAN_HOME, konanHomePath) + configuration.put(CLIConfigurationKeys.FLEXIBLE_PHASE_CONFIG, createFlexiblePhaseConfig(K2NativeCompilerArguments())) + configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, createLanguageVersionSettings()) + configuration.put(KonanConfigKeys.PRODUCE, CompilerOutputKind.FRAMEWORK) + configuration.put(KonanConfigKeys.AUTO_CACHEABLE_FROM, emptyList()) + configuration.put(KonanConfigKeys.CACHE_DIRECTORIES, emptyList()) + configuration.put(KonanConfigKeys.CACHED_LIBRARIES, emptyMap()) + configuration.put(KonanConfigKeys.FRAMEWORK_IMPORT_HEADERS, emptyList()) + configuration.put(KonanConfigKeys.EXPORT_KDOC, true) + return configuration + } + + private fun createLanguageVersionSettings() = LanguageVersionSettingsImpl( + languageVersion = LanguageVersion.LATEST_STABLE, + apiVersion = ApiVersion.LATEST_STABLE + ) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt new file mode 100644 index 00000000000..029bda5237e --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt @@ -0,0 +1,11 @@ +/* + * 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 org.jetbrains.kotlin.backend.konan.testUtils + +private const val konanHomePropertyKey = "org.jetbrains.kotlin.native.home" + +val konanHomePath: String + get() = System.getProperty(konanHomePropertyKey) ?: error("Missing System property: '$konanHomePropertyKey'") \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt new file mode 100644 index 00000000000..f6b38aa19f4 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt @@ -0,0 +1,11 @@ +/* + * 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 org.jetbrains.kotlin.backend.konan.testUtils + +import java.io.File + +val projectDir = File("kotlin-native/backend.native") +val testDataDir = projectDir.resolve("functionalTest/testData") \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/tests/Fe10ObjCExportHeaderGeneratorTest.kt b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/tests/Fe10ObjCExportHeaderGeneratorTest.kt new file mode 100644 index 00000000000..ef672c9a069 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/src/org/jetbrains/kotlin/backend/konan/tests/Fe10ObjCExportHeaderGeneratorTest.kt @@ -0,0 +1,105 @@ +/* + * 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 org.jetbrains.kotlin.backend.konan.tests + +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator +import org.jetbrains.kotlin.backend.konan.testUtils.AbstractFE10ObjCExportHeaderGeneratorTest +import org.junit.Test + +/** + * ## Test Scope + * This test will cover the generation of 'objc' headers. + * The corresponding class in would be [ObjCExportHeaderGenerator]. + * + * The input of the test are Kotlin source files; + * The output is the generated header files; + * The output will be compared to already checked in golden files. + * + * ## How to create a new test + * Every test has a corresponding 'root' directory. + * All directories are found in `backend.native/functionalTest/testData/objcexport`. + * + * 1) Create new root directory (e.g. myTest) in testData/objcexport + * 2) Place kotlin files into the directory e.g. testData/objcexport/myTest/Foo.kt + * 3) Create a test function and call ` doTest(objCExportTestDataDir.resolve("myTest"))` + * 4) The first invocation will fail the test, but generates the header that can be checked in (if sufficient) + */ +class Fe10ObjCExportHeaderGeneratorTest : AbstractFE10ObjCExportHeaderGeneratorTest() { + @Test + fun `test - simpleClass`() { + doTest(objCExportTestDataDir.resolve("simpleClass")) + } + + @Test + fun `test - simpleInterface`() { + doTest(objCExportTestDataDir.resolve("simpleInterface")) + } + + @Test + fun `test - simpleEnumClass`() { + doTest(objCExportTestDataDir.resolve("simpleEnumClass")) + } + + @Test + fun `test - simpleObject`() { + doTest(objCExportTestDataDir.resolve("simpleObject")) + } + + @Test + fun `test - topLevelFunction`() { + doTest(objCExportTestDataDir.resolve("topLevelFunction")) + } + + @Test + fun `test - topLevelProperty`() { + doTest(objCExportTestDataDir.resolve("topLevelProperty")) + } + + @Test + fun `test - sameClassNameInDifferentPackage`() { + doTest(objCExportTestDataDir.resolve("sameClassNameInDifferentPackage")) + } + + @Test + fun `test - samePropertyAndFunctionName`() { + doTest(objCExportTestDataDir.resolve("samePropertyAndFunctionName")) + } + + @Test + fun `test - classImplementingInterface`() { + doTest(objCExportTestDataDir.resolve("classImplementingInterface")) + } + + @Test + fun `test - interfaceImplementingInterface`() { + doTest(objCExportTestDataDir.resolve("interfaceImplementingInterface")) + } + + @Test + fun `test - classWithObjCNameAnnotation`() { + doTest(objCExportTestDataDir.resolve("classWithObjCNameAnnotation")) + } + + @Test + fun `test - functionWithObjCNameAnnotation`() { + doTest(objCExportTestDataDir.resolve("functionWithObjCNameAnnotation")) + } + + @Test + fun `test - classWithKDoc`() { + doTest(objCExportTestDataDir.resolve("classWithKDoc")) + } + + @Test + fun `test - classWithHidesFromObjCAnnotation`() { + doTest(objCExportTestDataDir.resolve("classWithHidesFromObjCAnnotation")) + } + + @Test + fun `test - functionWithThrowsAnnotation`() { + doTest(objCExportTestDataDir.resolve("functionWithThrowsAnnotation")) + } +} diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classImplementingInterface/!classImplementingInterface.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/classImplementingInterface/!classImplementingInterface.h new file mode 100644 index 00000000000..ba5bc4a02b5 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classImplementingInterface/!classImplementingInterface.h @@ -0,0 +1,41 @@ +#import +#import +#import +#import +#import +#import +#import + +@protocol Foo; + +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 + +@protocol Foo +@required +- (id)someMethod __attribute__((swift_name("someMethod()"))); +- (id)someMethodWithCovariantOverwrite __attribute__((swift_name("someMethodWithCovariantOverwrite()"))); +@property (readonly) int32_t someProperty __attribute__((swift_name("someProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface Bar : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (id)someMethod __attribute__((swift_name("someMethod()"))); +- (NSString *)someMethodWithCovariantOverwrite __attribute__((swift_name("someMethodWithCovariantOverwrite()"))); +@property (readonly) int32_t someProperty __attribute__((swift_name("someProperty"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classImplementingInterface/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/classImplementingInterface/Foo.kt new file mode 100644 index 00000000000..b7563d72447 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classImplementingInterface/Foo.kt @@ -0,0 +1,11 @@ +interface Foo { + val someProperty: Int + fun someMethod(): Any + fun someMethodWithCovariantOverwrite(): Any +} + +class Bar : Foo { + override val someProperty: Int = 42 + override fun someMethod(): Any = "" + override fun someMethodWithCovariantOverwrite(): String = "" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h new file mode 100644 index 00000000000..b0dc331818f --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h @@ -0,0 +1,29 @@ +#import +#import +#import +#import +#import +#import +#import + +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 NotHidden : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithHidesFromObjCAnnotation/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithHidesFromObjCAnnotation/Foo.kt new file mode 100644 index 00000000000..051a8f61636 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithHidesFromObjCAnnotation/Foo.kt @@ -0,0 +1,14 @@ +import kotlin.experimental.ExperimentalObjCRefinement + +@ExperimentalObjCRefinement +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@kotlin.native.HidesFromObjC +annotation class MyHiddenFromObjC + +@OptIn(ExperimentalObjCRefinement::class) +@MyHiddenFromObjC +class Hidden + +class NotHidden \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithKDoc/!classWithKDoc.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithKDoc/!classWithKDoc.h new file mode 100644 index 00000000000..4b9a18e5fdb --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithKDoc/!classWithKDoc.h @@ -0,0 +1,52 @@ +#import +#import +#import +#import +#import +#import +#import + +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 + + +/** + * This class [Foo] is documented. + */ +__attribute__((objc_subclassing_restricted)) +@interface Foo : Base + +/** + * This class [Foo] is documented. + */ +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + +/** + * This class [Foo] is documented. + */ ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + * This member function is documented + */ +- (void)someMemberFunction __attribute__((swift_name("someMemberFunction()"))); + +/** + * This member property is documented. + * It will return the 'The Answer to the Ultimate Question of Life, The Universe, and Everything' + */ +@property (readonly) int32_t someMemberProperty __attribute__((swift_name("someMemberProperty"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithKDoc/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithKDoc/Foo.kt new file mode 100644 index 00000000000..3bc4db1fce3 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithKDoc/Foo.kt @@ -0,0 +1,17 @@ +/** + * This class [Foo] is documented. + */ +class Foo { + /** + * This member function is documented + */ + fun someMemberFunction() { + + } + + /** + * This member property is documented. + * It will return the 'The Answer to the Ultimate Question of Life, The Universe, and Everything' + */ + val someMemberProperty = 42 +} diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h new file mode 100644 index 00000000000..bba9b1ce229 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h @@ -0,0 +1,30 @@ +#import +#import +#import +#import +#import +#import +#import + +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)) +__attribute__((swift_name("FooInSwift"))) +@interface FooInObjC : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithObjCNameAnnotation/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithObjCNameAnnotation/Foo.kt new file mode 100644 index 00000000000..715bb97bf86 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/classWithObjCNameAnnotation/Foo.kt @@ -0,0 +1,5 @@ +import kotlin.experimental.ExperimentalObjCName + +@OptIn(ExperimentalObjCName::class) +@kotlin.native.ObjCName("FooInObjC", "FooInSwift") +class Foo \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h new file mode 100644 index 00000000000..56647230711 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h @@ -0,0 +1,35 @@ +#import +#import +#import +#import +#import +#import +#import + +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 Foo : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)objcMemberFunction __attribute__((swift_name("swiftMemberFunction()"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface FooKt : Base ++ (NSString *)objcTopLevelFunction __attribute__((swift_name("swiftTopLevelFunction()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithObjCNameAnnotation/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithObjCNameAnnotation/Foo.kt new file mode 100644 index 00000000000..443c3d48afa --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithObjCNameAnnotation/Foo.kt @@ -0,0 +1,11 @@ +@file:OptIn(ExperimentalObjCName::class) + +import kotlin.experimental.ExperimentalObjCName + +@kotlin.native.ObjCName("objcTopLevelFunction", "swiftTopLevelFunction") +fun someTopLevelFunction() = "" + +class Foo { + @kotlin.native.ObjCName("objcMemberFunction", "swiftMemberFunction") + fun someMemberFunction() = Unit +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h new file mode 100644 index 00000000000..e44d1f7288b --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h @@ -0,0 +1,65 @@ +#import +#import +#import +#import +#import +#import +#import + +@class Throwable; + +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 + +@interface Throwable : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)initWithCause:(Throwable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)initWithMessage:(NSString * _Nullable)message cause:(Throwable * _Nullable)cause __attribute__((swift_name("init(message:cause:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) Throwable * _Nullable cause __attribute__((swift_name("cause"))); +@property (readonly) NSString * _Nullable message __attribute__((swift_name("message"))); +- (NSError *)asError __attribute__((swift_name("asError()"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface MyError : Throwable +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithCause:(Throwable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithMessage:(NSString * _Nullable)message cause:(Throwable * _Nullable)cause __attribute__((swift_name("init(message:cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end + +__attribute__((objc_subclassing_restricted)) +@interface FooKt : Base + +/** + * @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)barAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("bar()"))); + +/** + * @note This method converts instances of MyError to errors. + * Other uncaught Kotlin exceptions are fatal. +*/ ++ (BOOL)fooAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo()"))); + +/** + * @note This method converts all Kotlin exceptions to errors. +*/ ++ (NSString * _Nullable)someStringAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("someString()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithThrowsAnnotation/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithThrowsAnnotation/Foo.kt new file mode 100644 index 00000000000..6d17bf7bde9 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/functionWithThrowsAnnotation/Foo.kt @@ -0,0 +1,10 @@ +class MyError : Throwable() + +@Throws(MyError::class) +fun foo() = Unit + +@Throws(Throwable::class) +fun bar() = Unit + +@Throws(Throwable::class) +fun someString() = "" \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/interfaceImplementingInterface/!interfaceImplementingInterface.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/interfaceImplementingInterface/!interfaceImplementingInterface.h new file mode 100644 index 00000000000..8de552264c0 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/interfaceImplementingInterface/!interfaceImplementingInterface.h @@ -0,0 +1,36 @@ +#import +#import +#import +#import +#import +#import +#import + +@protocol Foo; + +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 + +@protocol Foo +@required +- (id)someMethod __attribute__((swift_name("someMethod()"))); +- (id)someMethodWithCovariantOverwrite __attribute__((swift_name("someMethodWithCovariantOverwrite()"))); +@property (readonly) int32_t someProperty __attribute__((swift_name("someProperty"))); +@end + +@protocol Bar +@required +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/interfaceImplementingInterface/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/interfaceImplementingInterface/Foo.kt new file mode 100644 index 00000000000..84cde0163bb --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/interfaceImplementingInterface/Foo.kt @@ -0,0 +1,9 @@ +interface Foo { + val someProperty: Int + fun someMethod(): Any + fun someMethodWithCovariantOverwrite(): Any +} + +interface Bar : Foo { + override fun someMethodWithCovariantOverwrite(): String = "" +} diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h new file mode 100644 index 00000000000..78d0f7fa007 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h @@ -0,0 +1,37 @@ +#import +#import +#import +#import +#import +#import +#import + +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 Foo : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)someMethodInFooA __attribute__((swift_name("someMethodInFooA()"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface Foo_ : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)someMethodInFooB __attribute__((swift_name("someMethodInFooB()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/a/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/a/Foo.kt new file mode 100644 index 00000000000..505991b083e --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/a/Foo.kt @@ -0,0 +1,5 @@ +package a + +class Foo { + fun someMethodInFooA() = "" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/b/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/b/Foo.kt new file mode 100644 index 00000000000..7d9a76fd431 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/sameClassNameInDifferentPackage/b/Foo.kt @@ -0,0 +1,5 @@ +package b + +class Foo { + fun someMethodInFooB() = "" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/samePropertyAndFunctionName/!samePropertyAndFunctionName.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/samePropertyAndFunctionName/!samePropertyAndFunctionName.h new file mode 100644 index 00000000000..ab675f8c32c --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/samePropertyAndFunctionName/!samePropertyAndFunctionName.h @@ -0,0 +1,29 @@ +#import +#import +#import +#import +#import +#import +#import + +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 ++ (NSString *)foo __attribute__((swift_name("foo()"))); +@property (class, readonly, getter=foo_) int32_t foo __attribute__((swift_name("foo"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/samePropertyAndFunctionName/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/samePropertyAndFunctionName/Foo.kt new file mode 100644 index 00000000000..4996dea0b0d --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/samePropertyAndFunctionName/Foo.kt @@ -0,0 +1,2 @@ +fun foo() = "" +val foo = 42 \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleClass/!simpleClass.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleClass/!simpleClass.h new file mode 100644 index 00000000000..db8954d9793 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleClass/!simpleClass.h @@ -0,0 +1,31 @@ +#import +#import +#import +#import +#import +#import +#import + +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 Foo : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)someMethod __attribute__((swift_name("someMethod()"))); +@property (readonly) int32_t someProperty __attribute__((swift_name("someProperty"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleClass/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleClass/Foo.kt new file mode 100644 index 00000000000..e9f0d76c448 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleClass/Foo.kt @@ -0,0 +1,4 @@ +class Foo { + val someProperty: Int = 42 + fun someMethod(): String = "" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleEnumClass/!simpleEnumClass.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleEnumClass/!simpleEnumClass.h new file mode 100644 index 00000000000..b8fa28ee217 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleEnumClass/!simpleEnumClass.h @@ -0,0 +1,85 @@ +#import +#import +#import +#import +#import +#import +#import + +@class EnumCompanion, Enum, Foo, Array; + +@protocol Comparable, 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 + +@protocol Comparable +@required +- (int32_t)compareToOther:(id _Nullable)other __attribute__((swift_name("compareTo(other:)"))); +@end + +@interface Enum : Base +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)); +@property (class, readonly, getter=companion) EnumCompanion *companion __attribute__((swift_name("companion"))); + +/** + * @note This method has protected visibility in Kotlin source and is intended only for use by subclasses. +*/ +- (id)clone __attribute__((swift_name("clone()"))); +- (int32_t)compareToOther:(E)other __attribute__((swift_name("compareTo(other:)"))); +- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)"))); +- (NSUInteger)hash __attribute__((swift_name("hash()"))); +- (NSString *)description __attribute__((swift_name("description()"))); +@property (readonly) NSString *name __attribute__((swift_name("name"))); +@property (readonly) int32_t ordinal __attribute__((swift_name("ordinal"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface Foo : Enum ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@property (class, readonly) Foo *a __attribute__((swift_name("a"))); +@property (class, readonly) Foo *b __attribute__((swift_name("b"))); +@property (class, readonly) Foo *c __attribute__((swift_name("c"))); ++ (Array *)values __attribute__((swift_name("values()"))); +@property (class, readonly) NSArray *entries __attribute__((swift_name("entries"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface EnumCompanion : Base ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) EnumCompanion *shared __attribute__((swift_name("shared"))); +@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/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleEnumClass/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleEnumClass/Foo.kt new file mode 100644 index 00000000000..6ee7cfa3e56 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleEnumClass/Foo.kt @@ -0,0 +1,3 @@ +enum class Foo { + A, B, C +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleInterface/!simpleInterface.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleInterface/!simpleInterface.h new file mode 100644 index 00000000000..38924fbfcb3 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleInterface/!simpleInterface.h @@ -0,0 +1,29 @@ +#import +#import +#import +#import +#import +#import +#import + +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 + +@protocol Foo +@required +- (NSString *)someMethod __attribute__((swift_name("someMethod()"))); +@property (readonly) int32_t someProperty __attribute__((swift_name("someProperty"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleInterface/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleInterface/Foo.kt new file mode 100644 index 00000000000..c4b91590033 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleInterface/Foo.kt @@ -0,0 +1,4 @@ +interface Foo { + val someProperty: Int + fun someMethod(): String +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleObject/!simpleObject.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleObject/!simpleObject.h new file mode 100644 index 00000000000..0ecdc6aae65 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleObject/!simpleObject.h @@ -0,0 +1,35 @@ +#import +#import +#import +#import +#import +#import +#import + +@class Foo; + +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 Foo : Base ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)foo __attribute__((swift_name("init()"))); +@property (class, readonly, getter=shared) Foo *shared __attribute__((swift_name("shared"))); +- (NSString *)someMethod __attribute__((swift_name("someMethod()"))); +@property (readonly) int32_t someProperty __attribute__((swift_name("someProperty"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleObject/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleObject/Foo.kt new file mode 100644 index 00000000000..07c3dbcbc11 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/simpleObject/Foo.kt @@ -0,0 +1,4 @@ +object Foo { + val someProperty = 42 + fun someMethod() = "" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelFunction/!topLevelFunction.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelFunction/!topLevelFunction.h new file mode 100644 index 00000000000..226c5760f28 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelFunction/!topLevelFunction.h @@ -0,0 +1,28 @@ +#import +#import +#import +#import +#import +#import +#import + +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 ++ (NSString *)myTopLevelFunction __attribute__((swift_name("myTopLevelFunction()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelFunction/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelFunction/Foo.kt new file mode 100644 index 00000000000..a6fae9204f7 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelFunction/Foo.kt @@ -0,0 +1 @@ +fun myTopLevelFunction() = "" \ No newline at end of file diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelProperty/!topLevelProperty.h b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelProperty/!topLevelProperty.h new file mode 100644 index 00000000000..8f24aba293c --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelProperty/!topLevelProperty.h @@ -0,0 +1,28 @@ +#import +#import +#import +#import +#import +#import +#import + +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 +@property (class, readonly) int32_t myTopLevelProperty __attribute__((swift_name("myTopLevelProperty"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelProperty/Foo.kt b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelProperty/Foo.kt new file mode 100644 index 00000000000..379c7107671 --- /dev/null +++ b/kotlin-native/backend.native/functionalTest/testData/objcexport/topLevelProperty/Foo.kt @@ -0,0 +1 @@ +val myTopLevelProperty = 42 \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index fcf349789ee..efa4a82cf29 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -192,6 +192,7 @@ tasks.named("run") { dependsOn(":kotlin-native:Interop:Indexer:check") dependsOn(":kotlin-native:Interop:StubGenerator:check") dependsOn(":native:kotlin-native-utils:check") + dependsOn(":kotlin-native:backend.native:check") } // Was a subset of tests. diff --git a/kotlin-native/backend.native/tests/objcexport/simpleClass.kt b/kotlin-native/backend.native/tests/objcexport/simpleClass.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt b/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt index c61bcb6e5c5..6f4e6e45d71 100644 --- a/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt +++ b/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt @@ -103,6 +103,11 @@ enum class JUnitMode { JUnit4, JUnit5 } +/** + * Convenience function to expose Project.projectTest for groovy + */ +fun projectTest(project: Project) = project.projectTest() + /** * @param parallel is redundant if @param jUnit5Enabled is true, because * JUnit5 supports parallel test execution by itself, without gradle help