1
1
package scala .quoted
2
2
package runtime .impl .printers
3
3
4
+ import dotty .tools .dotc .util .Chars
5
+
4
6
import scala .annotation .switch
5
7
8
+ import java .lang .StringBuilder
9
+
6
10
/** Printer for fully elaborated representation of the source code */
7
11
object SourceCode {
8
12
@@ -97,7 +101,7 @@ object SourceCode {
97
101
this += lineBreak() += " }"
98
102
}
99
103
100
- def result (): String = sb.result()
104
+ def result (): String = sb.toString
101
105
102
106
private def lineBreak (): String = " \n " + (" " * indent)
103
107
private def doubleLineBreak (): String = " \n\n " + (" " * indent)
@@ -438,7 +442,7 @@ object SourceCode {
438
442
case _ =>
439
443
inParens {
440
444
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 " : " )
442
446
def printTypeOrAnnots (tpe : TypeRepr ): Unit = tpe match {
443
447
case AnnotatedType (tp, annot) if tp == term.tpe =>
444
448
printAnnotation(annot)
@@ -957,8 +961,8 @@ object SourceCode {
957
961
958
962
}
959
963
960
- inline private val qc = ' \' '
961
- inline private val qSc = '"'
964
+ inline private val qc = " \' "
965
+ inline private val qSc = " \" "
962
966
963
967
def printConstant (const : Constant ): this .type = const match {
964
968
case UnitConstant () => this += highlightLiteral(" ()" )
@@ -970,8 +974,8 @@ object SourceCode {
970
974
case LongConstant (v) => this += highlightLiteral(v.toString + " L" )
971
975
case FloatConstant (v) => this += highlightLiteral(v.toString + " f" )
972
976
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))
975
979
case ClassOfConstant (v) =>
976
980
this += " classOf"
977
981
inSquare(printType(v))
@@ -1445,19 +1449,61 @@ object SourceCode {
1445
1449
private def += (x : Char ): this .type = { sb.append(x); this }
1446
1450
private def += (x : String ): this .type = { sb.append(x); this }
1447
1451
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).nn
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
1461
1507
1462
1508
private val names = collection.mutable.Map .empty[Symbol , String ]
1463
1509
private val namesIndex = collection.mutable.Map .empty[String , Int ]
0 commit comments