diff options
29 files changed, 703 insertions, 230 deletions
@@ -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>) && + * ... && 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/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} |