Native: don't generate .companion in ObjCExport if the companion is not exported

^KT-47462 Fixed
This commit is contained in:
Svyatoslav Scherbina
2021-06-25 21:59:08 +03:00
committed by Space
parent 786cb47450
commit eeffa49cd9
6 changed files with 78 additions and 5 deletions
@@ -78,7 +78,7 @@ internal fun ObjCExportedInterface.createCodeSpec(symbolTable: SymbolTable): Obj
methods += ObjCGetterForObjectInstance(namer.getObjectPropertySelector(descriptor), irClassSymbol)
}
if (descriptor.needCompanionObjectProperty(namer)) {
if (descriptor.needCompanionObjectProperty(namer, mapper)) {
methods += ObjCGetterForObjectInstance(namer.getCompanionObjectPropertySelector(descriptor),
symbolTable.referenceClass(descriptor.companionObjectDescriptor!!))
}
@@ -352,7 +352,7 @@ internal class ObjCExportTranslatorImpl(
}
}
if (descriptor.needCompanionObjectProperty(namer)) {
if (descriptor.needCompanionObjectProperty(namer, mapper)) {
add {
ObjCProperty(
ObjCExportNamer.companionObjectPropertyName, null,
@@ -1326,8 +1326,15 @@ private fun computeSuperClassType(descriptor: ClassDescriptor): KotlinType? = de
internal const val OBJC_SUBCLASSING_RESTRICTED = "objc_subclassing_restricted"
internal fun ClassDescriptor.needCompanionObjectProperty(namer: ObjCExportNamer) = hasCompanionObject &&
(kind != ClassKind.ENUM_CLASS || enumEntries.all { namer.getEnumEntrySelector(it) != ObjCExportNamer.companionObjectPropertyName })
internal fun ClassDescriptor.needCompanionObjectProperty(namer: ObjCExportNamer, mapper: ObjCExportMapper): Boolean {
val companionObject = companionObjectDescriptor
if (companionObject == null || !mapper.shouldBeExposed(companionObject)) return false
if (kind == ClassKind.ENUM_CLASS && enumEntries.any { namer.getEnumEntrySelector(it) == ObjCExportNamer.companionObjectPropertyName })
return false // 'companion' property would clash with enum entry, don't generate it.
return true
}
private fun Deprecation.toDeprecationAttribute(): String {
@@ -857,6 +857,22 @@ __attribute__((swift_name("KT43780Enum.Companion")))
@property (readonly) int32_t x __attribute__((swift_name("x")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ClassWithInternalCompanion")))
@interface KtClassWithInternalCompanion : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property (readonly) int32_t y __attribute__((swift_name("y")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ClassWithPrivateCompanion")))
@interface KtClassWithPrivateCompanion : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property (readonly) int32_t y __attribute__((swift_name("y")));
@end;
__attribute__((swift_name("Host")))
@protocol KtHost
@required
@@ -799,6 +799,22 @@ __attribute__((swift_name("KT43780Enum.Companion")))
@property (readonly) int32_t x __attribute__((swift_name("x")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ClassWithInternalCompanion")))
@interface KtClassWithInternalCompanion : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property (readonly) int32_t y __attribute__((swift_name("y")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ClassWithPrivateCompanion")))
@interface KtClassWithPrivateCompanion : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property (readonly) int32_t y __attribute__((swift_name("y")));
@end;
__attribute__((swift_name("Host")))
@protocol KtHost
@required
@@ -34,4 +34,29 @@ enum class KT43780Enum {
companion object {
val x = 11
}
}
}
class ClassWithInternalCompanion {
internal companion object {
val x = 12
}
val y = 13
}
class ClassWithPrivateCompanion {
private companion object {
val x = 14
}
val y = 15
}
// Shouldn't be exported at all:
internal class InternalClassWithCompanion {
companion object
}
private class PrivateClassWithCompanion {
companion object
}
@@ -37,6 +37,14 @@ private func testNameClash() throws {
try assertEquals(actual: KT43780Enum.otherEntry.name, expected: "OTHER_ENTRY")
}
// Reported as https://youtrack.jetbrains.com/issue/KT-47462
private func testUnexposedCompanion() throws {
// Just trying to ensure that the classes are accessible:
try assertEquals(actual: 13, expected: ClassWithInternalCompanion().y)
try assertEquals(actual: 15, expected: ClassWithPrivateCompanion().y)
// and this doesn't make the companions accessible as well.
}
class Kt43780Tests : SimpleTestProvider {
override init() {
@@ -45,5 +53,6 @@ class Kt43780Tests : SimpleTestProvider {
test("testObject", testObject)
test("testCompanionObject", testCompanionObject)
test("testNameClash", testNameClash)
test("testUnexposedCompanion", testUnexposedCompanion)
}
}