@@ -2,7 +2,10 @@ package dotty.tools
2
2
package dotc
3
3
package repl
4
4
5
- import java .io .{File , PrintWriter , StringWriter , Writer }
5
+ import java .io .{
6
+ File , PrintWriter , PrintStream , StringWriter , Writer , OutputStream ,
7
+ ByteArrayOutputStream => ByteOutputStream
8
+ }
6
9
import java .lang .{Class , ClassLoader }
7
10
import java .net .{URL , URLClassLoader }
8
11
@@ -24,6 +27,7 @@ import dotty.tools.backend.jvm.GenBCode
24
27
import Symbols ._ , Types ._ , Contexts ._ , StdNames ._ , Names ._ , NameOps ._
25
28
import Decorators ._
26
29
import scala .util .control .NonFatal
30
+ import printing .SyntaxHighlighting
27
31
28
32
/** An interpreter for Scala code which is based on the `dotc` compiler.
29
33
*
@@ -210,11 +214,11 @@ class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler wit
210
214
if (! req.compile())
211
215
Interpreter .Error // an error happened during compilation, e.g. a type error
212
216
else {
213
- val (interpreterResultString , succeeded) = req.loadAndRun()
217
+ val (resultStrings , succeeded) = req.loadAndRun()
214
218
if (delayOutput)
215
- previousOutput = clean(interpreterResultString) :: previousOutput
219
+ previousOutput = resultStrings.map(clean) : :: previousOutput
216
220
else if (printResults || ! succeeded)
217
- out.print(clean(interpreterResultString ))
221
+ resultStrings.map(x => out.print(clean(x) ))
218
222
if (succeeded) {
219
223
prevRequests += req
220
224
Interpreter .Success
@@ -383,24 +387,53 @@ class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler wit
383
387
names1 ++ names2
384
388
}
385
389
390
+ /** Sets both System.{out,err} and Console.{out,err} to supplied
391
+ * `os: OutputStream`
392
+ */
393
+ private def withOutput [T ](os : ByteOutputStream )(op : ByteOutputStream => T ) = {
394
+ val ps = new PrintStream (os)
395
+ val oldOut = System .out
396
+ val oldErr = System .err
397
+ System .setOut(ps)
398
+ System .setErr(ps)
399
+
400
+ try {
401
+ Console .withOut(os)(Console .withErr(os)(op(os)))
402
+ } finally {
403
+ System .setOut(oldOut)
404
+ System .setErr(oldErr)
405
+ }
406
+ }
407
+
386
408
/** load and run the code using reflection.
387
- * @return A pair consisting of the run's result as a string , and
409
+ * @return A pair consisting of the run's result as a `List[String]` , and
388
410
* a boolean indicating whether the run succeeded without throwing
389
411
* an exception.
390
412
*/
391
- def loadAndRun (): (String , Boolean ) = {
413
+ def loadAndRun (): (List [ String ] , Boolean ) = {
392
414
val interpreterResultObject : Class [_] =
393
415
Class .forName(resultObjectName, true , classLoader)
394
- val resultValMethod : java.lang.reflect.Method =
416
+ val valMethodRes : java.lang.reflect.Method =
395
417
interpreterResultObject.getMethod(" result" )
396
418
try {
397
- (resultValMethod.invoke(interpreterResultObject).toString, true )
419
+ withOutput(new ByteOutputStream ) { ps =>
420
+ val rawRes = valMethodRes.invoke(interpreterResultObject).toString
421
+ val res =
422
+ if (ictx.useColors) new String (SyntaxHighlighting (rawRes).toArray)
423
+ else rawRes
424
+ val prints = ps.toString(" utf-8" )
425
+ val printList = if (prints != " " ) prints :: Nil else Nil
426
+
427
+ if (! delayOutput) out.print(prints)
428
+
429
+ (printList :+ res, true )
430
+ }
398
431
} catch {
399
432
case NonFatal (ex) =>
400
433
def cause (ex : Throwable ): Throwable =
401
434
if (ex.getCause eq null ) ex else cause(ex.getCause)
402
435
val orig = cause(ex)
403
- (stringFrom(str => orig.printStackTrace(str)), false )
436
+ (stringFrom(str => orig.printStackTrace(str)) :: Nil , false )
404
437
}
405
438
}
406
439
0 commit comments