Sequence operation classification regarding their statefulness and laziness.

#KT-16994 Fixed
This commit is contained in:
Ilya Gorbunov
2017-03-21 16:23:04 +03:00
parent 0a4c43a5f1
commit 4018db680e
17 changed files with 865 additions and 0 deletions
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun aggregates(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -749,6 +750,7 @@ fun aggregates(): List<GenericFunction> {
Returns a sequence which performs the given [action] on each ${f.element} of the original sequence as they pass though it.
"""
}
sequenceClassification(intermediate, stateless)
body(Sequences) {
"""
return map {
@@ -791,5 +793,11 @@ fun aggregates(): List<GenericFunction> {
}
}
templates.forEach {
if (it.sequenceClassification.isEmpty()) {
it.sequenceClassification(terminal)
}
}
return templates
}
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun elements(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -753,5 +754,6 @@ fun elements(): List<GenericFunction> {
}
}
templates.forEach { it.sequenceClassification(terminal) }
return templates
}
@@ -17,6 +17,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun filtering(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -36,6 +37,7 @@ fun filtering(): List<GenericFunction> {
templates add f("drop(n: Int)") {
val n = "\$n"
doc { "Returns a list containing all elements except first [n] elements." }
sequenceClassification(nearly_stateless)
returns("List<T>")
body {
"""
@@ -106,6 +108,7 @@ fun filtering(): List<GenericFunction> {
templates add f("take(n: Int)") {
val n = "\$n"
doc { "Returns a list containing first [n] elements." }
sequenceClassification(nearly_stateless)
returns("List<T>")
body {
"""
@@ -763,5 +766,15 @@ fun filtering(): List<GenericFunction> {
}
}
val terminalOperationPattern = Regex("^\\w+To")
templates.forEach { with (it) {
if (sequenceClassification.isEmpty()) {
sequenceClassification(if (signature.contains("index", ignoreCase = true)) nearly_stateless else stateless)
}
sequenceClassification.add(0, if (terminalOperationPattern in signature) terminal else intermediate)
} }
return templates
}
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun generators(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -18,6 +19,7 @@ fun generators(): List<GenericFunction> {
"""
}
doc(Sequences) { "Returns a sequence containing all elements of the original sequence and then the given [element]." }
sequenceClassification(intermediate, stateless)
returns("List<T>")
returns("SELF", Sets, Sequences)
@@ -29,6 +31,7 @@ fun generators(): List<GenericFunction> {
only(Iterables, Collections, Sets, Sequences)
doc { "Returns a list containing all elements of the original collection and then the given [element]." }
sequenceClassification(intermediate, stateless)
returns("List<T>")
body {
"""
@@ -130,6 +133,7 @@ fun generators(): List<GenericFunction> {
the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result.
"""
}
sequenceClassification(intermediate, stateless)
body(Sequences) {
"""
return sequenceOf(this, elements.asSequence()).flatten()
@@ -185,6 +189,7 @@ fun generators(): List<GenericFunction> {
the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result.
"""
}
sequenceClassification(intermediate, stateless)
body(Sequences) {
"""
return this.plus(elements.asList())
@@ -243,6 +248,7 @@ fun generators(): List<GenericFunction> {
the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result.
"""
}
sequenceClassification(intermediate, stateless)
body(Sequences) {
"""
return sequenceOf(this, elements).flatten()
@@ -263,6 +269,7 @@ fun generators(): List<GenericFunction> {
"""
}
doc(Sequences) { "Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]." }
sequenceClassification(intermediate, nearly_stateless)
returns("List<T>")
returns("SELF", Sets, Sequences)
@@ -301,6 +308,7 @@ fun generators(): List<GenericFunction> {
doc(Sequences) { "Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]." }
sequenceClassification(intermediate, nearly_stateless)
body(Sequences) {
"""
return object: Sequence<T> {
@@ -360,6 +368,7 @@ fun generators(): List<GenericFunction> {
the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result.
"""
}
sequenceClassification(intermediate, stateful)
body(Sequences) {
"""
return object: Sequence<T> {
@@ -412,6 +421,7 @@ fun generators(): List<GenericFunction> {
the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result.
"""
}
sequenceClassification(intermediate, stateful)
body(Sequences) {
"""
if (elements.isEmpty()) return this
@@ -462,6 +472,8 @@ fun generators(): List<GenericFunction> {
Note that the source sequence and the sequence being subtracted are iterated only when an `iterator` is requested from
the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result.
The operation is _intermediate_ for this sequence and _terminal_ and _stateful_ for the [elements] sequence.
"""
}
body(Sequences) {
@@ -489,6 +501,7 @@ fun generators(): List<GenericFunction> {
while *second* list contains elements for which [predicate] yielded `false`.
"""
}
sequenceClassification(terminal)
returns("Pair<List<T>, List<T>>")
body {
"""
@@ -631,6 +644,7 @@ fun generators(): List<GenericFunction> {
Returns a sequence of values built from elements of both collections with same indexes using provided [transform]. Resulting sequence has length of shortest input sequences.
"""
}
sequenceClassification(intermediate, stateless)
typeParam("R")
typeParam("V")
returns("Sequence<V>")
@@ -740,6 +754,7 @@ fun generators(): List<GenericFunction> {
Resulting sequence has length of shortest input sequence.
"""
}
sequenceClassification(intermediate, stateless)
typeParam("R")
returns("Sequence<Pair<T, R>>")
body {
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun guards(): List<GenericFunction> {
val THIS = "\$this"
@@ -10,6 +11,7 @@ fun guards(): List<GenericFunction> {
templates add f("requireNoNulls()") {
only(Iterables, Sequences, InvariantArraysOfObjects, Lists)
doc { "Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements." }
sequenceClassification(intermediate, stateless)
typeParam("T : Any")
toNullableT = true
returns("SELF")
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun mapping(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -300,6 +301,7 @@ fun mapping(): List<GenericFunction> {
@sample samples.collections.Collections.Transformations.groupBy
"""
}
sequenceClassification(terminal, stateful)
typeParam("K")
returns("Map<K, List<T>>")
body { "return groupByTo(LinkedHashMap<K, MutableList<T>>(), keySelector)" }
@@ -321,6 +323,7 @@ fun mapping(): List<GenericFunction> {
@sample samples.collections.Collections.Transformations.groupBy
"""
}
sequenceClassification(terminal, stateful)
returns("M")
body {
"""
@@ -349,6 +352,7 @@ fun mapping(): List<GenericFunction> {
@sample samples.collections.Collections.Transformations.groupByKeysAndValues
"""
}
sequenceClassification(terminal, stateful)
typeParam("K")
typeParam("V")
returns("Map<K, List<V>>")
@@ -375,6 +379,7 @@ fun mapping(): List<GenericFunction> {
@sample samples.collections.Collections.Transformations.groupByKeysAndValues
"""
}
sequenceClassification(terminal, stateful)
returns("M")
body {
"""
@@ -417,5 +422,12 @@ fun mapping(): List<GenericFunction> {
}
}
val terminalOperationPattern = Regex("^\\w+To")
templates.forEach { with (it) {
if (sequenceClassification.isEmpty()) {
sequenceClassification(if (terminalOperationPattern in signature) terminal else intermediate)
sequenceClassification(if (signature.contains("index", ignoreCase = true)) nearly_stateless else stateless)
}
} }
return templates
}
@@ -41,5 +41,7 @@ fun numeric(): List<GenericFunction> {
}
}
templates.forEach { it.sequenceClassification(SequenceClass.terminal) }
return templates
}
@@ -1,6 +1,8 @@
package templates
import templates.Family.*
import templates.SequenceClass.intermediate
import templates.SequenceClass.stateful
fun ordering(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -123,6 +125,7 @@ fun ordering(): List<GenericFunction> {
doc(Sequences) {
"Returns a sequence that yields elements of this sequence sorted according to their natural sort order."
}
sequenceClassification(intermediate, stateful)
body(Sequences) {
"""
return object : Sequence<T> {
@@ -196,6 +199,7 @@ fun ordering(): List<GenericFunction> {
doc(Sequences) {
"Returns a sequence that yields elements of this sequence sorted descending according to their natural sort order."
}
sequenceClassification(intermediate, stateful)
}
templates add f("sortedArrayDescending()") {
@@ -253,6 +257,7 @@ fun ordering(): List<GenericFunction> {
doc(Sequences) {
"Returns a sequence that yields elements of this sequence sorted according to the specified [comparator]."
}
sequenceClassification(intermediate, stateful)
body(Sequences) {
"""
return object : Sequence<T> {
@@ -306,6 +311,7 @@ fun ordering(): List<GenericFunction> {
doc(Sequences) {
"Returns a sequence that yields elements of this sequence sorted according to natural sort order of the value returned by specified [selector] function."
}
sequenceClassification(intermediate, stateful)
body {
"return sortedWith(compareBy(selector))"
@@ -339,6 +345,7 @@ fun ordering(): List<GenericFunction> {
doc(Sequences) {
"Returns a sequence that yields elements of this sequence sorted descending according to natural sort order of the value returned by specified [selector] function."
}
sequenceClassification(intermediate, stateful)
body {
"return sortedWith(compareByDescending(selector))"
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun sets(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -14,6 +15,7 @@ fun sets(): List<GenericFunction> {
The returned set preserves the element iteration order of the original ${f.collection}.
"""
}
sequenceClassification(terminal)
returns("MutableSet<T>")
body {
"""
@@ -51,6 +53,7 @@ fun sets(): List<GenericFunction> {
returns("List<T>")
body { "return this.toMutableSet().toList()" }
sequenceClassification(intermediate, stateful)
returns(Sequences) { "Sequence<T>" }
body(Sequences) { "return this.distinctBy { it }" }
}
@@ -84,6 +87,7 @@ fun sets(): List<GenericFunction> {
inline(false, Sequences)
returns(Sequences) { "Sequence<T>" }
sequenceClassification(intermediate, stateful)
body(Sequences) {
"""
return DistinctSequence(this, selector)
@@ -373,5 +373,7 @@ fun snapshots(): List<GenericFunction> {
}
}
templates.forEach { it.sequenceClassification(SequenceClass.terminal) }
return templates
}
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.SequenceClass.*
fun strings(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -14,6 +15,7 @@ fun strings(): List<GenericFunction> {
elements will be appended, followed by the [truncated] string (which defaults to "...").
"""
}
sequenceClassification(terminal)
typeParam("A : Appendable")
returns { "A" }
body {
@@ -61,6 +63,7 @@ fun strings(): List<GenericFunction> {
elements will be appended, followed by the [truncated] string (which defaults to "...").
"""
}
sequenceClassification(terminal)
exclude(Strings)
returns("String")
@@ -76,6 +76,14 @@ enum class Platform {
JS
}
enum class SequenceClass {
terminal,
intermediate,
stateless,
nearly_stateless,
stateful
}
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)
@@ -213,6 +221,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") {
val customPrimitiveBodies = HashMap<Pair<Family, PrimitiveType>, String>()
val annotations = PlatformFamilyProperty<String>()
val sourceFile = FamilyProperty<SourceFile>()
val sequenceClassification = mutableListOf<SequenceClass>()
fun bodyForTypes(family: Family, vararg primitiveTypes: PrimitiveType, b: (PrimitiveType) -> String) {
include(family)
@@ -225,6 +234,10 @@ class GenericFunction(val signature: String, val keyword: String = "fun") {
typeParams.add(t)
}
fun sequenceClassification(vararg sequenceClass: SequenceClass) {
sequenceClassification.addAll(sequenceClass)
}
fun exclude(vararg families: Family) {
buildFamilies(buildFamilies.default!! - families)
}
@@ -442,6 +455,10 @@ class GenericFunction(val signature: String, val keyword: String = "fun") {
StringReader(methodDoc.trim()).forEachLine { line ->
builder.append(" * ").append(line.trim()).append("\n")
}
if (f == Sequences && sequenceClassification.isNotEmpty()) {
builder.append(" *\n")
builder.append(" * The operation is ${sequenceClassification.joinToString(" and ") { "_${it.toString().replace('_', ' ')}_" }}.\n")
}
builder.append(" */\n")
}