diff options
author | Martin Odersky <odersky@gmail.com> | 2016-08-07 17:29:24 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-08-16 17:34:42 +0200 |
commit | 8d4d9a363d90cc24bd79b18ea2ef7cba6a746bef (patch) | |
tree | 89305ec17cdc4d421047e0ec4a742a79b91a286f /src/dotty/tools/dotc/core/Decorators.scala | |
parent | d5f42680803e40f9b3698404848450d088fca07a (diff) | |
download | dotty-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.scala | 74 |
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: _*)) } } |