Improve inner/nested class names in framework
Use 'Outer.Inner' instead of 'OuterInner' for Swift Also do some refactoring and add other minor improvements.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
e4ca831f06
commit
1791ed5643
+72
-31
@@ -46,9 +46,6 @@ internal class ObjCExportNamerImpl(
|
|||||||
private val topLevelNamePrefix: String = moduleDescriptor.namePrefix
|
private val topLevelNamePrefix: String = moduleDescriptor.namePrefix
|
||||||
) : ObjCExportNamer {
|
) : ObjCExportNamer {
|
||||||
|
|
||||||
private fun String.mangleClassOrProtocolName(): ObjCExportNamer.ClassOrProtocolName =
|
|
||||||
ObjCExportNamer.ClassOrProtocolName(swiftName = this, objCName = "$topLevelNamePrefix${this}")
|
|
||||||
|
|
||||||
private fun String.toUnmangledClassOrProtocolName(): ObjCExportNamer.ClassOrProtocolName =
|
private fun String.toUnmangledClassOrProtocolName(): ObjCExportNamer.ClassOrProtocolName =
|
||||||
ObjCExportNamer.ClassOrProtocolName(swiftName = this, objCName = this)
|
ObjCExportNamer.ClassOrProtocolName(swiftName = this, objCName = this)
|
||||||
|
|
||||||
@@ -95,13 +92,15 @@ internal class ObjCExportNamerImpl(
|
|||||||
!mapper.canHaveSameName(first, second)
|
!mapper.canHaveSameName(first, second)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val classNames = object : Mapping<Any, String>() {
|
private inner open class GlobalNameMapping<in T : Any, N> : Mapping<T, N>() {
|
||||||
override fun conflict(first: Any, second: Any): Boolean = true
|
final override fun conflict(first: T, second: T): Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private val protocolNames = object : Mapping<Any, String>() {
|
private val objCClassNames = GlobalNameMapping<Any, String>()
|
||||||
override fun conflict(first: Any, second: Any): Boolean = true
|
private val objCProtocolNames = GlobalNameMapping<ClassDescriptor, String>()
|
||||||
}
|
|
||||||
|
// Classes and protocols share the same namespace in Swift.
|
||||||
|
private val swiftClassAndProtocolNames = GlobalNameMapping<Any, String>()
|
||||||
|
|
||||||
private abstract inner class ClassPropertyNameMapping<T : Any> : Mapping<T, String>() {
|
private abstract inner class ClassPropertyNameMapping<T : Any> : Mapping<T, String>() {
|
||||||
|
|
||||||
@@ -127,12 +126,26 @@ internal class ObjCExportNamerImpl(
|
|||||||
first.containingDeclaration == second.containingDeclaration
|
first.containingDeclaration == second.containingDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFileClassName(file: SourceFile): ObjCExportNamer.ClassOrProtocolName = classNames.getOrPut(file) {
|
override fun getFileClassName(file: SourceFile): ObjCExportNamer.ClassOrProtocolName {
|
||||||
val psiSourceFile = file as? PsiSourceFile ?: error("SourceFile '$file' is not PsiSourceFile")
|
val baseName by lazy {
|
||||||
val psiFile = psiSourceFile.psiFile
|
val psiSourceFile = file as? PsiSourceFile ?: error("SourceFile '$file' is not PsiSourceFile")
|
||||||
val ktFile = psiFile as? KtFile ?: error("PsiFile '$psiFile' is not KtFile")
|
val psiFile = psiSourceFile.psiFile
|
||||||
StringBuilder(PackagePartClassUtils.getFilePartShortName(ktFile.name)).mangledSequence { append("_") }
|
val ktFile = psiFile as? KtFile ?: error("PsiFile '$psiFile' is not KtFile")
|
||||||
}.mangleClassOrProtocolName()
|
PackagePartClassUtils.getFilePartShortName(ktFile.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
val objCName = objCClassNames.getOrPut(file) {
|
||||||
|
StringBuilder(topLevelNamePrefix).append(baseName)
|
||||||
|
.mangledBySuffixUnderscores()
|
||||||
|
}
|
||||||
|
|
||||||
|
val swiftName = swiftClassAndProtocolNames.getOrPut(file) {
|
||||||
|
StringBuilder(baseName)
|
||||||
|
.mangledBySuffixUnderscores()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ObjCExportNamer.ClassOrProtocolName(swiftName = swiftName, objCName = objCName)
|
||||||
|
}
|
||||||
|
|
||||||
private val predefinedClassNames = mapOf(
|
private val predefinedClassNames = mapOf(
|
||||||
builtIns.any to kotlinAnyName,
|
builtIns.any to kotlinAnyName,
|
||||||
@@ -140,22 +153,48 @@ internal class ObjCExportNamerImpl(
|
|||||||
builtIns.mutableMap to mutableMapName
|
builtIns.mutableMap to mutableMapName
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun getClassOrProtocolName(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName {
|
override fun getClassOrProtocolName(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName =
|
||||||
predefinedClassNames[descriptor]?.let { return it }
|
predefinedClassNames[descriptor]
|
||||||
|
?: ObjCExportNamer.ClassOrProtocolName(
|
||||||
|
swiftName = getClassOrProtocolSwiftName(descriptor),
|
||||||
|
objCName = getClassOrProtocolObjCName(descriptor)
|
||||||
|
)
|
||||||
|
|
||||||
val mapping = if (descriptor.isInterface) protocolNames else classNames
|
private fun getClassOrProtocolSwiftName(
|
||||||
|
descriptor: ClassDescriptor
|
||||||
|
): String = swiftClassAndProtocolNames.getOrPut(descriptor) {
|
||||||
|
StringBuilder().apply {
|
||||||
|
val containingDeclaration = descriptor.containingDeclaration
|
||||||
|
if (containingDeclaration is ClassDescriptor) {
|
||||||
|
append(getClassOrProtocolSwiftName(containingDeclaration))
|
||||||
|
.append(".").append(descriptor.name.asString())
|
||||||
|
} else {
|
||||||
|
appendTopLevelClassBaseName(descriptor)
|
||||||
|
}
|
||||||
|
}.mangledBySuffixUnderscores()
|
||||||
|
}
|
||||||
|
|
||||||
return mapping.getOrPut(descriptor) {
|
private fun getClassOrProtocolObjCName(descriptor: ClassDescriptor): String {
|
||||||
|
val objCMapping = if (descriptor.isInterface) objCProtocolNames else objCClassNames
|
||||||
|
return objCMapping.getOrPut(descriptor) {
|
||||||
StringBuilder().apply {
|
StringBuilder().apply {
|
||||||
if (descriptor.module != moduleDescriptor) {
|
val containingDeclaration = descriptor.containingDeclaration
|
||||||
append(descriptor.module.namePrefix)
|
if (containingDeclaration is ClassDescriptor) {
|
||||||
}
|
append(getClassOrProtocolObjCName(containingDeclaration))
|
||||||
|
.append(descriptor.name.asString().capitalize())
|
||||||
|
|
||||||
descriptor.parentsWithSelf.takeWhile { it is ClassDescriptor }
|
} else {
|
||||||
.toList().reversed()
|
append(topLevelNamePrefix).appendTopLevelClassBaseName(descriptor)
|
||||||
.joinTo(this, "") { it.name.asString().capitalize() }
|
}
|
||||||
}.mangledSequence { append("_") }
|
}.mangledBySuffixUnderscores()
|
||||||
}.mangleClassOrProtocolName()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.appendTopLevelClassBaseName(descriptor: ClassDescriptor) = apply {
|
||||||
|
if (descriptor.module != moduleDescriptor) {
|
||||||
|
append(descriptor.module.namePrefix)
|
||||||
|
}
|
||||||
|
append(descriptor.name.asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSelector(method: FunctionDescriptor): String = methodSelectors.getOrPut(method) {
|
override fun getSelector(method: FunctionDescriptor): String = methodSelectors.getOrPut(method) {
|
||||||
@@ -258,7 +297,7 @@ internal class ObjCExportNamerImpl(
|
|||||||
return objectInstanceSelectors.getOrPut(descriptor) {
|
return objectInstanceSelectors.getOrPut(descriptor) {
|
||||||
val name = descriptor.name.asString().decapitalize().mangleIfSpecialFamily("get")
|
val name = descriptor.name.asString().decapitalize().mangleIfSpecialFamily("get")
|
||||||
|
|
||||||
StringBuilder(name).mangledSequence { append("_") }
|
StringBuilder(name).mangledBySuffixUnderscores()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +311,7 @@ internal class ObjCExportNamerImpl(
|
|||||||
if (index == 0) lower else lower.capitalize()
|
if (index == 0) lower else lower.capitalize()
|
||||||
}.joinToString("").mangleIfSpecialFamily("the")
|
}.joinToString("").mangleIfSpecialFamily("the")
|
||||||
|
|
||||||
StringBuilder(name).mangledSequence { append("_") }
|
StringBuilder(name).mangledBySuffixUnderscores()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,8 +319,8 @@ internal class ObjCExportNamerImpl(
|
|||||||
val any = builtIns.any
|
val any = builtIns.any
|
||||||
|
|
||||||
predefinedClassNames.forEach { descriptor, name ->
|
predefinedClassNames.forEach { descriptor, name ->
|
||||||
// Note: it is a hack.
|
objCClassNames.forceAssign(descriptor, name.objCName)
|
||||||
classNames.forceAssign(descriptor, name.swiftName)
|
swiftClassAndProtocolNames.forceAssign(descriptor, name.swiftName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ClassDescriptor.method(name: String) =
|
fun ClassDescriptor.method(name: String) =
|
||||||
@@ -336,7 +375,7 @@ internal class ObjCExportNamerImpl(
|
|||||||
private fun String.startsWithWords(words: String) = this.startsWith(words) &&
|
private fun String.startsWithWords(words: String) = this.startsWith(words) &&
|
||||||
(this.length == words.length || !this[words.length].isLowerCase())
|
(this.length == words.length || !this[words.length].isLowerCase())
|
||||||
|
|
||||||
private abstract inner class Mapping<T : Any, N>() {
|
private abstract inner class Mapping<in T : Any, N>() {
|
||||||
private val elementToName = mutableMapOf<T, N>()
|
private val elementToName = mutableMapOf<T, N>()
|
||||||
private val nameToElements = mutableMapOf<N, MutableList<T>>()
|
private val nameToElements = mutableMapOf<N, MutableList<T>>()
|
||||||
|
|
||||||
@@ -390,6 +429,8 @@ private inline fun StringBuilder.mangledSequence(crossinline mangle: StringBuild
|
|||||||
this@mangledSequence.toString()
|
this@mangledSequence.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.mangledBySuffixUnderscores() = this.mangledSequence { append("_") }
|
||||||
|
|
||||||
private fun ObjCExportMapper.canHaveCommonSubtype(first: ClassDescriptor, second: ClassDescriptor): Boolean {
|
private fun ObjCExportMapper.canHaveCommonSubtype(first: ClassDescriptor, second: ClassDescriptor): Boolean {
|
||||||
if (first.isSubclassOf(second) || second.isSubclassOf(first)) {
|
if (first.isSubclassOf(second) || second.isSubclassOf(first)) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ func testDataClass() throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCompanionObj() throws {
|
func testCompanionObj() throws {
|
||||||
try assertEquals(actual: WithCompanionAndObjectCompanion().str, expected: "String")
|
try assertEquals(actual: WithCompanionAndObject.Companion().str, expected: "String")
|
||||||
try assertEquals(actual: ValuesKt.getCompanionObject().str, expected: "String")
|
try assertEquals(actual: ValuesKt.getCompanionObject().str, expected: "String")
|
||||||
|
|
||||||
let namedFromCompanion = ValuesKt.getCompanionObject().named
|
let namedFromCompanion = ValuesKt.getCompanionObject().named
|
||||||
|
|||||||
Reference in New Issue
Block a user