From 0438c7cf852432912fad1e5974318ba1ce21ecf1 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Thu, 12 Dec 2019 11:16:09 +0700 Subject: [PATCH] [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. --- .../kotlin/native/interop/gen/ObjCStubs.kt | 23 ++++++++----- .../kotlin/native/interop/gen/StubIr.kt | 33 ++++++++++++------- .../interop/gen/StubIrElementBuilders.kt | 24 ++++++++++---- .../native/interop/gen/StubIrExtensions.kt | 8 ++++- .../native/interop/gen/StubIrTextEmitter.kt | 17 +++++----- 5 files changed, 69 insertions(+), 36 deletions(-) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt index 88a3521513c..c698cee7bd3 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt @@ -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(), + constructors = methods.filterIsInstance(), 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 = - listOf(buildClassStub(StubOrigin.None)) + override fun build(): List { + 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) } } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt index abf7f5b0670..b2062a26c17 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt @@ -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 = listOf() ) +// TODO: Consider unifying these classes. sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolder { abstract val superClassInit: SuperClassInit? abstract val interfaces: List abstract val childrenClasses: List abstract val companion : Companion? + abstract val classifier: Classifier class Simple( - val classifier: Classifier, + override val classifier: Classifier, val modality: ClassStubModality, - val constructorParameters: List = emptyList(), + constructors: List = emptyList(), + methods: List = emptyList(), override val superClassInit: SuperClassInit? = null, override val interfaces: List = emptyList(), override val properties: List = emptyList(), @@ -256,27 +259,31 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde override val annotations: List = emptyList(), override val childrenClasses: List = emptyList(), override val companion: Companion? = null, - override val functions: List = emptyList(), override val simpleContainers: List = emptyList() - ) : ClassStub() + ) : ClassStub() { + override val functions: List = constructors + methods + } class Companion( + override val classifier: Classifier, + methods: List = emptyList(), override val superClassInit: SuperClassInit? = null, override val interfaces: List = emptyList(), override val properties: List = emptyList(), override val origin: StubOrigin = StubOrigin.None, override val annotations: List = emptyList(), override val childrenClasses: List = emptyList(), - override val functions: List = emptyList(), override val simpleContainers: List = emptyList() ) : ClassStub() { override val companion: Companion? = null + + override val functions: List = methods } class Enum( - val classifier: Classifier, + override val classifier: Classifier, val entries: List, - val constructorParameters: List = emptyList(), + constructors: List, override val superClassInit: SuperClassInit? = null, override val interfaces: List = emptyList(), override val properties: List = emptyList(), @@ -284,9 +291,10 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde override val annotations: List = emptyList(), override val childrenClasses: List = emptyList(), override val companion: Companion?= null, - override val functions: List = emptyList(), override val simpleContainers: List = emptyList() - ) : ClassStub() + ) : ClassStub() { + override val functions: List = 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, - override val annotations: List, + override val parameters: List = emptyList(), + override val annotations: List = emptyList(), + val isPrimary: Boolean, val visibility: VisibilityModifier = VisibilityModifier.PUBLIC ) : FunctionalStub { diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt index 938430ca664..7adafcdf464 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt @@ -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 diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt index 240985a9d2e..18c35bc621d 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt @@ -61,4 +61,10 @@ val StubContainer.defaultMemberModality: MemberStubModality } is ClassStub.Companion -> MemberStubModality.FINAL is ClassStub.Enum -> MemberStubModality.FINAL - } \ No newline at end of file + } + +/** + * Returns constructor that should be rendered in class header. + */ +val ClassStub.explicitPrimaryConstructor: ConstructorStub? + get() = functions.filterIsInstance().firstOrNull(ConstructorStub::isPrimary) \ No newline at end of file diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt index 565cbd58a6f..71e630c1911 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt @@ -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().apply { addIfNotNull(classStub.superClassInit?.let { renderSuperInit(it) }) addAll(classStub.interfaces.map { renderStubType(it) })