IDL2K better dictionary support: generate interfaces with builder function
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.idl2k
|
||||
|
||||
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ
|
||||
import java.util.*
|
||||
|
||||
private fun Operation.getterOrSetter() = this.attributes.map { it.call }.toSet().let { attributes ->
|
||||
@@ -22,7 +23,7 @@ fun generateFunction(repository: Repository, function: Operation, functionName:
|
||||
initializer = it.defaultValue,
|
||||
getterSetterNoImpl = false,
|
||||
override = false,
|
||||
readOnly = true,
|
||||
kind = AttributeKind.ARGUMENT,
|
||||
vararg = it.vararg,
|
||||
static = it.static
|
||||
)
|
||||
@@ -66,7 +67,7 @@ fun generateAttribute(putNoImpl: Boolean, repository: Repository, attribute: Att
|
||||
type = mapType(repository, attribute.type),
|
||||
initializer = attribute.defaultValue,
|
||||
getterSetterNoImpl = putNoImpl,
|
||||
readOnly = attribute.readOnly,
|
||||
kind = if (attribute.readOnly) AttributeKind.VAL else AttributeKind.VAR,
|
||||
override = false,
|
||||
vararg = attribute.vararg,
|
||||
static = attribute.static
|
||||
@@ -74,7 +75,7 @@ fun generateAttribute(putNoImpl: Boolean, repository: Repository, attribute: Att
|
||||
|
||||
private fun InterfaceDefinition.superTypes(repository: Repository) = superTypes.map { repository.interfaces[it] }.filterNotNull()
|
||||
private fun resolveDefinitionKind(repository: Repository, iface: InterfaceDefinition, constructors: List<ExtendedAttribute> = iface.findConstructors()): GenerateDefinitionKind =
|
||||
if (iface.dictionary || constructors.isNotEmpty() || iface.superTypes(repository).any { resolveDefinitionKind(repository, it) == GenerateDefinitionKind.CLASS }) {
|
||||
if (constructors.isNotEmpty() || iface.superTypes(repository).any { resolveDefinitionKind(repository, it) == GenerateDefinitionKind.CLASS }) {
|
||||
GenerateDefinitionKind.CLASS
|
||||
} else {
|
||||
GenerateDefinitionKind.TRAIT
|
||||
@@ -82,7 +83,7 @@ private fun resolveDefinitionKind(repository: Repository, iface: InterfaceDefini
|
||||
|
||||
private fun InterfaceDefinition.mapAttributes(repository: Repository) = attributes.map { generateAttribute(!dictionary, repository, it) }
|
||||
private fun InterfaceDefinition.mapOperations(repository: Repository) = operations.flatMap { generateFunctions(repository, it) }
|
||||
private fun Constant.mapConstant(repository : Repository) = GenerateAttribute(name, mapType(repository, type), value, false, true, false, false, true)
|
||||
private fun Constant.mapConstant(repository : Repository) = GenerateAttribute(name, mapType(repository, type), value, false, AttributeKind.VAL, false, false, true)
|
||||
private val EMPTY_CONSTRUCTOR = ExtendedAttribute(null, "Constructor", emptyList())
|
||||
|
||||
fun generateTrait(repository: Repository, iface: InterfaceDefinition): GenerateTraitOrClass {
|
||||
@@ -132,7 +133,8 @@ fun generateTrait(repository: Repository, iface: InterfaceDefinition): GenerateT
|
||||
memberFunctions = (iface.mapOperations(repository) + extensions.flatMap { it.mapOperations(repository) }).distinct().toList(),
|
||||
constants = (iface.constants.map { it.mapConstant(repository) } + extensions.flatMap { it.constants.map { it.mapConstant(repository) } }.distinct().toList()),
|
||||
primaryConstructor = primaryConstructorWithCall,
|
||||
secondaryConstructors = secondaryConstructorsWithCall
|
||||
secondaryConstructors = secondaryConstructorsWithCall,
|
||||
generateBuilderFunction = iface.dictionary
|
||||
)
|
||||
}
|
||||
|
||||
@@ -161,7 +163,8 @@ fun mapUnionType(it: UnionType) = GenerateTraitOrClass(
|
||||
memberFunctions = emptyList(),
|
||||
constants = emptyList(),
|
||||
primaryConstructor = null,
|
||||
secondaryConstructors = emptyList()
|
||||
secondaryConstructors = emptyList(),
|
||||
generateBuilderFunction = false
|
||||
)
|
||||
|
||||
fun generateUnionTypeTraits(allUnionTypes: Sequence<UnionType>): Sequence<GenerateTraitOrClass> = allUnionTypes.map(::mapUnionType)
|
||||
|
||||
@@ -25,12 +25,19 @@ data class Repository(
|
||||
val enums: Map<String, EnumDefinition>
|
||||
)
|
||||
|
||||
data class GenerateAttribute(val name: String, val type: Type, val initializer: String?, val getterSetterNoImpl: Boolean, val readOnly: Boolean, val override: Boolean, var vararg: Boolean, val static: Boolean)
|
||||
enum class AttributeKind {
|
||||
VAL, VAR, ARGUMENT
|
||||
}
|
||||
data class GenerateAttribute(val name: String, val type: Type, val initializer: String?, val getterSetterNoImpl: Boolean, val kind: AttributeKind, val override: Boolean, var vararg: Boolean, val static: Boolean)
|
||||
|
||||
val GenerateAttribute.getterNoImpl: Boolean
|
||||
get() = getterSetterNoImpl
|
||||
val GenerateAttribute.setterNoImpl: Boolean
|
||||
get() = getterSetterNoImpl && !readOnly
|
||||
get() = getterSetterNoImpl && kind == AttributeKind.VAR
|
||||
val GenerateAttribute.isVal: Boolean
|
||||
get() = kind == AttributeKind.VAL
|
||||
val GenerateAttribute.isVar: Boolean
|
||||
get() = kind == AttributeKind.VAR
|
||||
|
||||
val Type.typeSignature: String
|
||||
get() = when {
|
||||
@@ -74,7 +81,8 @@ data class GenerateTraitOrClass(
|
||||
val memberFunctions: List<GenerateFunction>,
|
||||
val constants: List<GenerateAttribute>,
|
||||
val primaryConstructor: ConstructorWithSuperTypeCall?,
|
||||
val secondaryConstructors: List<ConstructorWithSuperTypeCall>
|
||||
val secondaryConstructors: List<ConstructorWithSuperTypeCall>,
|
||||
val generateBuilderFunction: Boolean
|
||||
)
|
||||
|
||||
val GenerateFunction.signature: String
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.jetbrains.idl2k
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
private fun <O : Appendable> O.indent(commented: Boolean, level: Int) {
|
||||
private fun <O : Appendable> O.indent(commented: Boolean = false, level: Int) {
|
||||
if (commented) {
|
||||
append("//")
|
||||
}
|
||||
@@ -11,23 +11,31 @@ private fun <O : Appendable> O.indent(commented: Boolean, level: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Appendable.renderAttributeDeclaration(arg: GenerateAttribute, override: Boolean, open: Boolean, commented: Boolean, level: Int = 1) {
|
||||
indent(commented, level)
|
||||
|
||||
private fun Appendable.renderAttributeDeclaration(arg: GenerateAttribute, override: Boolean, open: Boolean, omitDefaults: Boolean = false) {
|
||||
when {
|
||||
override -> append("override ")
|
||||
open -> append("open ")
|
||||
arg.vararg -> append("vararg ")
|
||||
}
|
||||
|
||||
append(if (arg.readOnly) "val" else "var")
|
||||
append(" ")
|
||||
append(arg.name)
|
||||
append(when(arg.kind) {
|
||||
AttributeKind.VAL -> "val "
|
||||
AttributeKind.VAR -> "var "
|
||||
AttributeKind.ARGUMENT -> ""
|
||||
})
|
||||
append(arg.name.replaceKeywords())
|
||||
append(": ")
|
||||
append(arg.type.render())
|
||||
if (arg.initializer != null) {
|
||||
if (arg.initializer != null && !omitDefaults) {
|
||||
append(" = ")
|
||||
append(arg.initializer.replaceWrongConstants(arg.type))
|
||||
}
|
||||
}
|
||||
|
||||
private fun Appendable.renderAttributeDeclarationAsProperty(arg: GenerateAttribute, override: Boolean, open: Boolean, commented: Boolean, level: Int, omitDefaults: Boolean) {
|
||||
indent(commented, level)
|
||||
|
||||
renderAttributeDeclaration(arg, override, open, omitDefaults)
|
||||
|
||||
appendln()
|
||||
if (arg.getterNoImpl) {
|
||||
@@ -50,19 +58,10 @@ private fun String.replaceWrongConstants(type: Type) = when {
|
||||
}
|
||||
private fun String.replaceKeywords() = if (this in keywords) this + "_" else this
|
||||
|
||||
private fun Appendable.renderArgumentsDeclaration(args: List<GenerateAttribute>, omitDefaults: Boolean) =
|
||||
private fun Appendable.renderArgumentsDeclaration(args: List<GenerateAttribute>, omitDefaults: Boolean = false) =
|
||||
args.map {
|
||||
StringBuilder {
|
||||
if (it.vararg) {
|
||||
append("vararg ")
|
||||
}
|
||||
append(it.name.replaceKeywords())
|
||||
append(": ")
|
||||
append(it.type.render())
|
||||
if (!omitDefaults && it.initializer != null && it.initializer != "") {
|
||||
append(" = ")
|
||||
append(it.initializer.replaceWrongConstants(it.type))
|
||||
}
|
||||
renderAttributeDeclaration(it, it.override, false, omitDefaults)
|
||||
}
|
||||
}.joinTo(this, ", ", "(", ")")
|
||||
|
||||
@@ -90,10 +89,6 @@ private fun Appendable.renderFunctionDeclaration(f: GenerateFunction, override:
|
||||
}
|
||||
|
||||
private fun List<GenerateAttribute>.hasNoVars() = none { it.isVar }
|
||||
private val GenerateAttribute.isVal: Boolean
|
||||
get() = readOnly
|
||||
private val GenerateAttribute.isVar: Boolean
|
||||
get() = !readOnly
|
||||
|
||||
private fun GenerateAttribute.isCommented(parent: String) = "$parent.$name" in commentOutDeclarations || "$parent.$name: ${type.render()}" in commentOutDeclarations
|
||||
private fun GenerateFunction.isCommented(parent: String) =
|
||||
@@ -154,7 +149,13 @@ fun Appendable.render(allTypes: Map<String, GenerateTraitOrClass>, typeNamesToUn
|
||||
.filter { it !in superAttributes && !it.static && (it.isVar || (it.isVal && superAttributesByName[it.name]?.hasNoVars() ?: true)) }
|
||||
.map { it.dynamicIfUnknownType(allTypes.keySet()) }
|
||||
.groupBy { it.signature }.reduceValues().values().forEach { arg ->
|
||||
renderAttributeDeclaration(arg, override = arg.signature in superSignatures, open = iface.kind == GenerateDefinitionKind.CLASS && arg.readOnly, commented = arg.isCommented(iface.name))
|
||||
renderAttributeDeclarationAsProperty(arg,
|
||||
override = arg.signature in superSignatures,
|
||||
open = iface.kind == GenerateDefinitionKind.CLASS && arg.isVal,
|
||||
commented = arg.isCommented(iface.name),
|
||||
omitDefaults = iface.kind == GenerateDefinitionKind.TRAIT,
|
||||
level = 1
|
||||
)
|
||||
}
|
||||
iface.memberFunctions.filter { it !in superFunctions && !it.static }.map { it.dynamicIfUnknownType(allTypes.keySet()) }.groupBy { it.signature }.reduceValues(::betterFunction).values().forEach {
|
||||
renderFunctionDeclaration(it.fixRequiredArguments(iface.name), it.signature in superSignatures, commented = it.isCommented(iface.name))
|
||||
@@ -168,10 +169,10 @@ fun Appendable.render(allTypes: Map<String, GenerateTraitOrClass>, typeNamesToUn
|
||||
indent(false, 1)
|
||||
appendln("companion object {")
|
||||
iface.constants.forEach {
|
||||
renderAttributeDeclaration(it, override = false, open = false, level = 2, commented = it.isCommented(iface.name))
|
||||
renderAttributeDeclarationAsProperty(it, override = false, open = false, level = 2, commented = it.isCommented(iface.name), omitDefaults = false)
|
||||
}
|
||||
staticAttributes.forEach {
|
||||
renderAttributeDeclaration(it, override = false, open = false, level = 2, commented = it.isCommented(iface.name))
|
||||
renderAttributeDeclarationAsProperty(it, override = false, open = false, level = 2, commented = it.isCommented(iface.name), omitDefaults = false)
|
||||
}
|
||||
staticFunctions.forEach {
|
||||
renderFunctionDeclaration(it.fixRequiredArguments(iface.name), override = false, level = 2, commented = it.isCommented(iface.name))
|
||||
@@ -182,6 +183,35 @@ fun Appendable.render(allTypes: Map<String, GenerateTraitOrClass>, typeNamesToUn
|
||||
|
||||
appendln("}")
|
||||
appendln()
|
||||
|
||||
if (iface.generateBuilderFunction) {
|
||||
renderBuilderFunction(iface, allSuperTypes, allTypes.keySet())
|
||||
}
|
||||
}
|
||||
|
||||
fun Appendable.renderBuilderFunction(dictionary: GenerateTraitOrClass, allSuperTypes: List<GenerateTraitOrClass>, allTypes: Set<String>) {
|
||||
val fields = (dictionary.memberAttributes + allSuperTypes.flatMap { it.memberAttributes }).distinctBy { it.signature }.map { it.copy(kind = AttributeKind.ARGUMENT) }.dynamicIfUnknownType(allTypes)
|
||||
|
||||
append("inline fun ${dictionary.name}")
|
||||
renderArgumentsDeclaration(fields)
|
||||
appendln(": ${dictionary.name} {")
|
||||
|
||||
indent(level = 1)
|
||||
appendln("val o = js(\"({})\") as ${dictionary.name}")
|
||||
appendln()
|
||||
|
||||
for (field in fields) {
|
||||
indent(level = 1)
|
||||
appendln("o.`${field.name}` = ${field.name.replaceKeywords()}")
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
indent(level = 1)
|
||||
appendln("return o")
|
||||
|
||||
appendln("}")
|
||||
appendln()
|
||||
}
|
||||
|
||||
fun betterFunction(f1: GenerateFunction, f2: GenerateFunction): GenerateFunction =
|
||||
|
||||
Reference in New Issue
Block a user