blob: 3f58410a32659ff54eda00743be960bc525fd86c [file]
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package templates
import templates.Family.*
object Snapshots : TemplateGroupBase() {
init {
defaultBuilder {
sequenceClassification(SequenceClass.terminal)
specialFor(ArraysOfUnsigned) {
annotation("@ExperimentalUnsignedTypes")
}
}
}
val f_toCollection = fn("toCollection(destination: C)") {
includeDefault()
include(CharSequences)
} builder {
doc { "Appends all ${f.element.pluralize()} to the given [destination] collection." }
returns("C")
typeParam("C : MutableCollection<in T>")
body {
"""
for (item in this) {
destination.add(item)
}
return destination
"""
}
}
private fun optimizedSequenceToCollection(emptyFactory: String, singleElementFactory: String, dstType: String) =
"""
val it = iterator()
if (!it.hasNext())
return $emptyFactory()
val element = it.next()
if (!it.hasNext())
return $singleElementFactory(element)
val dst = $dstType<T>()
dst.add(element)
while (it.hasNext()) dst.add(it.next())
return dst
"""
val f_toSet = fn("toSet()") {
includeDefault()
include(CharSequences)
} builder {
doc {
"""
Returns a [Set] of all ${f.element.pluralize()}.
The returned set preserves the element iteration order of the original ${f.collection}.
"""
}
returns("Set<T>")
body(Iterables) {
"""
if (this is Collection) {
return when (size) {
0 -> emptySet()
1 -> setOf(if (this is List) this[0] else iterator().next())
else -> toCollection(LinkedHashSet<T>(mapCapacity(size)))
}
}
return toCollection(LinkedHashSet<T>()).optimizeReadOnlySet()
"""
}
body(Sequences) { optimizedSequenceToCollection("emptySet", "setOf", "LinkedHashSet") }
body(CharSequences, ArraysOfObjects, ArraysOfPrimitives) {
val size = f.code.size
val capacity = if (f == CharSequences || primitive == PrimitiveType.Char) "$size.coerceAtMost(128)" else size
"""
return when ($size) {
0 -> emptySet()
1 -> setOf(this[0])
else -> toCollection(LinkedHashSet<T>(mapCapacity($capacity)))
}
"""
}
}
val f_toHashSet = fn("toHashSet()") {
includeDefault()
include(CharSequences)
} builder {
doc { "Returns a new [HashSet] of all ${f.element.pluralize()}." }
returns("HashSet<T>")
body { "return toCollection(HashSet<T>(mapCapacity(collectionSizeOrDefault(12))))" }
body(Sequences) { "return toCollection(HashSet<T>())" }
body(CharSequences, ArraysOfObjects, ArraysOfPrimitives) {
val size = f.code.size
val capacity = if (f == CharSequences || primitive == PrimitiveType.Char) "$size.coerceAtMost(128)" else size
"return toCollection(HashSet<T>(mapCapacity($capacity)))"
}
}
val f_toSortedSet = fn("toSortedSet()") {
includeDefault()
include(CharSequences)
platforms(Platform.JVM)
} builder {
typeParam("T : Comparable<T>")
doc { "Returns a new [SortedSet][java.util.SortedSet] of all ${f.element.pluralize()}." }
returns("java.util.SortedSet<T>")
body { "return toCollection(java.util.TreeSet<T>())" }
}
val f_toSortedSet_comparator = fn("toSortedSet(comparator: Comparator<in T>)") {
include(Iterables, ArraysOfObjects, Sequences)
platforms(Platform.JVM)
} builder {
doc {
"""
Returns a new [SortedSet][java.util.SortedSet] of all ${f.element.pluralize()}.
Elements in the set returned are sorted according to the given [comparator].
"""
}
returns("java.util.SortedSet<T>")
body { "return toCollection(java.util.TreeSet<T>(comparator))" }
}
val f_toMutableList = fn("toMutableList()") {
includeDefault()
include(Collections, CharSequences)
} builder {
doc { "Returns a new [MutableList] filled with all ${f.element.pluralize()} of this ${f.collection}." }
returns("MutableList<T>")
body { "return toCollection(ArrayList<T>())" }
body(Iterables) {
"""
if (this is Collection<T>)
return this.toMutableList()
return toCollection(ArrayList<T>())
"""
}
body(Collections) { "return ArrayList(this)" }
body(CharSequences) { "return toCollection(ArrayList<T>(length))" }
body(ArraysOfObjects) { "return ArrayList(this.asCollection())" }
body(ArraysOfPrimitives) {
"""
val list = ArrayList<T>(size)
for (item in this) list.add(item)
return list
"""
}
}
val f_toList = fn("toList()") {
includeDefault()
include(Maps, CharSequences)
} builder {
doc { "Returns a [List] containing all ${f.element.pluralize()}." }
returns("List<T>")
body { "return this.toMutableList().optimizeReadOnlyList()" }
body(Iterables) {
"""
if (this is Collection) {
return when (size) {
0 -> emptyList()
1 -> listOf(if (this is List) get(0) else iterator().next())
else -> this.toMutableList()
}
}
return this.toMutableList().optimizeReadOnlyList()
"""
}
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
"""
return when (${f.code.size}) {
0 -> emptyList()
1 -> listOf(this[0])
else -> this.toMutableList()
}
"""
}
body(Sequences) { optimizedSequenceToCollection("emptyList", "listOf", "ArrayList") }
specialFor(Maps) {
doc { "Returns a [List] containing all key-value pairs." }
returns("List<Pair<K, V>>")
body {
"""
if (size == 0)
return emptyList()
val iterator = entries.iterator()
if (!iterator.hasNext())
return emptyList()
val first = iterator.next()
if (!iterator.hasNext())
return listOf(first.toPair())
val result = ArrayList<Pair<K, V>>(size)
result.add(first.toPair())
do {
result.add(iterator.next().toPair())
} while (iterator.hasNext())
return result
"""
}
}
}
val f_associate = fn("associate(transform: (T) -> Pair<K, V>)") {
includeDefault()
include(CharSequences)
} builder {
inline()
typeParam("K")
typeParam("V")
returns("Map<K, V>")
doc {
"""
Returns a [Map] containing key-value pairs provided by [transform] function
applied to ${f.element.pluralize()} of the given ${f.collection}.
If any of two pairs would have the same key the last one gets added to the map.
The returned map preserves the entry iteration order of the original ${f.collection}.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associate"
ArraysOfObjects, ArraysOfPrimitives -> "samples.collections.Arrays.Transformations.associateArrayOfPrimitives"
else -> "samples.collections.Collections.Transformations.associate"
})
body {
"""
val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)
return associateTo(LinkedHashMap<K, V>(capacity), transform)
"""
}
body(Sequences) {
"""
return associateTo(LinkedHashMap<K, V>(), transform)
"""
}
body(CharSequences) {
"""
val capacity = mapCapacity(length).coerceAtLeast(16)
return associateTo(LinkedHashMap<K, V>(capacity), transform)
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
val capacity = mapCapacity(size).coerceAtLeast(16)
return associateTo(LinkedHashMap<K, V>(capacity), transform)
"""
}
}
val f_associateTo = fn("associateTo(destination: M, transform: (T) -> Pair<K, V>)") {
includeDefault()
include(CharSequences)
} builder {
inline()
typeParam("K")
typeParam("V")
typeParam("M : MutableMap<in K, in V>")
returns("M")
doc {
"""
Populates and returns the [destination] mutable map with key-value pairs
provided by [transform] function applied to each ${f.element} of the given ${f.collection}.
If any of two pairs would have the same key the last one gets added to the map.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateTo"
ArraysOfObjects, ArraysOfPrimitives -> "samples.collections.Arrays.Transformations.associateArrayOfPrimitivesTo"
else -> "samples.collections.Collections.Transformations.associateTo"
})
body {
"""
for (element in this) {
destination += transform(element)
}
return destination
"""
}
}
val f_associateBy_key = fn("associateBy(keySelector: (T) -> K)") {
includeDefault()
include(CharSequences)
} builder {
inline()
typeParam("K")
doc {
"""
Returns a [Map] containing the ${f.element.pluralize()} from the given ${f.collection} indexed by the key
returned from [keySelector] function applied to each ${f.element}.
If any two ${f.element.pluralize()} would have the same key returned by [keySelector] the last one gets added to the map.
The returned map preserves the entry iteration order of the original ${f.collection}.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateBy"
ArraysOfObjects, ArraysOfPrimitives -> "samples.collections.Arrays.Transformations.associateArrayOfPrimitivesBy"
else -> "samples.collections.Collections.Transformations.associateBy"
})
returns("Map<K, T>")
// Collection size helper methods are private, so we fall back to the calculation from HashSet's Collection
// constructor.
body {
"""
val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, T>(capacity), keySelector)
"""
}
body(Sequences) {
"""
return associateByTo(LinkedHashMap<K, T>(), keySelector)
"""
}
body(CharSequences) {
"""
val capacity = mapCapacity(length).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, T>(capacity), keySelector)
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
val capacity = mapCapacity(size).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, T>(capacity), keySelector)
"""
}
}
val f_associateByTo_key = fn("associateByTo(destination: M, keySelector: (T) -> K)") {
includeDefault()
include(CharSequences)
} builder {
inline()
typeParam("K")
typeParam("M : MutableMap<in K, in T>")
returns("M")
doc {
"""
Populates and returns the [destination] mutable map with key-value pairs,
where key is provided by the [keySelector] function applied to each ${f.element} of the given ${f.collection}
and value is the ${f.element} itself.
If any two ${f.element.pluralize()} would have the same key returned by [keySelector] the last one gets added to the map.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateByTo"
ArraysOfObjects, ArraysOfPrimitives -> "samples.collections.Arrays.Transformations.associateArrayOfPrimitivesByTo"
else -> "samples.collections.Collections.Transformations.associateByTo"
})
body {
"""
for (element in this) {
destination.put(keySelector(element), element)
}
return destination
"""
}
}
val f_associateBy_key_value = fn("associateBy(keySelector: (T) -> K, valueTransform: (T) -> V)") {
includeDefault()
include(CharSequences)
} builder {
inline()
typeParam("K")
typeParam("V")
doc {
"""
Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to ${f.element.pluralize()} of the given ${f.collection}.
If any two ${f.element.pluralize()} would have the same key returned by [keySelector] the last one gets added to the map.
The returned map preserves the entry iteration order of the original ${f.collection}.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateByWithValueTransform"
ArraysOfObjects, ArraysOfPrimitives -> "samples.collections.Arrays.Transformations.associateArrayOfPrimitivesByWithValueTransform"
else -> "samples.collections.Collections.Transformations.associateByWithValueTransform"
})
returns("Map<K, V>")
/**
* Collection size helper methods are private, so we fall back to the calculation from HashSet's Collection
* constructor.
*/
body {
"""
val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, V>(capacity), keySelector, valueTransform)
"""
}
body(Sequences) {
"""
return associateByTo(LinkedHashMap<K, V>(), keySelector, valueTransform)
"""
}
body(CharSequences) {
"""
val capacity = mapCapacity(length).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, V>(capacity), keySelector, valueTransform)
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
val capacity = mapCapacity(size).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, V>(capacity), keySelector, valueTransform)
"""
}
}
val f_associateByTo_key_value = fn("associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V)") {
includeDefault()
include(CharSequences)
} builder {
inline()
typeParam("K")
typeParam("V")
typeParam("M : MutableMap<in K, in V>")
returns("M")
doc {
"""
Populates and returns the [destination] mutable map with key-value pairs,
where key is provided by the [keySelector] function and
and value is provided by the [valueTransform] function applied to ${f.element.pluralize()} of the given ${f.collection}.
If any two ${f.element.pluralize()} would have the same key returned by [keySelector] the last one gets added to the map.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateByToWithValueTransform"
ArraysOfObjects, ArraysOfPrimitives -> "samples.collections.Arrays.Transformations.associateArrayOfPrimitivesByToWithValueTransform"
else -> "samples.collections.Collections.Transformations.associateByToWithValueTransform"
})
body {
"""
for (element in this) {
destination.put(keySelector(element), valueTransform(element))
}
return destination
"""
}
}
val f_associateWith = fn("associateWith(valueSelector: (K) -> V)") {
include(Iterables, Sequences, CharSequences, ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned)
} builder {
inline()
specialFor(ArraysOfPrimitives, ArraysOfUnsigned) { inlineOnly() }
since("1.3")
specialFor(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) {
since("1.4")
}
typeParam("K", primary = true)
typeParam("V")
returns("Map<K, V>")
doc {
"""
Returns a [Map] where keys are ${f.element.pluralize()} from the given ${f.collection} and values are
produced by the [valueSelector] function applied to each ${f.element}.
If any two ${f.element.pluralize()} are equal, the last one gets added to the map.
The returned map preserves the entry iteration order of the original ${f.collection}.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateWith"
else -> "samples.collections.Collections.Transformations.associateWith"
})
body {
val capacity = when (family) {
Iterables -> "mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)"
CharSequences -> "mapCapacity(length.coerceAtMost(128)).coerceAtLeast(16)"
ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned -> if (primitive == PrimitiveType.Char) {
"mapCapacity(size.coerceAtMost(128)).coerceAtLeast(16)"
} else {
"mapCapacity(size).coerceAtLeast(16)"
}
else -> ""
}
"""
val result = LinkedHashMap<K, V>($capacity)
return associateWithTo(result, valueSelector)
"""
}
}
val f_associateWithTo = fn("associateWithTo(destination: M, valueSelector: (K) -> V)") {
include(Iterables, Sequences, CharSequences, ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned)
} builder {
inline()
specialFor(ArraysOfPrimitives, ArraysOfUnsigned) { inlineOnly() }
since("1.3")
specialFor(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) {
since("1.4")
}
typeParam("K", primary = true)
typeParam("V")
typeParam("M : MutableMap<in K, in V>")
returns("M")
doc {
"""
Populates and returns the [destination] mutable map with key-value pairs for each ${f.element} of the given ${f.collection},
where key is the ${f.element} itself and value is provided by the [valueSelector] function applied to that key.
If any two ${f.element.pluralize()} are equal, the last one overwrites the former value in the map.
"""
}
sample(when (family) {
CharSequences -> "samples.text.Strings.associateWithTo"
else -> "samples.collections.Collections.Transformations.associateWithTo"
})
body {
"""
for (element in this) {
destination.put(element, valueSelector(element))
}
return destination
"""
}
}
}