[ObjCExport] Fix extensions interface name

KT-66315
This commit is contained in:
eugene.levenetc
2024-03-04 18:09:20 +01:00
committed by Space Team
parent 2a445a04b0
commit 5c64832c0f
7 changed files with 70 additions and 43 deletions
@@ -4,7 +4,6 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCInterface
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCInterfaceImpl
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getFileName
private const val extensionsCategoryName = "Extensions"
@@ -49,26 +48,33 @@ internal val ObjCInterface.isExtensionsFacade: Boolean
* See related [getTopLevelFacade]
*/
context(KtAnalysisSession, KtObjCExportSession)
fun KtFileSymbol.getExtensionsFacade(): ObjCInterface? {
fun KtFileSymbol.getExtensionFacades(): List<ObjCInterface> {
val extensions = getFileScope()
.getCallableSymbols().filter { it.isExtension }
.toList().sortedWith(StableCallableOrder)
.ifEmpty { return null }
.toList()
.sortedWith(StableCallableOrder)
.ifEmpty { return emptyList() }
.groupBy {
val classSymbol = it.receiverParameter?.type?.expandedClassSymbol
classSymbol?.getObjCClassOrProtocolName()?.objCName
}
.mapNotNull { (key, value) ->
if (key == null) return@mapNotNull null else key to value
}
val fileName = getFileName()
?: throw IllegalStateException("File '$this' cannot be translated without file name")
return ObjCInterfaceImpl(
name = fileName,
comment = null,
origin = null,
attributes = emptyList(),
superProtocols = emptyList(),
members = extensions.mapNotNull { it.translateToObjCExportStub() },
categoryName = extensionsCategoryName,
generics = emptyList(),
superClass = null,
superClassGenerics = emptyList()
)
return extensions.map { (objCName, extensionSymbols) ->
ObjCInterfaceImpl(
name = objCName,
comment = null,
origin = null,
attributes = emptyList(),
superProtocols = emptyList(),
members = extensionSymbols.mapNotNull { ext -> ext.translateToObjCExportStub() },
categoryName = extensionsCategoryName,
generics = emptyList(),
superClass = null,
superClassGenerics = emptyList()
)
}
}
@@ -43,7 +43,7 @@ import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDefaultSuperClassOrPr
*
* Where `FooKt` would be the "top level interface file facade" returned by this function.
*
* See related [getExtensionsFacade]
* See related [getExtensionFacades]
*/
context(KtAnalysisSession, KtObjCExportSession)
fun KtFileSymbol.getTopLevelFacade(): ObjCInterface? {
@@ -109,10 +109,12 @@ private class KtObjCExportHeaderGenerator {
context(KtAnalysisSession, KtObjCExportSession)
private fun translateFileSymbol(symbol: KtFileSymbol) {
symbol.getExtensionsFacade()?.let { extensionFacade ->
objCStubs += extensionFacade
enqueueDependencyClasses(extensionFacade)
objCClassForwardDeclarations += extensionFacade.name
symbol.getExtensionFacades().let { extensionFacades ->
extensionFacades.forEach { facade ->
objCStubs += facade
enqueueDependencyClasses(facade)
objCClassForwardDeclarations += facade.name
}
}
symbol.getTopLevelFacade()?.let { topLevelFacade ->
@@ -146,10 +148,10 @@ private class KtObjCExportHeaderGenerator {
symbol.getDeclaredSuperInterfaceSymbols()
.filter { it.isVisibleInObjC() }
.forEach { superInterfaceSymbol ->
translateClassOrObjectSymbol(superInterfaceSymbol)?.let {
objCProtocolForwardDeclarations += it.name
translateClassOrObjectSymbol(superInterfaceSymbol)?.let {
objCProtocolForwardDeclarations += it.name
}
}
}
symbol.getSuperClassSymbolNotAny()?.let { superClassSymbol ->
translateClassOrObjectSymbol(superClassSymbol)?.let {
@@ -6,7 +6,7 @@
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
@class Foo;
@class ClazzA, ClazzB;
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
@@ -21,15 +21,27 @@ NS_ASSUME_NONNULL_BEGIN
#endif
__attribute__((objc_subclassing_restricted))
@interface Foo : Base
@interface ClazzA : Base
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (void)memberFun __attribute__((swift_name("memberFun()")));
@end
@interface Foo (Extensions)
- (void)extensionFunA __attribute__((swift_name("extensionFunA()")));
- (void)extensionFunB __attribute__((swift_name("extensionFunB()")));
__attribute__((objc_subclassing_restricted))
@interface ClazzB : Base
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (void)memberFun __attribute__((swift_name("memberFun()")));
@end
@interface ClazzA (Extensions)
- (void)extensionFunA1 __attribute__((swift_name("extensionFunA1()")));
- (void)extensionFunA2 __attribute__((swift_name("extensionFunA2()")));
@end
@interface ClazzB (Extensions)
- (void)extensionFunB1 __attribute__((swift_name("extensionFunB1()")));
- (void)extensionFunB2 __attribute__((swift_name("extensionFunB2()")));
@end
__attribute__((objc_subclassing_restricted))
@@ -1,9 +1,16 @@
fun topLevelFunA() {}
fun topLevelFunB() {}
fun Foo.extensionFunA() {}
fun Foo.extensionFunB() {}
fun ClazzA.extensionFunA1() {}
fun ClazzA.extensionFunA2() {}
class Foo {
fun ClazzB.extensionFunB1() {}
fun ClazzB.extensionFunB2() {}
class ClazzA {
fun memberFun() {}
}
class ClazzB {
fun memberFun() {}
}
@@ -6,7 +6,7 @@
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
@class Foo;
@class Clazz;
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
@@ -21,13 +21,13 @@ NS_ASSUME_NONNULL_BEGIN
#endif
__attribute__((objc_subclassing_restricted))
@interface Foo : Base
@interface Clazz : Base
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (void)memberFun __attribute__((swift_name("memberFun()")));
@end
@interface Foo (Extensions)
@interface Clazz (Extensions)
@property (readonly) int32_t extensionValA __attribute__((swift_name("extensionValA")));
@property (readonly) int32_t extensionValB __attribute__((swift_name("extensionValB")));
@property int32_t extensionVarA __attribute__((swift_name("extensionVarA")));
@@ -1,18 +1,18 @@
val topLevelPropA = 0
val topLevelPropB = 1
val Foo.extensionValA
val Clazz.extensionValA
get() = 0
val Foo.extensionValB
val Clazz.extensionValB
get() = 1
var Foo.extensionVarA
var Clazz.extensionVarA
get() = 0
set(value) {}
var Foo.extensionVarB
var Clazz.extensionVarB
get() = 1
set(value) {}
class Foo {
class Clazz {
fun memberFun() {}
}