From f64eecbdad93e4d2c82cde4a64cb8f60c293b6c7 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Thu, 5 Dec 2019 11:54:34 +0700 Subject: [PATCH] [StubIr] Get rid of ConstructorParameterStub Replaced it with FunctionParameterStub. --- .../kotlin/native/interop/gen/StubIr.kt | 19 +-- .../interop/gen/StubIrElementBuilders.kt | 17 +- .../native/interop/gen/StubIrTextEmitter.kt | 150 ++++++++++-------- 3 files changed, 100 insertions(+), 86 deletions(-) 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 6522f872646..abf7f5b0670 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 @@ -229,16 +229,8 @@ enum class VisibilityModifier { PRIVATE, PROTECTED, INTERNAL, PUBLIC } -class ConstructorParameterStub(val name: String, val type: StubType, val qualifier: Qualifier = Qualifier.NONE) { - sealed class Qualifier { - class VAL(val overrides: Boolean) : Qualifier() - class VAR(val overrides: Boolean) : Qualifier() - object NONE : Qualifier() - } -} - class GetConstructorParameter( - val constructorParameterStub: ConstructorParameterStub + val constructorParameterStub: FunctionParameterStub ) : ValueStub() class SuperClassInit( @@ -256,7 +248,7 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde class Simple( val classifier: Classifier, val modality: ClassStubModality, - val constructorParameters: List = emptyList(), + val constructorParameters: List = emptyList(), override val superClassInit: SuperClassInit? = null, override val interfaces: List = emptyList(), override val properties: List = emptyList(), @@ -284,7 +276,7 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde class Enum( val classifier: Classifier, val entries: List, - val constructorParameters: List = emptyList(), + val constructorParameters: List = emptyList(), override val superClassInit: SuperClassInit? = null, override val interfaces: List = emptyList(), override val properties: List = emptyList(), @@ -341,6 +333,11 @@ sealed class PropertyAccessor : FunctionalStub { val constant: ConstantStub? = null ) : Getter() + class GetConstructorParameter( + val constructorParameter: FunctionParameterStub, + override val annotations: List = emptyList() + ) : Getter() + class ExternalGetter( override val annotations: List = emptyList() ) : Getter() 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 aef2a0fe172..938430ca664 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 @@ -120,7 +120,7 @@ internal class StructStubBuilder( val superClass = context.platform.getRuntimeType("CStructVar") require(superClass is ClassifierStubType) - val rawPtrConstructorParam = ConstructorParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr")) + val rawPtrConstructorParam = FunctionParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr")) val superClassInit = SuperClassInit(superClass, listOf(GetConstructorParameter(rawPtrConstructorParam))) val companionSuper = superClass.nested("Type") @@ -173,7 +173,7 @@ internal class StructStubBuilder( KotlinPlatform.JVM -> { val classifier = context.getKotlinClassForPointed(s) val superClass = context.platform.getRuntimeType("COpaque") - val rawPtrConstructorParam = ConstructorParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr")) + 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)) @@ -194,8 +194,14 @@ internal class EnumStubBuilder( val baseType = baseTypeMirror.argType.toStubIrType() val clazz = (context.mirror(EnumType(enumDef)) as TypeMirror.ByValue).valueType.classifier - val qualifier = ConstructorParameterStub.Qualifier.VAL(overrides = true) - val valueParamStub = ConstructorParameterStub("value", baseType, qualifier) + val constructorParameter = FunctionParameterStub("value", baseType) + + val valueProperty = PropertyStub( + name = "value", + type = baseType, + kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.GetConstructorParameter(constructorParameter)), + modality = MemberStubModality.OVERRIDE, + origin = StubOrigin.None) val canonicalsByValue = enumDef.constants .groupingBy { it.value } @@ -216,8 +222,9 @@ internal class EnumStubBuilder( } val enum = ClassStub.Enum(clazz, canonicalEntries, + properties = listOf(valueProperty), origin = StubOrigin.Enum(enumDef), - constructorParameters = listOf(valueParamStub), + 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/StubIrTextEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt index c8b0c4d7537..565cbd58a6f 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 @@ -205,61 +205,8 @@ class StubIrTextEmitter( } } - override fun visitProperty(element: PropertyStub, owner: StubContainer?) { - if (element in bridgeBuilderResult.excludedStubs) return - - val modality = renderMemberModality(element.modality, owner) - val receiver = if (element.receiverType != null) "${renderStubType(element.receiverType)}." else "" - val name = if (owner?.isTopLevelContainer == true) { - getTopLevelPropertyDeclarationName(kotlinFile, element.name) - } else { - element.name.asSimpleName() - } - val header = "$receiver$name: ${renderStubType(element.type)}" - - if (element.kind is PropertyStub.Kind.Val && !nativeBridges.isSupported(element.kind.getter) - || element.kind is PropertyStub.Kind.Var && !nativeBridges.isSupported(element.kind.getter)) { - out(annotationForUnableToImport) - out("val $header") - out(" get() = TODO()") - } else { - element.annotations.forEach { - out(renderAnnotation(it)) - } - when (val kind = element.kind) { - is PropertyStub.Kind.Constant -> { - out("${modality}const val $header = ${renderValueUsage(kind.constant)}") - } - is PropertyStub.Kind.Val -> { - val shouldWriteInline = kind.getter is PropertyAccessor.Getter.SimpleGetter && kind.getter.constant != null - if (shouldWriteInline) { - out("${modality}val $header ${renderGetter(kind.getter)}") - } else { - out("${modality}val $header") - indent { - out(renderGetter(kind.getter)) - } - } - } - is PropertyStub.Kind.Var -> { - val isSupported = nativeBridges.isSupported(kind.setter) - val variableKind = if (isSupported) "var" else "val" - - out("$modality$variableKind $header") - indent { - out(renderGetter(kind.getter)) - if (isSupported) { - out(renderSetter(kind.setter)) - } - } - } - } - } - } - - // Try to use the provided name. If failed, mangle it with underscore and try again: - private tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, name: String): String = - scope.declareProperty(name) ?: getTopLevelPropertyDeclarationName(scope, name + "_") + override fun visitProperty(element: PropertyStub, owner: StubContainer?) = + emitProperty(element, owner) override fun visitConstructor(constructorStub: ConstructorStub, owner: StubContainer?) { constructorStub.annotations.forEach { @@ -319,6 +266,11 @@ class StubIrTextEmitter( out(";") emitEmptyLine() + enum.properties.forEach { + emitProperty(it, enum) + emitEmptyLine() + } + block("companion object") { enum.entries.forEach { entry -> entry.aliases.forEach { @@ -340,6 +292,67 @@ class StubIrTextEmitter( } } + // Try to use the provided name. If failed, mangle it with underscore and try again: + private tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, name: String): String = + scope.declareProperty(name) ?: getTopLevelPropertyDeclarationName(scope, name + "_") + + private fun emitProperty(element: PropertyStub, owner: StubContainer?) { + if (element in bridgeBuilderResult.excludedStubs) return + + val modality = renderMemberModality(element.modality, owner) + val receiver = if (element.receiverType != null) "${renderStubType(element.receiverType)}." else "" + val name = if (owner?.isTopLevelContainer == true) { + getTopLevelPropertyDeclarationName(kotlinFile, element.name) + } else { + element.name.asSimpleName() + } + val header = "$receiver$name: ${renderStubType(element.type)}" + + if (element.kind is PropertyStub.Kind.Val && !nativeBridges.isSupported(element.kind.getter) + || element.kind is PropertyStub.Kind.Var && !nativeBridges.isSupported(element.kind.getter)) { + out(annotationForUnableToImport) + out("val $header") + out(" get() = TODO()") + } else { + element.annotations.forEach { + out(renderAnnotation(it)) + } + when (val kind = element.kind) { + is PropertyStub.Kind.Constant -> { + out("${modality}const val $header = ${renderValueUsage(kind.constant)}") + } + is PropertyStub.Kind.Val -> { + val shouldWriteInline = kind.getter.let { + (it is PropertyAccessor.Getter.SimpleGetter && it.constant != null) + // We should render access to constructor parameter inline. + // Otherwise, it may be access to the property itself. (val f: Any get() = f) + || it is PropertyAccessor.Getter.GetConstructorParameter + } + if (shouldWriteInline) { + out("${modality}val $header ${renderGetter(kind.getter)}") + } else { + out("${modality}val $header") + indent { + out(renderGetter(kind.getter)) + } + } + } + is PropertyStub.Kind.Var -> { + val isSupported = nativeBridges.isSupported(kind.setter) + val variableKind = if (isSupported) "var" else "val" + + out("$modality$variableKind $header") + indent { + out(renderGetter(kind.getter)) + if (isSupported) { + out(renderSetter(kind.setter)) + } + } + } + } + } + } + private fun renderFunctionReceiver(receiver: ReceiverParameterStub): String { return renderStubType(receiver.type) } @@ -405,22 +418,13 @@ class StubIrTextEmitter( ClassStubModality.NONE -> "class " } - private fun renderConstructorParams(parameters: List): String = + private fun renderConstructorParams(parameters: List): String = if (parameters.isEmpty()) { "" } else { - parameters.joinToString(prefix = "(", postfix = ")") { renderConstructorParameter(it) } + parameters.joinToString(prefix = "(", postfix = ")") { renderFunctionParameter(it) } } - private fun renderConstructorParameter(parameterStub: ConstructorParameterStub): String { - val prefix = when (parameterStub.qualifier) { - is ConstructorParameterStub.Qualifier.VAL -> if (parameterStub.qualifier.overrides) "override val " else "val " - is ConstructorParameterStub.Qualifier.VAR -> if (parameterStub.qualifier.overrides) "override var " else "var " - ConstructorParameterStub.Qualifier.NONE -> "" - } - return "$prefix${parameterStub.name.asSimpleName()}: ${renderStubType(parameterStub.type)}" - } - private fun renderSuperInit(superClassInit: SuperClassInit): String { val parameters = superClassInit.arguments.joinToString(prefix = "(", postfix = ")") { renderValueUsage(it) } return "${renderStubType(superClassInit.type)}$parameters" @@ -514,10 +518,14 @@ class StubIrTextEmitter( private fun renderGetter(accessor: PropertyAccessor.Getter): String { val annotations = accessor.annotations.joinToString(separator = "") { renderAnnotation(it) + " " } - return annotations + if (accessor is PropertyAccessor.Getter.ExternalGetter) { - "external get" - } else { - "get() = ${renderPropertyAccessorBody(accessor)}" + return annotations + when (accessor) { + is PropertyAccessor.Getter.ExternalGetter -> { + "external get" + } + is PropertyAccessor.Getter.GetConstructorParameter -> "= ${renderPropertyAccessorBody(accessor)}" + else -> { + "get() = ${renderPropertyAccessorBody(accessor)}" + } } } @@ -539,6 +547,8 @@ class StubIrTextEmitter( } } + is PropertyAccessor.Getter.GetConstructorParameter -> accessor.constructorParameter.name + is PropertyAccessor.Getter.ArrayMemberAt -> "arrayMemberAt(${accessor.offset})" is PropertyAccessor.Getter.MemberAt -> {