summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala5
-rw-r--r--src/library/scala/Console.scala146
-rw-r--r--src/library/scala/collection/immutable/Range.scala2
-rw-r--r--src/library/scala/concurrent/Future.scala159
-rw-r--r--src/library/scala/io/AnsiColor.scala155
7 files changed, 382 insertions, 99 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index a32c21795d..a5744983b2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -76,7 +76,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
val origOwner = sym.originalOwner
// phase travel necessary: after flatten, the name includes the name of outer classes.
// if some outer name contains $anon, a non-anon class is considered anon.
- if (delambdafyInline() && sym.rawowner.isAnonymousFunction) {
+ if (delambdafyInline() && exitingPickler(sym.rawowner.isAnonymousFunction)) {
// SI-9105: special handling for anonymous functions under delambdafy:inline.
//
// class C { def t = () => { def f { class Z } } }
diff --git a/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala b/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala
index 6b435542a3..a1af3413ea 100644
--- a/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala
+++ b/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala
@@ -6,6 +6,7 @@ package scala.tools.nsc.classpath
import java.net.URL
import scala.annotation.tailrec
import scala.collection.mutable.ArrayBuffer
+import scala.reflect.internal.FatalError
import scala.reflect.io.AbstractFile
import scala.tools.nsc.util.ClassPath
import scala.tools.nsc.util.ClassRepresentation
@@ -72,7 +73,16 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
getDistinctEntries(_.sources(inPackage))
override private[nsc] def list(inPackage: String): ClassPathEntries = {
- val (packages, classesAndSources) = aggregates.map(_.list(inPackage)).unzip
+ val (packages, classesAndSources) = aggregates.map { cp =>
+ try {
+ cp.list(inPackage)
+ } catch {
+ case ex: java.io.IOException =>
+ val e = new FatalError(ex.getMessage)
+ e.initCause(ex)
+ throw e
+ }
+ }.unzip
val distinctPackages = packages.flatten.distinct
val distinctClassesAndSources = mergeClassesAndSources(classesAndSources: _*)
ClassPathEntries(distinctPackages, distinctClassesAndSources)
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index e190b57017..90ccaefe43 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -198,7 +198,7 @@ trait ContextErrors {
val foundType: Type = req.dealiasWiden match {
case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass =>
val retyped = typed (tree.duplicate.clearType())
- val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic)
+ val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic && !sym.isErroneous)
if (foundDecls.isEmpty || (found.typeSymbol eq NoSymbol)) found
else {
// The members arrive marked private, presumably because there was no
@@ -212,7 +212,8 @@ trait ContextErrors {
case _ =>
found
}
- assert(!foundType.isErroneous && !req.isErroneous, (foundType, req))
+ assert(!foundType.isErroneous, s"AdaptTypeError - foundType is Erroneous: $foundType")
+ assert(!req.isErroneous, s"AdaptTypeError - req is Erroneous: $req")
issueNormalTypeError(callee, withAddendum(callee.pos)(typeErrorMsg(foundType, req)))
infer.explainTypes(foundType, req)
diff --git a/src/library/scala/Console.scala b/src/library/scala/Console.scala
index 37127a93d5..0b079aae15 100644
--- a/src/library/scala/Console.scala
+++ b/src/library/scala/Console.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2003-2016, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -12,12 +12,115 @@ import java.io.{ BufferedReader, InputStream, InputStreamReader, OutputStream, P
import scala.io.{ AnsiColor, StdIn }
import scala.util.DynamicVariable
-/** Implements functionality for
- * printing Scala values on the terminal as well as reading specific values.
+/** Implements functionality for printing Scala values on the terminal. For reading values
+ * use [[scala.io.StdIn$ StdIn]].
* Also defines constants for marking up text on ANSI terminals.
*
+ * == Console Output ==
+ *
+ * Use the print methods to output text.
+ * {{{
+ * scala> Console.printf(
+ * "Today the outside temperature is a balmy %.1f°C. %<.1f°C beats the previous record of %.1f°C.\n",
+ * -137.0,
+ * -135.05)
+ * Today the outside temperature is a balmy -137.0°C. -137.0°C beats the previous record of -135.1°C.
+ * }}}
+ *
+ * == ANSI escape codes ==
+ * Use the ANSI escape codes for colorizing console output either to STDOUT or STDERR.
+ * {{{
+ * import Console.{GREEN, RED, RESET, YELLOW_B, UNDERLINED}
+ *
+ * object PrimeTest {
+ *
+ * def isPrime(): Unit = {
+ *
+ * val candidate = io.StdIn.readInt().ensuring(_ > 1)
+ *
+ * val prime = (2 to candidate - 1).forall(candidate % _ != 0)
+ *
+ * if (prime)
+ * Console.println(s"${RESET}${GREEN}yes${RESET}")
+ * else
+ * Console.err.println(s"${RESET}${YELLOW_B}${RED}${UNDERLINED}NO!${RESET}")
+ * }
+ *
+ * def main(args: Array[String]): Unit = isPrime()
+ *
+ * }
+ * }}}
+ *
+ * <table style="border: 10px solid #000;width:100%">
+ * <tr><td style="background-color:#000;color:#fff">$ scala PrimeTest</td></tr>
+ * <tr><td style="background-color:#000;color:#fff">1234567891</td></tr>
+ * <tr><td style="background-color:#000;color:#0f0">yes</td></tr>
+ * <tr><td style="background-color:#000;color:#fff">$ scala PrimeTest</td></tr>
+ * <tr><td style="background-color:#000;color:#fff">56474</td></tr>
+ * <tr><td style="background-color:#000;color:#fff"><span style="background-color:#ff0;color:#f00;text-decoration:underline">NO!</span></td></tr>
+ * </table>
+ *
+ * == IO redefinition ==
+ *
+ * Use IO redefinition to temporarily swap in a different set of input and/or output streams. In this example the stream based
+ * method above is wrapped into a function.
+ *
+ * {{{
+ * import java.io.{ByteArrayOutputStream, StringReader}
+ *
+ * object FunctionalPrimeTest {
+ *
+ * def isPrime(candidate: Int): Boolean = {
+ *
+ * val input = new StringReader(s"$candidate\n")
+ * val outCapture = new ByteArrayOutputStream
+ * val errCapture = new ByteArrayOutputStream
+ *
+ * Console.withIn(input) {
+ * Console.withOut(outCapture) {
+ * Console.withErr(errCapture) {
+ * PrimeTest.isPrime()
+ * }
+ * }
+ * }
+ *
+ * if (outCapture.toByteArray.nonEmpty) // "yes"
+ * true
+ * else if (errCapture.toByteArray.nonEmpty) // "NO!"
+ * false
+ * else throw new IllegalArgumentException(candidate.toString)
+ * }
+ *
+ * def main(args: Array[String]): Unit = {
+ * val primes = (2 to 50) filter (isPrime)
+ * println(s"First primes: $primes")
+ * }
+ *
+ * }
+ * }}}
+ *
+ *
+ * <table style="border: 10px solid #000;width:100%">
+ * <tr><td style="background-color:#000;color:#fff">$ scala FunctionalPrimeTest</td></tr>
+ * <tr><td style="background-color:#000;color:#fff">First primes: Vector(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47)</td></tr>
+ * </table>
+ *
* @author Matthias Zenger
* @version 1.0, 03/09/2003
+ *
+ * @groupname console-output Console Output
+ * @groupprio console-output 30
+ * @groupdesc console-output These methods provide output via the console.
+ *
+ * @groupname io-default IO Defaults
+ * @groupprio io-default 50
+ * @groupdesc io-default These values provide direct access to the standard IO channels
+ *
+ * @groupname io-redefinition IO Redefinition
+ * @groupprio io-redefinition 60
+ * @groupdesc io-redefinition These methods allow substituting alternative streams for the duration of
+ * a body of code. Threadsafe by virtue of [[scala.util.DynamicVariable]].
+ *
*/
object Console extends DeprecatedConsole with AnsiColor {
private val outVar = new DynamicVariable[PrintStream](java.lang.System.out)
@@ -29,11 +132,17 @@ object Console extends DeprecatedConsole with AnsiColor {
protected def setErrDirect(err: PrintStream): Unit = errVar.value = err
protected def setInDirect(in: BufferedReader): Unit = inVar.value = in
- /** The default output, can be overridden by `setOut` */
+ /** The default output, can be overridden by `withOut`
+ * @group io-default
+ */
def out = outVar.value
- /** The default error, can be overridden by `setErr` */
+ /** The default error, can be overridden by `withErr`
+ * @group io-default
+ */
def err = errVar.value
- /** The default input, can be overridden by `setIn` */
+ /** The default input, can be overridden by `withIn`
+ * @group io-default
+ */
def in = inVar.value
/** Sets the default output stream for the duration
@@ -48,6 +157,7 @@ object Console extends DeprecatedConsole with AnsiColor {
* the new output stream active
* @return the results of `thunk`
* @see `withOut[T](out:OutputStream)(thunk: => T)`
+ * @group io-redefinition
*/
def withOut[T](out: PrintStream)(thunk: =>T): T =
outVar.withValue(out)(thunk)
@@ -60,6 +170,7 @@ object Console extends DeprecatedConsole with AnsiColor {
* the new output stream active
* @return the results of `thunk`
* @see `withOut[T](out:PrintStream)(thunk: => T)`
+ * @group io-redefinition
*/
def withOut[T](out: OutputStream)(thunk: =>T): T =
withOut(new PrintStream(out))(thunk)
@@ -67,7 +178,7 @@ object Console extends DeprecatedConsole with AnsiColor {
/** Set the default error stream for the duration
* of execution of one thunk.
* @example {{{
- * withErr(Console.out) { println("This goes to default _out_") }
+ * withErr(Console.out) { err.println("This goes to default _out_") }
* }}}
*
* @param err the new error stream.
@@ -75,6 +186,7 @@ object Console extends DeprecatedConsole with AnsiColor {
* the new error stream active
* @return the results of `thunk`
* @see `withErr[T](err:OutputStream)(thunk: =>T)`
+ * @group io-redefinition
*/
def withErr[T](err: PrintStream)(thunk: =>T): T =
errVar.withValue(err)(thunk)
@@ -87,6 +199,7 @@ object Console extends DeprecatedConsole with AnsiColor {
* the new error stream active
* @return the results of `thunk`
* @see `withErr[T](err:PrintStream)(thunk: =>T)`
+ * @group io-redefinition
*/
def withErr[T](err: OutputStream)(thunk: =>T): T =
withErr(new PrintStream(err))(thunk)
@@ -105,8 +218,9 @@ object Console extends DeprecatedConsole with AnsiColor {
* @param thunk the code to execute with
* the new input stream active
*
- * @return the results of `thunk`
- * @see `withIn[T](in:InputStream)(thunk: =>T)`
+ * @return the results of `thunk`
+ * @see `withIn[T](in:InputStream)(thunk: =>T)`
+ * @group io-redefinition
*/
def withIn[T](reader: Reader)(thunk: =>T): T =
inVar.withValue(new BufferedReader(reader))(thunk)
@@ -117,8 +231,9 @@ object Console extends DeprecatedConsole with AnsiColor {
* @param in the new input stream.
* @param thunk the code to execute with
* the new input stream active
- * @return the results of `thunk`
- * @see `withIn[T](reader:Reader)(thunk: =>T)`
+ * @return the results of `thunk`
+ * @see `withIn[T](reader:Reader)(thunk: =>T)`
+ * @group io-redefinition
*/
def withIn[T](in: InputStream)(thunk: =>T): T =
withIn(new InputStreamReader(in))(thunk)
@@ -126,6 +241,7 @@ object Console extends DeprecatedConsole with AnsiColor {
/** Prints an object to `out` using its `toString` method.
*
* @param obj the object to print; may be null.
+ * @group console-output
*/
def print(obj: Any) {
out.print(if (null == obj) "null" else obj.toString())
@@ -134,29 +250,31 @@ object Console extends DeprecatedConsole with AnsiColor {
/** Flushes the output stream. This function is required when partial
* output (i.e. output not terminated by a newline character) has
* to be made visible on the terminal.
+ * @group console-output
*/
def flush() { out.flush() }
/** Prints a newline character on the default output.
+ * @group console-output
*/
def println() { out.println() }
/** Prints out an object to the default output, followed by a newline character.
*
* @param x the object to print.
+ * @group console-output
*/
def println(x: Any) { out.println(x) }
/** Prints its arguments as a formatted string to the default output,
* based on a string pattern (in a fashion similar to printf in C).
*
- * The interpretation of the formatting patterns is described in
- * <a href="" target="contentFrame" class="java/util/Formatter">
- * `java.util.Formatter`</a>.
+ * The interpretation of the formatting patterns is described in [[java.util.Formatter]].
*
* @param text the pattern for formatting the arguments.
* @param args the arguments used to instantiating the pattern.
* @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments
+ * @group console-output
*/
def printf(text: String, args: Any*) { out.print(text format (args : _*)) }
}
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index d3fe367e50..2fe75343d1 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -512,7 +512,7 @@ object Range {
// As there is no appealing default step size for not-really-integral ranges,
// we offer a partially constructed object.
- class Partial[T, U](f: T => U) {
+ class Partial[T, U](private val f: T => U) extends AnyVal {
def by(x: T): U = f(x)
}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index d9d3d572e8..8abd7feeb7 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -20,11 +20,14 @@ import scala.collection.generic.CanBuildFrom
import scala.reflect.ClassTag
-/** The trait that represents futures.
+/** A `Future` represents a value which may or may not *currently* be available,
+ * but will be available at some point, or an exception if that value could not be made available.
*
- * Asynchronous computations that yield futures are created with the `Future.apply` call:
+ * Asynchronous computations that yield futures are created with the `Future.apply` call and are computed using a supplied `ExecutionContext`,
+ * which can be backed by a Thread pool.
*
* {{{
+ * import ExecutionContext.Implicits.global
* val s = "Hello"
* val f: Future[String] = Future {
* s + " future!"
@@ -88,6 +91,7 @@ import scala.reflect.ClassTag
* thread. That is, the implementation may run multiple callbacks
* in a batch within a single `execute()` and it may run
* `execute()` either immediately or asynchronously.
+ * Completion of the Future must *happen-before* the invocation of the callback.
*/
trait Future[+T] extends Awaitable[T] {
import Future.{ InternalCallbackExecutor => internalExecutor }
@@ -101,9 +105,13 @@ trait Future[+T] extends Awaitable[T] {
* If the future has already been completed with a value,
* this will either be applied immediately or be scheduled asynchronously.
*
+ * Note that the returned value of `pf` will be discarded.
+ *
* $swallowsExceptions
* $multipleCallbacks
* $callbackInContext
+ *
+ * @group Callbacks
*/
@deprecated("use `foreach` or `onComplete` instead (keep in mind that they take total rather than partial functions)", "2.12")
def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = onComplete {
@@ -122,9 +130,13 @@ trait Future[+T] extends Awaitable[T] {
*
* Will not be called in case that the future is completed with a value.
*
+ * Note that the returned value of `pf` will be discarded.
+ *
* $swallowsExceptions
* $multipleCallbacks
* $callbackInContext
+ *
+ * @group Callbacks
*/
@deprecated("use `onComplete` or `failed.foreach` instead (keep in mind that they take total rather than partial functions)", "2.12")
def onFailure[U](@deprecatedName('callback) pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete {
@@ -139,24 +151,28 @@ trait Future[+T] extends Awaitable[T] {
* If the future has already been completed,
* this will either be applied immediately or be scheduled asynchronously.
*
+ * Note that the returned value of `f` will be discarded.
+ *
* $swallowsExceptions
* $multipleCallbacks
* $callbackInContext
*
* @tparam U only used to accept any return type of the given callback function
* @param f the function to be executed when this `Future` completes
+ * @group Callbacks
*/
def onComplete[U](@deprecatedName('func) f: Try[T] => U)(implicit executor: ExecutionContext): Unit
/* Miscellaneous */
- /** Returns whether the future has already been completed with
+ /** Returns whether the future had already been completed with
* a value or an exception.
*
* $nonDeterministic
*
- * @return `true` if the future is already completed, `false` otherwise
+ * @return `true` if the future was completed, `false` otherwise
+ * @group Polling
*/
def isCompleted: Boolean
@@ -164,12 +180,13 @@ trait Future[+T] extends Awaitable[T] {
*
* $nonDeterministic
*
- * If the future is not completed the returned value will be `None`.
- * If the future is completed the value will be `Some(Success(t))`
- * if it contains a valid result, or `Some(Failure(error))` if it contains
+ * If the future was not completed the returned value will be `None`.
+ * If the future was completed the value will be `Some(Success(t))`
+ * if it contained a valid result, or `Some(Failure(error))` if it contained
* an exception.
*
* @return `None` if the `Future` wasn't completed, `Some` if it was.
+ * @group Polling
*/
def value: Option[Try[T]]
@@ -182,6 +199,7 @@ trait Future[+T] extends Awaitable[T] {
* If the original `Future` is successful, the returned `Future` is failed with a `NoSuchElementException`.
*
* @return a failed projection of this `Future`.
+ * @group Transformations
*/
def failed: Future[Throwable] =
transform({
@@ -201,6 +219,7 @@ trait Future[+T] extends Awaitable[T] {
* @tparam U only used to accept any return type of the given callback function
* @param f the function which will be executed if this `Future` completes with a result,
* the return value of `f` will be discarded.
+ * @group Callbacks
*/
def foreach[U](f: T => U)(implicit executor: ExecutionContext): Unit = onComplete { _ foreach f }
@@ -209,10 +228,11 @@ trait Future[+T] extends Awaitable[T] {
* exception thrown when 's' or 'f' is applied, that exception will be propagated
* to the resulting future.
*
- * @tparam S the type of the returned `Future`
- * @param s function that transforms a successful result of the receiver into a successful result of the returned future
- * @param f function that transforms a failure of the receiver into a failure of the returned future
- * @return a `Future` that will be completed with the transformed value
+ * @tparam S the type of the returned `Future`
+ * @param s function that transforms a successful result of the receiver into a successful result of the returned future
+ * @param f function that transforms a failure of the receiver into a failure of the returned future
+ * @return a `Future` that will be completed with the transformed value
+ * @group Transformations
*/
def transform[S](s: T => S, f: Throwable => Throwable)(implicit executor: ExecutionContext): Future[S] =
transform {
@@ -224,9 +244,10 @@ trait Future[+T] extends Awaitable[T] {
* of this Future. If there is any non-fatal exception thrown when 'f'
* is applied then that exception will be propagated to the resulting future.
*
- * @tparam S the type of the returned `Future`
- * @param f function that transforms the result of this future
- * @return a `Future` that will be completed with the transformed value
+ * @tparam S the type of the returned `Future`
+ * @param f function that transforms the result of this future
+ * @return a `Future` that will be completed with the transformed value
+ * @group Transformations
*/
def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S]
@@ -234,9 +255,10 @@ trait Future[+T] extends Awaitable[T] {
* of this Future. If there is any non-fatal exception thrown when 'f'
* is applied then that exception will be propagated to the resulting future.
*
- * @tparam S the type of the returned `Future`
- * @param f function that transforms the result of this future
- * @return a `Future` that will be completed with the transformed value
+ * @tparam S the type of the returned `Future`
+ * @param f function that transforms the result of this future
+ * @return a `Future` that will be completed with the transformed value
+ * @group Transformations
*/
def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S]
@@ -257,11 +279,12 @@ trait Future[+T] extends Awaitable[T] {
* and `withFilter`. See [[scala.concurrent.Future#flatMap]] for an example of such a comprehension.
*
*
- * @tparam S the type of the returned `Future`
- * @param f the function which will be applied to the successful result of this `Future`
- * @return a `Future` which will be completed with the result of the application of the function
+ * @tparam S the type of the returned `Future`
+ * @param f the function which will be applied to the successful result of this `Future`
+ * @return a `Future` which will be completed with the result of the application of the function
+ * @group Transformations
*/
- def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = transform(_.map(f))
+ def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = transform(_ map f)
/** Creates a new future by applying a function to the successful result of
* this future, and returns the result of the function as the new future.
@@ -270,9 +293,10 @@ trait Future[+T] extends Awaitable[T] {
*
* $forComprehensionExamples
*
- * @tparam S the type of the returned `Future`
- * @param f the function which will be applied to the successful result of this `Future`
- * @return a `Future` which will be completed with the result of the application of the function
+ * @tparam S the type of the returned `Future`
+ * @param f the function which will be applied to the successful result of this `Future`
+ * @return a `Future` which will be completed with the result of the application of the function
+ * @group Transformations
*/
def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = transformWith {
case Success(s) => f(s)
@@ -282,7 +306,8 @@ trait Future[+T] extends Awaitable[T] {
/** Creates a new future with one level of nesting flattened, this method is equivalent
* to `flatMap(identity)`.
*
- * @tparam S the type of the returned `Future`
+ * @tparam S the type of the returned `Future`
+ * @group Transformations
*/
def flatten[S](implicit ev: T <:< Future[S]): Future[S] = flatMap(ev)(internalExecutor)
@@ -302,13 +327,15 @@ trait Future[+T] extends Awaitable[T] {
* Await.result(h, Duration.Zero) // throw a NoSuchElementException
* }}}
*
- * @param p the predicate to apply to the successful result of this `Future`
- * @return a `Future` which will hold the successful result of this `Future` if it matches the predicate or a `NoSuchElementException`
+ * @param p the predicate to apply to the successful result of this `Future`
+ * @return a `Future` which will hold the successful result of this `Future` if it matches the predicate or a `NoSuchElementException`
+ * @group Transformations
*/
def filter(@deprecatedName('pred) p: T => Boolean)(implicit executor: ExecutionContext): Future[T] =
map { r => if (p(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") }
/** Used by for-comprehensions.
+ * @group Transformations
*/
final def withFilter(p: T => Boolean)(implicit executor: ExecutionContext): Future[T] = filter(p)(executor)
@@ -332,9 +359,10 @@ trait Future[+T] extends Awaitable[T] {
* Await.result(h, Duration.Zero) // throw a NoSuchElementException
* }}}
*
- * @tparam S the type of the returned `Future`
- *  @param pf the `PartialFunction` to apply to the successful result of this `Future`
- * @return a `Future` holding the result of application of the `PartialFunction` or a `NoSuchElementException`
+ * @tparam S the type of the returned `Future`
+ * @param pf the `PartialFunction` to apply to the successful result of this `Future`
+ * @return a `Future` holding the result of application of the `PartialFunction` or a `NoSuchElementException`
+ * @group Transformations
*/
def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): Future[S] =
map {
@@ -353,9 +381,10 @@ trait Future[+T] extends Awaitable[T] {
* Future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3
* }}}
*
- * @tparam U the type of the returned `Future`
- * @param pf the `PartialFunction` to apply if this `Future` fails
- * @return a `Future` with the successful value of this `Future` or the result of the `PartialFunction`
+ * @tparam U the type of the returned `Future`
+ * @param pf the `PartialFunction` to apply if this `Future` fails
+ * @return a `Future` with the successful value of this `Future` or the result of the `PartialFunction`
+ * @group Transformations
*/
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] =
transform { _ recover pf }
@@ -373,9 +402,10 @@ trait Future[+T] extends Awaitable[T] {
* Future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue
* }}}
*
- * @tparam U the type of the returned `Future`
- * @param pf the `PartialFunction` to apply if this `Future` fails
- * @return a `Future` with the successful value of this `Future` or the outcome of the `Future` returned by the `PartialFunction`
+ * @tparam U the type of the returned `Future`
+ * @param pf the `PartialFunction` to apply if this `Future` fails
+ * @return a `Future` with the successful value of this `Future` or the outcome of the `Future` returned by the `PartialFunction`
+ * @group Transformations
*/
def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] =
transformWith {
@@ -391,9 +421,10 @@ trait Future[+T] extends Awaitable[T] {
* Otherwise, if `that` future fails, the resulting future is failed
* with the throwable stored in `that`.
*
- * @tparam U the type of the other `Future`
- * @param that the other `Future`
- * @return a `Future` with the results of both futures or the failure of the first of them that failed
+ * @tparam U the type of the other `Future`
+ * @param that the other `Future`
+ * @return a `Future` with the results of both futures or the failure of the first of them that failed
+ * @group Transformations
*/
def zip[U](that: Future[U]): Future[(T, U)] = {
implicit val ec = internalExecutor
@@ -410,11 +441,12 @@ trait Future[+T] extends Awaitable[T] {
* If the application of `f` throws a throwable, the resulting future
* is failed with that throwable if it is non-fatal.
*
- * @tparam U the type of the other `Future`
- * @tparam R the type of the resulting `Future`
- * @param that the other `Future`
- * @param f the function to apply to the results of `this` and `that`
- * @return a `Future` with the result of the application of `f` to the results of `this` and `that`
+ * @tparam U the type of the other `Future`
+ * @tparam R the type of the resulting `Future`
+ * @param that the other `Future`
+ * @param f the function to apply to the results of `this` and `that`
+ * @return a `Future` with the result of the application of `f` to the results of `this` and `that`
+ * @group Transformations
*/
def zipWith[U, R](that: Future[U])(f: (T, U) => R)(implicit executor: ExecutionContext): Future[R] =
flatMap(r1 => that.map(r2 => f(r1, r2)))(internalExecutor)
@@ -433,9 +465,10 @@ trait Future[+T] extends Awaitable[T] {
* h foreach println // Eventually prints 5
* }}}
*
- * @tparam U the type of the other `Future` and the resulting `Future`
- * @param that the `Future` whose result we want to use if this `Future` fails.
- * @return a `Future` with the successful result of this or that `Future` or the failure of this `Future` if both fail
+ * @tparam U the type of the other `Future` and the resulting `Future`
+ * @param that the `Future` whose result we want to use if this `Future` fails.
+ * @return a `Future` with the successful result of this or that `Future` or the failure of this `Future` if both fail
+ * @group Transformations
*/
def fallbackTo[U >: T](that: Future[U]): Future[U] =
if (this eq that) this
@@ -447,9 +480,10 @@ trait Future[+T] extends Awaitable[T] {
/** Creates a new `Future[S]` which is completed with this `Future`'s result if
* that conforms to `S`'s erased type or a `ClassCastException` otherwise.
*
- * @tparam S the type of the returned `Future`
- * @param tag the `ClassTag` which will be used to cast the result of this `Future`
- * @return a `Future` holding the casted result of this `Future` or a `ClassCastException` otherwise
+ * @tparam S the type of the returned `Future`
+ * @param tag the `ClassTag` which will be used to cast the result of this `Future`
+ * @return a `Future` holding the casted result of this `Future` or a `ClassCastException` otherwise
+ * @group Transformations
*/
def mapTo[S](implicit tag: ClassTag[S]): Future[S] = {
implicit val ec = internalExecutor
@@ -484,9 +518,12 @@ trait Future[+T] extends Awaitable[T] {
* }
* }}}
*
- * @tparam U only used to accept any return type of the given `PartialFunction`
- * @param pf a `PartialFunction` which will be conditionally applied to the outcome of this `Future`
- * @return a `Future` which will be completed with the exact same outcome as this `Future` but after the `PartialFunction` has been executed.
+ * $swallowsExceptions
+ *
+ * @tparam U only used to accept any return type of the given `PartialFunction`
+ * @param pf a `PartialFunction` which will be conditionally applied to the outcome of this `Future`
+ * @return a `Future` which will be completed with the exact same outcome as this `Future` but after the `PartialFunction` has been executed.
+ * @group Callbacks
*/
def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] =
transform {
@@ -598,6 +635,13 @@ object Future {
/** Starts an asynchronous computation and returns a `Future` instance with the result of that computation.
*
+ * The following expressions are equivalent:
+ *
+ * {{{
+ * val f1 = Future(expr)
+ * val f2 = Future.unit.map(_ => expr)
+ * }}}
+ *
* The result becomes available once the asynchronous computation is completed.
*
* @tparam T the type of the result
@@ -618,7 +662,7 @@ object Future {
*/
def sequence[A, M[X] <: TraversableOnce[X]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = {
in.foldLeft(successful(cbf(in))) {
- (fr, fa) => for (r <- fr; a <- fa) yield (r += a)
+ (fr, fa) => fr.zipWith(fa)(_ += _)
}.map(_.result())(InternalCallbackExecutor)
}
@@ -791,10 +835,9 @@ object Future {
* @return the `Future` of the `TraversableOnce` of results
*/
def traverse[A, B, M[X] <: TraversableOnce[X]](in: M[A])(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], executor: ExecutionContext): Future[M[B]] =
- in.foldLeft(successful(cbf(in))) { (fr, a) =>
- val fb = fn(a)
- for (r <- fr; b <- fb) yield (r += b)
- }.map(_.result())
+ in.foldLeft(successful(cbf(in))) {
+ (fr, a) => fr.zipWith(fn(a))(_ += _)
+ }.map(_.result())(InternalCallbackExecutor)
// This is used to run callbacks which are internal
diff --git a/src/library/scala/io/AnsiColor.scala b/src/library/scala/io/AnsiColor.scala
index 39e2e3b0ca..720049ba8e 100644
--- a/src/library/scala/io/AnsiColor.scala
+++ b/src/library/scala/io/AnsiColor.scala
@@ -1,52 +1,163 @@
package scala
package io
+/** ANSI escape codes providing control over text formatting and color on supporting text terminals.
+ *
+ * ==ANSI Style and Control Codes==
+ *
+ * This group of escape codes provides control over text styling. For example, to turn on reverse video with bold and
+ * then turn off all styling embed these codes,
+ *
+ * {{{
+ * import io.AnsiColor._
+ *
+ * object ColorDemo extends App {
+ *
+ * println(s"$REVERSED${BOLD}Hello 1979!$RESET")
+ * }
+ * }}}
+ *
+ * ==Foreground and Background Colors==
+ *
+ * Embedding ANSI color codes in text output will control the text foreground and background colors.
+ *
+ * <table>
+ * <tr><th style="padding:4px 15px;text-decoration:underline">Foreground</th><th style="width:50%"></th><th style="padding:4px 15px;text-decoration:underline">Background</th></tr>
+ * <tr><td style="padding:4px 15px">BLACK </td><td style="background-color:#000"></td><td style="padding:4px 15px">BLACK_B </td></tr>
+ * <tr><td style="padding:4px 15px">RED </td><td style="background-color:#f00"></td><td style="padding:4px 15px">RED_B </td></tr>
+ * <tr><td style="padding:4px 15px">GREEN </td><td style="background-color:#0f0"></td><td style="padding:4px 15px">GREEN_B </td></tr>
+ * <tr><td style="padding:4px 15px">YELLOW </td><td style="background-color:#ff0"></td><td style="padding:4px 15px">YELLOW_B </td></tr>
+ * <tr><td style="padding:4px 15px">BLUE </td><td style="background-color:#00f"></td><td style="padding:4px 15px">BLUE_B </td></tr>
+ * <tr><td style="padding:4px 15px">MAGENTA</td><td style="background-color:#f0f"></td><td style="padding:4px 15px">MAGENTA_B</td></tr>
+ * <tr><td style="padding:4px 15px">CYAN </td><td style="background-color:#0ff"></td><td style="padding:4px 15px">CYAN_B </td></tr>
+ * <tr><td style="padding:4px 15px">WHITE </td><td style="background-color:#fff"></td><td style="padding:4px 15px">WHITE_B </td></tr>
+ * </table>
+ *
+ * @groupname style-control ANSI Style and Control Codes
+ * @groupprio style-control 101
+ *
+ * @groupname color-black ANSI Black
+ * @groupdesc color-black <table style="width:100%"><tr><td style="background-color:#000">&nbsp;</td></tr></table>
+ * @groupprio color-black 110
+ *
+ * @groupname color-red ANSI Red
+ * @groupdesc color-red <table style="width:100%"><tr><td style="background-color:#f00">&nbsp;</td></tr></table>
+ * @groupprio color-red 120
+ *
+ * @groupname color-green ANSI Green
+ * @groupdesc color-green <table style="width:100%"><tr><td style="background-color:#0f0">&nbsp;</td></tr></table>
+ * @groupprio color-green 130
+ *
+ * @groupname color-yellow ANSI Yellow
+ * @groupdesc color-yellow <table style="width:100%"><tr><td style="background-color:#ff0">&nbsp;</td></tr></table>
+ * @groupprio color-yellow 140
+ *
+ * @groupname color-blue ANSI Blue
+ * @groupdesc color-blue <table style="width:100%"><tr><td style="background-color:#00f">&nbsp;</td></tr></table>
+ * @groupprio color-blue 150
+ *
+ * @groupname color-magenta ANSI Magenta
+ * @groupdesc color-magenta <table style="width:100%"><tr><td style="background-color:#f0f">&nbsp;</td></tr></table>
+ * @groupprio color-magenta 160
+ *
+ * @groupname color-cyan ANSI Cyan
+ * @groupdesc color-cyan <table style="width:100%"><tr><td style="background-color:#0ff">&nbsp;</td></tr></table>
+ * @groupprio color-cyan 170
+ *
+ * @groupname color-white ANSI White
+ * @groupdesc color-white <table style="width:100%"><tr><td style="background-color:#fff">&nbsp;</td></tr></table>
+ * @groupprio color-white 180
+ */
trait AnsiColor {
- /** Foreground color for ANSI black */
+ /** Foreground color for ANSI black
+ * @group color-black
+ */
final val BLACK = "\u001b[30m"
- /** Foreground color for ANSI red */
+ /** Foreground color for ANSI red
+ * @group color-red
+ */
final val RED = "\u001b[31m"
- /** Foreground color for ANSI green */
+ /** Foreground color for ANSI green
+ * @group color-green
+ */
final val GREEN = "\u001b[32m"
- /** Foreground color for ANSI yellow */
+ /** Foreground color for ANSI yellow
+ * @group color-yellow
+ */
final val YELLOW = "\u001b[33m"
- /** Foreground color for ANSI blue */
+ /** Foreground color for ANSI blue
+ * @group color-blue
+ */
final val BLUE = "\u001b[34m"
- /** Foreground color for ANSI magenta */
+ /** Foreground color for ANSI magenta
+ * @group color-magenta
+ */
final val MAGENTA = "\u001b[35m"
- /** Foreground color for ANSI cyan */
+ /** Foreground color for ANSI cyan
+ * @group color-cyan
+ */
final val CYAN = "\u001b[36m"
- /** Foreground color for ANSI white */
+ /** Foreground color for ANSI white
+ * @group color-white
+ */
final val WHITE = "\u001b[37m"
- /** Background color for ANSI black */
+ /** Background color for ANSI black
+ * @group color-black
+ */
final val BLACK_B = "\u001b[40m"
- /** Background color for ANSI red */
+ /** Background color for ANSI red
+ * @group color-red
+ */
final val RED_B = "\u001b[41m"
- /** Background color for ANSI green */
+ /** Background color for ANSI green
+ * @group color-green
+ */
final val GREEN_B = "\u001b[42m"
- /** Background color for ANSI yellow */
+ /** Background color for ANSI yellow
+ * @group color-yellow
+ */
final val YELLOW_B = "\u001b[43m"
- /** Background color for ANSI blue */
+ /** Background color for ANSI blue
+ * @group color-blue
+ */
final val BLUE_B = "\u001b[44m"
- /** Background color for ANSI magenta */
+ /** Background color for ANSI magenta
+ * @group color-magenta
+ */
final val MAGENTA_B = "\u001b[45m"
- /** Background color for ANSI cyan */
+ /** Background color for ANSI cyan
+ * @group color-cyan
+ */
final val CYAN_B = "\u001b[46m"
- /** Background color for ANSI white */
+ /** Background color for ANSI white
+ * @group color-white
+ */
final val WHITE_B = "\u001b[47m"
- /** Reset ANSI styles */
+ /** Reset ANSI styles
+ * @group style-control
+ */
final val RESET = "\u001b[0m"
- /** ANSI bold */
+ /** ANSI bold
+ * @group style-control
+ */
final val BOLD = "\u001b[1m"
- /** ANSI underlines */
+ /** ANSI underlines
+ * @group style-control
+ */
final val UNDERLINED = "\u001b[4m"
- /** ANSI blink */
+ /** ANSI blink
+ * @group style-control
+ */
final val BLINK = "\u001b[5m"
- /** ANSI reversed */
+ /** ANSI reversed
+ * @group style-control
+ */
final val REVERSED = "\u001b[7m"
- /** ANSI invisible */
+ /** ANSI invisible
+ * @group style-control
+ */
final val INVISIBLE = "\u001b[8m"
}