diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-11-25 09:23:06 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-11-26 15:01:11 +0100 |
commit | f12bb7bda4cd1e145ab5731ae6728f9e8dd2e54c (patch) | |
tree | ee95e631c21aebd0a9eafc6ceb9695808fea1cc3 /test | |
parent | 744425aab4f67805996388ea8620e81d1e4224b0 (diff) | |
download | scala-f12bb7bda4cd1e145ab5731ae6728f9e8dd2e54c.tar.gz scala-f12bb7bda4cd1e145ab5731ae6728f9e8dd2e54c.tar.bz2 scala-f12bb7bda4cd1e145ab5731ae6728f9e8dd2e54c.zip |
SI-4332 Plugs the gaps in views
These currently result in runtime errors:
scala> List(1).view.distinct.force
java.lang.UnsupportedOperationException: SeqView(...).newBuilder
scala> List(1).view.inits.toList
java.lang.UnsupportedOperationException: SeqView(...).newBuilder
Two tests are enclosed:
1. reflect on the views to make any method that returns
`Repr` is overriden in `*ViewLike`. This guards against
new additions to the collections API.
2. exercise the newly added overrides
Some care is needed with `tail`, we must re-override it
in `mutable.IndexedSeqView` to be explicit about the
end point of the slice, because the `IndexedSeqView#Sliced`
defines length in terms of that. (Higher up the chain, it
is just `iterator.size`, that's why `SeqView#tail` just sets
up a slice from `1 to Int.MaxValue`.)
Parallel collections views are not touched, as these are likely
to be deprecated or removed shortly.
Before this change, the test reported the following.
Not all of these methods were buggy. For instance, `sortBy`,
`sortWith` are implemented in terms of `sorted` which
was implemented in `SeqViewLike`. Even in those cases, I have
opted to override the methods in the `ViewLike` to guard
against changes in the base class implementation and to
simplify the rules in the test.
======================================================================
Checking scala.collection.TraversableView
======================================================================
trait TraversableLike
----------------------------------------------------------------------
def filterNot(p: A => Boolean): Repr
def inits: Iterator[Repr]
def tails: Iterator[Repr]
override def tail: Repr
======================================================================
Checking scala.collection.IterableView
======================================================================
trait IterableLike
----------------------------------------------------------------------
def dropRight(n: Int): Repr
def sliding(size: Int): Iterator[Repr]
def takeRight(n: Int): Repr
trait TraversableLike
----------------------------------------------------------------------
def filterNot(p: A => Boolean): Repr
def inits: Iterator[Repr]
def tails: Iterator[Repr]
override def tail: Repr
======================================================================
Checking scala.collection.SeqView
======================================================================
trait IterableLike
----------------------------------------------------------------------
def dropRight(n: Int): Repr
def sliding(size: Int): Iterator[Repr]
def takeRight(n: Int): Repr
trait SeqLike
----------------------------------------------------------------------
def combinations(n: Int): Iterator[Repr]
def distinct: Repr
def permutations: Iterator[Repr]
def sortBy[B](f: A => B)(implicit ord: scala.math.Ordering[B]): Repr
def sortWith(lt: (A, A) => Boolean): Repr
trait TraversableLike
----------------------------------------------------------------------
def filterNot(p: A => Boolean): Repr
def inits: Iterator[Repr]
def tails: Iterator[Repr]
override def tail: Repr
======================================================================
Checking scala.collection.mutable.IndexedSeqView
======================================================================
trait IndexedSeqOptimized
----------------------------------------------------------------------
override def dropRight(n: Int): Repr
override def tail: Repr
override def takeRight(n: Int): Repr
trait IterableLike
----------------------------------------------------------------------
def sliding(size: Int): Iterator[Repr]
trait SeqLike
----------------------------------------------------------------------
def combinations(n: Int): Iterator[Repr]
def distinct: Repr
def permutations: Iterator[Repr]
def sortBy[B](f: A => B)(implicit ord: scala.math.Ordering[B]): Repr
def sortWith(lt: (A, A) => Boolean): Repr
trait TraversableLike
----------------------------------------------------------------------
def filterNot(p: A => Boolean): Repr
def inits: Iterator[Repr]
def tails: Iterator[Repr]
======================================================================
Checking scala.collection.immutable.StreamView
======================================================================
trait IterableLike
----------------------------------------------------------------------
def dropRight(n: Int): Repr
def sliding(size: Int): Iterator[Repr]
def takeRight(n: Int): Repr
trait SeqLike
----------------------------------------------------------------------
def combinations(n: Int): Iterator[Repr]
def distinct: Repr
def permutations: Iterator[Repr]
def sortBy[B](f: A => B)(implicit ord: scala.math.Ordering[B]): Repr
def sortWith(lt: (A, A) => Boolean): Repr
trait TraversableLike
----------------------------------------------------------------------
def filterNot(p: A => Boolean): Repr
def inits: Iterator[Repr]
def tails: Iterator[Repr]
override def tail: Repr
Diffstat (limited to 'test')
-rw-r--r-- | test/files/run/t4332.check | 25 | ||||
-rw-r--r-- | test/files/run/t4332.scala | 44 | ||||
-rw-r--r-- | test/files/run/t4332b.scala | 35 |
3 files changed, 104 insertions, 0 deletions
diff --git a/test/files/run/t4332.check b/test/files/run/t4332.check new file mode 100644 index 0000000000..ff9d9b8647 --- /dev/null +++ b/test/files/run/t4332.check @@ -0,0 +1,25 @@ + +====================================================================== +Checking scala.collection.TraversableView +====================================================================== + + +====================================================================== +Checking scala.collection.IterableView +====================================================================== + + +====================================================================== +Checking scala.collection.SeqView +====================================================================== + + +====================================================================== +Checking scala.collection.mutable.IndexedSeqView +====================================================================== + + +====================================================================== +Checking scala.collection.immutable.StreamView +====================================================================== + diff --git a/test/files/run/t4332.scala b/test/files/run/t4332.scala new file mode 100644 index 0000000000..5a67922911 --- /dev/null +++ b/test/files/run/t4332.scala @@ -0,0 +1,44 @@ +import scala.tools.partest._ + +object Test extends DirectTest { + override def code = "" + lazy val global = newCompiler("-usejavacp") + import global._, definitions._ + + override def show() { + new global.Run() + // Once we plug all of the view gaps, the output should be empty! + checkViews() + } + + def isExempt(sym: Symbol) = { + val exempt = Set("view", "repr", "sliceWithKnownDelta", "sliceWithKnownBound", "transform") + (exempt contains sym.name.decoded) + } + + def checkView(viewType: Type, viewLikeType: Type) { + val sep = "=" * 70 + println(s"\n$sep\nChecking ${viewType.typeSymbol.fullName}\n$sep") + val termMembers = viewType.nonPrivateMembers.toList filter (_.isTerm) map fullyInitializeSymbol + val inheritedFromGenericCollection + = termMembers filterNot (_.owner.name.decoded contains "ViewLike") filterNot (_.owner == viewType.typeSymbol) + def returnsView(sym: Symbol) = viewType.memberType(sym).finalResultType contains viewType.typeSymbol + val needOverride = inheritedFromGenericCollection filterNot isExempt filter returnsView + + val grouped = needOverride.groupBy(_.owner).toSeq.sortBy { case (owner, _) => viewType baseTypeIndex owner } + val report = grouped.map { + case (owner, syms) => s"\n$owner\n${"-" * 70}\n${syms.map(_.defString).sorted.mkString("\n")}" + }.mkString("\n") + println(report) + } + + def checkViews() { + import collection._ + checkView(typeOf[TraversableView[_, _]], typeOf[TraversableViewLike[_, _, _]]) + checkView(typeOf[IterableView[_, _]], typeOf[IterableViewLike[_, _, _]]) + checkView(typeOf[SeqView[_, _]], typeOf[SeqViewLike[_, _, _]]) + checkView(typeOf[mutable.IndexedSeqView[_, _]], typeOf[SeqViewLike[_, _, _]]) + checkView(typeOf[immutable.StreamView[_, _]], typeOf[immutable.StreamViewLike[_, _, _]]) + // Parallel views not checked, assuming we will drop them in 2.11 + } +} diff --git a/test/files/run/t4332b.scala b/test/files/run/t4332b.scala new file mode 100644 index 0000000000..8ee069ca2d --- /dev/null +++ b/test/files/run/t4332b.scala @@ -0,0 +1,35 @@ +object Test extends App { + def check(expected: Any, actual: Any, msg: String = "") = { + if (expected != actual) + sys.error(s"($actual != $expected) $msg") + } + val ls = List(1, 3, 2, 1) + for (N <- -1 to (ls.length + 1)) { + check(ls.takeRight(N), ls.view.takeRight(N).toList, s"takeRight($N)") + check(ls.dropRight(N), ls.view.dropRight(N).toList, s"dropRight($N)") + } + for (N <- 1 to (ls.length + 1)) { + check(ls.sliding(N).toList, ls.view.sliding(N).toList.map(_.toList), s"sliding($N)") + check(ls.sliding(N, 2).toList, ls.view.sliding(N, 2).toList.map(_.toList), s"sliding($N, 2)") + } + for (b <- List(true, false)) + check(ls.filterNot(x => true), ls.view.filterNot(x => true), s"filterNot($b)") + + check(ls.inits.toList, ls.view.inits.toList.map(_.toList), "inits") + check(ls.tails.toList, ls.view.tails.toList.map(_.toList), "tails") + + check(ls.combinations(2).toList.map(_.toList), ls.view.combinations(2).toList.map(_.toList), "combinations(2)") + check(ls.permutations.toList.map(_.toList), ls.view.permutations.toList.map(_.toList), "permutations") + + check(ls.sortBy(_ * -1), ls.view.sortBy(_ * -1).toList, "sortBy") + check(ls.sortWith((x, y) => y < x), ls.view.sortWith((x, y) => y < x).toList, "sortWith") + check(ls.sorted, ls.view.sorted.toList, "sorted") + + check(ls.distinct, ls.view.distinct.toList, "distinct") + + check(ls.tail, ls.view.tail.toList, "tail") + + import collection.mutable.Buffer + check(Buffer(1, 2, 3).tail, Buffer(1, 2, 3).view.tail.toList, "Buffer#tail") + check(Buffer(1, 2, 3).tail.length, Buffer(1, 2, 3).view.tail.length, "Buffer#tail#length") +} |