Unify operations on Array<T> and Array<out T> (copyOf, copyOfRange) which return the same type as the receiver.
This commit is contained in:
@@ -203,8 +203,8 @@ public fun ShortArray.binarySearch(element: Short, fromIndex: Int = 0, toIndex:
|
||||
/**
|
||||
* Returns new array which is a copy of the original array.
|
||||
*/
|
||||
public fun <T> Array<out T>.copyOf(): Array<out T> {
|
||||
return Arrays.copyOf(this, size())
|
||||
public fun <T, A: Array<out T>> A.copyOf(): A {
|
||||
return Arrays.copyOf(this, size()) as A
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,14 +263,6 @@ public fun ShortArray.copyOf(): ShortArray {
|
||||
return Arrays.copyOf(this, size())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new array which is a copy of the original array.
|
||||
*/
|
||||
platformName("mutableCopyOf")
|
||||
public fun <T> Array<T>.copyOf(): Array<T> {
|
||||
return Arrays.copyOf(this, size())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new array which is a copy of the original array.
|
||||
*/
|
||||
@@ -345,8 +337,8 @@ public fun <T> Array<T>.copyOf(newSize: Int): Array<T?> {
|
||||
/**
|
||||
* Returns new array which is a copy of range of original array.
|
||||
*/
|
||||
public fun <T> Array<out T>.copyOfRange(fromIndex: Int, toIndex: Int): Array<out T> {
|
||||
return Arrays.copyOfRange(this, fromIndex, toIndex)
|
||||
public fun <T, A: Array<out T>> A.copyOfRange(fromIndex: Int, toIndex: Int): A {
|
||||
return Arrays.copyOfRange(this, fromIndex, toIndex) as A
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,14 +397,6 @@ public fun ShortArray.copyOfRange(fromIndex: Int, toIndex: Int): ShortArray {
|
||||
return Arrays.copyOfRange(this, fromIndex, toIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new array which is a copy of range of original array.
|
||||
*/
|
||||
platformName("mutableCopyOfRange")
|
||||
public fun <T> Array<T>.copyOfRange(fromIndex: Int, toIndex: Int): Array<T> {
|
||||
return Arrays.copyOfRange(this, fromIndex, toIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills original array with the provided value.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@ enum class Family {
|
||||
ArraysOfObjects,
|
||||
ArraysOfPrimitives,
|
||||
InvariantArraysOfObjects,
|
||||
ArraysOfObjectsSubtype,
|
||||
Strings,
|
||||
Ranges,
|
||||
RangesOfPrimitives,
|
||||
@@ -167,7 +168,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
|
||||
|
||||
fun build(vararg families: Family = Family.values()): String {
|
||||
val builder = StringBuilder()
|
||||
for (family in families.sortBy { it.name() }) {
|
||||
for (family in families.sortedBy { it.name() }) {
|
||||
if (buildFamilies.contains(family))
|
||||
build(builder, family)
|
||||
}
|
||||
@@ -177,7 +178,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
|
||||
fun build(builder: StringBuilder, f: Family) {
|
||||
val onlyPrimitives = buildFamilyPrimitives[f]
|
||||
if (f.isPrimitiveSpecialization || onlyPrimitives != null) {
|
||||
for (primitive in (onlyPrimitives ?: buildPrimitives).sortBy { it.name() })
|
||||
for (primitive in (onlyPrimitives ?: buildPrimitives).sortedBy { it.name() })
|
||||
build(builder, f, primitive)
|
||||
} else {
|
||||
build(builder, f, null)
|
||||
@@ -262,6 +263,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
|
||||
Sets -> "Set<$isAsteriskOrT>"
|
||||
Sequences -> "Sequence<$isAsteriskOrT>"
|
||||
InvariantArraysOfObjects -> "Array<T>"
|
||||
ArraysOfObjectsSubtype -> "A"
|
||||
ArraysOfObjects -> "Array<${isAsteriskOrT.replace("T", "out T")}>"
|
||||
Strings -> "String"
|
||||
Ranges -> "Range<$isAsteriskOrT>"
|
||||
@@ -275,8 +277,19 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
|
||||
fun String.renderType(): String = renderType(this, receiver)
|
||||
|
||||
fun effectiveTypeParams(): List<String> {
|
||||
fun getGenericTypeParameters(genericType: String) =
|
||||
genericType
|
||||
.dropWhile { it != '<' }
|
||||
.drop(1)
|
||||
.takeWhile { it != '>' }
|
||||
.split(",")
|
||||
.map { it.removePrefix("out").removePrefix("in").trim() }
|
||||
|
||||
// TODO: Model for type parameter
|
||||
val types = ArrayList(typeParams)
|
||||
if (f == ArraysOfObjectsSubtype) {
|
||||
types.add("A: Array<out T>")
|
||||
}
|
||||
if (f == Generic) {
|
||||
// ensure type parameter T, if it's not added to typeParams before
|
||||
if (!types.any { it == "T" || it.startsWith("T:")}) {
|
||||
@@ -285,9 +298,8 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
|
||||
return types
|
||||
}
|
||||
else if (primitive == null && f != Strings) {
|
||||
val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).takeWhile { it != '>' }.split(",")
|
||||
.map { it.removePrefix("out").removePrefix("in").trim() }
|
||||
for (implicit in implicitTypeParameters.reverse()) {
|
||||
val implicitTypeParameters = getGenericTypeParameters(receiver) + types.flatMap { getGenericTypeParameters(it) }
|
||||
for (implicit in implicitTypeParameters.reversed()) {
|
||||
if (implicit != "*" && !types.any { it.startsWith(implicit) || it.startsWith("reified " + implicit) }) {
|
||||
types.add(0, implicit)
|
||||
}
|
||||
@@ -295,7 +307,8 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
|
||||
|
||||
return types
|
||||
} else {
|
||||
// primitive type arrays should drop constraints
|
||||
// remove T as parameter
|
||||
// TODO: Substitute primitive or String instead of T in other parameters from effective types not from original typeParams
|
||||
return typeParams.filter { !it.startsWith("T") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,23 +51,27 @@ fun specialJVM(): List<GenericFunction> {
|
||||
|
||||
|
||||
templates add f("copyOfRange(fromIndex: Int, toIndex: Int)") {
|
||||
only(ArraysOfObjects, InvariantArraysOfObjects, ArraysOfPrimitives)
|
||||
only(ArraysOfObjectsSubtype, ArraysOfPrimitives)
|
||||
doc { "Returns new array which is a copy of range of original array." }
|
||||
returns("SELF")
|
||||
annotations(InvariantArraysOfObjects) { """platformName("mutableCopyOfRange")"""}
|
||||
body {
|
||||
"return Arrays.copyOfRange(this, fromIndex, toIndex)"
|
||||
}
|
||||
body(ArraysOfObjectsSubtype) {
|
||||
"return Arrays.copyOfRange(this, fromIndex, toIndex) as A"
|
||||
}
|
||||
}
|
||||
|
||||
templates add f("copyOf()") {
|
||||
only(ArraysOfObjects, InvariantArraysOfObjects, ArraysOfPrimitives)
|
||||
only(ArraysOfObjectsSubtype, ArraysOfPrimitives)
|
||||
doc { "Returns new array which is a copy of the original array." }
|
||||
returns("SELF")
|
||||
annotations(InvariantArraysOfObjects) { """platformName("mutableCopyOf")"""}
|
||||
body {
|
||||
"return Arrays.copyOf(this, size())"
|
||||
}
|
||||
body(ArraysOfObjectsSubtype) {
|
||||
"return Arrays.copyOf(this, size()) as A"
|
||||
}
|
||||
}
|
||||
|
||||
// This overload can cause nulls if array size is expanding, hence different return overload
|
||||
|
||||
Reference in New Issue
Block a user