Skip to content

Optimize Constant.escape #878

@retronym

Description

@retronym
Member

Something like this:

Index: src/reflect/scala/reflect/internal/Constants.scala
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala
--- a/src/reflect/scala/reflect/internal/Constants.scala	(revision b9f3f5609379aae3585b60a8e402a9a17283de56)
+++ b/src/reflect/scala/reflect/internal/Constants.scala	(date 1729069211440)
@@ -233,7 +233,9 @@
       else if (tag == ClazzTag) signature(typeValue)
       else value.toString()
 
-    def escapedChar(ch: Char): String = (ch: @switch) match {
+    def escapedChar(ch: Char): String = Option(escapedCharOrNull(ch)).getOrElse(String.valueOf(ch))
+
+    private def escapedCharOrNull(ch: Char): String = (ch: @switch) match {
       case '\b' => "\\b"
       case '\t' => "\\t"
       case '\n' => "\\n"
@@ -242,11 +244,26 @@
       case '"'  => "\\\""
       case '\'' => "\\\'"
       case '\\' => "\\\\"
-      case _    => if (ch.isControl) "\\u%04X".format(ch.toInt) else String.valueOf(ch)
+      case _    => if (ch.isControl) "\\u%04X".format(ch.toInt) else null
     }
 
     def escapedStringValue: String = {
-      def escape(text: String): String = text flatMap escapedChar
+      def escape(text: String): String = {
+        val builder = new java.lang.StringBuilder(text.length)
+        var i = 0
+        var replaced = false
+        while (i < builder.length) {
+          val ch = builder.charAt(i)
+          val replacement = escapedCharOrNull(ch)
+          if (replacement != null) {
+            replaced = true
+            builder.append(replacement)
+          } else builder.append(ch)
+          i += 1
+        }
+        if (replaced) builder.toString
+        else text
+      }
       tag match {
         case NullTag   => "null"
         case StringTag => "\"" + escape(stringValue) + "\""

The motivation is that this gets called indirectly by SBT ExtractApi.mkAnnotations in a codepath when assocs is empty but args is not. It prints the tree for the annotation argument in that case.

https://github.com/scala/scala/blob/5f4087b3aa029a30cb5a21fa003e180f000ce552/src/sbt-bridge/scala/tools/xsbt/ExtractAPI.scala#L259-L262

I can't remember what flavour of annotation ends up with this representation. Would be good to relate this to a particular source construct to complete our mental picture.

Activity

changed the title [-]Optimize Constant.escapa[/-] [+]Optimize Constant.escape[/+] on Oct 16, 2024
self-assigned this
on Oct 16, 2024
som-snytt

som-snytt commented on Oct 23, 2024

@som-snytt

@SethTisue if you haven't started editing yet, I'll type it in. I think I saw Dotty has the same code, so I'll do that at the same time. I fell asleep last night when I was going to look at the async in repl ticket.

SethTisue

SethTisue commented on Oct 23, 2024

@SethTisue
Member

If you want to take it, feel free! If you lose interest or get stuck, I can take it over.

som-snytt

som-snytt commented on Nov 18, 2024

@som-snytt

Somehow, I never lost interest.

added this to the 2.13.16 milestone on Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

    Development

    Participants

    @retronym@SethTisue@som-snytt

    Issue actions

      Optimize Constant.escape · Issue #878 · scala/scala-dev