@@ -14,6 +14,7 @@ import dotc.core.Symbols.{Symbol, defn}
14
14
import dotc .core .StdNames .{nme , str }
15
15
import dotc .printing .ReplPrinter
16
16
import dotc .reporting .Diagnostic
17
+ import dotc .transform .ValueClasses
17
18
18
19
/** This rendering object uses `ClassLoader`s to accomplish crossing the 4th
19
20
* wall (i.e. fetching back values from the compiled class files put into a
@@ -23,7 +24,7 @@ import dotc.reporting.Diagnostic
23
24
* `ReplDriver#resetToInitial` is called, the accompanying instance of
24
25
* `Rendering` is no longer valid.
25
26
*/
26
- private [repl] class Rendering (parentClassLoader : Option [ClassLoader ] = None ) {
27
+ private [repl] class Rendering (parentClassLoader : Option [ClassLoader ] = None ):
27
28
28
29
import Rendering ._
29
30
@@ -80,43 +81,53 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {
80
81
* then this bug will surface, so perhaps better not?
81
82
* https://github.com/scala/bug/issues/12337
82
83
*/
83
- private [repl] def truncate (str : String ): String = {
84
+ private [repl] def truncate (str : String ): String =
84
85
val showTruncated = " ... large output truncated, print value to show all"
85
86
val ncp = str.codePointCount(0 , str.length) // to not cut inside code point
86
87
if ncp <= MaxStringElements then str
87
88
else str.substring(0 , str.offsetByCodePoints(0 , MaxStringElements - 1 )) + showTruncated
88
- }
89
89
90
90
/** Return a String representation of a value we got from `classLoader()`. */
91
- private [repl] def replStringOf (value : Object )(using Context ): String = {
91
+ private [repl] def replStringOf (value : Object )(using Context ): String =
92
92
assert(myReplStringOf != null ,
93
93
" replStringOf should only be called on values creating using `classLoader()`, but `classLoader()` has not been called so far" )
94
94
val res = myReplStringOf(value)
95
95
if res == null then " null // non-null reference has null-valued toString" else truncate(res)
96
- }
97
96
98
97
/** Load the value of the symbol using reflection.
99
98
*
100
99
* Calling this method evaluates the expression using reflection
101
100
*/
102
- private def valueOf (sym : Symbol )(using Context ): Option [String ] = {
101
+ private def valueOf (sym : Symbol )(using Context ): Option [String ] =
103
102
val objectName = sym.owner.fullName.encode.toString.stripSuffix(" $" )
104
103
val resObj : Class [? ] = Class .forName(objectName, true , classLoader())
105
- val value =
106
- resObj
107
- .getDeclaredMethods.find(_.getName == sym.name.encode.toString )
108
- .map(_.invoke( null ) )
109
- val string = value.map(replStringOf(_))
104
+ val symValue = resObj
105
+ .getDeclaredMethods.find(_.getName == sym.name.encode.toString)
106
+ .flatMap(result => rewrapValueClass( sym.info.classSymbol, result.invoke( null )) )
107
+ val valueString = symValue .map(replStringOf )
108
+
110
109
if (! sym.is(Flags .Method ) && sym.info == defn.UnitType )
111
110
None
112
111
else
113
- string .map { s =>
112
+ valueString .map { s =>
114
113
if (s.startsWith(REPL_WRAPPER_NAME_PREFIX ))
115
114
s.drop(REPL_WRAPPER_NAME_PREFIX .length).dropWhile(c => c.isDigit || c == '$' )
116
115
else
117
116
s
118
117
}
119
- }
118
+
119
+ /** Rewrap value class to their Wrapper class
120
+ *
121
+ * @param sym Value Class symbol
122
+ * @param value underlying value
123
+ */
124
+ private def rewrapValueClass (sym : Symbol , value : Object )(using Context ): Option [Object ] =
125
+ if ValueClasses .isDerivedValueClass(sym) then
126
+ val valueClassName = sym.flatName.encode.toString
127
+ val valueClass = Class .forName(valueClassName, true , classLoader())
128
+ valueClass.getConstructors.headOption.map(_.newInstance(value))
129
+ else
130
+ Some (value)
120
131
121
132
def renderTypeDef (d : Denotation )(using Context ): Diagnostic =
122
133
infoDiagnostic(" // defined " ++ d.symbol.showUser, d)
@@ -171,9 +182,8 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {
171
182
private def infoDiagnostic (msg : String , d : Denotation )(using Context ): Diagnostic =
172
183
new Diagnostic .Info (msg, d.symbol.sourcePos)
173
184
174
- }
175
185
176
- object Rendering {
186
+ object Rendering :
177
187
final val REPL_WRAPPER_NAME_PREFIX = str.REPL_SESSION_LINE
178
188
179
189
extension (s : Symbol )
@@ -182,5 +192,3 @@ object Rendering {
182
192
val text = printer.dclText(s)
183
193
text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value)
184
194
}
185
-
186
- }
0 commit comments