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))
@@ -1445,19 +1449,61 @@ object SourceCode {
14451449 private def += (x : Char ): this .type = { sb.append(x); this }
14461450 private def += (x : String ): this .type = { sb.append(x); this }
14471451
1448- private def escapedChar (ch : Char ): String = (ch : @ switch) match {
1449- case '\b ' => " \\ b"
1450- case '\t ' => " \\ t"
1451- case '\n ' => " \\ n"
1452- case '\f ' => " \\ f"
1453- case '\r ' => " \\ r"
1454- case '"' => " \\\" "
1455- case '\' ' => " \\\' "
1456- case '\\ ' => " \\\\ "
1457- case _ => if ch.isControl then f " ${" \\ " }u ${ch.toInt}%04x " else String .valueOf(ch)
1458- }
1459-
1460- private def escapedString (str : String ): String = str flatMap escapedChar
1452+ private def escapedChar (ch : Char ): String =
1453+ if requiresFormat(ch) then
1454+ val b = StringBuilder ().append(qc)
1455+ escapedChar(b, ch)
1456+ b.append(qc).toString
1457+ else
1458+ qc + ch + qc
1459+
1460+ private def escapedChar (b : StringBuilder , c : Char ): Unit =
1461+ def quadNibble (b : StringBuilder , x : Int , i : Int ): Unit =
1462+ if i < 4 then
1463+ quadNibble(b, x >> 4 , i + 1 )
1464+ val n = x & 0xF
1465+ val c = if (n < 10 ) '0' + n else 'a' + (n - 10 )
1466+ b.append(c.toChar)
1467+ val replace = (c : @ switch) match
1468+ case '\b ' => " \\ b"
1469+ case '\t ' => " \\ t"
1470+ case '\n ' => " \\ n"
1471+ case '\f ' => " \\ f"
1472+ case '\r ' => " \\ r"
1473+ case '"' => " \\\" "
1474+ case '\' ' => " \\\' "
1475+ case '\\ ' => " \\\\ "
1476+ case c =>
1477+ if c.isControl then
1478+ b.append(" \\ u" )
1479+ quadNibble(b, c.toInt, 0 )
1480+ else
1481+ b.append(c)
1482+ return
1483+ b.append(replace)
1484+
1485+ private def requiresFormat (c : Char ): Boolean = (c : @ switch) match
1486+ case '\b ' | '\t ' | '\n ' | '\f ' | '\r ' | '"' | '\' ' | '\\ ' => true
1487+ case c => c.isControl
1488+
1489+ private def escapedString (text : String ): String =
1490+ def mustBuild : Boolean =
1491+ var i = 0
1492+ while i < text.length do
1493+ if requiresFormat(text.charAt(i)) then return true
1494+ i += 1
1495+ false
1496+ if mustBuild then
1497+ val b = StringBuilder (text.length + 16 )
1498+ b.append(qSc)
1499+ var i = 0
1500+ while i < text.length do
1501+ escapedChar(b, text.charAt(i))
1502+ i += 1
1503+ b.append(qSc)
1504+ b.toString
1505+ else
1506+ qSc + text + qSc
14611507
14621508 private val names = collection.mutable.Map .empty[Symbol , String ]
14631509 private val namesIndex = collection.mutable.Map .empty[String , Int ]
0 commit comments