Skip to content

Commit bbbe580

Browse files
committed
REPL - invoke pprint reflectively
fixes #24111 reflectively load the function each time, (i.e. don't cache). As this is a rare event (i.e user interaction), any cost is less of a concern. if cant load reflectively, then fallback to calling directly.
1 parent 71fcd1a commit bbbe580

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

compiler/src/dotty/tools/repl/Rendering.scala

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,35 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None):
2626

2727
var myClassLoader: AbstractFileClassLoader = uninitialized
2828

29+
private def pprintRender(value: Any, width: Int, height: Int, initialOffset: Int)(using Context): String = {
30+
def fallback() =
31+
dotty.shaded.pprint.PPrinter.BlackWhite.apply(
32+
value, width = width, height = height, initialOffset = initialOffset
33+
).plainText
34+
try
35+
val cl = classLoader()
36+
val pprintCls = Class.forName("dotty.shaded.pprint.PPrinter$BlackWhite$", false, cl)
37+
val fansiStrCls = Class.forName("dotty.shaded.fansi.Str", false, cl)
38+
val BlackWhite = pprintCls.getField("MODULE$").get(null)
39+
val BlackWhite_apply = pprintCls.getMethod("apply",
40+
classOf[Any], // value
41+
classOf[Int], // width
42+
classOf[Int], // height
43+
classOf[Int], // indentation
44+
classOf[Int], // initialOffset
45+
classOf[Boolean], // escape Unicode
46+
classOf[Boolean], // show field names
47+
)
48+
val FansiStr_plainText = fansiStrCls.getMethod("plainText")
49+
val fansiStr = BlackWhite_apply.invoke(
50+
BlackWhite, value, width, height, 2, initialOffset, false, true
51+
)
52+
FansiStr_plainText.invoke(fansiStr).asInstanceOf[String]
53+
catch
54+
case _: ClassNotFoundException => fallback()
55+
case _: NoSuchMethodException => fallback()
56+
}
57+
2958

3059
/** Class loader used to load compiled code */
3160
private[repl] def classLoader()(using Context) =
@@ -55,7 +84,7 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None):
5584
/** Return a String representation of a value we got from `classLoader()`. */
5685
private[repl] def replStringOf(sym: Symbol, value: Object)(using Context): String = {
5786
// pretty-print things with 100 cols 50 rows by default,
58-
dotty.shaded.pprint.PPrinter.BlackWhite.apply(value, width = 100, height = 50).plainText
87+
pprintRender(value, width = 100, height = 50, initialOffset = 0 /* TODO: include offset */)
5988
}
6089

6190
/** Load the value of the symbol using reflection.

0 commit comments

Comments
 (0)