diff --git a/libraries/tools/kotlin-stdlib-gen/pom.xml b/libraries/tools/kotlin-stdlib-gen/pom.xml index 6f21df7b668..59921ca6fd7 100644 --- a/libraries/tools/kotlin-stdlib-gen/pom.xml +++ b/libraries/tools/kotlin-stdlib-gen/pom.xml @@ -16,11 +16,28 @@ kotlin-stdlib-gen 1.1-SNAPSHOT - 1.0.4 - 1.0 + 1.1-M03 + 1.1 ${env.JAVA_HOME} + + + false + bintray-kotlin-kotlin-eap-1.1 + bintray + http://dl.bintray.com/kotlin/kotlin-eap-1.1 + + + + + false + bintray-kotlin-kotlin-eap-1.1 + bintray + http://dl.bintray.com/kotlin/kotlin-eap-1.1 + + + diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt index 07899c2992e..3ec60fc4896 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt @@ -64,7 +64,7 @@ fun generateCollectionsJsAPI(outDir: File) { fun generateCommonAPI(outDir: File) { (commonGenerators + ::specialJVM + ::specialJS).flatMap { it().sortedBy { it.signature }.asSequence() } - .groupByFileAndWrite(outDir, platform = null) + .groupByFileAndWrite(outDir, platform = Platform.Common) } @@ -72,7 +72,7 @@ fun generateCommonAPI(outDir: File) { private fun Sequence.groupByFileAndWrite( outDir: File, - platform: Platform?, + platform: Platform, fileNameBuilder: (SourceFile) -> String = { "_${it.name.capitalize()}.kt" } ) { val groupedConcreteFunctions = map { it.instantiate(platform) }.flatten().groupBy { it.sourceFile } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index a5d99b375ff..bb86aa3d34f 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -140,7 +140,7 @@ fun arrays(): List { val arrayType = primitive.name + "Array" f("to$arrayType()") { only(ArraysOfObjects, Collections) - buildFamilies.forEach { family -> onlyPrimitives(family, primitive) } + buildFamilies.default!!.forEach { family -> onlyPrimitives(family, primitive) } doc(ArraysOfObjects) { "Returns an array of ${primitive.name} containing all of the elements of this generic array." } doc(Collections) { "Returns an array of ${primitive.name} containing all of the elements of this collection." } returns(arrayType) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt index 2135000cae7..8a2bdb1c1f4 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Numeric.kt @@ -7,7 +7,7 @@ fun numeric(): List { templates add f("sum()") { exclude(Strings) - buildFamilies.forEach { family -> onlyPrimitives(family, numericPrimitives) } + buildFamilies.default!!.forEach { family -> onlyPrimitives(family, numericPrimitives) } doc { f -> "Returns the sum of all elements in the ${f.collection}." } returns("SUM") platformName("sumOf") @@ -24,7 +24,7 @@ fun numeric(): List { templates add f("average()") { exclude(Strings) - buildFamilies.forEach { family -> onlyPrimitives(family, numericPrimitives) } + buildFamilies.default!!.forEach { family -> onlyPrimitives(family, numericPrimitives) } doc { f -> "Returns an average value of elements in the ${f.collection}."} returns("Double") platformName("averageOf") diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt index bbeafb4675b..543ec2cede1 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt @@ -71,6 +71,7 @@ enum class Inline { } enum class Platform { + Common, JVM, JS } @@ -78,48 +79,91 @@ enum class Platform { data class Deprecation(val message: String, val replaceWith: String? = null, val level: DeprecationLevel = DeprecationLevel.WARNING) val forBinaryCompatibility = Deprecation("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +open class BaseSpecializedProperty { + protected open fun onKeySet(key: TKey) {} + + var default: TValue? = null + protected set +} + +open class PlatformSpecializedProperty() : BaseSpecializedProperty() { + private val valueBuilders = HashMap TValue)>>() + + operator fun get(platform: Platform, key: TKey): TValue? = run { + valueBuilders[platform]?.get(key) + ?: valueBuilders[null]?.get(key) + ?: valueBuilders[platform]?.get(null) + ?: valueBuilders[null]?.get(null) + }?.let { it(key) } + + fun isSpecializedFor(platform: Platform, key: TKey): Boolean + = valueBuilders[platform]?.contains(key) == true || valueBuilders[null]?.contains(key) == true + + operator fun set(platform: Platform?, keys: Collection, value: TValue) { + if (platform == null && keys.isEmpty()) default = value + set(platform, keys, { value }) + } + operator fun set(platform: Platform?, keys: Collection, value: (TKey)->TValue) { + val valueBuilders = valueBuilders.getOrPut(platform) { hashMapOf() } + if (keys.isEmpty()) + valueBuilders[null] = value; + else + for (key in keys) { + valueBuilders[key] = value + onKeySet(key) + } + } + +} + +open class SpecializedProperty() : BaseSpecializedProperty() { + private val valueBuilders = HashMap TValue)>() + + operator fun get(key: TKey): TValue? = (valueBuilders[key] ?: valueBuilders[null])?.let { it(key) } + + + operator fun set(keys: Collection, value: TValue) { + if (keys.isEmpty()) default = value + set(keys, { value }) + } + operator fun set(keys: Collection, value: (TKey)->TValue) { + if (keys.isEmpty()) + valueBuilders[null] = value; + else + for (key in keys) { + valueBuilders[key] = value + onKeySet(key) + } + } + +} + +operator fun SpecializedProperty.invoke(vararg keys: TKey, valueBuilder: (TKey) -> TValue) = set(keys.asList(), valueBuilder) +operator fun SpecializedProperty.invoke(value: TValue, vararg keys: TKey) = set(keys.asList(), value) +operator fun PlatformSpecializedProperty.invoke(vararg keys: TKey, valueBuilder: (TKey) -> TValue) = set(null, keys.asList(), valueBuilder) +operator fun PlatformSpecializedProperty.invoke(value: TValue, vararg keys: TKey) = set(null, keys.asList(), value) +operator fun PlatformSpecializedProperty.invoke(platform: Platform, vararg keys: TKey, valueBuilder: (TKey) -> TValue) = set(platform, keys.asList(), valueBuilder) +operator fun PlatformSpecializedProperty.invoke(platform: Platform, value: TValue, vararg keys: TKey) = set(platform, keys.asList(), value) + +typealias FamilyProperty = SpecializedProperty +typealias PlatformProperty = SpecializedProperty +typealias PlatformFamilyProperty = PlatformSpecializedProperty +typealias PlatformPrimitiveProperty = PlatformSpecializedProperty + +class DeprecationProperty() : PlatformFamilyProperty() +operator fun DeprecationProperty.invoke(value: String, vararg keys: Family) = set(null, keys.asList(), Deprecation(value)) + +class DocProperty() : PlatformFamilyProperty() +operator fun DocProperty.invoke(vararg keys: Family, valueBuilder: DocExtensions.(Family) -> String) = set(null, keys.asList(), { f -> valueBuilder(DocExtensions, f) }) + +class InlineProperty : PlatformFamilyProperty() +operator fun InlineProperty.invoke(vararg keys: Family) = set(null, keys.asList(), Inline.Yes) +operator fun InlineProperty.invoke(value: Boolean, vararg keys: Family) = set(null, keys.asList(), if (value) Inline.Yes else Inline.No) + class ConcreteFunction(val textBuilder: (Appendable) -> Unit, val sourceFile: SourceFile) class GenericFunction(val signature: String, val keyword: String = "fun") { - open class SpecializedProperty() { - private val valueBuilders = HashMap TValue)>() - - operator fun get(key: TKey): TValue? = (valueBuilders[key] ?: valueBuilders[null] ?: null)?.let { it(key) } - - operator fun set(keys: Collection, value: (TKey)->TValue) { - if (keys.isEmpty()) - valueBuilders[null] = value; - else - for (key in keys) { - valueBuilders[key] = value - onKeySet(key) - } - } - - protected open fun onKeySet(key: TKey) {} - } - - operator fun SpecializedProperty.invoke(vararg keys: TKey, valueBuilder: (TKey) -> TValue) = set(keys.asList(), valueBuilder) - operator fun SpecializedProperty.invoke(value: TValue, vararg keys: TKey) = set(keys.asList(), { value }) - - open class FamilyProperty() : SpecializedProperty() - open class PrimitiveProperty() : SpecializedProperty() -// -// operator fun FamilyProperty.invoke(vararg keys: Family, valueBuilder: (Family) -> TValue) = set(keys.map { null to it }, valueBuilder) -// operator fun SpecializedProperty.invoke(value: TValue, vararg keys: TKey) = set(keys.asList(), { value }) - - class DeprecationProperty() : FamilyProperty() - operator fun DeprecationProperty.invoke(value: String, vararg keys: Family) = set(keys.asList(), { Deprecation(value) }) - - class DocProperty() : FamilyProperty() - operator fun DocProperty.invoke(vararg keys: Family, valueBuilder: DocExtensions.(Family) -> String) = set(keys.asList(), { f -> valueBuilder(DocExtensions, f) }) - - class InlineProperty() : FamilyProperty() - operator fun InlineProperty.invoke(vararg keys: Family) = set(keys.asList(), { Inline.Yes }) - operator fun InlineProperty.invoke(value: Boolean, vararg keys: Family) = set(keys.asList(), { if (value) Inline.Yes else Inline.No }) - - data class TypeParameter(val original: String, val name: String, val constraint: TypeRef? = null) { constructor(simpleName: String) : this(simpleName, simpleName) @@ -139,31 +183,35 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { var toNullableT: Boolean = false - val receiverAsterisk = FamilyProperty() + val receiverAsterisk = PlatformFamilyProperty() - val buildFamilies = LinkedHashSet(defaultFamilies) - val buildPrimitives = LinkedHashSet(defaultPrimitives) - val buildFamilyPrimitives = FamilyProperty>() + val buildFamilies = PlatformProperty>().apply { + invoke(defaultFamilies) + } + //val buildFamilies = LinkedHashSet(defaultFamilies) + val buildFamilyPrimitives = PlatformFamilyProperty>().apply { + invoke(defaultPrimitives) + } - val customReceiver = FamilyProperty() - val customSignature = FamilyProperty() + val customReceiver = PlatformFamilyProperty() + val customSignature = PlatformFamilyProperty() val deprecate = DeprecationProperty() val doc = DocProperty() - val platformName = PrimitiveProperty() + val platformName = PlatformPrimitiveProperty() val inline = InlineProperty() val jvmOnly = FamilyProperty() - val since = FamilyProperty() + val since = PlatformFamilyProperty() val typeParams = ArrayList() - val returns = FamilyProperty() + val returns = PlatformFamilyProperty() val visibility = FamilyProperty() val operator = FamilyProperty() val infix = FamilyProperty() - val external = FamilyProperty() - val body = object : FamilyProperty() { + val external = PlatformFamilyProperty() + val body = object : PlatformFamilyProperty() { override fun onKeySet(key: Family) = include(key) } val customPrimitiveBodies = HashMap, String>() - val annotations = FamilyProperty() + val annotations = PlatformFamilyProperty() val sourceFile = FamilyProperty() fun bodyForTypes(family: Family, vararg primitiveTypes: PrimitiveType, b: (PrimitiveType) -> String) { @@ -178,12 +226,11 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } fun exclude(vararg families: Family) { - buildFamilies.removeAll(families.toList()) + buildFamilies(buildFamilies.default!! - families) } fun only(vararg families: Family) { - buildFamilies.clear() - buildFamilies.addAll(families.toList()) + buildFamilies(families.toSet()) } fun only(vararg primitives: PrimitiveType) { @@ -191,8 +238,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } fun only(primitives: Collection) { - buildPrimitives.clear() - buildPrimitives.addAll(primitives) + buildFamilyPrimitives(primitives.toSet()) } fun onlyPrimitives(family: Family, vararg primitives: PrimitiveType) { @@ -204,33 +250,29 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } fun include(vararg families: Family) { - buildFamilies.addAll(families.toList()) + buildFamilies(buildFamilies.default!! + families) } fun exclude(vararg p: PrimitiveType) { - buildPrimitives.removeAll(p.toList()) + buildFamilyPrimitives(buildFamilyPrimitives.default!! - p) } - fun include(vararg p: PrimitiveType) { - buildPrimitives.addAll(p.toList()) - } - - fun instantiate(platform: Platform?, vararg families: Family = Family.values()): List { + fun instantiate(platform: Platform, vararg families: Family = Family.values()): List { return families .sortedBy { it.ordinal } - .filter { buildFamilies.contains(it) } + .filter { buildFamilies[platform]!!.contains(it) } .filter { platform == Platform.JVM || jvmOnly[it] != true } - .flatMap { family -> instantiate(family, platform == null) } + .flatMap { family -> instantiate(family, platform) } } - fun instantiate(f: Family, headerOnly: Boolean): List { - val onlyPrimitives = buildFamilyPrimitives[f] + fun instantiate(f: Family, platform: Platform): List { + val onlyPrimitives = buildFamilyPrimitives[platform, f]!! - if (f.isPrimitiveSpecialization || onlyPrimitives != null) { - return (onlyPrimitives ?: buildPrimitives).sortedBy { it.ordinal } - .map { primitive -> ConcreteFunction( { build(it, f, primitive, headerOnly) }, sourceFileFor(f) ) } + if (f.isPrimitiveSpecialization || buildFamilyPrimitives.isSpecializedFor(platform, f)) { + return (onlyPrimitives).sortedBy { it.ordinal } + .map { primitive -> ConcreteFunction( { build(it, f, primitive, platform) }, sourceFileFor(f) ) } } else { - return listOf(ConcreteFunction( { build(it, f, null, headerOnly) }, sourceFileFor(f) )) + return listOf(ConcreteFunction( { build(it, f, null, platform) }, sourceFileFor(f) )) } } @@ -269,8 +311,9 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } */ - fun build(builder: Appendable, f: Family, primitive: PrimitiveType?, headerOnly: Boolean) { - val returnType = returns[f] ?: throw RuntimeException("No return type specified for $signature") + fun build(builder: Appendable, f: Family, primitive: PrimitiveType?, platform: Platform) { + val headerOnly: Boolean = platform == Platform.Common + val returnType = returns[platform, f] ?: throw RuntimeException("No return type specified for $signature") fun renderType(expression: String, receiver: String, self: String): String { val t = StringTokenizer(expression, " \t\n,:()<>?.", true) @@ -339,7 +382,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { return answer.toString() } - val isAsteriskOrT = if (receiverAsterisk[f] == true) "*" else "T" + val isAsteriskOrT = if (receiverAsterisk[platform, f] == true) "*" else "T" val self = (when (f) { Iterables -> "Iterable<$isAsteriskOrT>" Collections -> "Collection<$isAsteriskOrT>" @@ -359,7 +402,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { Generic -> "T" }) - val receiver = (customReceiver[f] ?: self).let { renderType(it, it, self) } + val receiver = (customReceiver[platform, f] ?: self).let { renderType(it, it, self) } fun String.renderType(): String = renderType(this, receiver, self) @@ -388,7 +431,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } } - doc[f]?.let { methodDoc -> + doc[platform, f]?.let { methodDoc -> builder.append("/**\n") StringReader(methodDoc.trim()).forEachLine { line -> builder.append(" * ").append(line.trim()).append("\n") @@ -396,7 +439,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { builder.append(" */\n") } - deprecate[f]?.let { deprecated -> + deprecate[platform, f]?.let { deprecated -> val args = listOfNotNull( "\"${deprecated.message}\"", deprecated.replaceWith?.let { "ReplaceWith(\"$it\")" }, @@ -406,7 +449,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } if (!f.isPrimitiveSpecialization && primitive != null) { - platformName[primitive] + platformName[platform, primitive] ?.replace("", primitive.name) ?.let { platformName -> builder.append("@kotlin.jvm.JvmName(\"${platformName}\")\n")} } @@ -414,13 +457,13 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { if (jvmOnly[f] ?: false) { builder.append("@kotlin.jvm.JvmVersion\n") } - since[f]?.let { since -> + since[platform, f]?.let { since -> builder.append("@SinceKotlin(\"$since\")\n") } - annotations[f]?.let { builder.append(it).append('\n') } + annotations[platform, f]?.let { builder.append(it).append('\n') } - if (inline[f] == Inline.Only) { + if (inline[platform, f] == Inline.Only) { builder.append("@kotlin.internal.InlineOnly").append('\n') } @@ -428,9 +471,9 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { if (headerOnly) { builder.append("header ") } - if (external[f] == true) + if (external[platform, f] == true) builder.append("external ") - if (inline[f]?.isInline() == true) + if (inline[platform, f]?.isInline() == true) builder.append("inline ") if (infix[f] == true) builder.append("infix ") @@ -448,7 +491,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { builder.append(receiverType) if (receiverType.isNotEmpty()) builder.append('.') - builder.append("${(customSignature[f] ?: signature).renderType()}: ${returnType.renderType()}") + builder.append("${(customSignature[platform, f] ?: signature).renderType()}: ${returnType.renderType()}") if (headerOnly) { builder.append("\n\n") @@ -459,8 +502,8 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { val body = ( primitive?.let { customPrimitiveBodies[f to primitive] } ?: - body[f] ?: - deprecate[f]?.replaceWith?.let { "return $it" } ?: + body[platform, f] ?: + deprecate[platform, f]?.replaceWith?.let { "return $it" } ?: throw RuntimeException("No body specified for $signature for ${f to primitive}") ).trim('\n') val indent: Int = body.takeWhile { it == ' ' }.length