Skip to content

[WIP] Fix #3007: Added silencing of the output in initial and cleanup commands #4933

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.jline.reader._
import scala.annotation.tailrec
import scala.collection.JavaConverters._


/** The state of the REPL contains necessary bindings instead of having to have
* mutation
*
Expand Down Expand Up @@ -70,7 +71,7 @@ class ReplDriver(settings: Array[String],
}

/** the initial, empty state of the REPL session */
protected[this] def initState = State(0, 0, Nil, rootCtx)
final def initialState = State(0, 0, Nil, rootCtx)

/** Reset state of repl to the initial state
*
Expand Down Expand Up @@ -101,7 +102,7 @@ class ReplDriver(settings: Array[String],
* observable outside of the CLI, for this reason, most helper methods are
* `protected final` to facilitate testing.
*/
final def runUntilQuit(): State = {
final def runUntilQuit(initialState: State = initialState): State = {
val terminal = new JLineTerminal()

/** Blockingly read a line, getting back a parse result */
Expand All @@ -127,7 +128,7 @@ class ReplDriver(settings: Array[String],
else loop(interpret(res)(state))
}

try withRedirectedOutput { loop(initState) }
try withRedirectedOutput { loop(initialState) }
finally terminal.close()
}

Expand All @@ -136,6 +137,9 @@ class ReplDriver(settings: Array[String],
interpret(parsed)
}

// TODO: i5069
final def bind(name: String, value: Any)(implicit state: State): State = state

private def withRedirectedOutput(op: => State): State =
Console.withOut(out) { Console.withErr(out) { op } }

Expand Down Expand Up @@ -308,7 +312,7 @@ class ReplDriver(settings: Array[String],

case Reset =>
resetToInitial()
initState
initialState

case Imports =>
state.imports.foreach(i => out.println(SyntaxHighlighting(i.show(state.context))))
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/repl/ReplTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ReplTest private (out: ByteArrayOutputStream) extends ReplDriver(
storedOutput()

def fromInitialState[A](op: State => A): A =
op(initState)
op(initialState)

implicit class TestingState(state: State) {
def andThen[A](op: State => A): A = op(state)
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/repl/ScriptedTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ScriptedTests extends ReplTest with MessageRendering {
resetToInitial()
val inputRes = extractInputs(prompt)
val buf = new ArrayBuffer[String]
inputRes.foldLeft(initState) { (state, input) =>
inputRes.foldLeft(initialState) { (state, input) =>
val (out, nstate) = evaluate(state, input, prompt)
buf.append(out)
nstate
Expand Down
29 changes: 10 additions & 19 deletions sbt-bridge/src/xsbt/ConsoleInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,6 @@ class ConsoleInterface {
def run(args: Array[String],
bootClasspathString: String,
classpathString: String,
// TODO: initial commands needs to be run under some form of special
// "silent" mode in the REPL. I.e. the effects should be had without
// any visual output.
//
// To do this we can use the `run` interface to the `ReplDriver` and
// pass it a special instance of `ParseResult` like `Silently(res: ParseResult)`
// and then observe the effects without printing to `ReplDriver#out`
//
// This way, the REPL can offer feedback on invalid commands but
// still function without stringly logic.
//
// This same principle can be applied to `cleanupCommands` and
// `bindValues`
//
// Steps:
//
// 1. Introduce `case class Silent(res: ParseResult) extends ParseResult`
// 2. Perform all steps in `interpret` as usual without printing to `out`
initialCommands: String,
cleanupCommands: String,
loader: ClassLoader,
Expand All @@ -51,6 +33,15 @@ class ConsoleInterface {
} ++
Array("-classpath", classpathString)

new ReplDriver(completeArgs, classLoader = Some(loader)).runUntilQuit()
val driver = new ReplDriver(completeArgs, classLoader = Some(loader))

val s0 = (bindNames, bindValues).zipped.foldLeft(driver.initialState) {
case (state, (name, value)) => driver.bind(name, value)(state)
}

val s1 = driver.run(initialCommands)(s0)
// TODO handle failure during initialisation
val s2 = driver.runUntilQuit(s1)
driver.run(cleanupCommands)(s2)
}
}