Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ class IterableOnceExtension[A](val iterable: IterableOnce[A]) extends AnyVal {
if (hint.isEmpty) ""
else s" Hint: $hint"

// if the iterable can only be iterated once, the 'knownSize' will decrement on iteration, so we store the value now
val knownSize = iterable.knownSize

val iter = iterable.iterator
if (iter.isEmpty) {
throw new NoSuchElementException(s"Iterable was expected to have exactly one element, but it is empty.$hintMaybe")
} else {
val res = iter.next()
if (iter.hasNext) {
val collectionSizeHint = iterable.knownSize match {
case -1 => "it has more than one" // cannot be computed cheaply, i.e. without traversing the collection
val collectionSizeHint = knownSize match {
case -1 => "it has more than one" // cannot be computed cheaply
case knownSize => s"it has $knownSize"
}
throw new AssertionError(s"Iterable was expected to have exactly one element, but $collectionSizeHint.$hintMaybe")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class IterableOnceExtensionTests extends AnyWordSpec with Matchers {
ArrayBuffer(1, 2).loneElement
}.getMessage should include("it has 2") // ArrayBuffer can 'cheaply' compute their size, so we can have it in the exception message

intercept[AssertionError] {
Iterator(1, 2).loneElement
}.getMessage should include("it has 2") // should know that it's two elements, even if iterator consumes elements after iteration

intercept[AssertionError] {
Seq(1, 2).loneElement("some context")
}.getMessage should include("it has more than one. Hint: some context")
Expand Down