diff --git a/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/KDocConfig.kt b/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/KDocConfig.kt index 229e6e90c67..be27a10e646 100644 --- a/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/KDocConfig.kt +++ b/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/KDocConfig.kt @@ -95,15 +95,7 @@ class KDocConfig() { protected class LongestFirstStringComparator() : Comparator { override fun compare(s1: String?, s2: String?): Int { - // TODO could we make this kind of code much easier? - if (s1 == s2) return 0 - if (s1 == null) return -1 - if (s2 == null) return 1 - var answer = s1.length() - s2.length() - if (answer == 0) { - answer = s1.compareTo(s2) - } - return answer + return compareBy(s1, s2, { (s: String) -> s.length() }) } override fun equals(obj : Any?) : Boolean { diff --git a/libraries/stdlib/src/Ordering.kt b/libraries/stdlib/src/Ordering.kt new file mode 100644 index 00000000000..546fe9fff82 --- /dev/null +++ b/libraries/stdlib/src/Ordering.kt @@ -0,0 +1,68 @@ +package kotlin + +import java.lang.Iterable +import java.util.Comparator +import java.util.Comparator + +/** + * Helper method for implementing [[Comparable]] methods using a list of functions + * to calculate the values to compare + */ +inline fun compareBy(a: T?, b: T?, vararg functions: Function1): Int { + if (a === b) return 0 + if (a == null) return - 1 + if (b == null) return 1 + for (fn in functions) { + val v1 = fn(a) + val v2 = fn(b) + val diff = compareValues(v1, v2) + if (diff != null) return diff + } + return compareValues(a, b) +} + +/** + * Compares the two values which may be [[Comparable]] otherwise + * the [[#hashCode()]] method is used as the difference + */ +inline fun compareValues(a: T?, b: T?): Int { + if (a == null) return - 1 + if (b == null) return 1 + if (a is Comparable) { + return a.compareTo(b) + } + if (a == b) { + return 0 + } + if (a is Object && b is Object) { + val diff = a.hashCode() - b.hashCode() + return if (diff == 0) 1 else diff + } else { + // TODO??? + return 1 + } +} + +/** + * Creates a comparator using the sequence of functions used to calcualte a value to compare on + */ +inline fun comparator(vararg functions: Function1): Comparator { + return FunctionComparator(functions) +} + +private class FunctionComparator(val functions: Array>): Comparator { + + fun toString(): String { + return "FunctionComparator${functions.toList()}" + } + + override fun compare(o1: T?, o2: T?): Int { + // TODO compile error + //return compareBy(o1, o2, functions) + throw UnsupportedOperationException("TODO") + } + + override fun equals(obj: Any?): Boolean { + return this == obj + } +} \ No newline at end of file diff --git a/libraries/stdlib/test/CompareTest.kt b/libraries/stdlib/test/CompareTest.kt new file mode 100644 index 00000000000..03d6c9d4c85 --- /dev/null +++ b/libraries/stdlib/test/CompareTest.kt @@ -0,0 +1,40 @@ +package test + +import org.junit.Test + +import kotlin.test.* + +class Item(val name: String, val rating: Int) + +/** + */ +class CompareTest { + val v1 = Item("wine", 9) + val v2 = Item("beer", 10) + + Test fun compareByNameFirst() { + val diff = compareBy(v1, v2, {(i: Item) -> i.name}, {(i: Item) -> i.rating}) + assertTrue(diff > 0) + } + + Test fun compareByRatingFirst() { + val diff = compareBy(v1, v2, {(i: Item) -> i.rating}, {(i: Item) -> i.name}) + assertTrue(diff < 0) + } + + Test fun compareSameObjectsByRatingFirst() { + val diff = compareBy(v1, v1, {(i: Item) -> i.rating}, {(i: Item) -> i.name}) + assertTrue(diff == 0) + } + + Test fun createComparator() { + val c = comparator({(i: Item) -> i.rating}, {(i: Item) -> i.name}) + println("Created comparator $c") +/* + val items = arrayList(v1, v2) + items.sort(c) + println("Sorted list in rating order $items") +*/ + + } +} \ No newline at end of file