summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/reflect/FormatInterpolator.scala
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-02-11 13:53:32 -0800
committerSom Snytt <som.snytt@gmail.com>2014-02-11 13:53:32 -0800
commitff4cfd575a9b731adc60582de447fafb5303eb49 (patch)
tree5a01de0954e811fd7e012f3f902c74c540837b8d /src/compiler/scala/tools/reflect/FormatInterpolator.scala
parentd4f5abf9002fd617e871d1f20fdcf531b38b26e1 (diff)
downloadscala-ff4cfd575a9b731adc60582de447fafb5303eb49.tar.gz
scala-ff4cfd575a9b731adc60582de447fafb5303eb49.tar.bz2
scala-ff4cfd575a9b731adc60582de447fafb5303eb49.zip
SI-8266 Deprecate octal escapes in f-interpolator
Also turns the f-interpolator into a migration assistant by suggesting alternatives for the standard escapes.
Diffstat (limited to 'src/compiler/scala/tools/reflect/FormatInterpolator.scala')
-rw-r--r--src/compiler/scala/tools/reflect/FormatInterpolator.scala51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/reflect/FormatInterpolator.scala b/src/compiler/scala/tools/reflect/FormatInterpolator.scala
index d5e674ebae..0258002850 100644
--- a/src/compiler/scala/tools/reflect/FormatInterpolator.scala
+++ b/src/compiler/scala/tools/reflect/FormatInterpolator.scala
@@ -81,7 +81,56 @@ abstract class FormatInterpolator {
case Literal(Constant(x: String)) => x
case _ => throw new IllegalArgumentException("internal error: argument parts must be a list of string literals")
}
- val s = StringContext.treatEscapes(s0)
+ def escapeHatch: PartialFunction[Throwable, String] = {
+ // trailing backslash, octal escape, or other
+ case e: StringContext.InvalidEscapeException =>
+ def errPoint = part.pos withPoint (part.pos.point + e.index)
+ def octalOf(c: Char) = Character.digit(c, 8)
+ def alt = {
+ def altOf(i: Int) = i match {
+ case '\b' => "\\b"
+ case '\t' => "\\t"
+ case '\n' => "\\n"
+ case '\f' => "\\f"
+ case '\r' => "\\r"
+ case '\"' => "\\u0022" // $" in future
+ case '\'' => "'"
+ case '\\' => """\\"""
+ case x => "\\u%04x" format x
+ }
+ val suggest = {
+ val r = "([0-7]{1,3}).*".r
+ (s0 drop e.index + 1) match {
+ case r(n) => altOf { (0 /: n) { case (a, o) => (8 * a) + (o - '0') } }
+ case _ => ""
+ }
+ }
+ val txt =
+ if ("" == suggest) ""
+ else s", use $suggest instead"
+ txt
+ }
+ def badOctal = {
+ def msg(what: String) = s"Octal escape literals are $what$alt."
+ if (settings.future) {
+ c.error(errPoint, msg("unsupported"))
+ s0
+ } else {
+ c.enclosingUnit.deprecationWarning(errPoint, msg("deprecated"))
+ try StringContext.treatEscapes(s0) catch escapeHatch
+ }
+ }
+ if (e.index == s0.length - 1) {
+ c.error(errPoint, """Trailing '\' escapes nothing.""")
+ s0
+ } else if (octalOf(s0(e.index + 1)) >= 0) {
+ badOctal
+ } else {
+ c.error(errPoint, e.getMessage)
+ s0
+ }
+ }
+ val s = try StringContext.processEscapes(s0) catch escapeHatch
val ms = fpat findAllMatchIn s
def errorLeading(op: Conversion) = op.errorAt(Spec, s"conversions must follow a splice; ${Conversion.literalHelp}")