From 078f0ff6e1178be260e6625890fd6984f8122d7c Mon Sep 17 00:00:00 2001 From: "eugene.levenetc" Date: Thu, 22 Feb 2024 15:28:22 +0100 Subject: [PATCH] [ObjCType] Add basic implementation of base method, fix tests KT-65687 --- .../analysisApiUtils/isVisibleInObjC.kt | 2 + .../jetbrains/kotlin/objcexport/baseMethod.kt | 22 +++ .../objcexport/translateToObjCHeader.kt | 4 +- .../objcexport/translateToObjCMethod.kt | 15 +- .../objcexport/translateToObjCProtocol.kt | 1 + .../objcexport/tests/IsVisibleInObjCTest.kt | 134 ++++++++++++++++++ .../konan/tests/ObjCDependenciesTypesTest.kt | 4 - .../tests/ObjCExportHeaderGeneratorTest.kt | 32 ++++- .../!multipleInheritance.h | 82 +++++++++++ .../headers/multipleInheritance/Foo.kt | 33 +++++ .../!privateGenericSuperInterface.h | 30 ++++ .../privateGenericSuperInterface/Foo.kt | 7 + .../!privateSuperInterface.h | 30 ++++ .../headers/privateSuperInterface/Foo.kt | 7 + ...ivateSuperInterfaceWithCovariantOverride.h | 30 ++++ .../Foo.kt | 7 + .../!superClassWithCovariantOverride.h | 38 +++++ .../superClassWithCovariantOverride/Foo.kt | 7 + 18 files changed, 471 insertions(+), 14 deletions(-) create mode 100644 native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/baseMethod.kt create mode 100644 native/objcexport-header-generator/testData/headers/multipleInheritance/!multipleInheritance.h create mode 100644 native/objcexport-header-generator/testData/headers/multipleInheritance/Foo.kt create mode 100644 native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/!privateGenericSuperInterface.h create mode 100644 native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/Foo.kt create mode 100644 native/objcexport-header-generator/testData/headers/privateSuperInterface/!privateSuperInterface.h create mode 100644 native/objcexport-header-generator/testData/headers/privateSuperInterface/Foo.kt create mode 100644 native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/!privateSuperInterfaceWithCovariantOverride.h create mode 100644 native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/Foo.kt create mode 100644 native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/!superClassWithCovariantOverride.h create mode 100644 native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/Foo.kt diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/isVisibleInObjC.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/isVisibleInObjC.kt index 6f3b63affd3..1ccc2c84c8e 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/isVisibleInObjC.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/isVisibleInObjC.kt @@ -36,6 +36,7 @@ internal fun KtCallableSymbol.isVisibleInObjC(): Boolean { if (this.isHiddenFromObjCByAnnotation()) return false if (this.isSealedClassConstructor()) return false if (this.isComponentNMethod() && this.getDirectlyOverriddenSymbols().isEmpty()) return false + getContainingSymbol()?.let { if (!it.isVisibleInObjC()) return false } return true } @@ -50,6 +51,7 @@ internal fun KtClassOrObjectSymbol.isVisibleInObjC(): Boolean { if (!this.classKind.isVisibleInObjC()) return false if (this.isExpect) return false if (this.isInlined()) return false + getContainingSymbol()?.let { if (!it.isVisibleInObjC()) return false } return true } diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/baseMethod.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/baseMethod.kt new file mode 100644 index 00000000000..4d96699f22a --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/baseMethod.kt @@ -0,0 +1,22 @@ +package org.jetbrains.kotlin.objcexport + +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC + +/** + * Very basic implementation + * + * It covers edge case: if something isn't visible in inheritance chain it should be skipped + * See [org.jetbrains.kotlin.objcexport.tests.IsContainingSymbolVisible] + * See also K1: + * - [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportMapperKt.getBaseMethods] + * - [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportMapperKt.isBaseMethod] + */ +context(KtAnalysisSession) +internal val KtFunctionSymbol.baseMethod: KtFunctionSymbol + get() { + val overriddenSymbols = getAllOverriddenSymbols().filter { symbol -> symbol.isVisibleInObjC() } + return if (overriddenSymbols.isEmpty()) this + else overriddenSymbols.last() as KtFunctionSymbol + } diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt index b8bd278b375..eb72e706e38 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCHeader.kt @@ -143,7 +143,9 @@ private class KtObjCExportHeaderGenerator { 2) Super interface / superclass symbol export stubs (result of translation) have to be present in the stubs list before the original stub */ - symbol.getDeclaredSuperInterfaceSymbols().forEach { superInterfaceSymbol -> + symbol.getDeclaredSuperInterfaceSymbols() + .filter { it.isVisibleInObjC() } + .forEach { superInterfaceSymbol -> translateClassOrObjectSymbol(superInterfaceSymbol)?.let { objCProtocolForwardDeclarations += it.name } diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt index c53981c3bfd..eb290edefc8 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCMethod.kt @@ -32,7 +32,17 @@ context(KtAnalysisSession, KtObjCExportSession) internal fun KtFunctionLikeSymbol.buildObjCMethod( unavailable: Boolean = false, ): ObjCMethod { - val bridge = getFunctionMethodBridge() + + val bridge = if (this is KtFunctionSymbol) { + /** + * Unlike constructor, a function can have base return type. + * So in case of function we need to call [getFunctionMethodBridge] on [baseMethod] + */ + baseMethod.getFunctionMethodBridge() + } else { + this.getFunctionMethodBridge() + } + val returnType: ObjCType = mapReturnType(bridge.returnBridge) val parameters = translateToObjCParameters(bridge) val selector = getSelector(bridge) @@ -75,7 +85,6 @@ internal fun KtFunctionLikeSymbol.buildObjCMethod( ) } - /** * [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamerKt.toValidObjCSwiftIdentifier] */ @@ -295,4 +304,4 @@ fun KtFunctionLikeSymbol.mapReturnType(returnBridge: MethodBridge.ReturnValue): MethodBridge.ReturnValue.Instance.FactoryResult, -> ObjCInstanceType } -} +} \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCProtocol.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCProtocol.kt index 1e077fa8697..849b5305e53 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCProtocol.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/translateToObjCProtocol.kt @@ -44,6 +44,7 @@ fun KtClassOrObjectSymbol.translateToObjCProtocol(): ObjCProtocol? { context(KtAnalysisSession, KtObjCExportSession) internal fun KtClassOrObjectSymbol.superProtocols(): List { return getDeclaredSuperInterfaceSymbols() + .filter { it.isVisibleInObjC() } .map { superInterface -> superInterface.getObjCClassOrProtocolName().objCName } .toList() } \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/IsVisibleInObjCTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/IsVisibleInObjCTest.kt index 71e8fecaf22..949c9aba156 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/IsVisibleInObjCTest.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/IsVisibleInObjCTest.kt @@ -181,4 +181,138 @@ class IsVisibleInObjCTest( assertFalse(fooSymbol.isVisibleInObjC()) } } + + @Test + fun `test - containing symbol visible`() { + val file = inlineSourceCodeAnalysis.createKtFile( + """ + class PublicClass { + fun foo() + } + """.trimIndent() + ) + + analyze(file) { + assertTrue(file.getClassOrFail("PublicClass").getFunctionOrFail("foo").isVisibleInObjC()) + } + } + + @Test + fun `test - invisible symbol inside private class`() { + val file = inlineSourceCodeAnalysis.createKtFile( + """ + private class PrivateClass { + fun foo() + } + """.trimIndent() + ) + + analyze(file) { + assertFalse(file.getClassOrFail("PrivateClass").getFunctionOrFail("foo").isVisibleInObjC()) + } + } + + @Test + fun `test - nested visible function`() { + val file = inlineSourceCodeAnalysis.createKtFile( + """ + class PublicA { + class PublicB { + class PublicC { + fun foo() {} + } + } + } + """.trimIndent() + ) + + analyze(file) { + val foo = file + .getClassOrFail("PublicA").getMemberScope() + .getClassOrFail("PublicB").getMemberScope() + .getClassOrFail("PublicC") + .getFunctionOrFail("foo") + assertTrue(foo.isVisibleInObjC()) + } + } + + @Test + fun `test - nested invisible function`() { + val file = inlineSourceCodeAnalysis.createKtFile( + """ + class PublicA { + private class PrivateB { + class PublicC { + fun foo() {} + } + } + } + """.trimIndent() + ) + + analyze(file) { + val foo = file + .getClassOrFail("PublicA").getMemberScope() + .getClassOrFail("PrivateB").getMemberScope() + .getClassOrFail("PublicC") + .getFunctionOrFail("foo") + assertFalse(foo.isVisibleInObjC()) + } + } + + @Test + fun `test - invisible symbol inside public class marked with @HidesFromObjC`() { + val file = inlineSourceCodeAnalysis.createKtFile( + """ + @kotlin.native.HidesFromObjC + annotation class HideIt + + @HideIt + class PublicClass { + fun foo() + } + """.trimIndent() + ) + + analyze(file) { + assertFalse(file.getClassOrFail("PublicClass").getFunctionOrFail("foo").isVisibleInObjC()) + } + } + + @Test + fun `test - invisible member inside nested class marked with @HidesFromObjC`() { + val file = inlineSourceCodeAnalysis.createKtFile( + """ + @kotlin.native.HidesFromObjC + annotation class HideIt + + + class PublicA { + fun publicA() = Unit + + @HideIt + class HiddenB { + fun hiddenB() = Unit + + class HiddenC { + fun hiddenC() = Unit + } + } + } + """.trimIndent() + ) + + analyze(file) { + val publicA = file.getClassOrFail("PublicA") + val hiddenB = publicA.getMemberScope().getClassOrFail("HiddenB") + val hiddenC = hiddenB.getMemberScope().getClassOrFail("HiddenC") + + assertFalse(hiddenB.isVisibleInObjC()) + assertFalse(hiddenC.isVisibleInObjC()) + + assertTrue(publicA.getFunctionOrFail("publicA").isVisibleInObjC()) + assertFalse(hiddenB.getFunctionOrFail("hiddenB").isVisibleInObjC()) + assertFalse(hiddenC.getFunctionOrFail("hiddenC").isVisibleInObjC()) + } + } } \ No newline at end of file diff --git a/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCDependenciesTypesTest.kt b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCDependenciesTypesTest.kt index 0edad274d1a..c12899d1a6f 100644 --- a/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCDependenciesTypesTest.kt +++ b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCDependenciesTypesTest.kt @@ -49,11 +49,7 @@ class ObjCDependenciesTypesTest( doTest(dependenciesDir.resolve("arrayList")) } - /** - * Int* type conversion issue: KT-65687 - */ @Test - @TodoAnalysisApi fun `test - implementIterator`() { doTest(dependenciesDir.resolve("implementIterator")) } 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 48c0247b3db..ac5ecacdee5 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 @@ -222,12 +222,7 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) { doTest(headersTestDataDir.resolve("classReferencingOtherClassAsReturnType")) } - /** - * - IntIterator has unwanted 'hasNext' exposed - * - IntIterator's next method returns int32_t instead of expected Int * - */ @Test - @TodoAnalysisApi fun `test - classReferencingDependencyClassAsReturnType`() { doTest(headersTestDataDir.resolve("classReferencingDependencyClassAsReturnType")) } @@ -321,9 +316,34 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) { doTest(headersTestDataDir.resolve("memberFunctionSignatureOrder")) } + @Test + fun `test - multiple inheritance`() { + doTest(headersTestDataDir.resolve("multipleInheritance")) + } + + @Test + fun `test - private super interface`() { + doTest(headersTestDataDir.resolve("privateSuperInterface")) + } + + @Test + fun `test- privateSuperInterfaceWithCovariantOverride`() { + doTest(headersTestDataDir.resolve("privateSuperInterfaceWithCovariantOverride")) + } + + @Test + fun `test - superClassWithCovariantOverride`() { + doTest(headersTestDataDir.resolve("superClassWithCovariantOverride")) + } + + @Test + fun `test - privateGenericSuperInterface`() { + doTest(headersTestDataDir.resolve("privateGenericSuperInterface")) + } + 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() KotlinTestUtils.assertEqualsToFile(root.resolve("!${root.nameWithoutExtension}.h"), generatedHeaders) } -} +} \ No newline at end of file diff --git a/native/objcexport-header-generator/testData/headers/multipleInheritance/!multipleInheritance.h b/native/objcexport-header-generator/testData/headers/multipleInheritance/!multipleInheritance.h new file mode 100644 index 00000000000..69fd47cc048 --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/multipleInheritance/!multipleInheritance.h @@ -0,0 +1,82 @@ +#import +#import +#import +#import +#import +#import +#import + +@class A, B; + +@protocol RootA, RootB; + +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 + + +/** + * inheritance chain: A > B > C + */ +@interface A : Base + +/** + * inheritance chain: A > B > C + */ +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + +/** + * inheritance chain: A > B > C + */ ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (T _Nullable)foo __attribute__((swift_name("foo()"))); +@end + +@interface B : A +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (Int *)foo __attribute__((swift_name("foo()"))); +@end + +@interface C : B +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (Int *)foo __attribute__((swift_name("foo()"))); +@end + + +/** + * inheritance tree: + * RootA RootB + * \ / + * Tree + */ +@protocol RootA +@required +- (id _Nullable)fooA __attribute__((swift_name("fooA()"))); +@end + +@protocol RootB +@required +- (id _Nullable)fooB __attribute__((swift_name("fooB()"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface Tree : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (Int *)fooA __attribute__((swift_name("fooA()"))); +- (NSString *)fooB __attribute__((swift_name("fooB()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/native/objcexport-header-generator/testData/headers/multipleInheritance/Foo.kt b/native/objcexport-header-generator/testData/headers/multipleInheritance/Foo.kt new file mode 100644 index 00000000000..20a73e6e7ae --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/multipleInheritance/Foo.kt @@ -0,0 +1,33 @@ +/** + * inheritance chain: A > B > C + */ +abstract class A { + abstract fun foo(): T +} + +open class B : A() { + override fun foo(): Int = 42 +} + +open class C : B() { + override fun foo(): Int = 42 +} + +/** + * inheritance tree: + * RootA RootB + * \ / + * Tree + */ +interface RootA { + fun fooA(): T +} + +interface RootB { + fun fooB(): T +} + +class Tree : RootA, RootB { + override fun fooA(): Int = 42 + override fun fooB(): String = "42" +} \ No newline at end of file diff --git a/native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/!privateGenericSuperInterface.h b/native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/!privateGenericSuperInterface.h new file mode 100644 index 00000000000..d68c01ef40e --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/!privateGenericSuperInterface.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)) +@interface PublicClass : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)foo __attribute__((swift_name("foo()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/Foo.kt b/native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/Foo.kt new file mode 100644 index 00000000000..37715c820f9 --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/privateGenericSuperInterface/Foo.kt @@ -0,0 +1,7 @@ +private interface PrivateInterface { + fun foo(): T +} + +class PublicClass : PrivateInterface { + override fun foo(): Int = error("stub") +} \ No newline at end of file diff --git a/native/objcexport-header-generator/testData/headers/privateSuperInterface/!privateSuperInterface.h b/native/objcexport-header-generator/testData/headers/privateSuperInterface/!privateSuperInterface.h new file mode 100644 index 00000000000..b94e85ddd9c --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/privateSuperInterface/!privateSuperInterface.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)) +@interface PublicB : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)foo __attribute__((swift_name("foo()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/native/objcexport-header-generator/testData/headers/privateSuperInterface/Foo.kt b/native/objcexport-header-generator/testData/headers/privateSuperInterface/Foo.kt new file mode 100644 index 00000000000..1f53533f176 --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/privateSuperInterface/Foo.kt @@ -0,0 +1,7 @@ +private interface PrivateA { + fun foo() +} + +class PublicB : PrivateA { + override fun foo() = Unit +} \ No newline at end of file diff --git a/native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/!privateSuperInterfaceWithCovariantOverride.h b/native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/!privateSuperInterfaceWithCovariantOverride.h new file mode 100644 index 00000000000..b3798fa5991 --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/!privateSuperInterfaceWithCovariantOverride.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)) +@interface PublicB : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)foo __attribute__((swift_name("foo()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/Foo.kt b/native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/Foo.kt new file mode 100644 index 00000000000..ce1f1ce8237 --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/privateSuperInterfaceWithCovariantOverride/Foo.kt @@ -0,0 +1,7 @@ +private interface PrivateA { + fun foo(): Any +} + +class PublicB : PrivateA { + override fun foo() : String = error("stub") +} \ No newline at end of file diff --git a/native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/!superClassWithCovariantOverride.h b/native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/!superClassWithCovariantOverride.h new file mode 100644 index 00000000000..2c1d04ea4ba --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/!superClassWithCovariantOverride.h @@ -0,0 +1,38 @@ +#import +#import +#import +#import +#import +#import +#import + +@class Bar; + +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 Bar : Base +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (id)foo __attribute__((swift_name("foo()"))); +@end + +__attribute__((objc_subclassing_restricted)) +@interface Foo : Bar +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)foo __attribute__((swift_name("foo()"))); +@end + +#pragma pop_macro("_Nullable_result") +#pragma clang diagnostic pop +NS_ASSUME_NONNULL_END diff --git a/native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/Foo.kt b/native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/Foo.kt new file mode 100644 index 00000000000..eac8ea51b4a --- /dev/null +++ b/native/objcexport-header-generator/testData/headers/superClassWithCovariantOverride/Foo.kt @@ -0,0 +1,7 @@ +abstract class Bar { + abstract fun foo(): Any +} + +class Foo : Bar() { + override fun foo(): String = error("stub") +}