diff options
-rw-r--r-- | src/partest/scala/tools/partest/ReplTest.scala | 13 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ILoop.scala | 64 | ||||
-rw-r--r-- | test/files/run/t4594-repl-settings.scala | 26 |
3 files changed, 93 insertions, 10 deletions
diff --git a/src/partest/scala/tools/partest/ReplTest.scala b/src/partest/scala/tools/partest/ReplTest.scala index edd1f705a4..7381b8af54 100644 --- a/src/partest/scala/tools/partest/ReplTest.scala +++ b/src/partest/scala/tools/partest/ReplTest.scala @@ -7,6 +7,7 @@ package scala.tools.partest import scala.tools.nsc.Settings import scala.tools.nsc.interpreter.ILoop +import scala.tools.partest.nest.FileUtil import java.lang.reflect.{ Method => JMethod, Field => JField } /** A trait for testing repl code. It drops the first line @@ -29,3 +30,15 @@ abstract class ReplTest extends DirectTest { } def show() = eval() foreach println } + +abstract class SessionTest extends ReplTest with FileUtil { + def session: String + override final def code = expected filter (_.startsWith(prompt)) map (_.drop(prompt.length)) mkString "\n" + def expected = session.stripMargin.lines.toList + final def prompt = "scala> " + override def show() = { + val out = eval().toList + if (out.size != expected.size) Console println s"Expected ${expected.size} lines, got ${out.size}" + if (out != expected) Console print compareContents(expected, out, "expected", "actual") + } +} diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index a84d076e76..e8265e55f4 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -7,22 +7,22 @@ package scala package tools.nsc package interpreter -import Predef.{ println => _, _ } -import java.io.{ BufferedReader, FileReader } -import session._ +import scala.language.{ implicitConversions, existentials } import scala.annotation.tailrec +import Predef.{ println => _, _ } +import interpreter.session._ +import StdReplTags._ import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName } -import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } -import io.{ File, Directory } -import util.ScalaClassLoader +import scala.tools.nsc.util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } +import scala.reflect.classTag +import scala.reflect.internal.util.{ BatchSourceFile, ScalaClassLoader } import ScalaClassLoader._ +import scala.reflect.io.{ File, Directory } import scala.tools.util._ -import scala.language.{implicitConversions, existentials} -import scala.reflect.classTag -import StdReplTags._ +import scala.collection.generic.Clearable import scala.concurrent.{ ExecutionContext, Await, Future, future } import ExecutionContext.Implicits._ -import scala.reflect.internal.util.BatchSourceFile +import java.io.{ BufferedReader, FileReader } /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. @@ -221,6 +221,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) nullary("replay", "reset execution and replay all previous commands", replay), nullary("reset", "reset the repl to its initial state, forgetting all session entries", resetCommand), shCommand, + cmd("settings", "[+|-]<options>", "+enable/-disable flags, set compiler options", changeSettings), nullary("silent", "disable/enable automatic printing of results", verbosity), cmd("type", "[-v] <expr>", "display the type of an expression without evaluating it", typeCommand), cmd("kind", "[-v] <expr>", "display the kind of expression's type", kindCommand), @@ -300,6 +301,49 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) intp.lastWarnings foreach { case (pos, msg) => intp.reporter.warning(pos, msg) } } + private def changeSettings(args: String): Result = { + def showSettings() = { + for (s <- settings.userSetSettings.toSeq.sorted) echo(s.toString) + } + def updateSettings() = { + // put aside +flag options + val (pluses, rest) = (args split "\\s+").toList partition (_.startsWith("+")) + val tmps = new Settings + val (ok, leftover) = tmps.processArguments(rest, processAll = true) + if (!ok) echo("Bad settings request.") + else if (leftover.nonEmpty) echo("Unprocessed settings.") + else { + // boolean flags set-by-user on tmp copy should be off, not on + val offs = tmps.userSetSettings filter (_.isInstanceOf[Settings#BooleanSetting]) + val (minuses, nonbools) = rest partition (arg => offs exists (_ respondsTo arg)) + // update non-flags + settings.processArguments(nonbools, processAll = true) + // also snag multi-value options for clearing, e.g. -Ylog: and -language: + for { + s <- settings.userSetSettings + if s.isInstanceOf[Settings#MultiStringSetting] || s.isInstanceOf[Settings#PhasesSetting] + if nonbools exists (arg => arg.head == '-' && arg.last == ':' && (s respondsTo arg.init)) + } s match { + case c: Clearable => c.clear() + case _ => + } + def update(bs: Seq[String], name: String=>String, setter: Settings#Setting=>Unit) = { + for (b <- bs) + settings.lookupSetting(name(b)) match { + case Some(s) => + if (s.isInstanceOf[Settings#BooleanSetting]) setter(s) + else echo(s"Not a boolean flag: $b") + case _ => + echo(s"Not an option: $b") + } + } + update(minuses, identity, _.tryToSetFromPropertyValue("false")) // turn off + update(pluses, "-" + _.drop(1), _.tryToSet(Nil)) // turn on + } + } + if (args.isEmpty) showSettings() else updateSettings() + } + private def javapCommand(line: String): Result = { if (javap == null) ":javap unavailable, no tools.jar at %s. Set JDK_HOME.".format(jdkHome) diff --git a/test/files/run/t4594-repl-settings.scala b/test/files/run/t4594-repl-settings.scala new file mode 100644 index 0000000000..d2335460e5 --- /dev/null +++ b/test/files/run/t4594-repl-settings.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.SessionTest + +// Detected repl transcript paste: ctrl-D to finish. +object Test extends SessionTest { + def session = +""" |Type in expressions to have them evaluated. + |Type :help for more information. + | + |scala> @deprecated(message="Please don't do that.", since="Time began.") def depp = "john" + |depp: String + | + |scala> def a = depp + |warning: there were 1 deprecation warning(s); re-run with -deprecation for details + |a: String + | + |scala> :settings +deprecation + | + |scala> def b = depp + |<console>:8: warning: method depp is deprecated: Please don't do that. + | def b = depp + | ^ + |b: String + | + |scala> """ +} |