From 87c055cc61c88d36cb3283a972209ef1fcad858f Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Sat, 18 Mar 2017 02:52:51 +0300 Subject: [PATCH] Fix progression iterators to respect the Iterator contract. #KT-16923 Fixed --- core/builtins/src/kotlin/ProgressionIterators.kt | 9 ++++++--- .../kotlin/generators/builtins/progressionIterators.kt | 3 ++- libraries/stdlib/test/ranges/RangeIterationTest.kt | 6 ++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/builtins/src/kotlin/ProgressionIterators.kt b/core/builtins/src/kotlin/ProgressionIterators.kt index 5a211127459..83b12d2b3c8 100644 --- a/core/builtins/src/kotlin/ProgressionIterators.kt +++ b/core/builtins/src/kotlin/ProgressionIterators.kt @@ -23,15 +23,16 @@ package kotlin.ranges * @property step the number by which the value is incremented on each step. */ internal class CharProgressionIterator(first: Char, last: Char, val step: Int) : CharIterator() { - private var next = first.toInt() private val finalElement = last.toInt() private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first.toInt() else finalElement override fun hasNext(): Boolean = hasNext override fun nextChar(): Char { val value = next if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() hasNext = false } else { @@ -46,15 +47,16 @@ internal class CharProgressionIterator(first: Char, last: Char, val step: Int) : * @property step the number by which the value is incremented on each step. */ internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : IntIterator() { - private var next = first private val finalElement = last private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first else finalElement override fun hasNext(): Boolean = hasNext override fun nextInt(): Int { val value = next if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() hasNext = false } else { @@ -69,15 +71,16 @@ internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : In * @property step the number by which the value is incremented on each step. */ internal class LongProgressionIterator(first: Long, last: Long, val step: Long) : LongIterator() { - private var next = first private val finalElement = last private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first else finalElement override fun hasNext(): Boolean = hasNext override fun nextLong(): Long { val value = next if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() hasNext = false } else { diff --git a/generators/src/org/jetbrains/kotlin/generators/builtins/progressionIterators.kt b/generators/src/org/jetbrains/kotlin/generators/builtins/progressionIterators.kt index 28a9d1d6898..99ec608bf34 100644 --- a/generators/src/org/jetbrains/kotlin/generators/builtins/progressionIterators.kt +++ b/generators/src/org/jetbrains/kotlin/generators/builtins/progressionIterators.kt @@ -36,15 +36,16 @@ fun integerProgressionIterator(kind: ProgressionKind): String { * @property step the number by which the value is incremented on each step. */ internal class ${t}ProgressionIterator(first: $t, last: $t, val step: $incrementType) : ${t}Iterator() { - private var next = first$toInt private val finalElement = last$toInt private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first$toInt else finalElement override fun hasNext(): Boolean = hasNext override fun next$t(): $t { val value = next if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() hasNext = false } else { diff --git a/libraries/stdlib/test/ranges/RangeIterationTest.kt b/libraries/stdlib/test/ranges/RangeIterationTest.kt index 5f13754f31b..54b6da5459e 100644 --- a/libraries/stdlib/test/ranges/RangeIterationTest.kt +++ b/libraries/stdlib/test/ranges/RangeIterationTest.kt @@ -1,6 +1,8 @@ package test.ranges import org.junit.Test +import test.collections.behaviors.iteratorBehavior +import test.collections.compare import kotlin.test.* public open class RangeIterationTestBase { @@ -41,6 +43,10 @@ public open class RangeIterationTestBase { assertTrue(sequence.none()) else assertEquals(expectedElements, sequence.toList()) + + compare(expectedElements.iterator(), sequence.iterator()) { + iteratorBehavior() + } } }