[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")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user