aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
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
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')
-rw-r--r--src/dotty/tools/dotc/core/Constraint.scala2
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala74
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala16
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala4
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala1
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala3
-rw-r--r--src/dotty/tools/dotc/core/Types.scala8
-rw-r--r--src/dotty/tools/dotc/core/classfile/ClassfileParser.scala27
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala4
10 files changed, 44 insertions, 97 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala
index e10523753..436b035dc 100644
--- a/src/dotty/tools/dotc/core/Constraint.scala
+++ b/src/dotty/tools/dotc/core/Constraint.scala
@@ -32,7 +32,7 @@ abstract class Constraint extends Showable {
def contains(tvar: TypeVar): Boolean
/** The constraint entry for given type parameter `param`, or NoType if `param` is not part of
- * the constraint domain.
+ * the constraint domain. Note: Low level, implementation dependent.
*/
def entry(param: PolyParam): Type
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: _*))
}
}
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 80daa9681..4f01c43cf 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -975,7 +975,7 @@ object Denotations {
| $sym2: ${sym2.info};
|they are both defined in ${sym1.owner} but have matching signatures
| ${denot1.info} and
- | ${denot2.info}$fromWhere""".stripMargin,
+ | ${denot2.info}$fromWhere""",
denot2.info, denot2.info)
}
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 9d96f2b15..47ec541ab 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -669,9 +669,9 @@ object SymDenotations {
val cls = owner.enclosingSubClass
if (!cls.exists)
fail(
- s""" Access to protected $this not permitted because
+ i""" Access to protected $this not permitted because
| enclosing ${ctx.owner.enclosingClass.showLocated} is not a subclass of
- | ${owner.showLocated} where target is defined""".stripMargin)
+ | ${owner.showLocated} where target is defined""")
else if (
!( isType // allow accesses to types from arbitrary subclasses fixes #4737
|| pre.baseTypeRef(cls).exists // ??? why not use derivesFrom ???
@@ -679,9 +679,9 @@ object SymDenotations {
|| (owner is ModuleClass) // don't perform this check for static members
))
fail(
- s""" Access to protected ${symbol.show} not permitted because
+ i""" Access to protected ${symbol.show} not permitted because
| prefix type ${pre.widen.show} does not conform to
- | ${cls.showLocated} where the access takes place""".stripMargin)
+ | ${cls.showLocated} where the access takes place""")
else true
}
@@ -1933,10 +1933,10 @@ object SymDenotations {
else ("", "the signature")
val name = ctx.fresh.setSetting(ctx.settings.debugNames, true).nameString(denot.name)
ctx.error(
- s"""|bad symbolic reference. A signature$location
- |refers to $name in ${denot.owner.showKind} ${denot.owner.showFullName} which is not available.
- |It may be completely missing from the current classpath, or the version on
- |the classpath might be incompatible with the version used when compiling $src.""".stripMargin)
+ i"""bad symbolic reference. A signature$location
+ |refers to $name in ${denot.owner.showKind} ${denot.owner.showFullName} which is not available.
+ |It may be completely missing from the current classpath, or the version on
+ |the classpath might be incompatible with the version used when compiling $src.""")
if (ctx.debug) throw new Error()
initializeToDefaults(denot)
}
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index a62a88dfb..3f801bda5 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -70,8 +70,8 @@ class SymbolLoaders {
// require yjp.jar at runtime. See SI-2089.
if (ctx.settings.termConflict.isDefault)
throw new TypeError(
- sm"""$owner contains object and package with same name: $pname
- |one of them needs to be removed from classpath""")
+ i"""$owner contains object and package with same name: $pname
+ |one of them needs to be removed from classpath""")
else if (ctx.settings.termConflict.value == "package") {
ctx.warning(
s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.")
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index d46ea6b0f..38b2c8bd6 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -510,6 +510,7 @@ object Symbols {
def toText(printer: Printer): Text = printer.toText(this)
def showLocated(implicit ctx: Context): String = ctx.locatedText(this).show
+ def showExtendedLocation(implicit ctx: Context): String = ctx.extendedLocationText(this).show
def showDcl(implicit ctx: Context): String = ctx.dclText(this).show
def showKind(implicit ctx: Context): String = ctx.kindString(this)
def showName(implicit ctx: Context): String = ctx.nameString(this)
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index d6ada7244..091999412 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -6,7 +6,6 @@ import Types._, Contexts._, Symbols._, Flags._, Names._, NameOps._, Denotations.
import Decorators._
import StdNames.{nme, tpnme}
import collection.mutable
-import printing.Disambiguation.disambiguated
import util.{Stats, DotClass, SimpleMap}
import config.Config
import config.Printers._
@@ -1469,7 +1468,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
/** Show subtype goal that led to an assertion failure */
def showGoal(tp1: Type, tp2: Type)(implicit ctx: Context) = {
- println(disambiguated(implicit ctx => s"assertion failure for ${tp1.show} <:< ${tp2.show}, frozen = $frozenConstraint"))
+ println(ex"assertion failure for $tp1 <:< $tp2, frozen = $frozenConstraint")
def explainPoly(tp: Type) = tp match {
case tp: PolyParam => ctx.echo(s"polyparam ${tp.show} found in ${tp.binder.show}")
case tp: TypeRef if tp.symbol.exists => ctx.echo(s"typeref ${tp.show} found in ${tp.symbol.owner.show}")
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 3e04e9c77..1bfd6eaee 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1493,11 +1493,11 @@ object Types {
(sym.owner.derivesFrom(lastSymbol.owner) ||
selfTypeOf(sym).derivesFrom(lastSymbol.owner) ||
selfTypeOf(lastSymbol).derivesFrom(sym.owner))),
- s"""data race? overwriting symbol of type ${this.show},
- |long form = $this of class ${this.getClass},
+ i"""data race? overwriting symbol of type $this,
+ |long form = $toString of class $getClass,
|last sym id = ${lastSymbol.id}, new sym id = ${sym.id},
|last owner = ${lastSymbol.owner}, new owner = ${sym.owner},
- |period = ${ctx.phase} at run ${ctx.runId}""".stripMargin)
+ |period = ${ctx.phase} at run ${ctx.runId}""")
}
protected def sig: Signature = Signature.NotAMethod
@@ -3799,7 +3799,7 @@ object Types {
class MissingType(pre: Type, name: Name)(implicit ctx: Context) extends TypeError(
i"""cannot resolve reference to type $pre.$name
- |the classfile defining the type might be missing from the classpath${otherReason(pre)}""".stripMargin) {
+ |the classfile defining the type might be missing from the classpath${otherReason(pre)}""") {
if (ctx.debug) printStackTrace()
}
diff --git a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index a6d381693..4ea98f7c3 100644
--- a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -56,26 +56,21 @@ class ClassfileParser(
case e: RuntimeException =>
if (ctx.debug) e.printStackTrace()
throw new IOException(
- sm"""class file $classfile is broken, reading aborted with ${e.getClass}
- |${Option(e.getMessage).getOrElse("")}""")
+ i"""class file $classfile is broken, reading aborted with ${e.getClass}
+ |${Option(e.getMessage).getOrElse("")}""")
}
private def parseHeader(): Unit = {
val magic = in.nextInt
if (magic != JAVA_MAGIC)
- throw new IOException("class file '" + in.file + "' "
- + "has wrong magic number 0x" + toHexString(magic)
- + ", should be 0x" + toHexString(JAVA_MAGIC))
+ throw new IOException(s"class file '${in.file}' has wrong magic number 0x${toHexString(magic)}, should be 0x${toHexString(JAVA_MAGIC)}")
val minorVersion = in.nextChar.toInt
val majorVersion = in.nextChar.toInt
if ((majorVersion < JAVA_MAJOR_VERSION) ||
((majorVersion == JAVA_MAJOR_VERSION) &&
(minorVersion < JAVA_MINOR_VERSION)))
- throw new IOException("class file '" + in.file + "' "
- + "has unknown version "
- + majorVersion + "." + minorVersion
- + ", should be at least "
- + JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION)
+ throw new IOException(
+ s"class file '${in.file}' has unknown version $majorVersion.$minorVersion, should be at least $JAVA_MAJOR_VERSION.$JAVA_MINOR_VERSION")
}
/** Return the class symbol of the given name. */
@@ -817,12 +812,12 @@ class ClassfileParser(
getMember(owner, innerName.toTypeName)
}
assert(result ne NoSymbol,
- sm"""failure to resolve inner class:
- |externalName = $externalName,
- |outerName = $outerName,
- |innerName = $innerName
- |owner.fullName = ${owner.showFullName}
- |while parsing ${classfile}""")
+ i"""failure to resolve inner class:
+ |externalName = $externalName,
+ |outerName = $outerName,
+ |innerName = $innerName
+ |owner.fullName = ${owner.showFullName}
+ |while parsing ${classfile}""")
result
case None =>
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index 8ea4cecde..0d91e8cd6 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -177,8 +177,8 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
protected def errorBadSignature(msg: String, original: Option[RuntimeException] = None)(implicit ctx: Context) = {
val ex = new BadSignature(
- sm"""error reading Scala signature of $classRoot from $source:
- |error occurred at position $readIndex: $msg""")
+ i"""error reading Scala signature of $classRoot from $source:
+ |error occurred at position $readIndex: $msg""")
if (ctx.debug || true) original.getOrElse(ex).printStackTrace() // temporarily enable printing of original failure signature to debug failing builds
throw ex
}