summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2013-07-03 02:06:25 -0700
committerSom Snytt <som.snytt@gmail.com>2013-07-04 07:55:15 -0700
commit596b85373b0203e7557f71e1bced980e277ec751 (patch)
treeb379fbd87975937dd2d750bc276e2c65ec333d65
parent4222849b14e64f668e7250bc2decef15eea5822a (diff)
downloadscala-596b85373b0203e7557f71e1bced980e277ec751.tar.gz
scala-596b85373b0203e7557f71e1bced980e277ec751.tar.bz2
scala-596b85373b0203e7557f71e1bced980e277ec751.zip
SI-4594 Repl settings command
A settings command for the rest of us. The usual command line options are used, except that boolean flags are enabled with +flag and disabled with -flag. ``` scala> :settings +deprecation scala> new BigInt(java.math.BigInteger.TEN) { } <console>:8: warning: inheritance from class BigInt in package math is deprecated: This class will me made final. new BigInt(java.math.BigInteger.TEN) { } ^ res0: BigInt = 10 scala> :settings -deprecation scala> new BigInt(java.math.BigInteger.TEN) { } res1: BigInt = 10 ``` Multivalue "colon" options can be reset by supplying no values after the colon. This behavior is different from the command line. ``` scala> 1 toString warning: there were 1 feature warning(s); re-run with -feature for details res0: String = 1 scala> :settings -language:postfixOps scala> 1 toString res1: String = 1 scala> :settings -d = . -encoding = UTF-8 -explaintypes = false -language = List(postfixOps) -nowarn = false scala> :settings -language: scala> :settings -d = . -encoding = UTF-8 -explaintypes = false -language = List() -nowarn = false ```
-rw-r--r--src/partest/scala/tools/partest/ReplTest.scala13
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala64
-rw-r--r--test/files/run/t4594-repl-settings.scala26
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> """
+}