[ObjCType] Add basic implementation of base method, fix tests
KT-65687
This commit is contained in:
committed by
Space Team
parent
1c2570ed7e
commit
078f0ff6e1
+2
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+22
@@ -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
|
||||
}
|
||||
+3
-1
@@ -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
|
||||
}
|
||||
|
||||
+12
-3
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -44,6 +44,7 @@ fun KtClassOrObjectSymbol.translateToObjCProtocol(): ObjCProtocol? {
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
internal fun KtClassOrObjectSymbol.superProtocols(): List<String> {
|
||||
return getDeclaredSuperInterfaceSymbols()
|
||||
.filter { it.isVisibleInObjC() }
|
||||
.map { superInterface -> superInterface.getObjCClassOrProtocolName().objCName }
|
||||
.toList()
|
||||
}
|
||||
+134
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
-4
@@ -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"))
|
||||
}
|
||||
|
||||
+26
-6
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
@class A<T>, B<T>;
|
||||
|
||||
@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<T> : 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<T> : A<Int *>
|
||||
- (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<Int *>
|
||||
- (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 <RootA, RootB>
|
||||
- (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
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* inheritance chain: A > B > C
|
||||
*/
|
||||
abstract class A<T> {
|
||||
abstract fun foo(): T
|
||||
}
|
||||
|
||||
open class B<T> : A<Int>() {
|
||||
override fun foo(): Int = 42
|
||||
}
|
||||
|
||||
open class C : B<Int>() {
|
||||
override fun foo(): Int = 42
|
||||
}
|
||||
|
||||
/**
|
||||
* inheritance tree:
|
||||
* RootA RootB
|
||||
* \ /
|
||||
* Tree
|
||||
*/
|
||||
interface RootA<T> {
|
||||
fun fooA(): T
|
||||
}
|
||||
|
||||
interface RootB<T> {
|
||||
fun fooB(): T
|
||||
}
|
||||
|
||||
class Tree : RootA<Int>, RootB<String> {
|
||||
override fun fooA(): Int = 42
|
||||
override fun fooB(): String = "42"
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
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
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
private interface PrivateInterface<T> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
class PublicClass : PrivateInterface<Int> {
|
||||
override fun foo(): Int = error("stub")
|
||||
}
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
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
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
private interface PrivateA {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
class PublicB : PrivateA {
|
||||
override fun foo() = Unit
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
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
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
private interface PrivateA {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
class PublicB : PrivateA {
|
||||
override fun foo() : String = error("stub")
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
@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
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
abstract class Bar {
|
||||
abstract fun foo(): Any
|
||||
}
|
||||
|
||||
class Foo : Bar() {
|
||||
override fun foo(): String = error("stub")
|
||||
}
|
||||
Reference in New Issue
Block a user