Skip to content

Commit 08eccc7

Browse files
committed
Remove unneeded swift_name attributes from Objective-C headers
Partial fix for KT-81447 Native: Objective-C: Excessive 'swift_name' attributes being generated Removes swift_name attribute from declarations that would already have that swift name. Initially focusing on properties and and simple methods that have no parameters. The excessive use of swift_attributes creates large headers, and even larger pcm files generated from those headers.
1 parent 3bff839 commit 08eccc7

File tree

155 files changed

+1935
-2186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+1935
-2186
lines changed

kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ internal fun ObjCExportedInterface.createCodeSpec(symbolTable: SymbolTable): Obj
9090

9191
if (descriptor.kind == ClassKind.ENUM_CLASS) {
9292
descriptor.enumEntries.mapTo(methods) {
93-
ObjCGetterForKotlinEnumEntry(symbolTable.descriptorExtension.referenceEnumEntry(it), namer.getEnumEntrySelector(it))
93+
ObjCGetterForKotlinEnumEntry(
94+
symbolTable.descriptorExtension.referenceEnumEntry(it),
95+
namer.getEnumEntryName(it).objCName)
9496
}
9597

9698
descriptor.getEnumValuesFunctionDescriptor()?.let {
@@ -133,7 +135,7 @@ internal fun <S : IrFunctionSymbol> createObjCMethodSpecBaseMethod(
133135
): ObjCMethodSpec.BaseMethod<S> {
134136
require(mapper.isBaseMethod(descriptor))
135137

136-
val selector = namer.getSelector(descriptor)
138+
val selector = namer.getFunctionName(descriptor).objCName
137139
val bridge = mapper.bridgeMethod(descriptor)
138140

139141
return ObjCMethodSpec.BaseMethod(symbol, bridge, selector)

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/errors.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ internal val KtObjCExportSession.errorInterface
5151
returnType = ObjCInstanceType,
5252
selectors = listOf("init"),
5353
parameters = emptyList(),
54-
attributes = listOf("swift_name(\"init()\")", "objc_designated_initializer")
54+
attributes = listOf("objc_designated_initializer")
5555
),
5656
ObjCMethod(
5757
comment = null,

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/getDefaultSuperClassOrProtocolName.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import org.jetbrains.kotlin.objcexport.getObjCKotlinStdlibClassOrProtocolName
88
* Some entities like top level functions are wrapped into classes with Base super class.
99
*
1010
* @interface FooKt : Base
11-
* + (NSString *)myTopLevelFunction __attribute__((swift_name("myTopLevelFunction()")));
11+
* + (NSString *)myTopLevelFunction;
1212
* @end
1313
*/
1414
internal fun KtObjCExportSession.getDefaultSuperClassOrProtocolName(): ObjCExportClassOrProtocolName {

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/buildCompanionProperty.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ internal fun ObjCExportContext.buildCompanionProperty(classSymbol: KaClassSymbol
3737
}),
3838
propertyAttributes = listOf("class", "readonly"),
3939
getterName = propertyName,
40-
declarationAttributes = listOf(swiftNameAttribute(propertyName))
40+
declarationAttributes = emptyList(),
4141
)
4242
}

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/buildThrowableAsErrorMethod.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ internal fun buildThrowableAsErrorMethod(): ObjCMethod {
1414
returnType = ObjCClassType("NSError"),
1515
selectors = listOf("asError"),
1616
parameters = emptyList(),
17-
attributes = listOf(swiftNameAttribute("asError()")),
17+
attributes = emptyList(),
1818
origin = null
1919
)
2020
}

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/mangling/ObjCMethodMangler.kt

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,35 @@ import org.jetbrains.kotlin.backend.konan.objcexport.swiftNameAttribute
1818
*/
1919
internal class ObjCMethodMangler {
2020

21-
private val mangledMethods = mutableMapOf<String, ObjCMemberDetails>()
21+
private val mangledMethods = mutableSetOf<String>()
2222

2323
fun mangle(member: ObjCExportStub, containingStub: ObjCExportStub): ObjCExportStub {
24-
if (!member.isSwiftNameMethod()) return member
25-
require(member is ObjCMethod)
26-
if (!contains(member)) {
27-
cacheMember(member)
28-
return member
29-
} else {
30-
val key = getMemberKey(member)
31-
val attribute = mangledMethods[key] ?: error("No cached item for $member")
32-
val mangledAttribute = attribute.mangleAttribute()
33-
val cloned = member.copy(
34-
mangledSelectors = buildMangledSelectors(mangledAttribute),
35-
mangledParameters = buildMangledParameters(mangledAttribute),
36-
swiftNameAttribute = buildMangledSwiftNameMethodAttribute(mangledAttribute, containingStub),
37-
containingStubName = containingStub.name
38-
)
39-
mangledMethods[key] = mangledAttribute
40-
return cloned
24+
if (member is ObjCMethod) {
25+
var cloned: ObjCMethod = member
26+
while (true) {
27+
val key = getMemberKey(cloned)
28+
if (!mangledMethods.contains(key)) {
29+
mangledMethods.add(key)
30+
return cloned
31+
}
32+
val newSelectors = cloned.selectors.toMutableList()
33+
val lastIndex = newSelectors.lastIndex
34+
var lastSelector = newSelectors[lastIndex]
35+
if (lastSelector.endsWith(":")) {
36+
// - (void)foo:; -> -(void)foo_:;
37+
// - (void)foo:bar:; -> -(void)foo:bar_:;
38+
lastSelector = lastSelector.dropLast(1) + "_:"
39+
} else {
40+
// - (void)foo; -> -(void)foo_;
41+
lastSelector += "_"
42+
}
43+
newSelectors[lastIndex] = lastSelector
44+
cloned = member.copy(
45+
mangledSelectors = newSelectors,
46+
containingStubName = containingStub.name
47+
)
48+
}
4149
}
42-
}
43-
44-
private fun contains(member: ObjCExportStub): Boolean {
45-
if (!member.isSwiftNameMethod()) return false
46-
return mangledMethods[getMemberKey(member as ObjCMethod)] != null
47-
}
48-
49-
private fun cacheMember(member: ObjCMethod) {
50-
val memberKey = getMemberKey(member)
51-
val swiftNameAttr = getSwiftNameAttribute(member)
52-
mangledMethods[memberKey] = parseSwiftMethodNameAttribute(swiftNameAttr, member.returnType == ObjCInstanceType, member.parameters)
50+
return member
5351
}
5452
}

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/mangling/ObjCPropertyMangler.kt

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,33 @@ class ObjCPropertyMangler {
1414
private val mangledProperties = hashSetOf<String>()
1515

1616
fun mangle(member: ObjCExportStub, containingStub: ObjCExportStub): ObjCExportStub {
17-
return if (member.isSwiftNameProperty()) {
18-
val key = getSwiftNameAttribute(member as ObjCProperty)
19-
if (mangledProperties.contains(key)) {
17+
return if (member is ObjCProperty) {
18+
val name = member.name
19+
if (mangledProperties.contains(name)) {
2020
val copy = if (containingStub.isExtensionFacade) {
21-
val attr = parseSwiftPropertyNameAttribute(getSwiftNameAttribute(member))
2221
member.copy(
23-
name = member.name + "_",
22+
name = name + "_",
2423
propertyAttributes = null,
25-
declarationAttributes = listOf(buildMangledSwiftNamePropertyAttribute(attr.mangleAttribute()))
24+
declarationAttributes = null
2625
)
2726
} else {
2827
member.copy(
29-
name = member.name,
30-
propertyAttributes = "getter=${member.name}_",
28+
name = name,
29+
propertyAttributes = "getter=${name}_",
3130
declarationAttributes = null
3231
)
3332
}
34-
mangledProperties.add(getSwiftNameAttribute(copy))
3533
copy
3634
} else {
37-
mangledProperties.add(key)
35+
mangledProperties.add(name)
3836
member
3937
}
40-
} else if (member.isSwiftNameMethod()) {
41-
mangledProperties.add(getSwiftNameAttribute(member as ObjCMethod).replace("()", ""))
38+
} else if (member is ObjCMethod && member.selectors.size == 1 && member.parameters.isEmpty()) {
39+
mangledProperties.add(member.selectors[0])
4240
member
4341
} else {
4442
// Leave it as it is since it is neither property, nor method
4543
member
4644
}
4745
}
48-
}
49-
50-
private fun buildMangledSwiftNamePropertyAttribute(attribute: ObjCMemberDetails): String {
51-
return "swift_name(\"${attribute.name + attribute.postfix}\")"
5246
}

native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/mangling/copyObjCStub.kt

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,12 @@ internal fun ObjCProperty.copy(
2727
*/
2828
internal fun ObjCMethod.copy(
2929
mangledSelectors: List<String>,
30-
mangledParameters: List<String>,
31-
swiftNameAttribute: String,
3230
containingStubName: String,
3331
): ObjCMethod {
3432
val selectorsSize = mangledSelectors.size
3533
val parametersSize = this.parameters.size
3634
val methodName = this.name
37-
require((selectorsSize == parametersSize) || (selectorsSize == 1 && mangledParameters.isEmpty())) {
35+
require((selectorsSize == parametersSize) || (selectorsSize == 1 && parametersSize == 0)) {
3836
"'$containingStubName.$methodName': selectors of doesn't match parameters count: " +
3937
"selectors($mangledSelectors): $selectorsSize, " +
4038
"parameters(${this.parameters.joinToString { it.name }}): $parametersSize"
@@ -47,9 +45,70 @@ internal fun ObjCMethod.copy(
4745
selectors = mangledSelectors,
4846
parameters = this.parameters,
4947
attributes = this.attributes.map { attr ->
50-
if (attr.startsWith("swift_name")) swiftNameAttribute else attr
48+
if (attr.startsWith("swift_name")) remangledSwiftName(mangledSelectors, this.attributes) else attr
5149
},
5250
extras = this.extras
5351
)
52+
}
5453

55-
}
54+
/**
55+
* Create a swift name based on the selectors and attributes.
56+
*/
57+
internal fun ObjCMethod.remangledSwiftName(mangledSelectors: List<String>, attributes: List<String>): String {
58+
fun isConstructor(attributes: List<String>) : Boolean {
59+
return attributes.contains("objc_designated_initializer")
60+
}
61+
62+
val swiftName = StringBuilder("swift_name(\"")
63+
val count = if (mangledSelectors[0].endsWith(":")) mangledSelectors.size else mangledSelectors.size - 1
64+
if (count == 0) {
65+
// - (void)bar; -> bar()
66+
swiftName.append(mangledSelectors[0] + "()")
67+
} else {
68+
val selector = mangledSelectors[0]
69+
val lastUppercaseChar = selector.indexOfLast { it.isUpperCase() }
70+
if (isConstructor(attributes)) {
71+
// - (instancetype)initWithA:...; -> init(a:)
72+
var prefix = selector.take(lastUppercaseChar)
73+
if (prefix.endsWith("With")) {
74+
prefix = prefix.dropLast(4)
75+
}
76+
swiftName.append(
77+
prefix
78+
+ "("
79+
+ selector.substring(lastUppercaseChar).replaceFirstChar { it.lowercase() })
80+
} else if (lastUppercaseChar == -1 && selector.endsWith("_:")) {
81+
//- (Foo *)days_... -> days(__:...)
82+
//- (Foo *)days__... -> days(___:...)
83+
val index = selector.indexOf("_")
84+
swiftName.append(selector.substring(0, index) + "(")
85+
for (i in index until selector.length) {
86+
swiftName.append("_")
87+
}
88+
swiftName.append(":")
89+
} else {
90+
if (lastUppercaseChar == -1) {
91+
// - (void)bar:; -> bar:(_)
92+
swiftName.append(selector.dropLast(1) + "(_")
93+
if (count > 1) {
94+
// - (void)bar:...; -> bar:(_:...
95+
swiftName.append(":")
96+
}
97+
} else {
98+
// - (void)doBar:...; -> do(bar:...)
99+
swiftName.append(
100+
selector.take(lastUppercaseChar)
101+
+ "("
102+
+ selector.substring(lastUppercaseChar).replaceFirstChar { it.lowercase() })
103+
}
104+
}
105+
if (count > 1) {
106+
for (i in 1 until count) {
107+
swiftName.append(mangledSelectors[i])
108+
}
109+
}
110+
swiftName.append(")")
111+
}
112+
swiftName.append("\")")
113+
return swiftName.toString()
114+
}

0 commit comments

Comments
 (0)