diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala | 12 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala | 5 | ||||
-rw-r--r-- | src/library/scala/Console.scala | 146 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Range.scala | 2 | ||||
-rw-r--r-- | src/library/scala/concurrent/Future.scala | 159 | ||||
-rw-r--r-- | src/library/scala/io/AnsiColor.scala | 155 |
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"> </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"> </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"> </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"> </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"> </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"> </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"> </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"> </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" } |