aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Decorators.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-08-07 17:29:24 +0200
committerMartin Odersky <odersky@gmail.com>2016-08-16 17:34:42 +0200
commit8d4d9a363d90cc24bd79b18ea2ef7cba6a746bef (patch)
tree89305ec17cdc4d421047e0ec4a742a79b91a286f /src/dotty/tools/dotc/core/Decorators.scala
parentd5f42680803e40f9b3698404848450d088fca07a (diff)
downloaddotty-8d4d9a363d90cc24bd79b18ea2ef7cba6a746bef.tar.gz
dotty-8d4d9a363d90cc24bd79b18ea2ef7cba6a746bef.tar.bz2
dotty-8d4d9a363d90cc24bd79b18ea2ef7cba6a746bef.zip
New string infterpolators
Roll `sm` and `i` into one interpolator (also called `i`) Evolve `d` to `em` interpolator (for error messages) New interpolator `ex` with more explanations, replaces disambiguation.
Diffstat (limited to 'src/dotty/tools/dotc/core/Decorators.scala')
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala74
1 files changed, 13 insertions, 61 deletions
diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala
index 7d108a459..387e7e466 100644
--- a/src/dotty/tools/dotc/core/Decorators.scala
+++ b/src/dotty/tools/dotc/core/Decorators.scala
@@ -8,6 +8,7 @@ import util.Positions.Position, util.SourcePosition
import collection.mutable.ListBuffer
import dotty.tools.dotc.transform.TreeTransforms._
import scala.language.implicitConversions
+import printing.Formatting._
/** This object provides useful implicit decorators for types defined elsewhere */
object Decorators {
@@ -150,72 +151,23 @@ object Decorators {
implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition =
ctx.source.atPos(pos)
- /** The i"..." string interpolator adds two features to the s interpolator:
- * 1) On all Showables, `show` is called instead of `toString`
- * 2) Lists can be formatted using the desired separator between two `%` signs,
- * eg `i"myList = (${myList}%, %)"`
- */
implicit class StringInterpolators(val sc: StringContext) extends AnyVal {
- def i(args: Any*)(implicit ctx: Context): String = {
-
- def treatArg(arg: Any, suffix: String): (Any, String) = arg match {
- case arg: Seq[_] if suffix.nonEmpty && suffix.head == '%' =>
- val (rawsep, rest) = suffix.tail.span(_ != '%')
- val sep = StringContext.treatEscapes(rawsep)
- if (rest.nonEmpty) (arg map treatSingleArg mkString sep, rest.tail)
- else (arg, suffix)
- case _ =>
- (treatSingleArg(arg), suffix)
- }
-
- def treatSingleArg(arg: Any) : Any =
- try
- arg match {
- case arg: Showable => arg.show(ctx.addMode(Mode.FutureDefsOK))
- case _ => arg
- }
- catch {
- case ex: Exception => throw ex // s"(missing due to $ex)"
- }
+ /** General purpose string formatting */
+ def i(args: Any*)(implicit ctx: Context): String =
+ new StringFormatter(sc).assemble(args)
- val prefix :: suffixes = sc.parts.toList
- val (args1, suffixes1) = (args, suffixes).zipped.map(treatArg(_, _)).unzip
- new StringContext(prefix :: suffixes1.toList: _*).s(args1: _*)
- }
+ /** Formatting for error messages: Like `i` but suppress follow-on
+ * error messages after the first one if some of their arguments are "non-sensical".
+ */
+ def em(args: Any*)(implicit ctx: Context): String =
+ new ErrorMessageFormatter(sc).assemble(args)
- /** Lifted from scala.reflect.internal.util
- * A safe combination of [[scala.collection.immutable.StringLike#stripMargin]]
- * and [[scala.StringContext#raw]].
- *
- * The margin of each line is defined by whitespace leading up to a '|' character.
- * This margin is stripped '''before''' the arguments are interpolated into to string.
- *
- * String escape sequences are '''not''' processed; this interpolater is designed to
- * be used with triple quoted Strings.
- *
- * {{{
- * scala> val foo = "f|o|o"
- * foo: String = f|o|o
- * scala> sm"""|${foo}
- * |"""
- * res0: String =
- * "f|o|o
- * "
- * }}}
+ /** Formatting with added explanations: Like `em`, but add explanations to
+ * give more info about type variables and to disambiguate where needed.
*/
- final def sm(args: Any*): String = {
- def isLineBreak(c: Char) = c == '\n' || c == '\f' // compatible with StringLike#isLineBreak
- def stripTrailingPart(s: String) = {
- val (pre, post) = s.span(c => !isLineBreak(c))
- pre + post.stripMargin
- }
- val stripped: List[String] = sc.parts.toList match {
- case head :: tail => head.stripMargin :: (tail map stripTrailingPart)
- case Nil => Nil
- }
- new StringContext(stripped: _*).raw(args: _*)
- }
+ def ex(args: Any*)(implicit ctx: Context): String =
+ explained2(implicit ctx => em(args: _*))
}
}