[StubIr] Refactor ClassStub

1. Add explicit primary constructor
2. Add constructor to the companion object

All these changes are required to make ClassStub translation to KmClass easier.
This commit is contained in:
Sergey Bogolepov
2019-12-12 11:16:09 +07:00
committed by Sergey Bogolepov
parent d045bd4b09
commit 0438c7cf85
5 changed files with 69 additions and 36 deletions
@@ -166,7 +166,7 @@ private class ObjCMethodStubBuilder(
context.configuration.disableDesignatedInitializerChecks
val annotations = listOf(AnnotationStub.ObjC.Constructor(method.selector, designated))
val constructor = ConstructorStub(parameters, annotations)
val constructor = ConstructorStub(parameters, annotations, isPrimary = false)
constructor
}
is ObjCCategory -> {
@@ -206,7 +206,7 @@ private class ObjCMethodStubBuilder(
receiver = receiver,
typeParameters = listOf(typeParameter),
external = true,
origin = StubOrigin.None,
origin = StubOrigin.Synthetic,
annotations = annotations,
modality = MemberStubModality.FINAL
)
@@ -434,7 +434,7 @@ internal abstract class ObjCContainerStubBuilder(
val defaultConstructor = if (container is ObjCClass && methodToStub.values.none { it.isDefaultConstructor() }) {
// Always generate default constructor.
// If it is not produced for an init method, then include it manually:
ConstructorStub(listOf(), listOf(), VisibilityModifier.PROTECTED)
ConstructorStub(isPrimary = false, visibility = VisibilityModifier.PROTECTED)
} else null
return Pair(
@@ -448,7 +448,8 @@ internal abstract class ObjCContainerStubBuilder(
return ClassStub.Simple(
classifier,
properties = properties,
functions = methods,
methods = methods.filterIsInstance<FunctionStub>(),
constructors = methods.filterIsInstance<ConstructorStub>(),
origin = origin,
modality = modality,
annotations = listOf(externalObjCAnnotation),
@@ -466,8 +467,13 @@ internal sealed class ObjCClassOrProtocolStubBuilder(
container,
metaContainerStub = object : ObjCContainerStubBuilder(context, container, metaContainerStub = null) {
override fun build(): List<StubIrElement> =
listOf(buildClassStub(StubOrigin.None))
override fun build(): List<StubIrElement> {
val origin = when (container) {
is ObjCProtocol -> StubOrigin.ObjCProtocol(container, isMeta = true)
is ObjCClass -> StubOrigin.ObjCClass(container, isMeta = true)
}
return listOf(buildClassStub(origin))
}
}
)
@@ -493,8 +499,9 @@ internal class ObjCClassStubBuilder(
).toStubIrType()
val superClassInit = SuperClassInit(companionSuper)
val companion = ClassStub.Companion(superClassInit, listOf(objCClassType))
val classStub = buildClassStub(StubOrigin.ObjCClass(clazz), companion)
val companionClassifier = context.getKotlinClassFor(clazz, isMeta = false).nested("Companion")
val companion = ClassStub.Companion(companionClassifier, emptyList(), superClassInit, listOf(objCClassType))
val classStub = buildClassStub(StubOrigin.ObjCClass(clazz, isMeta = false), companion)
return listOf(*metaContainerStub!!.build().toTypedArray(), classStub)
}
}
@@ -159,7 +159,7 @@ sealed class AnnotationStub(val classifier: Classifier) {
ObjC(Classifier.topLevel(cinteropPackage, "ObjCConstructor"))
class ExternalClass(val protocolGetter: String = "", val binaryName: String = "") :
ObjC(Classifier.topLevel(cinteropPackage, "ExternalClass"))
ObjC(Classifier.topLevel(cinteropPackage, "ExternalObjCClass"))
}
sealed class CCall(classifier: Classifier) : AnnotationStub(classifier) {
@@ -238,17 +238,20 @@ class SuperClassInit(
val arguments: List<ValueStub> = listOf()
)
// TODO: Consider unifying these classes.
sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolder {
abstract val superClassInit: SuperClassInit?
abstract val interfaces: List<StubType>
abstract val childrenClasses: List<ClassStub>
abstract val companion : Companion?
abstract val classifier: Classifier
class Simple(
val classifier: Classifier,
override val classifier: Classifier,
val modality: ClassStubModality,
val constructorParameters: List<FunctionParameterStub> = emptyList(),
constructors: List<ConstructorStub> = emptyList(),
methods: List<FunctionStub> = emptyList(),
override val superClassInit: SuperClassInit? = null,
override val interfaces: List<StubType> = emptyList(),
override val properties: List<PropertyStub> = emptyList(),
@@ -256,27 +259,31 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde
override val annotations: List<AnnotationStub> = emptyList(),
override val childrenClasses: List<ClassStub> = emptyList(),
override val companion: Companion? = null,
override val functions: List<FunctionalStub> = emptyList(),
override val simpleContainers: List<SimpleStubContainer> = emptyList()
) : ClassStub()
) : ClassStub() {
override val functions: List<FunctionalStub> = constructors + methods
}
class Companion(
override val classifier: Classifier,
methods: List<FunctionStub> = emptyList(),
override val superClassInit: SuperClassInit? = null,
override val interfaces: List<StubType> = emptyList(),
override val properties: List<PropertyStub> = emptyList(),
override val origin: StubOrigin = StubOrigin.None,
override val annotations: List<AnnotationStub> = emptyList(),
override val childrenClasses: List<ClassStub> = emptyList(),
override val functions: List<FunctionalStub> = emptyList(),
override val simpleContainers: List<SimpleStubContainer> = emptyList()
) : ClassStub() {
override val companion: Companion? = null
override val functions: List<FunctionalStub> = methods
}
class Enum(
val classifier: Classifier,
override val classifier: Classifier,
val entries: List<EnumEntryStub>,
val constructorParameters: List<FunctionParameterStub> = emptyList(),
constructors: List<ConstructorStub>,
override val superClassInit: SuperClassInit? = null,
override val interfaces: List<StubType> = emptyList(),
override val properties: List<PropertyStub> = emptyList(),
@@ -284,9 +291,10 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde
override val annotations: List<AnnotationStub> = emptyList(),
override val childrenClasses: List<ClassStub> = emptyList(),
override val companion: Companion?= null,
override val functions: List<FunctionalStub> = emptyList(),
override val simpleContainers: List<SimpleStubContainer> = emptyList()
) : ClassStub()
) : ClassStub() {
override val functions: List<FunctionalStub> = constructors
}
override val meta: StubContainerMeta = StubContainerMeta()
@@ -419,8 +427,9 @@ class FunctionStub(
// TODO: should we support non-trivial constructors?
class ConstructorStub(
override val parameters: List<FunctionParameterStub>,
override val annotations: List<AnnotationStub>,
override val parameters: List<FunctionParameterStub> = emptyList(),
override val annotations: List<AnnotationStub> = emptyList(),
val isPrimary: Boolean,
val visibility: VisibilityModifier = VisibilityModifier.PUBLIC
) : FunctionalStub {
@@ -121,22 +121,28 @@ internal class StructStubBuilder(
val superClass = context.platform.getRuntimeType("CStructVar")
require(superClass is ClassifierStubType)
val rawPtrConstructorParam = FunctionParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr"))
val primaryConstructor = ConstructorStub(
parameters = listOf(rawPtrConstructorParam),
isPrimary = true,
annotations = emptyList()
)
val superClassInit = SuperClassInit(superClass, listOf(GetConstructorParameter(rawPtrConstructorParam)))
val companionSuper = superClass.nested("Type")
val typeSize = listOf(IntegralConstantStub(def.size, 4, true), IntegralConstantStub(def.align.toLong(), 4, true))
val companionSuperInit = SuperClassInit(companionSuper, typeSize)
val companion = ClassStub.Companion(companionSuperInit)
val companionClassifier = classifier.nested("Companion")
val companion = ClassStub.Companion(companionClassifier, emptyList(), companionSuperInit)
return listOf(ClassStub.Simple(
classifier,
origin = StubOrigin.Struct(decl),
properties = fields.filterNotNull() + if (platform == KotlinPlatform.NATIVE) bitFields else emptyList(),
functions = emptyList(),
constructors = listOf(primaryConstructor),
methods = emptyList(),
modality = ClassStubModality.NONE,
annotations = listOfNotNull(structAnnotation),
superClassInit = superClassInit,
constructorParameters = listOf(rawPtrConstructorParam),
companion = companion
))
}
@@ -176,7 +182,13 @@ internal class StructStubBuilder(
val rawPtrConstructorParam = FunctionParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr"))
val superClassInit = SuperClassInit(superClass, listOf(GetConstructorParameter(rawPtrConstructorParam)))
val origin = StubOrigin.Struct(s)
listOf(ClassStub.Simple(classifier, ClassStubModality.NONE, listOf(rawPtrConstructorParam), superClassInit, origin = origin))
val primaryConstructor = ConstructorStub(listOf(rawPtrConstructorParam), emptyList(), isPrimary = true)
listOf(ClassStub.Simple(
classifier,
ClassStubModality.NONE,
constructors = listOf(primaryConstructor),
superClassInit = superClassInit,
origin = origin))
}
KotlinPlatform.NATIVE -> emptyList()
}
@@ -220,11 +232,11 @@ internal class EnumStubBuilder(
val aliases = aliasConstants.filter { it.value == constant.value }.map { EnumEntryStub.Alias(it.name) }
EnumEntryStub(constant.name, literal, aliases)
}
val primaryConstructor = ConstructorStub(listOf(constructorParameter), emptyList(), isPrimary = true)
val enum = ClassStub.Enum(clazz, canonicalEntries,
constructors = listOf(primaryConstructor),
properties = listOf(valueProperty),
origin = StubOrigin.Enum(enumDef),
constructorParameters = listOf(constructorParameter),
interfaces = listOf(context.platform.getRuntimeType("CEnum"))
)
context.bridgeComponentsBuilder.enumToTypeMirror[enum] = baseTypeMirror
@@ -61,4 +61,10 @@ val StubContainer.defaultMemberModality: MemberStubModality
}
is ClassStub.Companion -> MemberStubModality.FINAL
is ClassStub.Enum -> MemberStubModality.FINAL
}
}
/**
* Returns constructor that should be rendered in class header.
*/
val ClassStub.explicitPrimaryConstructor: ConstructorStub?
get() = functions.filterIsInstance<ConstructorStub>().firstOrNull(ConstructorStub::isPrimary)
@@ -160,10 +160,13 @@ class StubIrTextEmitter(
if (element is ClassStub.Enum) {
emitEnumBody(element)
} else {
element.children.forEach {
emitEmptyLine()
it.accept(this, element)
}
element.children
// We render a primary constructor as part of a header.
.filterNot { it is ConstructorStub && it.isPrimary }
.forEach {
emitEmptyLine()
it.accept(this, element)
}
}
}
}
@@ -395,11 +398,7 @@ class StubIrTextEmitter(
is ClassStub.Companion -> "companion object"
is ClassStub.Enum -> renderClassifierDeclaration(classStub.classifier)
}
val constructorParams = when (classStub) {
is ClassStub.Simple -> renderConstructorParams(classStub.constructorParameters)
is ClassStub.Companion -> ""
is ClassStub.Enum -> renderConstructorParams(classStub.constructorParameters)
}
val constructorParams = classStub.explicitPrimaryConstructor?.parameters?.let(this::renderConstructorParams) ?: ""
val inheritance = mutableListOf<String>().apply {
addIfNotNull(classStub.superClassInit?.let { renderSuperInit(it) })
addAll(classStub.interfaces.map { renderStubType(it) })