From 25a2d721899881ff8dde28d6975648a0bad769f5 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 4 Feb 2011 08:29:20 +0000 Subject: After discovering #3376 was fixed I gave in and... After discovering #3376 was fixed I gave in and tried to write a test. Now that the fiddling is over you can write repl tests without creating 5000 streams and settings. Look at test/files/run/bug3376.scala or jvm/interpreter.scala to see. Test case closes #3376, no review. --- .../scala/tools/nsc/interpreter/ILoop.scala | 22 +++++++++++- test/files/jvm/interpreter.scala | 42 ++++------------------ test/files/run/bug3376.check | 13 +++++++ test/files/run/bug3376.scala | 16 +++++++++ 4 files changed, 57 insertions(+), 36 deletions(-) create mode 100644 test/files/run/bug3376.check create mode 100644 test/files/run/bug3376.scala diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index e0a49554ed..b7cd227efc 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -17,7 +17,7 @@ import scala.annotation.tailrec import scala.util.control.Exception.{ ignoring } import scala.collection.mutable.ListBuffer import scala.concurrent.ops -import util.{ ClassPath } +import util.{ ClassPath, stringFromWriter, stringFromStream } import interpreter._ import io.File @@ -770,6 +770,26 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter) object ILoop { implicit def loopToInterpreter(repl: ILoop): IMain = repl.intp + /** Creates an interpreter loop with default settings and feeds + * the given code to it as input. + */ + def run(code: String): String = { + import java.io.{ BufferedReader, StringReader, OutputStreamWriter } + + stringFromStream { ostream => + Console.withOut(ostream) { + val input = new BufferedReader(new StringReader(code)) + val output = new PrintWriter(new OutputStreamWriter(ostream)) + val repl = new ILoop(input, output) + val settings = new Settings + settings.classpath.value = sys.props("java.class.path") + + repl main settings + } + } + } + def run(lines: List[String]): String = run(lines map (_ + "\n") mkString) + // provide the enclosing type T // in order to set up the interpreter's classpath and parent class loader properly def breakIf[T: Manifest](assertion: => Boolean, args: NamedParam*): Unit = diff --git a/test/files/jvm/interpreter.scala b/test/files/jvm/interpreter.scala index 2c2756828b..70ad900305 100644 --- a/test/files/jvm/interpreter.scala +++ b/test/files/jvm/interpreter.scala @@ -2,6 +2,8 @@ import scala.tools.nsc._ import java.io.{BufferedReader, StringReader, PrintWriter, Writer, OutputStreamWriter} +import interpreter.ILoop + object Test { val testCodeString = // basics @@ -144,43 +146,13 @@ def f(e: Exp) = e match {{ // non-exhaustive warning here .text - /** A writer that skips the first line of text. The first - * line of interpreter output is skipped because it includes - * a version number. */ - class Skip1Writer(writer: Writer) extends Writer { - var seenNL = false - - def write(cbuf: Array[Char], off: Int, len: Int) { - if (seenNL) - writer.write(cbuf, off, len) - else { - val slice : Array[Char] = cbuf.slice(off, off+len) - val i = slice.indexOf('\n') - if (i >= 0) { - seenNL = true - writer.write(slice, i+1, slice.length-(i+1)) - } else { - // skip it - } - } - } - - def close() { writer.close() } - def flush() { writer.flush() } - } - - def main(args: Array[String]) { - val input = new BufferedReader(new StringReader(testCodeString)) - val output = new PrintWriter( - new Skip1Writer(new OutputStreamWriter(Console.out))) - val repl = new InterpreterLoop(input, output) - val settings = new Settings - // when running that compiler, give it a scala-library to the classpath - settings.classpath.value = System.getProperty("java.class.path") - repl.main(settings) - println() + // This drops the first line of output because the repl + // prints a version number. + (ILoop run testCodeString).lines drop 1 foreach println + val settings = new Settings + settings.classpath.value = sys.props("java.class.path") val interp = new Interpreter(settings) interp.interpret("def plusOne(x: Int) = x + 1") interp.interpret("plusOne(5)") diff --git a/test/files/run/bug3376.check b/test/files/run/bug3376.check new file mode 100644 index 0000000000..7286096022 --- /dev/null +++ b/test/files/run/bug3376.check @@ -0,0 +1,13 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> +scala> defined class M + +scala> m1: M[Int] = mmm + +scala> m2: M[Float] = mmm + +scala> m3: M[String] = mmm + +scala> diff --git a/test/files/run/bug3376.scala b/test/files/run/bug3376.scala new file mode 100644 index 0000000000..5cff50185c --- /dev/null +++ b/test/files/run/bug3376.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.interpreter._ + +object Test { + class M[@specialized T] { } + + val code = """ + |class M[@specialized T] { override def toString = "mmm" } + |val m1 = new M[Int]() + |val m2 = new M[Float]() + |val m3 = new M[String]() + |""".stripMargin + + def main(args: Array[String]): Unit = { + (ILoop run code).lines drop 1 foreach println + } +} -- cgit v1.2.3