From 85e2844f8fce4a4b53d938e7fce5e0247cf66797 Mon Sep 17 00:00:00 2001 From: Vasil Vasilev Date: Thu, 2 Feb 2023 14:13:09 +0100 Subject: [PATCH 1/2] Add support for disabling redirected output in the REPL driver for usage in worksheets in the Scala Plugin for IntelliJ IDEA - Calling `setOut/setErr` in a concurrent environment without any synchronization (such as the Scala compile server in the Scala Plugin for IntelliJ IDEA, which is used to execute Scala 3 worksheets) can lead to unpredictable outcomes where the out/err streams are not restored properly after changing. - This change adds a new default method `redirectOutput` which can be overriden by others to control the redirecting behavior of the REPL driver. --- .../src/dotty/tools/repl/ReplDriver.scala | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index b072d58f6bb7..0f29591e2121 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -187,19 +187,23 @@ class ReplDriver(settings: Array[String], // TODO: i5069 final def bind(name: String, value: Any)(using state: State): State = state + protected def redirectOutput: Boolean = true + // redirecting the output allows us to test `println` in scripted tests private def withRedirectedOutput(op: => State): State = { - val savedOut = System.out - val savedErr = System.err - try { - System.setOut(out) - System.setErr(out) - op - } - finally { - System.setOut(savedOut) - System.setErr(savedErr) - } + if redirectOutput then + val savedOut = System.out + val savedErr = System.err + try { + System.setOut(out) + System.setErr(out) + op + } + finally { + System.setOut(savedOut) + System.setErr(savedErr) + } + else op } private def newRun(state: State, reporter: StoreReporter = newStoreReporter) = { From 11ef198e6d9c50bb31a01480b3877f6dbba545a5 Mon Sep 17 00:00:00 2001 From: Vasil Vasilev Date: Mon, 6 Feb 2023 12:08:05 +0100 Subject: [PATCH 2/2] Add scaladoc documentation for `ReplDriver#redirectOutput` --- compiler/src/dotty/tools/repl/ReplDriver.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 0f29591e2121..905f4f06de08 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -187,6 +187,17 @@ class ReplDriver(settings: Array[String], // TODO: i5069 final def bind(name: String, value: Any)(using state: State): State = state + /** + * Controls whether the `System.out` and `System.err` streams are set to the provided constructor parameter instance + * of [[java.io.PrintStream]] during the execution of the repl. On by default. + * + * Disabling this can be beneficial when executing a repl instance inside a concurrent environment, for example a + * thread pool (such as the Scala compile server in the Scala Plugin for IntelliJ IDEA). + * + * In such environments, indepently executing `System.setOut` and `System.setErr` without any synchronization can + * lead to unpredictable results when restoring the original streams (dependent on the order of execution), leaving + * the Java process in an inconsistent state. + */ protected def redirectOutput: Boolean = true // redirecting the output allows us to test `println` in scripted tests