Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize Constant.escape #878

Open
retronym opened this issue Oct 16, 2024 · 0 comments
Open

Optimize Constant.escape #878

retronym opened this issue Oct 16, 2024 · 0 comments
Assignees

Comments

@retronym
Copy link
Member

retronym commented Oct 16, 2024

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.

@retronym retronym changed the title Optimize Constant.escapa Optimize Constant.escape Oct 16, 2024
@SethTisue SethTisue self-assigned this Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants