summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml6
-rw-r--r--src/compiler/scala/reflect/internal/Chars.scala36
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala4
-rw-r--r--src/compiler/scala/tools/ant/templates/tool-windows.tmpl1
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala10
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala34
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala4
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala6
-rw-r--r--src/library/scala/collection/immutable/List.scala247
-rw-r--r--src/library/scala/collection/immutable/Map.scala1
-rw-r--r--src/library/scala/collection/immutable/Range.scala122
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala2
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala3
-rw-r--r--test/benchmarks/src/scala/collection/immutable/range-bench.scala61
-rwxr-xr-xtest/files/jvm/mkLibNatives.bat2
-rw-r--r--test/files/pos/t4063.scala39
-rw-r--r--test/files/pos/t4273.scala8
-rw-r--r--test/files/run/t4024.scala11
-rw-r--r--test/files/run/t5053.check6
-rw-r--r--test/files/run/t5053.scala20
-rw-r--r--test/files/scalacheck/CheckEither.scala8
-rw-r--r--test/files/scalacheck/range.scala81
-rwxr-xr-xtest/partest.bat1
-rw-r--r--test/scaladoc/resources/SI_5054_q7.scala8
-rw-r--r--test/scaladoc/resources/SI_5287.scala17
-rw-r--r--test/scaladoc/scala/html.flags1
-rw-r--r--test/scaladoc/scala/html/HtmlFactoryTest.flags1
-rw-r--r--test/scaladoc/scala/html/HtmlFactoryTest.scala183
-rwxr-xr-xtools/get-scala-revision10
29 files changed, 703 insertions, 230 deletions
diff --git a/build.xml b/build.xml
index d179b8e240..1770da7317 100644
--- a/build.xml
+++ b/build.xml
@@ -213,8 +213,7 @@ INITIALISATION
<property name="scalac.args.optimise" value=""/>
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
This is to facilitate testing new command line options which do not yet exist in starr. -->
- <property name="scalac.args.quickonly" value=""/>
-
+ <property name="scalac.args.quickonly" value=""/>
<property name="scalac.args.all" value="${scalac.args} ${scalac.args.optimise}"/>
<property name="scalac.args.quick" value="${scalac.args.all} ${scalac.args.quickonly}"/>
<!-- Setting-up Ant contrib tasks -->
@@ -233,7 +232,6 @@ INITIALISATION
<exec osfamily="windows" executable="tools/get-scala-revision.bat" outputproperty="git.describe" failifexecutionfails="false" />
<!-- some default in case something went wrong getting the revision -->
<property name="git.describe" value="-unknown-"/>
-
<property name="init.avail" value="yes"/>
<!-- Generating version number -->
@@ -241,7 +239,7 @@ INITIALISATION
<property
name="version.number"
value="${version.major}.${version.minor}.${version.patch}.${git.describe}"/>
-
+
<!-- And print-out what we are building -->
<echo message=" build time: ${time.human}" />
<echo message=" java version: ${java.vm.name} ${java.version}" />
diff --git a/src/compiler/scala/reflect/internal/Chars.scala b/src/compiler/scala/reflect/internal/Chars.scala
index 7bd37618ed..f2c90a6721 100644
--- a/src/compiler/scala/reflect/internal/Chars.scala
+++ b/src/compiler/scala/reflect/internal/Chars.scala
@@ -21,27 +21,31 @@ trait Chars {
final val SU = '\u001A'
/** Convert a character digit to an Int according to given base,
- * -1 if no success */
+ * -1 if no success
+ */
def digit2int(ch: Char, base: Int): Int = {
- if ('0' <= ch && ch <= '9' && ch < '0' + base)
- ch - '0'
- else if ('A' <= ch && ch < 'A' + base - 10)
- ch - 'A' + 10
- else if ('a' <= ch && ch < 'a' + base - 10)
- ch - 'a' + 10
- else
- -1
+ val num = (
+ if (ch <= '9') ch - '0'
+ else if ('a' <= ch && ch <= 'z') ch - 'a' + 10
+ else if ('A' <= ch && ch <= 'Z') ch - 'A' + 10
+ else -1
+ )
+ if (0 <= num && num < base) num else -1
}
+ /** Buffer for creating '\ u XXXX' strings. */
+ private[this] val char2uescapeArray = Array[Char]('\\', 'u', 0, 0, 0, 0)
/** Convert a character to a backslash-u escape */
def char2uescape(c: Char): String = {
- var rest = c.toInt
- val buf = new StringBuilder
- for (i <- 1 to 4) {
- buf ++= (rest % 16).toHexString
- rest = rest / 16
- }
- "\\u" + buf.toString.reverse
+ @inline def hexChar(ch: Int): Char =
+ ( if (ch < 10) '0' else 'A' - 10 ) + ch toChar
+
+ char2uescapeArray(2) = hexChar((c >> 12) )
+ char2uescapeArray(3) = hexChar((c >> 8) % 16)
+ char2uescapeArray(4) = hexChar((c >> 4) % 16)
+ char2uescapeArray(5) = hexChar((c ) % 16)
+
+ new String(char2uescapeArray)
}
/** Is character a line break? */
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 75fd733e7e..bc0c81a54b 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -1097,6 +1097,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def typeParams: List[Symbol] =
if (isMonomorphicType) Nil
else {
+ // analogously to the "info" getter, here we allow for two completions:
+ // one: sourceCompleter to LazyType, two: LazyType to completed type
+ if (validTo == NoPeriod)
+ atPhase(phaseOf(infos.validFrom))(rawInfo load this)
if (validTo == NoPeriod)
atPhase(phaseOf(infos.validFrom))(rawInfo load this)
diff --git a/src/compiler/scala/tools/ant/templates/tool-windows.tmpl b/src/compiler/scala/tools/ant/templates/tool-windows.tmpl
index c59d46683e..9f1fbc4524 100644
--- a/src/compiler/scala/tools/ant/templates/tool-windows.tmpl
+++ b/src/compiler/scala/tools/ant/templates/tool-windows.tmpl
@@ -86,3 +86,4 @@ goto :eof
:end
@@endlocal
+exit /b %errorlevel%
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/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 91ac00d946..f319abd060 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -374,7 +374,9 @@ abstract class UnCurry extends InfoTransform
assert(toArraySym != NoSymbol)
def getManifest(tp: Type): Tree = {
val manifestOpt = localTyper.findManifest(tp, false)
- if (!manifestOpt.tree.isEmpty) manifestOpt.tree
+ // Don't want bottom types getting any further than this (SI-4024)
+ if (tp.typeSymbol.isBottomClass) getManifest(AnyClass.tpe)
+ else if (!manifestOpt.tree.isEmpty) manifestOpt.tree
else if (tp.bounds.hi ne tp) getManifest(tp.bounds.hi)
else localTyper.getManifestTree(tree.pos, tp, false)
}
diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala
index 60870cc835..fbecad98fe 100644
--- a/src/library/scala/collection/TraversableViewLike.scala
+++ b/src/library/scala/collection/TraversableViewLike.scala
@@ -192,6 +192,12 @@ trait TraversableViewLike[+A,
override def groupBy[K](f: A => K): immutable.Map[K, This] =
thisSeq groupBy f mapValues (xs => newForced(xs))
+ override def unzip[A1, A2](implicit asPair: A => (A1, A2)) =
+ (newMapped(x => asPair(x)._1), newMapped(x => asPair(x)._2)) // TODO - Performance improvements.
+
+ override def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)) =
+ (newMapped(x => asTriple(x)._1), newMapped(x => asTriple(x)._2), newMapped(x => asTriple(x)._3)) // TODO - Performance improvements.
+
override def toString = viewToString
}
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>) &amp;&amp;
+ * ... &amp;&amp; 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 &amp;&amp; (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/Map.scala b/src/library/scala/collection/immutable/Map.scala
index 45cf088dd9..bbefd983fd 100644
--- a/src/library/scala/collection/immutable/Map.scala
+++ b/src/library/scala/collection/immutable/Map.scala
@@ -47,6 +47,7 @@ trait Map[A, +B] extends Iterable[(A, B)]
def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, d)
/** The same map with a given default value.
+ * Note: `get`, `contains`, `iterator`, `keys`, etc are not affected by `withDefaultValue`.
*
* Invoking transformer methods (e.g. `map`) will not preserve the default value.
*
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index e891f8bec8..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,31 +91,49 @@ extends collection.AbstractSeq[Int]
def isInclusive = false
+ 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()
+ }
+
+ 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
+ }
+ }
+
+ @inline final def apply(idx: Int): Int = {
+ validateMaxLength()
+ if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(idx.toString)
+ else start + (step * idx)
+ }
+
@inline final override def foreach[@specialized(Unit) U](f: Int => U) {
- if (length > 0) {
- val last = this.last
+ if (validateRangeBoundaries(f)) {
var i = start
- while (i != last) {
+ val terminal = terminalElement
+ val step = this.step
+ while (i != terminal) {
f(i)
i += step
}
- f(i)
}
}
- 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)
- }
-
/** Creates a new range containing the first `n` elements of this range.
*
* $doesNotUseBuilders
@@ -104,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)
)
@@ -117,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)
)
@@ -153,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
}
@@ -161,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)
)
@@ -190,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.
*/
@@ -215,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
@@ -228,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 _ =>
@@ -239,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)
}
}
@@ -350,3 +387,4 @@ object Range {
// super.foreach(f)
}
}
+ \ No newline at end of file
diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala
index 2a10458457..350e64739f 100644
--- a/src/library/scala/collection/parallel/immutable/ParRange.scala
+++ b/src/library/scala/collection/parallel/immutable/ParRange.scala
@@ -88,7 +88,7 @@ self =>
/* accessors */
override def foreach[U](f: Int => U): Unit = {
- rangeleft.foreach(f)
+ rangeleft.foreach(f.asInstanceOf[Int => Unit])
ind = len
}
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/benchmarks/src/scala/collection/immutable/range-bench.scala b/test/benchmarks/src/scala/collection/immutable/range-bench.scala
new file mode 100644
index 0000000000..e167ff04e8
--- /dev/null
+++ b/test/benchmarks/src/scala/collection/immutable/range-bench.scala
@@ -0,0 +1,61 @@
+package scala.collection.immutable
+package benchmarks
+
+object RangeTest {
+ // not inlined any more, needs investigation
+ //
+ // class XXS {
+ // private val array = Array.range(0, 100)
+ // def tst = { var sum = 0; for (i <- 0 until array.length) sum += array(i); sum }
+ // }
+
+ var x: Int = 0
+
+ def foreachSum(max: Int): Int = {
+ var sum = 0
+ 1 to max foreach (sum += _)
+ sum
+ }
+ def whileSum(max: Int) = {
+ var sum = 0
+ var num = 1
+ while (num <= max) {
+ sum += num
+ num += 1
+ }
+ sum
+ }
+
+ def show(max: Int, foreachNanos: Long, whileNanos: Long) {
+ val winner = if (foreachNanos < whileNanos) "foreachSum" else "whileSum"
+ val ratio = if (foreachNanos < whileNanos) foreachNanos.toDouble / whileNanos else whileNanos.toDouble / foreachNanos
+ println("1 to %d:, %12s wins, %.3f: foreach %.3f while %.3f".format(
+ max, winner, ratio,
+ foreachNanos.toDouble / 1000000L,
+ whileNanos.toDouble / 1000000L)
+ )
+ }
+
+ def run(max: Int) = {
+ val foreachFirst = util.Random.nextBoolean
+ val t1 = System.nanoTime
+ x = if (foreachFirst) foreachSum(max) else whileSum(max)
+ val t2 = System.nanoTime
+ x = if (foreachFirst) whileSum(max) else foreachSum(max)
+ val t3 = System.nanoTime
+
+ val foreachNanos = if (foreachFirst) t2 - t1 else t3 - t2
+ val whileNanos = if (foreachFirst) t3 - t2 else t2 - t1
+ show(max, foreachNanos, whileNanos)
+ }
+
+ def main(args: Array[String]): Unit = {
+ var max = if (args.isEmpty) 100 else args(0).toInt
+ while (max > 0) {
+ run(max)
+ run(max)
+ run(max)
+ max += (max / 7)
+ }
+ }
+}
diff --git a/test/files/jvm/mkLibNatives.bat b/test/files/jvm/mkLibNatives.bat
index e11b6ee21c..2f99f7aab5 100755
--- a/test/files/jvm/mkLibNatives.bat
+++ b/test/files/jvm/mkLibNatives.bat
@@ -67,4 +67,4 @@ goto end
:end
if "%OS%"=="Windows_NT" @endlocal
-
+exit /b %errorlevel%
diff --git a/test/files/pos/t4063.scala b/test/files/pos/t4063.scala
new file mode 100644
index 0000000000..5e19c42edc
--- /dev/null
+++ b/test/files/pos/t4063.scala
@@ -0,0 +1,39 @@
+trait Parallel
+trait Parallelizable[+ParRepr <: Parallel]
+
+trait PIterableLike[+T, +Repr <: Parallel] extends Parallel with Parallelizable[PIterableLike[T, Repr]]
+
+trait PMap[K, V] extends PIterableLike[(K, V), PMap[K, V]]
+trait PSet[T] extends PIterableLike[T, PSet[T]]
+
+trait CIterableLike[+T, +Repr]
+
+trait CSet[T] extends CIterableLike[T, CSet[T]] with Parallelizable[PSet[T]]
+
+trait CMap[K, V] extends CIterableLike[(K, V), CMap[K, V]] with Parallelizable[PMap[K, V]]
+
+object Test {
+ var x = 0
+
+ def main() {
+ val map: CMap[Int, CSet[Int]] = new CMap[Int, CSet[Int]] {}
+ val set: CSet[Int] = new CSet[Int] {}
+
+ // should infer type argument
+ //map.synchronized[CIterableLike[Any, Any] with Parallelizable[PIterableLike[Any, Parallel with Parallelizable[Parallel]]]] {
+ // or:
+ //map.synchronized[CIterableLike[Any, Any] with Parallelizable[PIterableLike[Any, Parallel]]] {
+ // or, maybe it could also infer existential types:
+ //map.synchronized[CIterableLike[Any, _] with Parallelizable[PIterableLike[Any, _]]] {
+
+ map.synchronized {
+ if (x == 0) {
+ map
+ } else {
+ set
+ }
+ }
+
+ }
+}
+
diff --git a/test/files/pos/t4273.scala b/test/files/pos/t4273.scala
new file mode 100644
index 0000000000..9a942e8325
--- /dev/null
+++ b/test/files/pos/t4273.scala
@@ -0,0 +1,8 @@
+class A {
+ implicit def compareComparables[T](x: T)(implicit ord: Ordering[T]) = new ord.Ops(x)
+
+ class Bippy
+ implicit val bippyOrdering = new Ordering[Bippy] { def compare(x: Bippy, y: Bippy) = util.Random.nextInt }
+
+ (new Bippy) < (new Bippy)
+} \ No newline at end of file
diff --git a/test/files/run/t4024.scala b/test/files/run/t4024.scala
index ef768beb99..7c62a3fc6e 100644
--- a/test/files/run/t4024.scala
+++ b/test/files/run/t4024.scala
@@ -5,5 +5,16 @@ object Test extends App {
val m = x.getClass.getMethod("toString")
assert(m.invoke(x, (Nil: List[AnyRef]): _*) == "abc")
+
+ Test2.main(Array())
}
+
+object Test2 {
+ def main(args: Array[String]): Unit = {
+ val x = "abc"
+ val m = x.getClass.getMethod("toString")
+ m.invoke(x, Nil: _*)
+ m.invoke(x, Seq(): _*)
+ }
+}
diff --git a/test/files/run/t5053.check b/test/files/run/t5053.check
new file mode 100644
index 0000000000..5ec39bbdeb
--- /dev/null
+++ b/test/files/run/t5053.check
@@ -0,0 +1,6 @@
+true
+true
+true
+true
+true
+true
diff --git a/test/files/run/t5053.scala b/test/files/run/t5053.scala
new file mode 100644
index 0000000000..e46dad5ac6
--- /dev/null
+++ b/test/files/run/t5053.scala
@@ -0,0 +1,20 @@
+object Test extends App {
+ {
+ val (left, right) = Seq((1, "a"), (1, "a"), (1, "a"), (3, "c")).view.unzip
+ println(left.isInstanceOf[scala.collection.SeqViewLike[_,_,_]])
+ val (l, m, r) = Seq((1, 1.0, "a"), (1, 1.0, "a"), (1, 1.0, "a"), (3, 3.0, "c")).view.unzip3
+ println(l.isInstanceOf[scala.collection.SeqViewLike[_,_,_]])
+ }
+ {
+ val (left, right) = Iterable((1, "a"), (1, "a"), (1, "a"), (3, "c")).view.unzip
+ println(left.isInstanceOf[scala.collection.IterableViewLike[_,_,_]])
+ val (l, m, r) = Iterable((1, 1.0, "a"), (1, 1.0, "a"), (1, 1.0, "a"), (3, 3.0, "c")).view.unzip3
+ println(l.isInstanceOf[scala.collection.IterableViewLike[_,_,_]])
+ }
+ {
+ val (left, right) = Traversable((1, "a"), (1, "a"), (1, "a"), (3, "c")).view.unzip
+ println(left.isInstanceOf[scala.collection.TraversableViewLike[_,_,_]])
+ val (l, m, r) = Traversable((1, 1.0, "a"), (1, 1.0, "a"), (1, 1.0, "a"), (3, 3.0, "c")).view.unzip3
+ println(l.isInstanceOf[scala.collection.TraversableViewLike[_,_,_]])
+ }
+}
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/partest.bat b/test/partest.bat
index 0b3f5fbf33..4c97a53122 100755
--- a/test/partest.bat
+++ b/test/partest.bat
@@ -101,3 +101,4 @@ goto end
:end
if "%OS%"=="Windows_NT" @endlocal
+exit /b %errorlevel%
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) => {
diff --git a/tools/get-scala-revision b/tools/get-scala-revision
index 3977a61040..b27b6ddc82 100755
--- a/tools/get-scala-revision
+++ b/tools/get-scala-revision
@@ -7,8 +7,8 @@
# not like releases come out so often that we are duty-bound
# to recalculate this every time.
-# git merge-base v2.9.1 master
-devbase="d6f3184fc8"
+# git merge-base v2.8.2 v2.9.1 master
+devbase="df13e31bbb"
# reimplementing git describe hopefully in a way which works
# without any particular tags, branches, or recent versions of git.
@@ -16,7 +16,9 @@ devbase="d6f3184fc8"
# dev-NNNN-g<sha>
# where NNNN is the number of commits since devbase, which
# is the merge-base of the most recent release and master.
-# Presently hardcoded to reduce uncertainty, v2.9.1/master.
+# Presently hardcoded to reduce uncertainty, v2.8.2/v2.9.1/master.
commits=$(git --no-pager log --pretty=oneline $devbase..HEAD | wc -l)
sha=$(git rev-list -n 1 HEAD)
-printf "dev-%s-g%s\n" $commits ${sha:0:7}
+datestr=$(date "+%Y-%m-%d")
+
+printf "rdev-%s-%s-g%s\n" $commits $datestr ${sha:0:7}