diff options
author | Josh Suereth <joshua.suereth@gmail.com> | 2011-12-18 10:54:49 -0500 |
---|---|---|
committer | Josh Suereth <joshua.suereth@gmail.com> | 2011-12-18 10:54:49 -0500 |
commit | 56a366c854457f842522a481701be2f1f1b318c7 (patch) | |
tree | 3819bdcfe76a07be7027694299f86d7ec7aad5d4 | |
parent | 971536593f33f357356b4c58d8a66742755801b8 (diff) | |
parent | a332a39d316f0223f00a31999b76a369f9e6fee4 (diff) | |
download | scala-56a366c854457f842522a481701be2f1f1b318c7.tar.gz scala-56a366c854457f842522a481701be2f1f1b318c7.tar.bz2 scala-56a366c854457f842522a481701be2f1f1b318c7.zip |
Merge branch 'master' into xsbt
-rwxr-xr-x | src/compiler/scala/tools/nsc/ast/DocComments.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala | 34 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/List.scala | 247 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Range.scala | 185 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/CompileManager.scala | 3 | ||||
-rw-r--r-- | test/files/scalacheck/CheckEither.scala | 8 | ||||
-rw-r--r-- | test/files/scalacheck/range.scala | 81 | ||||
-rw-r--r-- | test/scaladoc/resources/SI_5054_q7.scala | 8 | ||||
-rw-r--r-- | test/scaladoc/resources/SI_5287.scala | 17 | ||||
-rw-r--r-- | test/scaladoc/scala/html.flags | 1 | ||||
-rw-r--r-- | test/scaladoc/scala/html/HtmlFactoryTest.flags | 1 | ||||
-rw-r--r-- | test/scaladoc/scala/html/HtmlFactoryTest.scala | 183 |
12 files changed, 511 insertions, 267 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index 8d52a7bd2c..f9c818daf0 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -99,7 +99,7 @@ trait DocComments { self: Global => */ def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = { def getUseCases(dc: DocComment) = { - for (uc <- dc.useCases; defn <- uc.expandedDefs(site)) yield + for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield (defn, expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site), uc.pos) @@ -346,7 +346,7 @@ trait DocComments { self: Global => var defined: List[Symbol] = List() // initialized by Typer var aliases: List[Symbol] = List() // initialized by Typer - def expandedDefs(site: Symbol): List[Symbol] = { + def expandedDefs(sym: Symbol, site: Symbol): List[Symbol] = { def select(site: Type, name: Name, orElse: => Type): Type = { val member = site.nonPrivateMember(name) @@ -424,8 +424,10 @@ trait DocComments { self: Global => } for (defn <- defined) yield { - defn.cloneSymbol.setFlag(Flags.SYNTHETIC).setInfo( - substAliases(defn.info).asSeenFrom(site.thisType, defn.owner)) + val useCase = defn.cloneSymbol + useCase.owner = sym.owner + useCase.flags = sym.flags + useCase.setFlag(Flags.SYNTHETIC).setInfo(substAliases(defn.info).asSeenFrom(site.thisType, sym.owner)) } } } diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 1fe96ed447..7eb8c393f3 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -100,11 +100,15 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { if (inTpl == null) None else thisFactory.comment(sym, inTpl) override def inTemplate = inTpl override def toRoot: List[MemberImpl] = this :: inTpl.toRoot - def inDefinitionTemplates = - if (inTpl == null) - makeRootPackage.toList - else - makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) + def inDefinitionTemplates = this match { + case mb: NonTemplateMemberEntity if (mb.useCaseOf.isDefined) => + mb.useCaseOf.get.inDefinitionTemplates + case _ => + if (inTpl == null) + makeRootPackage.toList + else + makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) + } def visibility = { if (sym.isPrivateLocal) PrivateInInstance() else if (sym.isProtectedLocal) ProtectedInInstance() @@ -119,18 +123,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { else Public() } } - def flags = this match { - // workaround for uninitialized flags in use cases - see SI-5054 - case m: NonTemplateMemberEntity if (m.useCaseOf.isDefined) => - m.useCaseOf.get.flags - case _ => - val fgs = mutable.ListBuffer.empty[Paragraph] - if (sym.isImplicit) fgs += Paragraph(Text("implicit")) - if (sym.isSealed) fgs += Paragraph(Text("sealed")) - if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract")) - if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract")) - if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final")) - fgs.toList + def flags = { + val fgs = mutable.ListBuffer.empty[Paragraph] + if (sym.isImplicit) fgs += Paragraph(Text("implicit")) + if (sym.isSealed) fgs += Paragraph(Text("sealed")) + if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract")) + if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract")) + if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final")) + fgs.toList } def deprecation = if (sym.isDeprecated) diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 531eac6c01..c6f056bd81 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -277,6 +277,9 @@ sealed abstract class List[+A] extends AbstractSeq[A] override def toStream : Stream[A] = if (isEmpty) Stream.Empty else new Stream.Cons(head, tail.toStream) + + @deprecated("use `distinct` instead", "2.8.0") + def removeDuplicates: List[A] = distinct } /** The empty list. @@ -343,6 +346,8 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend */ object List extends SeqFactory[List] { + import scala.collection.{Iterable, Seq, IndexedSeq} + /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] @@ -352,6 +357,248 @@ object List extends SeqFactory[List] { override def empty[A]: List[A] = Nil override def apply[A](xs: A*): List[A] = xs.toList + + /** Create a sorted list with element values `v,,>n+1,, = step(v,,n,,)` + * where `v,,0,, = start` and elements are in the range between `start` + * (inclusive) and `end` (exclusive). + * + * @param start the start value of the list + * @param end the end value of the list + * @param step the increment function of the list, which given `v,,n,,`, + * computes `v,,n+1,,`. Must be monotonically increasing + * or decreasing. + * @return the sorted list of all integers in range `[start;end)`. + */ + @deprecated("use `iterate` instead", "2.8.0") + def range(start: Int, end: Int, step: Int => Int): List[Int] = { + val up = step(start) > start + val down = step(start) < start + val b = new ListBuffer[Int] + var i = start + while ((!up || i < end) && (!down || i > end)) { + b += i + val next = step(i) + if (i == next) + throw new IllegalArgumentException("the step function did not make any progress on "+ i) + i = next + } + b.toList + } + + /** Create a list containing several copies of an element. + * + * @param n the length of the resulting list + * @param elem the element composing the resulting list + * @return a list composed of `n` elements all equal to `elem` + */ + @deprecated("use `fill` instead", "2.8.0") + def make[A](n: Int, elem: A): List[A] = { + val b = new ListBuffer[A] + var i = 0 + while (i < n) { + b += elem + i += 1 + } + b.toList + } + + /** Concatenate all the elements of a given list of lists. + * + * @param xss the list of lists that are to be concatenated + * @return the concatenation of all the lists + */ + @deprecated("use `xss.flatten` instead of `List.flatten(xss)`", "2.8.0") + def flatten[A](xss: List[List[A]]): List[A] = { + val b = new ListBuffer[A] + for (xs <- xss) { + var xc = xs + while (!xc.isEmpty) { + b += xc.head + xc = xc.tail + } + } + b.toList + } + + /** Transforms a list of pairs into a pair of lists. + * + * @param xs the list of pairs to unzip + * @return a pair of lists. + */ + @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") + def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = { + val b1 = new ListBuffer[A] + val b2 = new ListBuffer[B] + var xc = xs + while (!xc.isEmpty) { + b1 += xc.head._1 + b2 += xc.head._2 + xc = xc.tail + } + (b1.toList, b2.toList) + } + + /** Transforms an iterable of pairs into a pair of lists. + * + * @param xs the iterable of pairs to unzip + * @return a pair of lists. + */ + @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") + def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) = + xs.foldRight[(List[A], List[B])]((Nil, Nil)) { + case ((x, y), (xs, ys)) => (x :: xs, y :: ys) + } + + /** + * Returns the `Left` values in the given `Iterable` of `Either`s. + */ + @deprecated("use `xs collect { case Left(x: A) => x }` instead of `List.lefts(xs)`", "2.8.0") + def lefts[A, B](es: Iterable[Either[A, B]]) = + es.foldRight[List[A]](Nil)((e, as) => e match { + case Left(a) => a :: as + case Right(_) => as + }) + + /** + * Returns the `Right` values in the given `Iterable` of `Either`s. + */ + @deprecated("use `xs collect { case Right(x: B) => x }` instead of `List.rights(xs)`", "2.8.0") + def rights[A, B](es: Iterable[Either[A, B]]) = + es.foldRight[List[B]](Nil)((e, bs) => e match { + case Left(_) => bs + case Right(b) => b :: bs + }) + + /** Transforms an Iterable of Eithers into a pair of lists. + * + * @param xs the iterable of Eithers to separate + * @return a pair of lists. + */ + @deprecated("use `(for (Left(x) <- es) yield x, for (Right(x) <- es) yield x)` instead", "2.8.0") + def separate[A,B](es: Iterable[Either[A, B]]): (List[A], List[B]) = + es.foldRight[(List[A], List[B])]((Nil, Nil)) { + case (Left(a), (lefts, rights)) => (a :: lefts, rights) + case (Right(b), (lefts, rights)) => (lefts, b :: rights) + } + + /** Converts an iterator to a list. + * + * @param it the iterator to convert + * @return a list that contains the elements returned by successive + * calls to `it.next` + */ + @deprecated("use `it.toList` instead of `List.toList(it)`", "2.8.0") + def fromIterator[A](it: Iterator[A]): List[A] = it.toList + + /** Converts an array into a list. + * + * @param arr the array to convert + * @return a list that contains the same elements than `arr` + * in the same order + */ + @deprecated("use `array.toList` instead of `List.fromArray(array)`", "2.8.0") + def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length) + + /** Converts a range of an array into a list. + * + * @param arr the array to convert + * @param start the first index to consider + * @param len the length of the range to convert + * @return a list that contains the same elements than `arr` + * in the same order + */ + @deprecated("use `array.view(start, end).toList` instead of `List.fromArray(array, start, end)`", "2.8.0") + def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = { + var res: List[A] = Nil + var i = start + len + while (i > start) { + i -= 1 + res = arr(i) :: res + } + res + } + + /** Returns the list resulting from applying the given function `f` + * to corresponding elements of the argument lists. + * + * @param f function to apply to each pair of elements. + * @return `[f(a,,0,,,b,,0,,), ..., f(a,,n,,,b,,n,,)]` if the lists are + * `[a,,0,,, ..., a,,k,,]`, `[b,,0,,, ..., b,,l,,]` and + * `n = min(k,l)` + */ + @deprecated("use `(xs, ys).zipped.map(f)` instead of `List.map2(xs, ys)(f)`", "2.8.0") + def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = { + val b = new ListBuffer[C] + var xc = xs + var yc = ys + while (!xc.isEmpty && !yc.isEmpty) { + b += f(xc.head, yc.head) + xc = xc.tail + yc = yc.tail + } + b.toList + } + + /** Tests whether the given predicate `p` holds + * for all corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return `(p(a<sub>0</sub>,b<sub>0</sub>) && + * ... && p(a<sub>n</sub>,b<sub>n</sub>))]` + * if the lists are `[a<sub>0</sub>, ..., a<sub>k</sub>]`; + * `[b<sub>0</sub>, ..., b<sub>l</sub>]` + * and `n = min(k,l)` + */ + @deprecated("use `(xs, ys).zipped.forall(f)` instead of `List.forall2(xs, ys)(f)`", "2.8.0") + def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { + var xc = xs + var yc = ys + while (!xc.isEmpty && !yc.isEmpty) { + if (!f(xc.head, yc.head)) return false + xc = xc.tail + yc = yc.tail + } + true + } + + /** Tests whether the given predicate `p` holds + * for some corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return `n != 0 && (p(a<sub>0</sub>,b<sub>0</sub>) || + * ... || p(a<sub>n</sub>,b<sub>n</sub>))]` if the lists are + * `[a<sub>0</sub>, ..., a<sub>k</sub>]`, + * `[b<sub>0</sub>, ..., b<sub>l</sub>]` and + * `n = min(k,l)` + */ + @deprecated("use `(xs, ys).zipped.exists(f)` instead of `List.exists2(xs, ys)(f)`", "2.8.0") + def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { + var xc = xs + var yc = ys + while (!xc.isEmpty && !yc.isEmpty) { + if (f(xc.head, yc.head)) return true + xc = xc.tail + yc = yc.tail + } + false + } + + /** Transposes a list of lists. + * pre: All element lists have the same length. + * + * @param xss the list of lists + * @return the transposed list of lists + */ + @deprecated("use `xss.transpose` instead of `List.transpose(xss)`", "2.8.0") + def transpose[A](xss: List[List[A]]): List[List[A]] = { + val buf = new ListBuffer[List[A]] + var yss = xss + while (!yss.head.isEmpty) { + buf += (yss map (_.head)) + yss = (yss map (_.tail)) + } + buf.toList + } } /** Only used for list serialization */ diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 16d7e68dee..c92c0268b6 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -51,15 +51,35 @@ extends collection.AbstractSeq[Int] { override def par = new ParRange(this) - // This member is designed to enforce conditions: - // (step != 0) && (length <= Int.MaxValue), - // but cannot be evaluated eagerly because we have a pattern where ranges - // are constructed like: "x to y by z" - // The "x to y" piece should not trigger an exception. So the calculation - // is delayed, which means it will not fail fast for those cases where failing - // was correct. - private lazy val numRangeElements: Int = Range.count(start, end, step, isInclusive) - + private def gap = end.toLong - start.toLong + private def isExact = gap % step == 0 + private def hasStub = isInclusive || !isExact + private def longLength = gap / step + ( if (hasStub) 1 else 0 ) + + // Check cannot be evaluated eagerly because we have a pattern where + // ranges are constructed like: "x to y by z" The "x to y" piece + // should not trigger an exception. So the calculation is delayed, + // which means it will not fail fast for those cases where failing was + // correct. + override final val isEmpty = ( + (start > end && step > 0) + || (start < end && step < 0) + || (start == end && !isInclusive) + ) + final val numRangeElements: Int = { + if (step == 0) throw new IllegalArgumentException("step cannot be 0.") + else if (isEmpty) 0 + else { + val len = longLength + if (len > scala.Int.MaxValue) -1 + else len.toInt + } + } + final val lastElement = start + (numRangeElements - 1) * step + final val terminalElement = start + numRangeElements * step + + override def last = if (isEmpty) Nil.last else lastElement + protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step) /** Create a new range with the `start` and `end` values of this range and @@ -71,93 +91,46 @@ extends collection.AbstractSeq[Int] def isInclusive = false - override def length: Int = numRangeElements - override lazy val last: Int = - if (length == 0) Nil.last - else locationAfterN(length - 1) - - final override def isEmpty = length == 0 - - @inline - final def apply(idx: Int): Int = { - if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(idx.toString) - locationAfterN(idx) + override def size = length + override def length = if (numRangeElements < 0) fail() else numRangeElements + + private def description = "%d %s %d by %s".format(start, if (isInclusive) "to" else "until", end, step) + private def fail() = throw new IllegalArgumentException(description + ": seqs cannot contain more than Int.MaxValue elements.") + private def validateMaxLength() { + if (numRangeElements < 0) + fail() } - /** @note Making foreach run as fast as a while loop is a challenge. - * The key elements which I can observe making a difference are: - * - * - the inner loop should be as small as possible - * - the inner loop should be monomorphic - * - the inner loop should perform no boxing and no avoidable tests - * - * This is achieved by: - * - * - keeping initialization logic out of the inner loop - * - dispatching to custom variations based on initial conditions - * - tricking the compiler into always calling Function1#apply$mcVI$sp - * - * The last one is important and less than obvious. Even when foreach - * was specialized on Unit, only Int => Unit arguments benefited from it. - * Other function types would be accepted, but in the absence of full - * specialization the integer argument was boxed on every call. For example: - * - class A { - final def f(x: Int): Int = x + 1 - // Calls Range.foreach, which calls Function1.apply - def g1 = 1 until 100 foreach { x => f(x) } - // Calls Range.foreach$mVc$sp, which calls Function1.apply$mcVI$sp - def g2 = 1 until 100 foreach { x => f(x) ; () } - } - * - * However! Since the result of the closure is always discarded, we - * simply cast it to Int => Unit, thereby executing the fast version. - * The seemingly looming ClassCastException can never arrive. - */ - @inline final override def foreach[U](f: Int => U) { - if (step < 0) { - if (isInclusive) foreachDownIn(f.asInstanceOf[Int => Unit]) - else foreachDownEx(f.asInstanceOf[Int => Unit]) - } - else { - if (isInclusive) foreachUpIn(f.asInstanceOf[Int => Unit]) - else foreachUpEx(f.asInstanceOf[Int => Unit]) + def validateRangeBoundaries(f: Int => Any): Boolean = { + validateMaxLength() + + start != Int.MinValue || end != Int.MinValue || { + var count = 0 + var num = start + while (count < numRangeElements) { + f(num) + count += 1 + num += step + } + false } } - /** !!! These methods must be public or they will not be inlined. - * But they are certainly not intended to be part of the API. - * This collision between inlining requirements and access semantics - * is highly unfortunate and must be resolved. - * - * Proposed band-aid: an @internal annotation. - */ - @inline final def foreachDownIn(f: Int => Unit) { - var i = start - while (i >= end) { - f(i) - i += step - } - } - @inline final def foreachUpIn(f: Int => Unit) { - var i = start - while (i <= end) { - f(i) - i += step - } + @inline final def apply(idx: Int): Int = { + validateMaxLength() + if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(idx.toString) + else start + (step * idx) } - @inline final def foreachDownEx(f: Int => Unit) { - var i = start - while (i > end) { - f(i) - i += step - } - } - @inline final def foreachUpEx(f: Int => Unit) { - var i = start - while (i < end) { - f(i) - i += step + + @inline final override def foreach[@specialized(Unit) U](f: Int => U) { + if (validateRangeBoundaries(f)) { + var i = start + val terminal = terminalElement + val step = this.step + while (i != terminal) { + f(i) + i += step + } } } @@ -169,8 +142,8 @@ extends collection.AbstractSeq[Int] * @return a new range consisting of `n` first elements. */ final override def take(n: Int): Range = ( - if (n <= 0 || length == 0) newEmptyRange(start) - else if (n >= length) this + if (n <= 0 || isEmpty) newEmptyRange(start) + else if (n >= numRangeElements) this else new Range.Inclusive(start, locationAfterN(n - 1), step) ) @@ -182,8 +155,8 @@ extends collection.AbstractSeq[Int] * @return a new range consisting of all the elements of this range except `n` first elements. */ final override def drop(n: Int): Range = ( - if (n <= 0 || length == 0) this - else if (n >= length) newEmptyRange(end) + if (n <= 0 || isEmpty) this + else if (n >= numRangeElements) newEmptyRange(end) else copy(locationAfterN(n), end, step) ) @@ -218,7 +191,7 @@ extends collection.AbstractSeq[Int] var current = start var counted = 0 - while (counted < length && p(current)) { + while (counted < numRangeElements && p(current)) { counted += 1 current += step } @@ -226,7 +199,7 @@ extends collection.AbstractSeq[Int] } // Tests whether a number is within the endpoints, without testing // whether it is a member of the sequence (i.e. when step > 1.) - private def isWithinBoundaries(elem: Int) = (length > 0) && ( + private def isWithinBoundaries(elem: Int) = !isEmpty && ( (step > 0 && start <= elem && elem <= last ) || (step < 0 && last <= elem && elem <= start) ) @@ -255,21 +228,21 @@ extends collection.AbstractSeq[Int] * * $doesNotUseBuilders */ - final override def takeRight(n: Int): Range = drop(length - n) + final override def takeRight(n: Int): Range = drop(numRangeElements - n) /** Creates a new range consisting of the initial `length - n` elements of the range. * * $doesNotUseBuilders */ - final override def dropRight(n: Int): Range = take(length - n) + final override def dropRight(n: Int): Range = take(numRangeElements - n) /** Returns the reverse of this range. * * $doesNotUseBuilders */ final override def reverse: Range = - if (length > 0) new Range.Inclusive(last, start, -step) - else this + if (isEmpty) this + else new Range.Inclusive(last, start, -step) /** Make range inclusive. */ @@ -280,10 +253,9 @@ extends collection.AbstractSeq[Int] final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0) final override def sum[B >: Int](implicit num: Numeric[B]): Int = { - val len = length - if (len == 0) 0 - else if (len == 1) head - else (len.toLong * (head + last) / 2).toInt + if (isEmpty) 0 + else if (numRangeElements == 1) head + else (numRangeElements.toLong * (head + last) / 2).toInt } override def toIterable = this @@ -293,7 +265,7 @@ extends collection.AbstractSeq[Int] override def equals(other: Any) = other match { case x: Range => (x canEqual this) && (length == x.length) && ( - (length == 0) || // all empty sequences are equal + isEmpty || // all empty sequences are equal (start == x.start && last == x.last) // same length and same endpoints implies equality ) case _ => @@ -304,7 +276,7 @@ extends collection.AbstractSeq[Int] */ override def toString() = { - val endStr = if (length > Range.MAX_PRINT) ", ... )" else ")" + val endStr = if (numRangeElements > Range.MAX_PRINT) ", ... )" else ")" take(Range.MAX_PRINT).mkString("Range(", ", ", endStr) } } @@ -415,3 +387,4 @@ object Range { // super.foreach(f) } } +
\ No newline at end of file diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala index f4ebfb7e7d..68688ff949 100644 --- a/src/partest/scala/tools/partest/nest/CompileManager.scala +++ b/src/partest/scala/tools/partest/nest/CompileManager.scala @@ -75,7 +75,8 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler { val logWriter = new FileWriter(log) // check whether there is a ".flags" file - val flagsFileName = "%s.flags" format (basename(log.getName) dropRight 4) // 4 is "-run" or similar + val logFile = basename(log.getName) + val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-"))) val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse "" val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0) val args = allOpts.toList diff --git a/test/files/scalacheck/CheckEither.scala b/test/files/scalacheck/CheckEither.scala index a7e50877a7..0145d3321f 100644 --- a/test/files/scalacheck/CheckEither.scala +++ b/test/files/scalacheck/CheckEither.scala @@ -8,7 +8,7 @@ import org.scalacheck.Test.{Params, check} import org.scalacheck.ConsoleReporter.testStatsEx import Function.tupled -object CheckEither extends Properties("Either") { +object Test extends Properties("Either") { implicit def arbitraryEither[X, Y](implicit xa: Arbitrary[X], ya: Arbitrary[Y]): Arbitrary[Either[X, Y]] = Arbitrary[Either[X, Y]](oneOf(arbitrary[X].map(Left(_)), arbitrary[Y].map(Right(_)))) @@ -186,9 +186,3 @@ object CheckEither extends Properties("Either") { STest.checkProperties(STest.Params(testCallback = ConsoleReporter(0)), this) } } - -object Test { - def main(args: Array[String]): Unit = { - CheckEither.runTests() - } -} diff --git a/test/files/scalacheck/range.scala b/test/files/scalacheck/range.scala index 56295f204c..72979115be 100644 --- a/test/files/scalacheck/range.scala +++ b/test/files/scalacheck/range.scala @@ -12,10 +12,16 @@ class Counter(r: Range) { if (cnt % 500000000L == 0L) { println("Working: %s %d %d" format (str, cnt, x)) } - if (cnt > (Int.MaxValue.toLong + 1) * 2) - error("Count exceeds maximum possible for an Int Range") - if ((r.step > 0 && last.exists(_ > x)) || (r.step < 0 && last.exists(_ < x))) - error("Range wrapped: %d %s" format (x, last.toString)) + if (cnt > (Int.MaxValue.toLong + 1) * 2) { + val msg = "Count exceeds maximum possible for an Int Range: %s" format str + println(msg) // exception is likely to be eaten by an out of memory error + sys error msg + } + if ((r.step > 0 && last.exists(_ > x)) || (r.step < 0 && last.exists(_ < x))) { + val msg = "Range %s wrapped: %d %s" format (str, x, last.toString) + println(msg) // exception is likely to be eaten by an out of memory error + sys error msg + } last = Some(x) } } @@ -23,29 +29,40 @@ class Counter(r: Range) { abstract class RangeTest(kind: String) extends Properties("Range "+kind) { def myGen: Gen[Range] - val genRange = for { - start <- arbitrary[Int] - end <- arbitrary[Int] - step <- Gen.choose(1, (start - end).abs + 1) - } yield if (start < end) Range(start, end, step) else Range(start, end, -step) - - val genReasonableSizeRange = for { - start <- choose(-Int.MinValue, Int.MaxValue) - end <- choose(-Int.MinValue, Int.MaxValue) + def genReasonableSizeRange = oneOf(genArbitraryRange, genBoundaryRange) + + def genArbitraryRange = for { + start <- choose(Int.MinValue, Int.MaxValue) + end <- choose(Int.MinValue, Int.MaxValue) step <- choose(-Int.MaxValue, Int.MaxValue) } yield Range(start, end, if (step == 0) 100 else step) - val genSmallRange = for { + def genBoundaryRange = for { + boundary <- oneOf(Int.MinValue, -1, 0, 1, Int.MaxValue) + isStart <- arbitrary[Boolean] + size <- choose(1, 100) + step <- choose(1, 101) + } yield { + val signum = if (boundary == 0) 1 else boundary.signum + if (isStart) Range(boundary, boundary - size * boundary.signum, - step * signum) + else Range(boundary - size * boundary.signum, boundary, step * signum) + } + + + def genSmallRange = for { start <- choose(-100, 100) end <- choose(-100, 100) step <- choose(1, 1) } yield if (start < end) Range(start, end, step) else Range(start, end, -step) - val genRangeByOne = for { - start <- arbitrary[Int] - end <- arbitrary[Int] - if (end.toLong - start.toLong).abs <= 10000000L - } yield if (start < end) Range(start, end) else Range(end, start) + def genRangeByOne = oneOf(genRangeOpenByOne, genRangeClosedByOne) + + def genRangeOpenByOne = for { + r <- oneOf(genSmallRange, genBoundaryRange) + if (r.end.toLong - r.start.toLong).abs <= 10000000L + } yield if (r.start < r.end) Range(r.start, r.end) else Range(r.end, r.start) + + def genRangeClosedByOne = for (r <- genRangeOpenByOne) yield r.start to r.end def str(r: Range) = "Range["+r.start+", "+r.end+", "+r.step+(if (r.isInclusive) "]" else ")") @@ -71,7 +88,8 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { def multiple(r: Range, x: Int) = (x.toLong - r.start) % r.step == 0 - property("foreach.step") = forAll(myGen) { r => + property("foreach.step") = forAllNoShrink(myGen) { r => +// println("foreach.step "+str(r)) var allValid = true val cnt = new Counter(r) // println("--------------------") @@ -84,6 +102,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { } property("foreach.inside.range") = forAll(myGen) { r => +// println("foreach.inside.range "+str(r)) var allValid = true var last: Option[Int] = None val cnt = new Counter(r) @@ -94,6 +113,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { } property("foreach.visited.size") = forAll(myGen) { r => +// println("foreach.visited.size "+str(r)) var visited = 0L val cnt = new Counter(r) r foreach { x => cnt(x) @@ -108,14 +128,17 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { } property("length") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r => +// println("length "+str(r)) (r.length == expectedSize(r)) :| str(r) } property("isEmpty") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r => +// println("isEmpty "+str(r)) (r.isEmpty == (expectedSize(r) == 0L)) :| str(r) } property("contains") = forAll(myGen, arbInt.arbitrary) { (r, x) => +// println("contains "+str(r)) // println("----------------") // println(str(r)) // println(x) @@ -126,11 +149,13 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { } property("take") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r)), arbInt.arbitrary) { (r, x) => +// println("take "+str(r)) val t = r take x (t.size == (0 max x min r.size) && t.start == r.start && t.step == r.step) :| str(r)+" / "+str(t)+": "+x } property("init") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r => +// println("init "+str(r)) (r.size == 0) || { val t = r.init (t.size + 1 == r.size) && (t.isEmpty || t.head == r.head) @@ -138,6 +163,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { } property("takeWhile") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r)), arbInt.arbitrary) { (r, x) => +// println("takeWhile "+str(r)) val t = (if (r.step > 0) r takeWhile (_ <= x) else r takeWhile(_ >= x)) if (r.size == 0) { (t.size == 0) :| str(r)+" / "+str(t)+": "+x @@ -148,6 +174,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { } property("reverse.toSet.equal") = forAll(myGen) { r => +// println("reverse.toSet.equal "+str(r)) val reversed = r.reverse val aresame = r.toSet == reversed.toSet if (!aresame) { @@ -157,7 +184,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { println(r.toSet) println(reversed.toSet) } - aresame + aresame :| str(r) } } @@ -178,11 +205,11 @@ object InclusiveRangeTest extends RangeTest("inclusive") { } object ByOneRangeTest extends RangeTest("byOne") { - override def myGen = genSmallRange + override def myGen = genRangeByOne } object InclusiveByOneRangeTest extends RangeTest("inclusiveByOne") { - override def myGen = for (r <- genSmallRange) yield r.inclusive + override def myGen = for (r <- genRangeByOne) yield r.inclusive } object SmallValuesRange extends RangeTest("smallValues") { @@ -207,9 +234,11 @@ object TooLargeRange extends Properties("Too Large Range") { object Test extends Properties("Range") { import org.scalacheck.{ Test => STest } - List(NormalRangeTest, InclusiveRangeTest, ByOneRangeTest, InclusiveByOneRangeTest, TooLargeRange) foreach { ps => - STest.checkProperties(STest.Params(testCallback = ConsoleReporter(0)), ps) - } + include(NormalRangeTest) + include(InclusiveRangeTest) + include(ByOneRangeTest) + include(InclusiveByOneRangeTest) + include(TooLargeRange) } /* Mini-benchmark diff --git a/test/scaladoc/resources/SI_5054_q7.scala b/test/scaladoc/resources/SI_5054_q7.scala index 26d4b5fcf4..1bd120e30c 100644 --- a/test/scaladoc/resources/SI_5054_q7.scala +++ b/test/scaladoc/resources/SI_5054_q7.scala @@ -6,17 +6,17 @@ trait SI_5054_q7 { * * @param lost a lost parameter * @return some integer - * @usecase def test(): Int + * @usecase def test1(): Int * * This takes the implicit value in scope. * - * Example: `test()` + * Example: `test1()` * - * @usecase def test(explicit: Int): Int + * @usecase def test2(explicit: Int): Int * * This takes the explicit value passed. * - * Example: `test(3)` + * Example: `test2(3)` */ def test(implicit lost: Int): Int } diff --git a/test/scaladoc/resources/SI_5287.scala b/test/scaladoc/resources/SI_5287.scala new file mode 100644 index 0000000000..141ab15325 --- /dev/null +++ b/test/scaladoc/resources/SI_5287.scala @@ -0,0 +1,17 @@ +trait SI_5287_A { + def method(implicit a: Int): Int = a +} + +trait SI_5287_B extends SI_5287_A { + override def method(implicit a: Int): Int = a + 1 +} + +trait SI_5287 extends SI_5287_B{ + /** + * Some explanation + * + * @usecase def method(): Int + * The usecase explanation + */ + override def method(implicit a: Int): Int = a + 3 +}
\ No newline at end of file diff --git a/test/scaladoc/scala/html.flags b/test/scaladoc/scala/html.flags new file mode 100644 index 0000000000..b2264ec4f4 --- /dev/null +++ b/test/scaladoc/scala/html.flags @@ -0,0 +1 @@ +-encoding UTF-8
\ No newline at end of file diff --git a/test/scaladoc/scala/html/HtmlFactoryTest.flags b/test/scaladoc/scala/html/HtmlFactoryTest.flags new file mode 100644 index 0000000000..b2264ec4f4 --- /dev/null +++ b/test/scaladoc/scala/html/HtmlFactoryTest.flags @@ -0,0 +1 @@ +-encoding UTF-8
\ No newline at end of file diff --git a/test/scaladoc/scala/html/HtmlFactoryTest.scala b/test/scaladoc/scala/html/HtmlFactoryTest.scala index d1bfbb023f..5b17affbf0 100644 --- a/test/scaladoc/scala/html/HtmlFactoryTest.scala +++ b/test/scaladoc/scala/html/HtmlFactoryTest.scala @@ -21,6 +21,9 @@ object XMLUtil { } object Test extends Properties("HtmlFactory") { + + final val RESOURCES = "test/scaladoc/resources/" + import scala.tools.nsc.doc.{DocFactory, Settings} import scala.tools.nsc.doc.model.IndexModelFactory import scala.tools.nsc.doc.html.HtmlFactory @@ -47,7 +50,7 @@ object Test extends Properties("HtmlFactory") { def createTemplates(basename: String) = { val result = scala.collection.mutable.Map[String, scala.xml.NodeSeq]() - createFactory.makeUniverse(List("test/scaladoc/resources/"+basename)) match { + createFactory.makeUniverse(List(RESOURCES+basename)) match { case Some(universe) => { val index = IndexModelFactory.makeIndex(universe) (new HtmlFactory(universe, index)).writeTemplates((page) => { @@ -61,7 +64,7 @@ object Test extends Properties("HtmlFactory") { } def createReferenceIndex(basename: String) = { - createFactory.makeUniverse(List("test/scaladoc/resources/"+basename)) match { + createFactory.makeUniverse(List(RESOURCES+basename)) match { case Some(universe) => { val index = IndexModelFactory.makeIndex(universe) val pages = index.firstLetterIndex.map({ @@ -81,6 +84,52 @@ object Test extends Properties("HtmlFactory") { val html = scala.stripSuffix(".scala") + ".html" createTemplates(scala)(html) } + + /** + * See checkTextOnly(scalaFile: String, checks: List[String]) + */ + def checkText1(scalaFile: String, check: String, debug: Boolean = true): Boolean = checkText(scalaFile, List(check), debug) + + /** + * This tests the text without the markup - ex: + * + * <h4 class="signature"> + * <span class="modifier_kind"> + * <span class="modifier">implicit</span> + * <span class="kind">def</span> + * </span> + * <span class="symbol"> + * <span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span> + * </span> + * </h4> + * + * becomes: + * + * implicit def test(): Int + * + * and is required to contain the text in the given checks + * + * NOTE: Comparison is done ignoring all whitespace + */ + def checkText(scalaFile: String, checks: List[String], debug: Boolean = true): Boolean = { + val htmlFile = scalaFile.stripSuffix(".scala") + ".html" + val htmlText = createTemplates(scalaFile)(htmlFile).text.replace('→',' ').replaceAll("\\s+","") + var result = true + + for (check <- checks) { + val checkText = check.replace('→',' ').replaceAll("\\s+","") + val checkValue = htmlText.contains(checkText) + if (debug && (!checkValue)) { + Console.err.println("Check failed: ") + Console.err.println("HTML: " + htmlText) + Console.err.println("Check: " + checkText) + } + result &&= checkValue + } + + result + } + def shortComments(root: scala.xml.Node) = XMLUtil.stripGroup(root).descendant.flatMap { @@ -377,113 +426,43 @@ object Test extends Properties("HtmlFactory") { createTemplate("SI_4898.scala") true } - - // A piece of the signature - corresponding to the use case - def signature(no: Int, modifier: String) = (""" - <li visbl="pub" name="SI_5054_q""" + no + """#test" data-isabs="false"> - <a id="test():Int"></a> - <h4 class="signature"> - <span class="modifier_kind"> - <span class="modifier">""" + modifier + """</span> - <span class="kind">def</span> - </span> - <span class="symbol"> - <span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span> - </span> - </h4> - <p class="shortcomment cmt">[use case] - </p> - </li>""").replaceAll("\\s+", "") - property("Use cases should override their original members") = { - createTemplate("SI_5054_q1.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(signature(1, "")) - case _ => false - } - } - - property("Use cases should keep their flags - final should not be lost") = { - createTemplate("SI_5054_q2.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(signature(2, "final")) - case _ => false - } - } + property("Use cases should override their original members") = + checkText1("SI_5054_q1.scala", """def test(): Int""") && + !checkText1("SI_5054_q1.scala", """def test(implicit lost: Int): Int""") - property("Use cases should keep their flags - implicit should not be lost") = { - createTemplate("SI_5054_q3.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(signature(3, "implicit")) - case _ => false - } - } - property("Use cases should keep their flags - real abstract should not be lost") = { - createTemplate("SI_5054_q4.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(signature(4, "abstract")) - case _ => false - } - } - - property("Use cases should keep their flags - traits should not be affected") = { - createTemplate("SI_5054_q5.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(signature(5, "")) - case _ => false - } - } - - property("Use cases should keep their flags - traits should not be affected") = { - createTemplate("SI_5054_q6.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(signature(6, "abstract")) - case _ => false - } - } + property("Use cases should keep their flags - final should not be lost") = + checkText1("SI_5054_q2.scala", """final def test(): Int""") - val useCaseExplanation = """ - </li><li visbl="pub" name="SI_5054_q7#test" data-isabs="false"> - <a id="test():Int"></a> - <h4 class="signature"> - <span class="modifier_kind"> - <span class="modifier">abstract </span> - <span class="kind">def</span> - </span> - <span class="symbol"> - <span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span> - </span> - </h4> - <p class="shortcomment cmt">[use case] This takes the implicit value in scope.</p><div class="fullcomment">[use case] <div class="comment cmt"><p>This takes the implicit value in scope.</p><p>Example: <code>test()</code></p></div><dl class="paramcmts block"><dt>returns</dt><dd class="cmt"><p>some integer - </p></dd></dl></div> - </li><li visbl="pub" name="SI_5054_q7#test" data-isabs="false"> - <a id="test(Int):Int"></a> - <h4 class="signature"> - <span class="modifier_kind"> - <span class="modifier">abstract </span> - <span class="kind">def</span> - </span> - <span class="symbol"> - <span class="name">test</span><span class="params">(<span name="explicit">explicit: <span name="scala.Int" class="extype">Int</span></span>)</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span> - </span> - </h4> - <p class="shortcomment cmt">[use case] This takes the explicit value passed.</p><div class="fullcomment">[use case] <div class="comment cmt"><p>This takes the explicit value passed.</p><p>Example: <code>test(3)</code></p></div><dl class="paramcmts block"><dt>returns</dt><dd class="cmt"><p>some integer - </p></dd></dl></div> - </li> - """.replaceAll("\\s+","") - - property("Use case individual signature test") = { - createTemplate("SI_5054_q7.scala") match { - case node: scala.xml.Node => - node.toString.replaceAll("\\s+","").contains(useCaseExplanation) - case _ => false - } - } + property("Use cases should keep their flags - implicit should not be lost") = + checkText1("SI_5054_q3.scala", """implicit def test(): Int""") + + property("Use cases should keep their flags - real abstract should not be lost") = + checkText1("SI_5054_q4.scala", """abstract def test(): Int""") + + property("Use cases should keep their flags - traits should not be affected") = + checkText1("SI_5054_q5.scala", """def test(): Int""") + + property("Use cases should keep their flags - traits should not be affected") = + checkText1("SI_5054_q6.scala", """abstract def test(): Int""") + + property("Use case individual signature test") = + checkText("SI_5054_q7.scala", List( + """abstract def test2(explicit: Int): Int [use case] This takes the explicit value passed.""", + """abstract def test1(): Int [use case] This takes the implicit value in scope.""")) + + property("Display correct \"Definition classes\"") = + checkText1("SI_5287.scala", + """def method(): Int + [use case] The usecase explanation + [use case] The usecase explanation + Definition Classes SI_5287 SI_5287_B SI_5287_A""", debug=true) + // explanation appears twice, as small comment and full comment { val files = createTemplates("basic.scala") - println(files) + //println(files) property("class") = files.get("com/example/p1/Clazz.html") match { case Some(node: scala.xml.Node) => { |