From d18b086113e579267f15f35bc9f8b7144c604f52 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Mon, 20 Apr 2015 22:16:19 +0300 Subject: [PATCH] Refactor stdlib generator engine. Introduce special class to hold generic function properties. --- .../kotlin-stdlib-gen/src/templates/Engine.kt | 148 ++++++------------ 1 file changed, 47 insertions(+), 101 deletions(-) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt index 7e325f5e104..03e9ccda91d 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt @@ -37,98 +37,61 @@ enum class PrimitiveType(val name: String) { class GenericFunction(val signature: String, val keyword: String = "fun") : Comparable { + + open class SpecializedProperty() { + private val values = HashMap() + + fun get(key: TKey): TValue? = values.getOrElse(key, { values.getOrElse(null, { null }) }) + + fun set(keys: Collection, value: TValue) { + if (keys.isEmpty()) + values[null] = value; + else + for (key in keys) { + values[key] = value + onKeySet(key) + } + } + + fun invoke(vararg keys: TKey, valueBuilder: ()-> TValue) = set(keys.asList(), valueBuilder()) + fun invoke(value: TValue, vararg keys: TKey) = set(keys.asList(), value) + + protected open fun onKeySet(key: TKey) {} + } + + open class FamilyProperty() : SpecializedProperty() + open class PrimitiveProperty() : SpecializedProperty() + + val defaultFamilies = array(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, Strings) val defaultPrimitives = PrimitiveType.values() val numericPrimitives = array(PrimitiveType.Int, PrimitiveType.Long, PrimitiveType.Byte, PrimitiveType.Short, PrimitiveType.Double, PrimitiveType.Float) var toNullableT: Boolean = false - var defaultInline = false var receiverAsterisk = false - val inlineFamilies = HashMap() val buildFamilies = LinkedHashSet(defaultFamilies.toList()) val buildPrimitives = LinkedHashSet(defaultPrimitives.toList()) - var deprecate: String = "" - val deprecates = hashMapOf() - - var doc: String = "" - val docs = HashMap() - - var platformName: String? = null - val platformNames = hashMapOf() - - var defaultBody: String = "" - val bodies = HashMap() - val customPrimitiveBodies = HashMap, String>() - - var defaultReturnType = "" - val returnTypes = HashMap() - + val deprecate = FamilyProperty() + val doc = FamilyProperty() + val platformName = PrimitiveProperty() + val inline = FamilyProperty() val typeParams = ArrayList() - - fun body(vararg families: Family, b: () -> String) { - if (families.isEmpty()) - defaultBody = b() - else { - for (f in families) { - include(f) - bodies[f] = b() - } - } + val returns = FamilyProperty() + val body = object : FamilyProperty() { + override fun onKeySet(key: Family) = include(key) } + val customPrimitiveBodies = HashMap, String>() fun bodyForTypes(family: Family, vararg primitiveTypes: PrimitiveType, b: () -> String) { include(family) - for (f in primitiveTypes) { - customPrimitiveBodies.put(family to f, b()) + for (primitive in primitiveTypes) { + customPrimitiveBodies.put(family to primitive, b()) } } - fun doc(vararg families: Family, b: () -> String) { - if (families.isEmpty()) - doc = b() - else { - for (f in families) { - docs[f] = b() - } - } - } - - fun deprecate(vararg families: Family, b: () -> String) { - if (families.isEmpty()) - deprecate = b() - else { - for (f in families) { - deprecates[f] = b() - } - } - } - - fun platformName(name: String, vararg primitives: PrimitiveType) { - if (primitives.isEmpty()) - platformName = name - else - for (primitive in primitives) { - platformNames[primitive] = name - } - } - - fun returns(vararg families: Family, b: () -> String) { - if (families.isEmpty()) - defaultReturnType = b() - else { - for (f in families) { - returnTypes[f] = b() - } - } - } - - fun returns(r: String) { - defaultReturnType = r - } - fun typeParam(t: String) { typeParams.add(t) } @@ -137,14 +100,6 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp receiverAsterisk = v } - fun inline(value: Boolean, vararg families: Family) { - if (families.isEmpty()) - defaultInline = value - else - for (f in families) - inlineFamilies.put(f, value) - } - fun exclude(vararg families: Family) { buildFamilies.removeAll(families.toList()) } @@ -197,7 +152,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp }.toString() builder.append(text) builder.appendln() - if (deprecates[f] == null && deprecate.isEmpty()) + if (deprecate[f] == null) // (deprecates[f] == null && deprecate.isEmpty()) builder.appendln("deprecated(\"Migrate to using Sequence and respective functions\")") val streamText = text .replace("Sequence", "Stream") @@ -209,9 +164,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp } fun doBuild(builder: StringBuilder, f: Family, primitive: PrimitiveType?) { - val returnType = returnTypes[f] ?: defaultReturnType - if (returnType.isEmpty()) - throw RuntimeException("No return type specified for $signature") + val returnType = returns[f] ?: throw RuntimeException("No return type specified for $signature") val isAsteriskOrT = if (receiverAsterisk) "*" else "T" val receiver = when (f) { @@ -321,8 +274,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp } } - val methodDoc = docs[f] ?: doc - if (methodDoc != "") { + doc[f]?.let { methodDoc -> builder.append("/**\n") StringReader(methodDoc).forEachLine { val line = it.trim() @@ -332,19 +284,19 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp } builder.append(" */\n") } - val deprecated = deprecates[f] ?: deprecate - if (deprecated != "") { + + deprecate[f]?.let { deprecated -> builder.append("deprecated(\"$deprecated\")\n") } if (!f.isPrimitiveSpecialization && primitive != null) { - val platformName = (platformNames[primitive] ?: platformName) ?.let { it.replace("", primitive.name)} - if (platformName != null) - builder.append("platformName(\"${platformName}\")\n") + platformName[primitive] + ?.replace("", primitive.name) + ?.let { platformName -> builder.append("platformName(\"${platformName}\")\n")} } builder.append("public ") - if (inlineFamilies[f] ?: defaultInline) + if (inline[f] == true) builder.append("inline ") builder.append("$keyword ") @@ -364,14 +316,14 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp builder.append(".${signature.renderType()}: ${returnType.renderType()}") if (keyword == "fun") builder.append(" {") - val body = (customPrimitiveBodies[f to primitive] ?: bodies[f] ?: defaultBody).trim("\n") + val body = (customPrimitiveBodies[f to primitive] ?: body[f] ?: throw RuntimeException("No body specified for $signature for ${f to primitive}")).trim('\n') val indent: Int = body.takeWhile { it == ' ' }.length() builder.append('\n') StringReader(body).forEachLine { var count = indent val line = it.dropWhile { count-- > 0 && it == ' ' }.renderType() - if (line.isNotEmpty()) { + if (!line.isEmpty()) { builder.append(" ").append(line) builder.append("\n") } @@ -383,12 +335,6 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp public override fun compareTo(other: GenericFunction): Int = this.signature.compareTo(other.signature) } -fun String.trimTrailingSpaces(): String { - var answer = this; - while (answer.endsWith(' ') || answer.endsWith('\n')) answer = answer.substring(0, answer.length() - 1) - return answer -} - fun f(signature: String, init: GenericFunction.() -> Unit): GenericFunction { val gf = GenericFunction(signature) gf.init()