11package scala .quoted
22package runtime .impl .printers
33
4+ import dotty .tools .dotc .util .Chars
5+
46import scala .annotation .switch
57
8+ import java .lang .StringBuilder
9+
610/** Printer for fully elaborated representation of the source code */
711object SourceCode {
812
@@ -97,7 +101,7 @@ object SourceCode {
97101 this += lineBreak() += " }"
98102 }
99103
100- def result (): String = sb.result()
104+ def result (): String = sb.toString
101105
102106 private def lineBreak (): String = " \n " + (" " * indent)
103107 private def doubleLineBreak (): String = " \n\n " + (" " * indent)
@@ -438,7 +442,7 @@ object SourceCode {
438442 case _ =>
439443 inParens {
440444 printTree(term)
441- this += (if (dotty.tools.dotc.util. Chars .isOperatorPart(sb.last)) " : " else " : " )
445+ this += (if Chars .isOperatorPart(sb.charAt(sb.length - 1 )) then " : " else " : " )
442446 def printTypeOrAnnots (tpe : TypeRepr ): Unit = tpe match {
443447 case AnnotatedType (tp, annot) if tp == term.tpe =>
444448 printAnnotation(annot)
@@ -957,8 +961,8 @@ object SourceCode {
957961
958962 }
959963
960- inline private val qc = ' \' '
961- inline private val qSc = '"'
964+ inline private val qc = " \' "
965+ inline private val qSc = " \" "
962966
963967 def printConstant (const : Constant ): this .type = const match {
964968 case UnitConstant () => this += highlightLiteral(" ()" )
@@ -970,8 +974,8 @@ object SourceCode {
970974 case LongConstant (v) => this += highlightLiteral(v.toString + " L" )
971975 case FloatConstant (v) => this += highlightLiteral(v.toString + " f" )
972976 case DoubleConstant (v) => this += highlightLiteral(v.toString)
973- case CharConstant (v) => this += highlightString(s " ${qc}${ escapedChar(v)}${qc} " )
974- case StringConstant (v) => this += highlightString(s " ${qSc}${ escapedString(v)}${qSc} " )
977+ case CharConstant (v) => this += highlightString(escapedChar(v))
978+ case StringConstant (v) => this += highlightString(escapedString(v))
975979 case ClassOfConstant (v) =>
976980 this += " classOf"
977981 inSquare(printType(v))
@@ -1444,19 +1448,61 @@ object SourceCode {
14441448 private def += (x : Char ): this .type = { sb.append(x); this }
14451449 private def += (x : String ): this .type = { sb.append(x); this }
14461450
1447- private def escapedChar (ch : Char ): String = (ch : @ switch) match {
1448- case '\b ' => " \\ b"
1449- case '\t ' => " \\ t"
1450- case '\n ' => " \\ n"
1451- case '\f ' => " \\ f"
1452- case '\r ' => " \\ r"
1453- case '"' => " \\\" "
1454- case '\' ' => " \\\' "
1455- case '\\ ' => " \\\\ "
1456- case _ => if ch.isControl then f " ${" \\ " }u ${ch.toInt}%04x " else String .valueOf(ch).nn
1457- }
1458-
1459- private def escapedString (str : String ): String = str flatMap escapedChar
1451+ private def escapedChar (ch : Char ): String =
1452+ if requiresFormat(ch) then
1453+ val b = StringBuilder ().append(qc)
1454+ escapedChar(b, ch)
1455+ b.append(qc).toString
1456+ else
1457+ qc + ch + qc
1458+
1459+ private def escapedChar (b : StringBuilder , c : Char ): Unit =
1460+ def quadNibble (b : StringBuilder , x : Int , i : Int ): Unit =
1461+ if i < 4 then
1462+ quadNibble(b, x >> 4 , i + 1 )
1463+ val n = x & 0xF
1464+ val c = if (n < 10 ) '0' + n else 'a' + (n - 10 )
1465+ b.append(c.toChar)
1466+ val replace = (c : @ switch) match
1467+ case '\b ' => " \\ b"
1468+ case '\t ' => " \\ t"
1469+ case '\n ' => " \\ n"
1470+ case '\f ' => " \\ f"
1471+ case '\r ' => " \\ r"
1472+ case '"' => " \\\" "
1473+ case '\' ' => " \\\' "
1474+ case '\\ ' => " \\\\ "
1475+ case c =>
1476+ if c.isControl then
1477+ b.append(" \\ u" )
1478+ quadNibble(b, c.toInt, 0 )
1479+ else
1480+ b.append(c)
1481+ return
1482+ b.append(replace)
1483+
1484+ private def requiresFormat (c : Char ): Boolean = (c : @ switch) match
1485+ case '\b ' | '\t ' | '\n ' | '\f ' | '\r ' | '"' | '\' ' | '\\ ' => true
1486+ case c => c.isControl
1487+
1488+ private def escapedString (text : String ): String =
1489+ def mustBuild : Boolean =
1490+ var i = 0
1491+ while i < text.length do
1492+ if requiresFormat(text.charAt(i)) then return true
1493+ i += 1
1494+ false
1495+ if mustBuild then
1496+ val b = StringBuilder (text.length + 16 )
1497+ b.append(qSc)
1498+ var i = 0
1499+ while i < text.length do
1500+ escapedChar(b, text.charAt(i))
1501+ i += 1
1502+ b.append(qSc)
1503+ b.toString
1504+ else
1505+ qSc + text + qSc
14601506
14611507 private [this ] val names = collection.mutable.Map .empty[Symbol , String ]
14621508 private [this ] val namesIndex = collection.mutable.Map .empty[String , Int ]
0 commit comments