[ObjCExport] Translate superClass and superClass generics for class and objects
^KT-65384 Verification Pending
This commit is contained in:
committed by
Space Team
parent
c22149c642
commit
5b11308d1b
+1
-1
@@ -25,4 +25,4 @@ internal fun KtClassOrObjectSymbol.getDeclaredSuperInterfaceSymbols(): List<KtCl
|
||||
.filter { !it.isCloneable } // TODO: Write unit test for this
|
||||
.filter { superInterface -> superInterface.classKind == KtClassKind.INTERFACE }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
+25
-15
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.objcexport.analysisApiUtils
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
|
||||
|
||||
/**
|
||||
* Tries to find the superclass [KtClassOrObjectSymbol] symbol which is *not* kotlin.Any
|
||||
@@ -28,20 +26,32 @@ import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
|
||||
*/
|
||||
context(KtAnalysisSession)
|
||||
internal fun KtClassOrObjectSymbol.getSuperClassSymbolNotAny(): KtClassOrObjectSymbol? {
|
||||
return getSuperClassTypeNotAny()?.expandedClassSymbol
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find the supertype of this [KtClassOrObjectSymbol] which is a superclass (not Any)
|
||||
* ```kotlin
|
||||
* abstract class A
|
||||
*
|
||||
* class B: A
|
||||
*
|
||||
* fun example() {
|
||||
* val symbolOfB = // ...
|
||||
* val typeRepresentingA = symbolOfB.getSuperClassTypeNotAny()
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
context(KtAnalysisSession)
|
||||
internal fun KtClassOrObjectSymbol.getSuperClassTypeNotAny(): KtNonErrorClassType? {
|
||||
return superTypes.firstNotNullOfOrNull find@{ superType ->
|
||||
if (superType.isAny) return@find null
|
||||
if (superType.isError && superType is KtClassErrorType) {
|
||||
//Header should have just a Base type in case unresolved super type
|
||||
return@find null
|
||||
}
|
||||
if (superType is KtClassType) {
|
||||
val classifier = superType.qualifiers.firstNotNullOfOrNull { qualifier ->
|
||||
(qualifier as? KtClassTypeQualifier.KtResolvedClassTypeQualifier)?.symbol
|
||||
if (superType.isAny || superType.isError) return@find null
|
||||
if (superType is KtNonErrorClassType) {
|
||||
val classSymbol = superType.expandedClassSymbol ?: return@find null
|
||||
if (classSymbol.classKind.isClass) {
|
||||
return superType
|
||||
}
|
||||
|
||||
if (classifier is KtClassOrObjectSymbol && classifier.classKind.isClass) return@find classifier
|
||||
}
|
||||
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.objcexport
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportClassOrProtocolName
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCNonNullReferenceType
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDefaultSuperClassOrProtocolName
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getSuperClassTypeNotAny
|
||||
|
||||
internal data class KtObjCSuperClassTranslation(
|
||||
val superClassName: ObjCExportClassOrProtocolName,
|
||||
val superClassGenerics: List<ObjCNonNullReferenceType>,
|
||||
)
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
internal fun KtClassOrObjectSymbol.translateSuperClass(): KtObjCSuperClassTranslation {
|
||||
val superClassType = getSuperClassTypeNotAny()
|
||||
val superClassName = superClassType?.getSuperClassName() ?: getDefaultSuperClassOrProtocolName()
|
||||
|
||||
val superClassGenerics: List<ObjCNonNullReferenceType> = superTypes
|
||||
.filterIsInstance<KtNonErrorClassType>()
|
||||
.find { type ->
|
||||
val classSymbol = type.classSymbol as? KtClassOrObjectSymbol ?: return@find false
|
||||
classSymbol.classKind.isClass
|
||||
}
|
||||
?.ownTypeArguments
|
||||
.orEmpty()
|
||||
.mapNotNull { typeProjection -> typeProjection.type?.mapToReferenceTypeIgnoringNullability() }
|
||||
|
||||
return KtObjCSuperClassTranslation(superClassName, superClassGenerics)
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.objcexport
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCProtocol
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDeclaredSuperInterfaceSymbols
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
internal fun KtClassOrObjectSymbol.translateSuperInterfaces(): List<ObjCProtocol> {
|
||||
return getDeclaredSuperInterfaceSymbols().mapNotNull { superInterfaceSymbol ->
|
||||
superInterfaceSymbol.translateToObjCProtocol()
|
||||
}
|
||||
}
|
||||
+25
-23
@@ -4,10 +4,10 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.nameOrAnonymous
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDefaultSuperClassOrProtocolName
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getSuperClassSymbolNotAny
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
@@ -15,9 +15,6 @@ fun KtClassOrObjectSymbol.translateToObjCClass(): ObjCClass? {
|
||||
require(classKind == KtClassKind.CLASS)
|
||||
if (!isVisibleInObjC()) return null
|
||||
|
||||
val superClass = getSuperClassSymbolNotAny()
|
||||
val kotlinAnyName = getDefaultSuperClassOrProtocolName()
|
||||
val superName = if (superClass == null) kotlinAnyName else getSuperClassName()
|
||||
val enumKind = this.classKind == KtClassKind.ENUM_CLASS
|
||||
val final = if (this is KtSymbolWithModality) this.modality == Modality.FINAL else false
|
||||
val attributes = if (enumKind || final) listOf(OBJC_SUBCLASSING_RESTRICTED) else emptyList()
|
||||
@@ -25,6 +22,8 @@ fun KtClassOrObjectSymbol.translateToObjCClass(): ObjCClass? {
|
||||
val name = getObjCClassOrProtocolName()
|
||||
val comment: ObjCComment? = annotationsList.translateToObjCComment()
|
||||
val origin: ObjCExportStubOrigin = getObjCExportStubOrigin()
|
||||
|
||||
val superClass = translateSuperClass()
|
||||
val superProtocols: List<String> = superProtocols()
|
||||
|
||||
val members: List<ObjCExportStub> = getMemberScope().getCallableSymbols().plus(getMemberScope().getConstructors())
|
||||
@@ -33,20 +32,25 @@ fun KtClassOrObjectSymbol.translateToObjCClass(): ObjCClass? {
|
||||
.toList()
|
||||
|
||||
val categoryName: String? = null
|
||||
val generics: List<ObjCGenericTypeDeclaration> = emptyList()
|
||||
val superClassGenerics: List<ObjCNonNullReferenceType> = emptyList()
|
||||
|
||||
val generics: List<ObjCGenericTypeDeclaration> = typeParameters.map { typeParameter ->
|
||||
ObjCGenericTypeParameterDeclaration(
|
||||
typeParameter.nameOrAnonymous.asString().toValidObjCSwiftIdentifier(),
|
||||
ObjCVariance.fromKotlinVariance(typeParameter.variance)
|
||||
)
|
||||
}
|
||||
|
||||
return ObjCInterfaceImpl(
|
||||
name.objCName,
|
||||
comment,
|
||||
origin,
|
||||
attributes,
|
||||
superProtocols,
|
||||
members,
|
||||
categoryName,
|
||||
generics,
|
||||
superName.objCName,
|
||||
superClassGenerics
|
||||
name = name.objCName,
|
||||
comment = comment,
|
||||
origin = origin,
|
||||
attributes = attributes,
|
||||
superProtocols = superProtocols,
|
||||
members = members,
|
||||
categoryName = categoryName,
|
||||
generics = generics,
|
||||
superClass = superClass.superClassName.objCName,
|
||||
superClassGenerics = superClass.superClassGenerics
|
||||
)
|
||||
}
|
||||
|
||||
@@ -60,10 +64,8 @@ private fun abbreviate(name: String): String {
|
||||
return normalizedName
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue KT-65384
|
||||
* And K1 implementation [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.translateClass]
|
||||
*/
|
||||
private fun KtClassOrObjectSymbol.getSuperClassName(): ObjCExportClassOrProtocolName {
|
||||
return ObjCExportClassOrProtocolName("UnimplementedSwiftName", "UnimplementedObjCName")
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
internal fun KtNonErrorClassType.getSuperClassName(): ObjCExportClassOrProtocolName? {
|
||||
val classSymbol = expandedClassSymbol ?: return null
|
||||
return classSymbol.getObjCClassOrProtocolName()
|
||||
}
|
||||
+5
-6
@@ -47,7 +47,6 @@ fun translateToObjCHeader(files: List<KtFile>): ObjCHeader {
|
||||
|
||||
/* Add the classId to already processed classIds and do not redo if already processed */
|
||||
val stub = translatedClassifiers.getOrPut(classId) {
|
||||
|
||||
val translatedObjCClassOrProtocol = when (symbol.classKind) {
|
||||
KtClassKind.INTERFACE -> symbol.translateToObjCProtocol()
|
||||
KtClassKind.CLASS -> symbol.translateToObjCClass()
|
||||
@@ -56,7 +55,11 @@ fun translateToObjCHeader(files: List<KtFile>): ObjCHeader {
|
||||
} ?: return result
|
||||
|
||||
symbol.getDeclaredSuperInterfaceSymbols().forEach { superInterfaceSymbol ->
|
||||
result.addAll(process(superInterfaceSymbol))
|
||||
result.addAll(process(superInterfaceSymbol, true))
|
||||
}
|
||||
|
||||
symbol.getSuperClassSymbolNotAny()?.let { superClassSymbol ->
|
||||
process(superClassSymbol, true)
|
||||
}
|
||||
|
||||
result.add(translatedObjCClassOrProtocol)
|
||||
@@ -123,10 +126,6 @@ fun translateToObjCHeader(files: List<KtFile>): ObjCHeader {
|
||||
classForwardDeclarations.add(errorForwardClass)
|
||||
}
|
||||
|
||||
protocolForwardDeclarations += stubs
|
||||
.filterIsInstance<ObjCClass>()
|
||||
.flatMap { it.superProtocols }
|
||||
|
||||
return ObjCHeader(
|
||||
stubs = stubs,
|
||||
classForwardDeclarations = classForwardDeclarations,
|
||||
|
||||
+12
-16
@@ -6,8 +6,6 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDefaultSuperClassOrProtocolName
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getSuperClassSymbolNotAny
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
@@ -15,9 +13,6 @@ fun KtClassOrObjectSymbol.translateToObjCObject(): ObjCClass? {
|
||||
require(classKind == KtClassKind.OBJECT)
|
||||
if (!isVisibleInObjC()) return null
|
||||
|
||||
val superClass = getSuperClassSymbolNotAny()
|
||||
val kotlinAnyName = getDefaultSuperClassOrProtocolName()
|
||||
val superName = if (superClass == null) kotlinAnyName else throw RuntimeException("Super class translation isn't implemented yet")
|
||||
val enumKind = this.classKind == KtClassKind.ENUM_CLASS
|
||||
val final = if (this is KtSymbolWithModality) this.modality == Modality.FINAL else false
|
||||
val attributes = if (enumKind || final) listOf(OBJC_SUBCLASSING_RESTRICTED) else emptyList()
|
||||
@@ -28,25 +23,26 @@ fun KtClassOrObjectSymbol.translateToObjCObject(): ObjCClass? {
|
||||
val superProtocols: List<String> = superProtocols()
|
||||
val categoryName: String? = null
|
||||
val generics: List<ObjCGenericTypeDeclaration> = emptyList()
|
||||
val superClassGenerics: List<ObjCNonNullReferenceType> = emptyList()
|
||||
val objectMembers = getDefaultMembers()
|
||||
|
||||
val superClass = translateSuperClass()
|
||||
|
||||
getMemberScope().getCallableSymbols()
|
||||
.sortedWith(StableCallableOrder)
|
||||
.flatMap { it.translateToObjCExportStubs() }
|
||||
.forEach { objectMembers.add(it) }
|
||||
|
||||
return ObjCInterfaceImpl(
|
||||
name.objCName,
|
||||
comment,
|
||||
origin,
|
||||
attributes,
|
||||
superProtocols,
|
||||
objectMembers,
|
||||
categoryName,
|
||||
generics,
|
||||
superName.objCName,
|
||||
superClassGenerics
|
||||
name = name.objCName,
|
||||
comment = comment,
|
||||
origin = origin,
|
||||
attributes = attributes,
|
||||
superProtocols = superProtocols,
|
||||
members = objectMembers,
|
||||
categoryName = categoryName,
|
||||
generics = generics,
|
||||
superClass = superClass.superClassName.objCName,
|
||||
superClassGenerics = superClass.superClassGenerics
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCProtocol
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCProtocolImpl
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.toNameAttributes
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDeclaredSuperInterfaceSymbols
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isCloneable
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
@@ -45,7 +44,6 @@ fun KtClassOrObjectSymbol.translateToObjCProtocol(): ObjCProtocol? {
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
internal fun KtClassOrObjectSymbol.superProtocols(): List<String> {
|
||||
return getDeclaredSuperInterfaceSymbols()
|
||||
.filter { superInterface -> !superInterface.isCloneable }
|
||||
.map { superInterface -> superInterface.getObjCClassOrProtocolName().objCName }
|
||||
.toList()
|
||||
}
|
||||
+1
-1
@@ -60,7 +60,7 @@ internal fun KtType.translateToObjCReferenceType(): ObjCReferenceType {
|
||||
* [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.mapReferenceTypeIgnoringNullability]
|
||||
*/
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
private fun KtType.mapToReferenceTypeIgnoringNullability(): ObjCNonNullReferenceType {
|
||||
internal fun KtType.mapToReferenceTypeIgnoringNullability(): ObjCNonNullReferenceType {
|
||||
val fullyExpandedType = fullyExpandedType
|
||||
val classId = (fullyExpandedType as? KtNonErrorClassType)?.classId
|
||||
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ class ForwardedClassesAndProtocolsDependenciesTest(
|
||||
fun getInterface(): InterfaceB = error("error")
|
||||
""",
|
||||
protocols = setOf("InterfaceB", "InterfaceA"),
|
||||
classes = setOf("ClassB")
|
||||
classes = setOf("ClassB", "ClassA")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+15
@@ -233,6 +233,21 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) {
|
||||
doTest(headersTestDataDir.resolve("extensionFunctions"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - classWithGenerics`() {
|
||||
doTest(headersTestDataDir.resolve("classWithGenerics"))
|
||||
}
|
||||
|
||||
/**
|
||||
* - init method missing
|
||||
* - 'new constructor' missing
|
||||
*/
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - objectWithGenericSuperclass`() {
|
||||
doTest(headersTestDataDir.resolve("objectWithGenericSuperclass"))
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
#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<T1, T2>;
|
||||
|
||||
@protocol I1, I2;
|
||||
|
||||
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 A<T1, T2> : Base
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||
@end
|
||||
|
||||
@protocol I1
|
||||
@required
|
||||
@end
|
||||
|
||||
@protocol I2
|
||||
@required
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface Foo<T> : A<T, NSString *> <I1, I2>
|
||||
- (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
|
||||
@@ -0,0 +1,6 @@
|
||||
open class A<T1, T2>
|
||||
|
||||
interface I1<T>
|
||||
interface I2<T>
|
||||
|
||||
class Foo<T> : I1<T>, I2<String>, A<T, String>()
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
#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<T1, T2>, Foo;
|
||||
|
||||
@protocol I;
|
||||
|
||||
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 A<T1, T2> : Base
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||
@end
|
||||
|
||||
@protocol I
|
||||
@required
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface Foo : A<Int *, NSString *> <I>
|
||||
+ (instancetype)alloc __attribute__((unavailable));
|
||||
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
|
||||
+ (instancetype)new __attribute__((unavailable));
|
||||
+ (instancetype)foo __attribute__((swift_name("init()")));
|
||||
@property (class, readonly, getter=shared) Foo *shared __attribute__((swift_name("shared")));
|
||||
@end
|
||||
|
||||
#pragma pop_macro("_Nullable_result")
|
||||
#pragma clang diagnostic pop
|
||||
NS_ASSUME_NONNULL_END
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
abstract class A<T1, T2>
|
||||
interface I<T>
|
||||
|
||||
object Foo : A<Int, String>(), I<String>
|
||||
Reference in New Issue
Block a user