summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-04-11 00:32:00 +0000
committerPaul Phillips <paulp@improving.org>2010-04-11 00:32:00 +0000
commite93c1a93a2c8a40265b34bb9f1dd61b9470c908d (patch)
treeb9f13ffbe1d1ef59380e32f74380f9797b7fd2cb
parent71b6aca681ab697304590a96b13847b9bba141dc (diff)
downloadscala-e93c1a93a2c8a40265b34bb9f1dd61b9470c908d.tar.gz
scala-e93c1a93a2c8a40265b34bb9f1dd61b9470c908d.tar.bz2
scala-e93c1a93a2c8a40265b34bb9f1dd61b9470c908d.zip
Introduces scala.tools.cmd providing command li...
Introduces scala.tools.cmd providing command line tool infrastructure. For a quick look at what can be done, see scala.tools.cmd.Demo For a more involved, potentially eye-straining look, see scala.tools.partest.PartestSpec To experience it through the eyes of Joe Partest User, run test/partest Review by community.
-rw-r--r--src/compiler/scala/tools/cmd/CommandLine.scala107
-rw-r--r--src/compiler/scala/tools/cmd/Demo.scala85
-rw-r--r--src/compiler/scala/tools/cmd/FromString.scala72
-rw-r--r--src/compiler/scala/tools/cmd/Instance.scala23
-rw-r--r--src/compiler/scala/tools/cmd/Interpolation.scala59
-rw-r--r--src/compiler/scala/tools/cmd/Meta.scala62
-rw-r--r--src/compiler/scala/tools/cmd/Opt.scala91
-rw-r--r--src/compiler/scala/tools/cmd/Parser.scala52
-rw-r--r--src/compiler/scala/tools/cmd/Property.scala71
-rw-r--r--src/compiler/scala/tools/cmd/Reference.scala98
-rw-r--r--src/compiler/scala/tools/cmd/Spec.scala45
-rw-r--r--src/compiler/scala/tools/cmd/package.scala28
-rw-r--r--src/compiler/scala/tools/nsc/io/File.scala12
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala10
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala14
-rw-r--r--src/compiler/scala/tools/nsc/util/CommandLineParser.scala142
-rw-r--r--src/compiler/scala/tools/nsc/util/CommandLineSpec.scala150
-rw-r--r--src/compiler/scala/tools/nsc/util/ShowPickled.scala5
-rw-r--r--src/library/scala/util/Properties.scala1
-rw-r--r--src/partest/scala/tools/partest/Compilable.scala4
-rw-r--r--src/partest/scala/tools/partest/Config.scala3
-rw-r--r--src/partest/scala/tools/partest/Partest.scala14
-rw-r--r--src/partest/scala/tools/partest/PartestSpec.scala134
-rw-r--r--src/partest/scala/tools/partest/Runner.scala5
-rw-r--r--src/partest/scala/tools/partest/ant/JavaTask.scala12
-rw-r--r--src/partest/scala/tools/partest/ant/PartestTask.scala90
-rw-r--r--src/partest/scala/tools/partest/package.scala6
-rwxr-xr-xtest/partest6
28 files changed, 909 insertions, 492 deletions
diff --git a/src/compiler/scala/tools/cmd/CommandLine.scala b/src/compiler/scala/tools/cmd/CommandLine.scala
new file mode 100644
index 0000000000..8cb4c00b14
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/CommandLine.scala
@@ -0,0 +1,107 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import scala.collection.mutable.ListBuffer
+
+/** An instance of a command line, parsed according to a Spec.
+ */
+class CommandLine(val spec: Reference, val originalArgs: List[String]) {
+ def this(spec: Reference, line: String) = this(spec, Parser tokenize line)
+ def this(spec: Reference, args: Array[String]) = this(spec, args.toList)
+
+ import spec.{ isAnyOption, isUnaryOption, isBinaryOption, isExpandOption }
+
+ def assumeBinary = true
+ def enforceArity = true
+ def onlyKnownOptions = false
+
+ val Terminator = "--"
+ val ValueForUnaryOption = "true" // so if --opt is given, x(--opt) = true
+
+ def mapForUnary(opt: String) = Map(opt -> ValueForUnaryOption)
+ def errorFn(msg: String) = println(msg)
+
+ /** argMap is option -> argument (or "" if it is a unary argument)
+ * residualArgs are what is left after removing the options and their args.
+ */
+ lazy val (argMap, residualArgs) = {
+ val residualBuffer = new ListBuffer[String]
+
+ def isOption(s: String) = isAnyOption(s) || ((s startsWith "-") && !onlyKnownOptions)
+
+ def unknownOption(opt: String) =
+ errorFn("Option '%s' not recognized.".format(opt))
+ def missingArg(opt: String, what: String) =
+ errorFn("Option '%s' requires argument, found %s instead.".format(opt, what))
+
+ def loop(args: List[String]): Map[String, String] = {
+ def residual(xs: List[String]) = { residualBuffer ++= xs ; Map[String, String]() }
+
+ /** Returns Some(List(args)) if this option expands to an
+ * argument list and it's not returning only the same arg.
+ */
+ def expand(s1: String) = {
+ if (isExpandOption(s1)) {
+ val s2 = spec expandArg s1
+ if (s2 == List(s1)) None
+ else Some(s2)
+ }
+ else None
+ }
+
+ args match {
+ case Nil => Map()
+ case Terminator :: xs => residual(xs)
+ case x :: Nil =>
+ expand(x) foreach (exp => return loop(exp))
+ if (isBinaryOption(x) && enforceArity)
+ missingArg(x, "EOF")
+
+ if (isUnaryOption(x)) mapForUnary(x)
+ else residual(args)
+ case x1 :: x2 :: xs =>
+ expand(x1) foreach (exp => return loop(exp ++ args.tail))
+
+ if (x2 == Terminator) mapForUnary(x1) ++ residual(xs)
+ else if (isUnaryOption(x1)) mapForUnary(x1) ++ loop(args.tail)
+ else if (isBinaryOption(x1)) Map(x1 -> x2) ++ loop(xs)
+ else residual(List(x1)) ++ loop(args.tail)
+ }
+ }
+
+ (loop(originalArgs), residualBuffer map stripQuotes toList)
+ }
+
+ def apply(arg: String) = argMap(arg)
+ def get(arg: String) = argMap get arg
+ def isSet(arg: String) = argMap contains arg
+
+ def getOrElse(arg: String, orElse: => String) = if (isSet(arg)) apply(arg) else orElse
+
+ override def toString() = argMap.toString + " " + residualArgs.toString
+}
+
+object CommandLine {
+ def apply(args: List[String], unary: List[String], binary: List[String]) = {
+ /** XXX Temporarily assembling a fake spec so we can continue to
+ * do ad-hoc parsing based on a list of unary and binary args.
+ * Should either clean this up or do it differently.
+ */
+ object NoSpec extends Reference {
+ unary foreach (_ --? )
+ binary foreach (_ --| )
+
+ protected def creator(args: List[String]) = error("No Spec")
+ def programInfo = Spec.Names("", "")
+ lazy val referenceSpec = this
+ }
+
+ new CommandLine(NoSpec, args)
+ }
+}
+
diff --git a/src/compiler/scala/tools/cmd/Demo.scala b/src/compiler/scala/tools/cmd/Demo.scala
new file mode 100644
index 0000000000..7014e6b4d7
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Demo.scala
@@ -0,0 +1,85 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+/** A sample command specification for illustrative purposes.
+ * First take advantage of the meta-options:
+ *
+ * // this command creates an executable runner script "demo"
+ * % scala scala.tools.cmd.Demo --generate-runner demo
+ *
+ * // this one creates and sources a completion file - note backticks
+ * % `./demo --bash`
+ *
+ * // and now you have a runner with working completion
+ * % ./demo --<tab>
+ * --action --defint --int
+ * --bash --defstr --str
+ * --defenv --generate-runner --unary
+ *
+ * The normal option configuration is plausibly self-explanatory.
+ */
+trait DemoSpec extends Spec with Meta.StdOpts with Interpolation {
+ lazy val referenceSpec = DemoSpec
+ lazy val programInfo = Spec.Names("demo", "scala.tools.cmd.Demo")
+
+ help("""Usage: demo [<options>]""")
+ heading("Unary options:")
+
+ val optIsUnary = "unary" / "a unary option" --? ;
+ ("action" / "a body which may be run") --> println("Hello, I am the --action body.")
+
+ heading("Binary options:")
+ val optopt = "str" / "an optional String" --|
+ val optoptInt = ("int" / "an optional Int") . --^[Int]
+ val optEnv = "defenv" / "an optional String" defaultToEnv "PATH"
+ val optDefault = "defstr" / "an optional String" defaultTo "default"
+ val optDefaultInt = "defint" / "an optional Int" defaultTo -1
+ val optExpand = "alias" / "an option which expands" expandTo ("--int", "15")
+}
+
+object DemoSpec extends DemoSpec with Property {
+ lazy val propMapper = new PropertyMapper(DemoSpec)
+
+ type ThisCommandLine = SpecCommandLine
+ def creator(args: List[String]) =
+ new SpecCommandLine(args) {
+ override def onlyKnownOptions = true
+ override def errorFn(msg: String) = { println("Error: " + msg) ; System.exit(0) }
+ }
+}
+
+class Demo(args: List[String]) extends {
+ val parsed = DemoSpec(args: _*)
+} with DemoSpec with Instance {
+ import java.lang.reflect._
+
+ def helpMsg = DemoSpec.helpMsg
+ def demoSpecMethods = this.getClass.getMethods.toList
+ private def isDemo(m: Method) = (m.getName startsWith "opt") && !(m.getName contains "$") && (m.getParameterTypes.isEmpty)
+
+ def demoString(ms: List[Method]) = {
+ val longest = ms map (_.getName.length) max
+ val formatStr = " %-" + longest + "s: %s"
+ val xs = ms map (m => formatStr.format(m.getName, m.invoke(this)))
+
+ xs mkString ("Demo(\n ", "\n ", "\n)\n")
+ }
+
+ override def toString = demoString(demoSpecMethods filter isDemo)
+}
+
+object Demo {
+ def main(args: Array[String]): Unit = {
+ val runner = new Demo(args.toList)
+
+ if (args.isEmpty)
+ println(runner.helpMsg)
+
+ println(runner)
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala
new file mode 100644
index 0000000000..81454e7a30
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/FromString.scala
@@ -0,0 +1,72 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import nsc.io.{ Path, File, Directory }
+import reflect.OptManifest
+
+/** A general mechanism for defining how a command line argument
+ * (always a String) is transformed into an arbitrary type. A few
+ * example instances are in the companion object, but in general
+ * either IntFromString will suffice or you'll want custom transformers.
+ */
+abstract class FromString[+T](implicit m: OptManifest[T]) extends PartialFunction[String, T] {
+ def apply(s: String): T
+ def isDefinedAt(s: String): Boolean = true
+ def zero: T = apply("")
+
+ def targetString: String = m.toString
+}
+
+object FromString {
+ // We need these because we clash with the String => Path implicits.
+ private def toFile(s: String) = new File(new java.io.File(s))
+ private def toDir(s: String) = new Directory(new java.io.File(s))
+
+ /** Path related stringifiers.
+ */
+ val ExistingFile: FromString[File] = new FromString[File] {
+ override def isDefinedAt(s: String) = toFile(s).isFile
+ def apply(s: String): File =
+ if (isDefinedAt(s)) toFile(s)
+ else cmd.runAndExit(println("'%s' is not an existing file." format s))
+ }
+ val ExistingDir: FromString[Directory] = new FromString[Directory] {
+ override def isDefinedAt(s: String) = toDir(s).isDirectory
+ def apply(s: String): Directory =
+ if (isDefinedAt(s)) toDir(s)
+ else cmd.runAndExit(println("'%s' is not an existing directory." format s))
+ }
+ def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] {
+ private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory
+ override def isDefinedAt(s: String) = resolve(s).isDirectory
+ def apply(s: String): Directory =
+ if (isDefinedAt(s)) resolve(s)
+ else cmd.runAndExit(println("'%s' is not an existing directory." format resolve(s)))
+ }
+
+ /** Argument expander, i.e. turns single argument "foo bar baz" into argument
+ * list "foo", "bar", "baz".
+ */
+ val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]] {
+ def apply(s: String) = toArgs(s)
+ }
+
+ /** Identity.
+ */
+ implicit val StringFromString: FromString[String] = new FromString[String] {
+ def apply(s: String): String = s
+ }
+
+ /** Implicit as the most likely to be useful as-is.
+ */
+ implicit val IntFromString: FromString[Int] = new FromString[Int] {
+ override def isDefinedAt(s: String) = safeToInt(s).isDefined
+ def apply(s: String) = safeToInt(s).get
+ def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None }
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/Instance.scala b/src/compiler/scala/tools/cmd/Instance.scala
new file mode 100644
index 0000000000..4d319b98cc
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Instance.scala
@@ -0,0 +1,23 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+/** The trait mixed into each instance of a specification.
+ *
+ * @see Reference
+ */
+trait Instance extends Spec {
+ def parsed: CommandLine
+
+ protected def help(str: => String): Unit = ()
+
+ def isSet(s: String) = parsed isSet toOpt(s)
+ def originalArgs = parsed.originalArgs
+
+ type OptionMagic = Opt.Instance
+ protected implicit def optionMagicAdditions(name: String) = new Opt.Instance(programInfo, parsed, name)
+}
diff --git a/src/compiler/scala/tools/cmd/Interpolation.scala b/src/compiler/scala/tools/cmd/Interpolation.scala
new file mode 100644
index 0000000000..6b86a35bb9
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Interpolation.scala
@@ -0,0 +1,59 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+/** Interpolation logic for generated files. The idea is to be
+ * able to write in terms of @@THIS@@ and @@THAT@@ and the reference
+ * specification knows enough to perform the substitutions. Warrants
+ * expansion.
+ */
+trait Interpolation {
+ self: Spec =>
+
+ private lazy val reference = referenceSpec
+ import reference._
+
+ object interpolate {
+ def mapper: Map[String, () => String] = Map(
+ "PROGRAM" -> (() => programInfo.runner),
+ "ALLOPTIONS" -> (() => options.all mkString " "),
+ "MAINCLASS" -> (() => programInfo.mainClass)
+ )
+
+ private def mark(key: String) = "@@" + key + "@@"
+ def apply(template: String) = mapper.foldLeft(template) { case (s, (key, f)) => s.replaceAll(mark(key), f()) }
+ }
+}
+
+object Interpolation {
+ /** A simple template for generating bash completion functions.
+ */
+ lazy val bashTemplate = """
+ |_@@PROGRAM@@()
+ |{
+ | local cur opts base
+ | COMPREPLY=()
+ | cur="${COMP_WORDS[COMP_CWORD]}"
+ | opts="@@ALLOPTIONS@@"
+ |
+ | COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
+ | _filedir
+ | return 0
+ |} && complete -F _@@PROGRAM@@ @@PROGRAM@@
+ """.stripMargin
+
+ /** A simple template for generating a runner script.
+ */
+ val runnerTemplate = """
+ |#!/bin/sh
+ |#
+ |
+ |scala @@MAINCLASS@@ $*
+ |
+ """.stripMargin
+}
+
diff --git a/src/compiler/scala/tools/cmd/Meta.scala b/src/compiler/scala/tools/cmd/Meta.scala
new file mode 100644
index 0000000000..5a09766b13
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Meta.scala
@@ -0,0 +1,62 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import nsc.io.File
+import Interpolation._
+
+/** Meta-options for command line tools. We could have all kinds
+ * of additional goodness here, but for now it's completion and script
+ * generation. See Demo for example usage.
+ */
+object Meta {
+ trait Opt {
+ def name: String
+ def action: () => Unit
+ }
+
+ trait StdOpts {
+ self: Spec with Interpolation =>
+
+ Bash.name --> runAndExit(Bash.action())
+ val runnerFileName = Runner.name --| ;
+
+ if (runnerFileName.isDefined)
+ runAndExit(Runner.action())
+
+ /** I think we're as close as we can get to bundling completion with
+ * the program given the constraints imposed by bash. This outputs
+ * the completion function to a tempfile and echoes ". /path/to/file"
+ * to the console. Place it inside backtickes like `partest --bash`
+ * and voila, you have absorbed command completion.
+ */
+ object Bash extends Opt {
+ val name = "bash"
+ val action = () => {
+ val file = File.makeTemp("scala.cmd.bash")
+ file writeAll interpolate(bashTemplate)
+
+ // Would be nice to print something like this but comments are
+ // not always comments in bash, and breaking it is worse.
+ // Console println ("# Run the following line, or issue the --bash command in `backticks`.")
+ Console println (". " + file.normalize.path)
+ }
+ }
+
+ /** A very basic runner script.
+ */
+ object Runner extends Opt {
+ val name = "generate-runner"
+ val action = () => {
+ val file = File(runnerFileName.get)
+ file writeAll interpolate(runnerTemplate)
+ file setExecutable true
+ ()
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/Opt.scala b/src/compiler/scala/tools/cmd/Opt.scala
new file mode 100644
index 0000000000..9e3c324deb
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Opt.scala
@@ -0,0 +1,91 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import nsc.Properties.envOrElse
+import Spec.Names
+
+/** Machinery for what amounts to a command line specification DSL.
+ * It is designed so the same specification trait can be used for
+ * two different purposes: generating a singleton specification object
+ * (trait Reference) and providing well typed vals for every configurable
+ * option in response to any given set of arguments (trait Instance).
+ */
+object Opt {
+ trait Error {
+ self: Implicit =>
+
+ protected def fail(msg: String) = runAndExit(println(programInfo.runner + ": " + msg))
+ protected def failOption(arg: String, why: String) = fail("%s: '%s' is %s".format(opt, arg, why))
+ }
+
+ trait Implicit {
+ def name: String
+ def programInfo: Names
+ protected def opt = toOpt(name)
+
+ def --? : Boolean // --opt is set
+ def --> (body: => Unit): Unit // if --opt is set, execute body
+ def --| : Option[String] // --opt <arg: String> is optional, result is Option[String]
+ def --^[T: FromString] : Option[T] // --opt <arg: T> is optional, result is Option[T]
+
+ def optMap[T](f: String => T) = --| map f
+
+ /** Names.
+ */
+ def defaultTo[T: FromString](default: T): T
+ def defaultToEnv(envVar: String): String
+ def choiceOf[T: FromString](choices: T*): Option[T]
+ def expandTo(args: String*): Unit
+
+ /** Help.
+ */
+ def /(descr: String): String // --opt has help description 'descr'
+ }
+
+ class Reference(val programInfo: Names, val options: Reference.Accumulators, val name: String) extends Implicit {
+ import options._
+
+ def --? = { addUnary(opt) ; false }
+ def --> (body: => Unit) = { addUnary(opt) }
+ def --| = { addBinary(opt) ; None }
+ def --^[T: FromString] = { addBinary(opt) ; None }
+
+ def defaultTo[T: FromString](default: T) = { addBinary(opt) ; addHelpDefault(() => default.toString) ; default }
+ def defaultToEnv(envVar: String) = { addBinary(opt) ; addHelpEnvDefault(envVar) ; "" }
+ def choiceOf[T: FromString](choices: T*) = { addBinary(opt) ; None }
+ def expandTo(args: String*) = { addExpand(name, args.toList) ; addHelpAlias(() => args mkString " ") }
+
+ def /(descr: String) = returning(name)(_ => addHelp(() => helpFormatStr.format(opt, descr)))
+ }
+
+ class Instance(val programInfo: Names, val parsed: CommandLine, val name: String) extends Implicit with Error {
+ def --? = parsed isSet opt
+ def --> (body: => Unit) = if (parsed isSet opt) body
+ def --| = parsed get opt
+ def --^[T: FromString] = {
+ val fs = implicitly[FromString[T]]
+ --| map { arg =>
+ if (fs isDefinedAt arg) fs(arg)
+ else failOption(arg, "not a " + fs.targetString)
+ }
+ }
+
+ def defaultTo[T: FromString](default: T) = --^[T] getOrElse default
+ def defaultToEnv(envVar: String) = --| getOrElse envOrElse(envVar, "")
+ def expandTo(args: String*) = ()
+
+ def choiceOf[T: FromString](choices: T*) = {
+ --^[T] map { arg =>
+ if (choices contains arg) arg
+ else failOption(arg.toString, "not a valid choice from " + choices)
+ }
+ }
+
+ def /(descr: String) = name
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/Parser.scala b/src/compiler/scala/tools/cmd/Parser.scala
new file mode 100644
index 0000000000..f4bce745e2
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Parser.scala
@@ -0,0 +1,52 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import scala.util.parsing.combinator._
+import scala.util.parsing.input.CharArrayReader.EofCh
+
+/** A simple (overly so) command line parser.
+ * !!! This needs a thorough test suite to make sure quoting is
+ * done correctly and portably.
+ */
+trait ParserUtil extends Parsers {
+ class ParserPlus[+T](underlying: Parser[T]) {
+ def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b }
+ def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a }
+ }
+ protected implicit def parser2parserPlus[T](p: Parser[T]): ParserPlus[T] = new ParserPlus(p)
+}
+
+object Parser extends RegexParsers with ParserUtil {
+ override def skipWhitespace = false
+
+ def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x))
+ def elemOf(xs: Elem*): Parser[Elem] = elem("elemOf", xs contains _)
+ def escaped(ch: Char): Parser[String] = "\\" + ch
+ def mkQuoted(ch: Char): Parser[String] = (
+ elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString)
+ | failure("Unmatched %s in input." format ch)
+ )
+
+ /** Apparently windows can't deal with the quotes sticking around. */
+ lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x)
+ lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"")
+ lazy val token: Parser[String] = """\S+""".r
+
+ lazy val argument: Parser[String] = squoted | dquoted | token
+ lazy val commandLine: Parser[List[String]] = phrase(repsep(argument, whiteSpace))
+
+ class ParseException(msg: String) extends RuntimeException(msg)
+
+ def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x))
+ def tokenize(line: String, errorFn: String => Unit): List[String] = {
+ parse(commandLine, line.trim) match {
+ case Success(args, _) => args
+ case NoSuccess(msg, rest) => errorFn(msg) ; Nil
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/Property.scala b/src/compiler/scala/tools/cmd/Property.scala
new file mode 100644
index 0000000000..009e7e6142
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Property.scala
@@ -0,0 +1,71 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import nsc.io._
+import java.util.Properties
+import java.io.FileInputStream
+
+/** Contains logic for translating a property key/value pair into
+ * equivalent command line arguments. The default settings will
+ * translate, given programInfo.runner == "foo" :
+ *
+ * foo.bar=true to --bar // if --bar is unary
+ * foo.bar=quux to --bar quux // if --bar is binary
+ */
+class PropertyMapper(reference: Reference) extends (((String, String)) => List[String]) {
+ import reference._
+ lazy val RunnerName = programInfo.runner
+
+ // e.g. "partest.shootout" -> "--shootout"
+ def propNameToOptionName(key: String): Option[String] = (key split '.').toList match {
+ case List(RunnerName, name) => Some(name)
+ case _ => None
+ }
+
+ def isPassThrough(key: String): Boolean = false // e.g. "partest.options"
+ def onError(key: String, value: String): Unit = () // called when translate fails
+
+ def translate(key: String, value: String): List[String] = {
+ val opt = toOpt(key)
+
+ if (isUnaryOption(key) && isTrue(value)) List(opt)
+ else if (isBinaryOption(key)) List(opt, value)
+ else returning(Nil)(_ => onError(key, value))
+ }
+ def isTrue(value: String) = List("yes", "on", "true") contains value.toLowerCase
+
+ def apply(kv: (String, String)): List[String] = {
+ val (k, v) = kv
+
+ if (isPassThrough(k)) toArgs(v)
+ else propNameToOptionName(k) match {
+ case Some(optName) => translate(optName, v)
+ case _ => Nil
+ }
+ }
+}
+
+trait Property extends Reference {
+ def propMapper: PropertyMapper
+ override def propertyArgs: List[String] = systemPropertiesToOptions
+
+ def loadProperties(file: File): Properties =
+ returning(new Properties)(_ load new FileInputStream(file.path))
+
+ def systemPropertiesToOptions: List[String] =
+ propertiesToOptions(System.getProperties)
+
+ def propertiesToOptions(file: File): List[String] =
+ propertiesToOptions(loadProperties(file))
+
+ def propertiesToOptions(props: java.util.Properties): List[String] = {
+ import collection.JavaConversions._
+ propertiesToOptions(props.toList)
+ }
+ def propertiesToOptions(props: List[(String, String)]) = props flatMap propMapper
+}
diff --git a/src/compiler/scala/tools/cmd/Reference.scala b/src/compiler/scala/tools/cmd/Reference.scala
new file mode 100644
index 0000000000..695868191b
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Reference.scala
@@ -0,0 +1,98 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+import collection.mutable.ListBuffer
+import nsc.Properties.envOrNone
+
+/** Mixes in the specification trait and uses the vals therein to
+ * side-effect private accumulators. From this emerges formatted help,
+ * lists of unary and binary arguments, an apply which can creates
+ * instances of the specification, and etc.
+ *
+ * @see Instance
+ */
+trait Reference extends Spec {
+ lazy val options = new Reference.Accumulators()
+ import options._
+
+ def helpMsg = options.helpMsg
+ def propertyArgs: List[String] = Nil
+
+ def isUnaryOption(s: String) = unary contains toOpt(s)
+ def isBinaryOption(s: String) = binary contains toOpt(s)
+ def isExpandOption(s: String) = expansionMap contains toOpt(s)
+ def isAnyOption(s: String) = isUnaryOption(s) || isBinaryOption(s) || isExpandOption(s)
+
+ def expandArg(arg: String) = expansionMap.getOrElse(fromOpt(arg), List(arg))
+
+ protected def help(str: => String) = addHelp(() => str)
+
+ type ThisCommandLine <: SpecCommandLine
+ class SpecCommandLine(args: List[String]) extends CommandLine(Reference.this, args) { }
+ protected def creator(args: List[String]): ThisCommandLine
+ final def apply(args: String*): ThisCommandLine = creator(propertyArgs ++ args flatMap expandArg)
+
+ type OptionMagic = Opt.Reference
+ protected implicit def optionMagicAdditions(name: String) = new Opt.Reference(programInfo, options, name)
+}
+
+object Reference {
+ val MaxLine = 80
+
+ class Accumulators() {
+ private var _help = new ListBuffer[() => String]
+ private var _unary = List[String]()
+ private var _binary = List[String]()
+ private var _expand = Map[String, List[String]]()
+
+ def helpFormatStr = " %-" + longestArg + "s %s"
+ def defaultFormatStr = (" " * (longestArg + 7)) + "%s"
+
+ def addUnary(s: String) = _unary +:= s
+ def addBinary(s: String) = _binary +:= s
+
+ def addExpand(opt: String, expanded: List[String]) =
+ _expand += (opt -> expanded)
+
+ def mapHelp(g: String => String) = {
+ val idx = _help.length - 1
+ val f = _help(idx)
+
+ _help(idx) = () => g(f())
+ }
+
+ def addHelp(f: () => String) = _help += f
+ def addHelpAlias(f: () => String) = mapHelp { s =>
+ val str = "alias for '%s'" format f()
+ def noHelp = (helpFormatStr.format("", "")).length == s.length
+ val str2 = if (noHelp) str else " (" + str + ")"
+
+ s + str2
+ }
+ def addHelpDefault(f: () => String) = mapHelp { s =>
+ val str = "(default: %s)" format f()
+
+ if (s.length + str.length < MaxLine) s + " " + str
+ else defaultFormatStr.format(s, str)
+ }
+ def addHelpEnvDefault(name: String) = mapHelp { s =>
+ val line1 = "%s (default: %s)".format(s, name)
+ val envNow = envOrNone(name) map ("'" + _ + "'") getOrElse "unset"
+ val line2 = defaultFormatStr.format("Currently " + envNow)
+
+ line1 + "\n" + line2
+ }
+
+ lazy val unary = (_unary ++ _expand.keys).distinct
+ lazy val binary = _binary.distinct
+ lazy val all = unary ++ binary
+ lazy val expansionMap = _expand
+ lazy val helpMsg = _help map (f => f() + "\n") mkString
+ lazy val longestArg = all map (_.length) max
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/Spec.scala b/src/compiler/scala/tools/cmd/Spec.scala
new file mode 100644
index 0000000000..c8283165d9
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/Spec.scala
@@ -0,0 +1,45 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+
+/** This trait works together with others in scala.tools.cmd to allow
+ * declaratively specifying a command line program, with many attendant
+ * benefits. See scala.tools.cmd.DemoSpec for an example.
+ */
+trait Spec {
+ def referenceSpec: Reference
+ def programInfo: Spec.Names
+
+ protected def help(str: => String): Unit
+ protected def heading(str: => String): Unit = help("\n " + str)
+
+ type OptionMagic <: Opt.Implicit
+ protected implicit def optionMagicAdditions(s: String): OptionMagic
+}
+
+object Spec {
+ case class Names(runner: String, mainClass: String) { }
+
+ class Accumulator[T: FromString]() {
+ private var _buf: List[T] = Nil
+
+ def convert(s: String) = implicitly[FromString[T]] apply s
+ def apply(s: String): T = returning(convert(s))(_buf +:= _)
+
+ lazy val get = _buf
+ }
+
+ class Choices[T: FromString](val xs: List[T]) {
+ def fs: FromString[T] = implicitly[FromString[T]]
+ def contains(x: T) = xs contains x
+ override def toString = xs.mkString("{ ", ", ", " }")
+ }
+
+ class EnvironmentVar(val name: String) {
+ override def toString = "${%s}" format name
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/package.scala b/src/compiler/scala/tools/cmd/package.scala
new file mode 100644
index 0000000000..33d3892077
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/package.scala
@@ -0,0 +1,28 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+
+package object cmd {
+ def returning[T](x: T)(f: T => Unit): T = { f(x) ; x }
+
+ private[cmd] def debug(msg: String) = println(msg)
+
+ def runAndExit(body: => Unit): Nothing = {
+ body
+ System exit 0
+ error("unreachable")
+ }
+
+ def toOpt(s: String) = if (s startsWith "--") s else "--" + s
+ def fromOpt(s: String) = s stripPrefix "--"
+ def toArgs(line: String) = Parser tokenize line
+ def fromArgs(args: List[String]) = args mkString " "
+
+ def stripQuotes(s: String) = {
+ def isQuotedBy(c: Char) = s.length > 0 && s.head == c && s.last == c
+ if (List('"', '\'') exists isQuotedBy) s.tail.init else s
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/io/File.scala b/src/compiler/scala/tools/nsc/io/File.scala
index 74bac3baf4..66a0da3a0f 100644
--- a/src/compiler/scala/tools/nsc/io/File.scala
+++ b/src/compiler/scala/tools/nsc/io/File.scala
@@ -136,4 +136,16 @@ with Streamable.Chars {
true
}
+
+ /** Reflection since we're into the java 6+ API.
+ */
+ def setExecutable(executable: Boolean, ownerOnly: Boolean = true): Boolean = {
+ type JBoolean = java.lang.Boolean
+ val method =
+ try classOf[JFile].getMethod("setExecutable", classOf[Boolean], classOf[Boolean])
+ catch { case _: NoSuchMethodException => return false }
+
+ try method.invoke(jfile, executable: JBoolean, ownerOnly: JBoolean).asInstanceOf[JBoolean].booleanValue
+ catch { case _: Exception => false }
+ }
}
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index 44ab9c6062..8012b9389b 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -4,15 +4,13 @@
*/
// $Id$
-package scala.tools.nsc
+package scala.tools
+package nsc
package settings
import io.AbstractFile
-import util.{ ClassPath, CommandLineParser }
-import annotation.elidable
import scala.tools.util.StringOps
import scala.collection.mutable.ListBuffer
-import interpreter.{ returning }
/** A mutable Settings object.
*/
@@ -84,7 +82,7 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
/** Split the given line into parameters.
*/
- def splitParams(line: String) = CommandLineParser.tokenize(line, errorFn)
+ def splitParams(line: String) = cmd.Parser.tokenize(line, errorFn)
/** Returns any unprocessed arguments.
*/
@@ -426,7 +424,7 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
prependPath: StringSetting,
appendPath: StringSetting)
extends StringSetting(name, arg, descr, default) {
- import ClassPath.join
+ import util.ClassPath.join
def prepend(s: String) = prependPath.value = join(s, prependPath.value)
def append(s: String) = appendPath.value = join(appendPath.value, s)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index fda0097226..1b6b8297ef 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -4,22 +4,18 @@
*/
// $Id$
-package scala.tools.nsc
+package scala.tools
+package nsc
package settings
-import io.AbstractFile
-import util.{ ClassPath, SourceFile, CommandLineParser }
import annotation.elidable
-import scala.tools.util.{ PathResolver, StringOps }
-import scala.collection.mutable.{ HashSet, ListBuffer }
-import scala.collection.immutable.TreeSet
-import interpreter.{ returning }
+import scala.tools.util.PathResolver.Defaults
+import scala.collection.mutable.HashSet
trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
self: MutableSettings =>
- import PathResolver.{ Defaults, Environment }
- import Defaults.{ scalaUserClassPath }
+ import Defaults.scalaUserClassPath
/** Set of settings */
protected lazy val allSettings = HashSet[Setting]()
diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
deleted file mode 100644
index 869c6a97e9..0000000000
--- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
+++ /dev/null
@@ -1,142 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package util
-
-import scala.util.parsing.combinator._
-import scala.util.parsing.input.{ Reader }
-import scala.util.parsing.input.CharArrayReader.EofCh
-import scala.collection.mutable.ListBuffer
-
-/** A simple command line parser to replace the several different
- * simple ones spread around trunk.
- */
-
-trait ParserUtil extends Parsers {
- class ParserPlus[+T](underlying: Parser[T]) {
- def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b }
- def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a }
- }
- protected implicit def parser2parserPlus[T](p: Parser[T]): ParserPlus[T] = new ParserPlus(p)
-}
-
-case class CommandLine(
- args: List[String],
- unaryOptions: List[String],
- binaryOptions: List[String]
-) {
- def this(args: List[String]) = this(args, Nil, Nil)
- def this(args: Array[String]) = this(args.toList, Nil, Nil)
- def this(line: String) = this(CommandLineParser tokenize line, Nil, Nil)
-
- def withUnary(xs: List[String]) = copy(unaryOptions = xs)
- def withBinary(xs: List[String]) = copy(binaryOptions = xs)
-
- def allOptions = unaryOptions ++ binaryOptions
- def originalArgs = args
- def assumeBinary = true
- def enforceArity = true
- def onlyKnownOptions = false
-
- val Terminator = "--"
- val ValueForUnaryOption = "true" // so if --opt is given, x(--opt) = true
-
- def mapForUnary(opt: String) = Map(opt -> ValueForUnaryOption)
- def errorFn(msg: String) = println(msg)
-
- /** argMap is option -> argument (or "" if it is a unary argument)
- * residualArgs are what is left after removing the options and their args.
- */
- lazy val (argMap, residualArgs) = {
- val residualBuffer = new ListBuffer[String]
-
- def stripQuotes(s: String) = {
- def isQuotedBy(c: Char) = s.length > 0 && s.head == c && s.last == c
- if (List('"', '\'') exists isQuotedBy) s.tail.init else s
- }
-
- def isValidOption(s: String) = !onlyKnownOptions || (unaryOptions contains s) || (binaryOptions contains s)
- def isOption(s: String) = (s startsWith "-") && (isValidOption(s) || { unknownOption(s) ; false })
- def isUnary(s: String) = isOption(s) && (unaryOptions contains s)
- def isBinary(s: String) = isOption(s) && !isUnary(s) && (assumeBinary || (binaryOptions contains s))
-
- def unknownOption(opt: String) =
- errorFn("Option '%s' not recognized.".format(opt))
- def missingArg(opt: String, what: String) =
- errorFn("Option '%s' requires argument, found %s instead.".format(opt, what))
-
- def loop(args: List[String]): Map[String, String] = {
- def residual(xs: List[String]) = { residualBuffer ++= xs ; Map[String, String]() }
- if (args.isEmpty) return Map()
- val hd :: rest = args
- if (rest.isEmpty) {
- if (isBinary(hd) && enforceArity)
- missingArg(hd, "EOF")
-
- if (isOption(hd)) mapForUnary(hd) else residual(args)
- }
- else
- if (hd == Terminator) residual(rest)
- else {
- val hd1 :: hd2 :: rest = args
-
- if (hd2 == Terminator) mapForUnary(hd1) ++ residual(rest)
- else if (isUnary(hd1)) mapForUnary(hd1) ++ loop(hd2 :: rest)
- else if (isBinary(hd1)) {
- // Disabling this check so
- // --scalacopts "-verbose" works. We can't tell if it's quoted,
- // the shell does us in.
- //
- // if (isOption(hd2) && enforceArity)
- // missingArg(hd1, hd2)
-
- Map(hd1 -> hd2) ++ loop(rest)
- }
- else { residual(List(hd1)) ++ loop(hd2 :: rest) }
- }
- }
-
- (loop(args), residualBuffer map stripQuotes toList)
- }
-
- def isSet(arg: String) = args contains arg
- def get(arg: String) = argMap get arg
- def getOrElse(arg: String, orElse: => String) = if (isSet(arg)) apply(arg) else orElse
- def apply(arg: String) = argMap(arg)
-
- override def toString() = "CommandLine(\n%s)\n" format (args map (" " + _ + "\n") mkString)
-}
-
-object CommandLineParser extends RegexParsers with ParserUtil {
- override def skipWhitespace = false
-
- def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x))
- def elemOf(xs: Elem*): Parser[Elem] = elem("elemOf", xs contains _)
- def escaped(ch: Char): Parser[String] = "\\" + ch
- def mkQuoted(ch: Char): Parser[String] = (
- elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString)
- | failure("Unmatched %s in input." format ch)
- )
-
- /** Apparently windows can't deal with the quotes sticking around. */
- lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x)
- lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"")
- lazy val token: Parser[String] = """\S+""".r
-
- lazy val argument: Parser[String] = squoted | dquoted | token
- lazy val commandLine: Parser[List[String]] = phrase(repsep(argument, whiteSpace))
-
- class ParseException(msg: String) extends RuntimeException(msg)
-
- def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x))
- def tokenize(line: String, errorFn: String => Unit): List[String] = {
- parse(commandLine, line.trim) match {
- case Success(args, _) => args
- case NoSuccess(msg, rest) => errorFn(msg) ; Nil
- }
- }
- def apply(line: String) = new CommandLine(tokenize(line))
-}
diff --git a/src/compiler/scala/tools/nsc/util/CommandLineSpec.scala b/src/compiler/scala/tools/nsc/util/CommandLineSpec.scala
deleted file mode 100644
index 826255e86f..0000000000
--- a/src/compiler/scala/tools/nsc/util/CommandLineSpec.scala
+++ /dev/null
@@ -1,150 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package util
-
-import Properties._
-import io._
-import CommandLineSpec._
-import CommandLineParser.tokenize
-
-/** This trait works together with CommandLine to allow declaratively
- * specifying a command line program, with many attendant benefits.
- * See scala.tools.partest.PartestSpec for a full example.
- */
-
-trait CommandLineSpec {
- def parsed: CommandLine
- def isReferenceSpec: Boolean = false
- def isPassthroughProperty(name: String): Boolean = false
- def isSysPropOption(key: String): Option[String] = None
-
- protected var _expandingOptions: Map[String, List[String]] = Map()
-
- private var _helpMessage: String = ""
- private var _unaryOptions: List[String] = Nil
- private var _binaryOptions: List[String] = Nil
- private def allOptions = if (isReferenceSpec) Nil else parsed.allOptions
- private def longestArg = if (allOptions.isEmpty) 1 else allOptions map (_.length) max
- private def unquoted(s: String) = {
- def isQuoted = (s.head == '\'' || s.head == '"') && s.head == s.last
-
- if (s == null || s.length < 2 || !isQuoted) s
- else s drop 1 dropRight 1
- }
-
- protected def help(str: String) = if (isReferenceSpec) () else _helpMessage += (str.stripMargin + "\n")
- protected def heading(s: String) = if (isReferenceSpec) () else help("\n " + s)
-
- /** The various operators:
- * val isCond1 = "cond1" ? // --cond1 is unary, cond1 is boolean
- * "cond2" ?> body // --cond2 is unary, body is executed if it is given
- * "cond3" ?+> List(x1, x2...) // --cond3 is unary, arguments on rhs will be substituted in as if given
- * val val1 = "val1" |> "alt" // --val1 is binary, val1 is String, alt used if none given
- * val val2 = "val2" >> // --val2 is binary, val2 is Option[String], None if none given
- */
- protected class OptionStringAdditions(name: String) {
- val s = toOpt(name)
- def ?+>(args: List[String]): Unit = { _unaryOptions +:= s ; if (isReferenceSpec) _expandingOptions += (name -> args) }
-
- def ? : Boolean = { _unaryOptions +:= s ; if (isReferenceSpec) false else parsed isSet s }
- def ?>(body: => Unit): Unit = { _unaryOptions +:= s ; if (isReferenceSpec) () else if (parsed isSet s) body }
- def |>(alt: String): String = { _binaryOptions +:= s ; if (isReferenceSpec) "" else parsed.getOrElse(s, alt) }
- def >> : Option[String] = { _binaryOptions +:= s ; if (isReferenceSpec) None else parsed get s }
-
- def /(description: String) = {
- val formatStr = " %-" + longestArg + "s %s"
- help(formatStr.format(s, description))
-
- name
- }
- }
- protected implicit def stringAdditions(s: String) = new OptionStringAdditions(s)
-
- lazy val unaryOptions = _unaryOptions.distinct
- lazy val binaryOptions = _binaryOptions.distinct
- lazy val expandingOptions = _expandingOptions.keys.toList
- lazy val helpMsg = _helpMessage
-
- def isUnaryOption(s: String) = unaryOptions contains toOpt(s)
- def isBinaryOption(s: String) = binaryOptions contains toOpt(s)
- def isExpandingOption(s: String) = expandingOptions contains toOpt(s)
-
- private def sysPropToOptions(k: String, v: String): List[String] = {
- if (isPassthroughProperty(k)) toArgs(v)
- else isSysPropOption(k).toList flatMap { optName =>
- val opt = toOpt(optName)
-
- if (isUnaryOption(optName)) List(opt)
- else if (isBinaryOption(optName)) List(opt, v)
- else {
- if (warnSuspiciousProperties) {
- println("Warning, this looks like a command line option but I don't understand it.")
- println("Ignoring: " + k + "=" + v)
- }
- Nil
- }
- }
- }
- def warnSuspiciousProperties: Boolean = true
- def sysPropsAsOptions() = allSystemProperties.toList flatMap (sysPropToOptions _).tupled
-
- def isSet(s: String) = parsed isSet toOpt(s)
- def reconstruct: List[String] = {
- val unary = unaryOptions filter (parsed isSet _)
- val binary = binaryOptions collect { case x if parsed isSet x => List(x, parsed(x)) }
- val resid = parsed.residualArgs
-
- unary ++ binary.flatten ++ resid
- }
-
- def bashCompletion(programName: String) = {
- val opts = unaryOptions ++ binaryOptions
- bashCompletionTemplate.replaceAll("@@PROGRAM@@", programName).replaceAll("@@OPTIONS@@", opts mkString " ")
- }
-}
-
-trait CommandLineReferenceSpec extends CommandLineSpec {
- final override def isReferenceSpec: Boolean = true
- final def apply(args: String*) = creator(args.toList flatMap expandArg)
-
- protected lazy val expansionMap = _expandingOptions
- protected def creator(args: List[String]) = new ThisCommandLine(args)
- protected def expandArg(arg: String) = expansionMap.getOrElse(fromOpt(arg), List(arg))
-
- class ThisCommandLine(args: List[String]) extends CommandLine(args, unaryOptions, binaryOptions) {
- }
-}
-
-object CommandLineSpec {
- def toOpt(s: String) = if (s startsWith "--") s else "--" + s
- def fromOpt(s: String) = s stripPrefix "--"
- def toArgs(line: String) = tokenize(line)
- def fromArgs(args: List[String]) = args mkString " "
-
- def allSystemProperties: Map[String, String] = {
- import collection.JavaConversions._
-
- System.getProperties.toMap
- }
-
- /** A very simple template for generating bash completion functions.
- */
- val bashCompletionTemplate = """
- |_@@PROGRAM@@()
- |{
- | local cur opts base
- | COMPREPLY=()
- | cur="${COMP_WORDS[COMP_CWORD]}"
- | opts="@@OPTIONS@@"
- |
- | COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
- | _filedir
- | return 0
- |}
- |complete -F _@@PROGRAM@@ @@PROGRAM@@
- """.stripMargin
-}
diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
index 197eb28661..740e42192b 100644
--- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala
+++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
@@ -4,7 +4,8 @@
*/
// $Id$
-package scala.tools.nsc
+package scala.tools
+package nsc
package util
import java.io.{File, FileInputStream, PrintStream, IOException}
@@ -290,7 +291,7 @@ object ShowPickled extends Names {
/** Option --bare suppresses numbers so the output can be diffed.
*/
def main(args: Array[String]) {
- val parsed = CommandLine(args.toList, List("--bare"), Nil)
+ val parsed = cmd.CommandLine(args.toList, List("--bare"), Nil)
def isBare = parsed isSet "--bare"
parsed.residualArgs foreach { arg =>
diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala
index b781e46be5..3a08fa0482 100644
--- a/src/library/scala/util/Properties.scala
+++ b/src/library/scala/util/Properties.scala
@@ -54,6 +54,7 @@ private[scala] trait PropertiesTrait
def clearProp(name: String) = System.clearProperty(name)
def envOrElse(name: String, alt: String) = Option(System getenv name) getOrElse alt
+ def envOrNone(name: String) = Option(System getenv name)
// for values based on propFilename
def scalaPropOrElse(name: String, alt: String): String = scalaProps.getProperty(name, alt)
diff --git a/src/partest/scala/tools/partest/Compilable.scala b/src/partest/scala/tools/partest/Compilable.scala
index a1d987ad6d..c11532f278 100644
--- a/src/partest/scala/tools/partest/Compilable.scala
+++ b/src/partest/scala/tools/partest/Compilable.scala
@@ -27,8 +27,10 @@ trait PartestCompilation {
// }
def javac(args: List[String]): Boolean = {
+ val allArgString = fromArgs(javacpArg :: javacOpts :: args)
+
// javac -d outdir -classpath <basepath> <files>
- val cmd = "%s -d %s %s %s".format(javacCmd, outDir, javacpArg, fromArgs(args))
+ val cmd = "%s -d %s %s".format(javacCmd, outDir, allArgString)
def traceMsg =
if (isVerbose) cmd
else "%s -d %s %s".format(tracePath(Path(javacCmd)), tracePath(outDir), fromArgs(args))
diff --git a/src/partest/scala/tools/partest/Config.scala b/src/partest/scala/tools/partest/Config.scala
index 7d8bb80835..288a3034e9 100644
--- a/src/partest/scala/tools/partest/Config.scala
+++ b/src/partest/scala/tools/partest/Config.scala
@@ -23,8 +23,6 @@ trait Config {
* run we only allocate one worker so the output isn't interspersed.
*/
def workerTimeout = 3600 // 1 hour, probably overly generous
- def testTimeout = testTimeout_ flatMap safeToInt getOrElse 900 // test timeout
- def testWarning = testWarning_ flatMap safeToInt getOrElse (testTimeout / 10) // test warning
def numWorkers = if (isDryRun) 1 else propOrElse("partest.actors", "8").toInt
def expectedErrors = propOrElse("partest.errors", "0").toInt
def poolSize = (wrapAccessControl(propOrNone("actors.corePoolSize")) getOrElse "16").toInt
@@ -121,6 +119,7 @@ trait Config {
"Java binaries in: " + javaBin,
"Java runtime is: " + javaInfoString,
"Java runtime options: " + (Process.javaVmArguments mkString " "),
+ "Javac options are: " + universe.javacOpts,
"Java options are: " + universe.javaOpts,
"Source directory is: " + src,
"Selected categories: " + (selectedCategories mkString " "),
diff --git a/src/partest/scala/tools/partest/Partest.scala b/src/partest/scala/tools/partest/Partest.scala
index 019ed270e5..d6adcc6053 100644
--- a/src/partest/scala/tools/partest/Partest.scala
+++ b/src/partest/scala/tools/partest/Partest.scala
@@ -6,7 +6,7 @@ package scala.tools
package partest
import nsc.io._
-import nsc.util.CommandLine
+import nsc.util._
import category.AllCategories
/** Global object for a Partest run. It is completely configured by the list
@@ -15,10 +15,15 @@ import category.AllCategories
* for the complete list.
*/
class Partest(args: List[String]) extends {
- val parsed = PartestSpecReference(args: _*)
-} with Universe with PartestSpec with AllCategories {
+ val parsed = PartestSpec(args: _*)
+} with Universe with PartestSpec with cmd.Instance with AllCategories {
- debug("Partest object created with args: " + (args mkString " "))
+ if (parsed.propertyArgs.nonEmpty)
+ debug("Partest property args: " + fromArgs(parsed.propertyArgs))
+
+ debug("Partest created with args: " + fromArgs(args))
+
+ def helpMsg = PartestSpec.helpMsg
// The abstract values from Universe.
lazy val testBuildDir = searchForDir(buildDir)
@@ -30,7 +35,6 @@ class Partest(args: List[String]) extends {
// Coarse validation of partest directory: holds a file called partest.
(partestDir / "partest").isFile || error("'%s' is not a valid partest directory." format partestDir)
- def runSets = toArgs(parsed.getOrElse("--runsets", ""))
def specifiedTests = parsed.residualArgs map (x => Path(x).normalize)
def specifiedKinds = testKinds filter (x => isSet(x) || (runSets contains x))
def specifiedCats = specifiedKinds flatMap (x => allCategories find (_.kind == x))
diff --git a/src/partest/scala/tools/partest/PartestSpec.scala b/src/partest/scala/tools/partest/PartestSpec.scala
index a8a1d9b0cb..e4259d70be 100644
--- a/src/partest/scala/tools/partest/PartestSpec.scala
+++ b/src/partest/scala/tools/partest/PartestSpec.scala
@@ -6,9 +6,8 @@
package scala.tools
package partest
-import Properties._
import nsc.io._
-import nsc.util.{ CommandLine, CommandLineSpec, CommandLineReferenceSpec }
+import cmd._
/** This takes advantage of bits of scala goodness to fully define a command
* line program with a minimum of duplicated code. When the specification object
@@ -16,93 +15,90 @@ import nsc.util.{ CommandLine, CommandLineSpec, CommandLineReferenceSpec }
* a private accumulator. What emerges is a full list of the valid unary
* and binary arguments, as well as autogenerated help.
*/
-trait PartestSpec extends CommandLineSpec {
- override def isPassthroughProperty(key: String) = key == "partest.options"
- override def isSysPropOption(key: String) = {
- val segments = (key split '.').toList
- if (segments.size == 2 && segments.head == "partest") Some(segments.last)
- else None
- }
-
- private var _testKinds: List[String] = Nil
- private def kind(s: String) = returning(s)(_testKinds +:= _)
+trait PartestSpec extends Spec with Meta.StdOpts with Interpolation {
+ def referenceSpec = PartestSpec
+ def programInfo = Spec.Names("partest", "scala.tools.partest.Runner")
+ private val kind = new Spec.Accumulator[String]()
+ protected def testKinds = kind.get
- def testKinds = _testKinds
- def versionMsg = Properties.versionMsg
+ private implicit val tokenizeString = FromString.ArgumentsFromString // String => List[String]
help("""
+ |# Pro Tip! Instant bash completion: `partest --bash` (note backticks)
|Usage: partest [<options>] [<test> <test> ...]
| <test>: a path to a test designator, typically a .scala file or a directory.
- | Examples: files/pos/test1.scala, files/res/bug785""")
-
- heading ("Test categories:")
- val isAll = ("all" / "run all tests (default, unless no options given)" ?)
- (kind("pos") / "Compile files that are expected to build" ?)
- (kind("neg") / "Compile files that are expected to fail" ?)
- (kind("run") / "Test JVM backend" ?)
- (kind("jvm") / "Test JVM backend" ?)
- (kind("res") / "Run resident compiler scenarii" ?)
- (kind("buildmanager") / "Run Build Manager scenarii" ?)
- (kind("scalacheck") / "Run Scalacheck tests" ?)
- (kind("script") / "Run script files" ?)
- (kind("shootout") / "Run shootout tests" ?)
- (kind("scalap") / "Run scalap tests" ?)
+ | Examples: files/pos/test1.scala, files/res/bug785
+ |
+ | Test categories:""".stripMargin)
+
+ val isAll = ("all" / "run all tests (default, unless no options given)" --?)
+ (kind("pos") / "Compile files that are expected to build" --?)
+ (kind("neg") / "Compile files that are expected to fail" --?)
+ (kind("run") / "Test JVM backend" --?)
+ (kind("jvm") / "Test JVM backend" --?)
+ (kind("res") / "Run resident compiler scenarii" --?)
+ (kind("buildmanager") / "Run Build Manager scenarii" --?)
+ (kind("scalacheck") / "Run Scalacheck tests" --?)
+ (kind("script") / "Run script files" --?)
+ (kind("shootout") / "Run shootout tests" --?)
+ (kind("scalap") / "Run scalap tests" --?)
heading ("""Test "smart" categories:""")
- val grepExpr = "grep" / "run all tests with a source file containing <expr>" >>
- val isFailed = "failed" / "run all tests which failed on the last run" ?
+ val grepExpr = "grep" / "run all tests with a source file containing <expr>" --|
+ val isFailed = "failed" / "run all tests which failed on the last run" --?
heading ("Specifying paths and additional flags, ~ means repository root:")
- val rootDir = "rootdir" / "path from ~ to partest (default: test)" |> "test"
- val buildDir = "builddir" / "path from ~ to test build (default: build/pack)" |> "build/pack"
- val srcDir = "srcdir" / "path from --rootdir to sources (default: files)" |> "files"
- val javaOpts = "javaopts" / "flags to java on all runs (overrides JAVA_OPTS)" |> envOrElse("JAVA_OPTS", "")
- val scalacOpts = "scalacopts" / "flags to scalac on all tests (overrides SCALAC_OPTS)" |> envOrElse("SCALAC_OPTS", "")
- ("pack" / "alias for --builddir build/pack") ?+> List("--builddir", "build/pack")
- ("quick" / "alias for --builddir build/quick") ?+> List("--builddir", "build/quick")
+ val rootDir = "rootdir" / "path from ~ to partest" defaultTo "test"
+ val buildDir = "builddir" / "path from ~ to test build" defaultTo "build/pack"
+ val srcDir = "srcdir" / "path from --rootdir to sources" defaultTo "files"
+ val javaOpts = "javaopts" / "flags to java on all runs" defaultToEnv "JAVA_OPTS"
+ val javacOpts = "javacopts" / "flags to javac on all runs" defaultToEnv "JAVAC_OPTS"
+ val scalacOpts = "scalacopts" / "flags to scalac on all tests" defaultToEnv "SCALAC_OPTS"
+
+ "pack" / "" expandTo ("--builddir", "build/pack")
+ "quick" / "" expandTo ("--builddir", "build/quick")
heading ("Options influencing output:")
- val isTrace = "trace" / "show the individual steps taken by each test" ?
- val isShowDiff = "show-diff" / "show diff between log and check file" ?
- val isShowLog = "show-log" / "show log on failures" ?
- val isDryRun = "dry-run" / "do not run tests, only show their traces." ?
- val isTerse = "terse" / "be less verbose (almost silent except for failures)" ?
- val isVerbose = "verbose" / "be more verbose (additive with --trace)" ?
- val isDebug = "debug" / "maximum debugging output" ?
- val isAnsi = "ansi" / "print output in color" ?
+ val isTrace = "trace" / "show the individual steps taken by each test" --?
+ val isShowDiff = "show-diff" / "show diff between log and check file" --?
+ val isShowLog = "show-log" / "show log on failures" --?
+ val isDryRun = "dry-run" / "do not run tests, only show their traces." --?
+ val isTerse = "terse" / "be less verbose (almost silent except for failures)" --?
+ val isVerbose = "verbose" / "be more verbose (additive with --trace)" --?
+ val isDebug = "debug" / "maximum debugging output" --?
+ val isAnsi = "ansi" / "print output in color" --?
heading ("Other options:")
- val timeout_ = "timeout" / "Overall timeout in seconds" |> "14400"
- val testWarning_ = "test-warning" / "Test warning in seconds" >> ; // defaults to testTimeout / 10
- val testTimeout_ = "test-timeout" / "Test timeout in seconds" >> ; // defaults to 900
- val isCleanup = "cleanup" / "delete all stale files and dirs before run" ?
- val isNoCleanup = "nocleanup" / "do not delete any logfiles or object dirs" ?
- val isStats = "stats" / "collect and print statistics about the tests" ?
- val isValidate = "validate" / "examine test filesystem for inconsistencies" ?
- val isVersion = "version" / "print version" ?
+ val timeout = "timeout" / "Overall timeout in seconds" defaultTo 14400
+ val testWarning = "test-warning" / "Test warning in seconds" defaultTo 90
+ val testTimeout = "test-timeout" / "Test timeout in seconds" defaultTo 900
+ val isCleanup = "cleanup" / "delete all stale files and dirs before run" --?
+ val isNoCleanup = "nocleanup" / "do not delete any logfiles or object dirs" --?
+ val isStats = "stats" / "collect and print statistics about the tests" --?
+ val isValidate = "validate" / "examine test filesystem for inconsistencies" --?
+
+ "version" / "print version" --> runAndExit(println(Properties.versionMsg))
// no help for anything below this line - secret options
// mostly intended for property configuration.
- val runsets = "runsets" |> ""
- val isNoAlarms = ("noalarms" ?)
- val isInsideAnt = ("is-in-ant" ?)
+ val runSets = ("runsets" --^) getOrElse Nil
+ val isNoAlarms = "noalarms" --?
+ val isInsideAnt = "is-in-ant" --?
}
-object PartestSpecReference extends PartestSpec with CommandLineReferenceSpec {
- import CommandLineSpec._
+object PartestSpec extends PartestSpec with Property {
+ lazy val propMapper = new PropertyMapper(PartestSpec) {
+ override def isPassThrough(key: String) = key == "partest.options"
+ }
- def parsed: CommandLine = null
- override def creator(args: List[String]) =
- new ThisCommandLine(args) {
- override def onlyKnownOptions = true
- override def errorFn(msg: String) = printAndExit("Error: " + msg)
- }
+ type ThisCommandLine = PartestCommandLine
+ class PartestCommandLine(args: List[String]) extends SpecCommandLine(args) {
+ override def onlyKnownOptions = true
+ override def errorFn(msg: String) = printAndExit("Error: " + msg)
- def main(args: Array[String]): Unit = println(bashCompletion("partest"))
+ def propertyArgs = PartestSpec.propertyArgs
+ }
- /** Append bash completion for partest to the given file.
- */
- def appendCompletionTo(f: File) = f appendAll bashCompletion("partest")
+ override def creator(args: List[String]): PartestCommandLine = new PartestCommandLine(args)
}
-
diff --git a/src/partest/scala/tools/partest/Runner.scala b/src/partest/scala/tools/partest/Runner.scala
index 7f67c93478..1a28e60896 100644
--- a/src/partest/scala/tools/partest/Runner.scala
+++ b/src/partest/scala/tools/partest/Runner.scala
@@ -9,13 +9,10 @@ package partest
import nsc.io._
object Runner {
- def main(mainArgs: Array[String]) {
- val propArgs = PartestSpecReference.sysPropsAsOptions()
- val args = (propArgs ++ mainArgs).toList
+ def main(args: Array[String]) {
val runner = Partest(args: _*)
import runner._
- if (isVersion) return println(versionMsg)
if (args.isEmpty) return println(helpMsg)
if (isValidate) return validateAll()
diff --git a/src/partest/scala/tools/partest/ant/JavaTask.scala b/src/partest/scala/tools/partest/ant/JavaTask.scala
index 0bebf91368..6740554dd8 100644
--- a/src/partest/scala/tools/partest/ant/JavaTask.scala
+++ b/src/partest/scala/tools/partest/ant/JavaTask.scala
@@ -12,19 +12,21 @@ package ant
import org.apache.tools.ant.Task
import org.apache.tools.ant.taskdefs.Java
-import org.apache.tools.ant.types.{ EnumeratedAttribute, Commandline, Environment, PropertySet }
+import org.apache.tools.ant.types.Environment
import scala.tools.nsc.io._
-import scala.tools.nsc.util.{ ClassPath, CommandLineSpec }
-import CommandLineSpec._
+import scala.tools.nsc.util.ClassPath
+import cmd.Spec._
class JavaTask extends Java {
override def getTaskName() = "partest"
private val scalaRunnerClass = "scala.tools.nsc.MainGenericRunner"
+ private val partestRunnerClass = "scala.tools.partest.Runner"
+ def defaultJvmArgs = "-Xms64M -Xmx768M -Xss768K -XX:MaxPermSize=96M"
protected def rootDir = prop("partest.rootdir") getOrElse (baseDir / "test").path
- protected def partestJVMArgs = prop("partest.jvm.args") getOrElse "-Xms64M -Xmx768M -Xss768K -XX:MaxPermSize=96M"
- protected def runnerArgs = List("-usejavacp", "scala.tools.partest.Runner", "--javaopts", partestJVMArgs)
+ protected def partestJVMArgs = prop("partest.jvm.args") getOrElse defaultJvmArgs
+ protected def runnerArgs = List("-usejavacp", partestRunnerClass, "--javaopts", partestJVMArgs)
private def baseDir = Directory(getProject.getBaseDir)
private def prop(s: String) = Option(getProject getProperty s)
diff --git a/src/partest/scala/tools/partest/ant/PartestTask.scala b/src/partest/scala/tools/partest/ant/PartestTask.scala
deleted file mode 100644
index 65848fabb0..0000000000
--- a/src/partest/scala/tools/partest/ant/PartestTask.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-/**** Note -- this isn't used anymore, but I left it in for the moment. ****/
-
-package scala.tools
-package partest
-package ant
-
-import java.io.{ File => JFile }
-
-import org.apache.tools.ant.Task
-import org.apache.tools.ant.types.{ Reference, FileSet}
-
-import scala.reflect.BeanProperty
-import scala.tools.ant.sabbus.CompilationPathProperty
-import scala.tools.nsc.io
-import scala.tools.nsc.util.CommandLineSpec._
-
-class PartestTask extends Task with CompilationPathProperty {
- /** Used only in ant task */
- @BeanProperty protected var errorOnFailed: Boolean = _
- @BeanProperty protected var jUnitReportDir: JFile = _
-
- /** Propagated to partest run via system properties */
- @BeanProperty protected var debug: Boolean = _
- @BeanProperty protected var javaOpts: String = _
- @BeanProperty protected var partestOpts: String = _
- @BeanProperty protected var runSets: String = _
- @BeanProperty protected var scalacOpts: String = _
- @BeanProperty protected var showDiff: Boolean = _
- @BeanProperty protected var showLog: Boolean = _
- @BeanProperty protected var srcDir: String = _
- @BeanProperty protected var timeout: Int = _
-
- /** Translating ant information into command line arguments. */
- private def notEmpty(s: String) = s != null && s.length > 0
- private def quoted(s: String) = if (s exists (_.isWhitespace)) "\"" + s.trim + "\"" else s
- private def optionCollection = List[(Boolean, () => List[String])](
- debug -> (() => List("--debug")),
- showLog -> (() => List("--show-log")),
- showDiff -> (() => List("--show-diff")),
- (timeout > 0) -> (() => List("--timeout", timeout.toString)),
- notEmpty(javaOpts) -> (() => List("--javaopts", javaOpts)),
- notEmpty(scalacOpts) -> (() => List("--scalacopts", scalacOpts)),
- notEmpty(srcDir) -> (() => List("--srcdir", srcDir)),
- notEmpty(partestOpts) -> (() => toArgs(partestOpts))
- )
-
- private def antPropOrNone(name: String) = Option(getProject getProperty name)
- private def antPropsToCommandLine() = {
- setProp("partest.isInAnt", "true")
- val partestDir = antPropOrNone("partest.dir") getOrElse error("Mandatory attribute 'partest.dir' is not set.")
-
- val root = List("--rootdir", io.Path(partestDir).path)
- val opts = optionCollection collect { case (true, f) => f() } flatten
- val sets = Option(runSets).toList flatMap toArgs map toOpt
-
- root ++ opts ++ sets
- }
- private def antRunTests() = {
- val args = antPropsToCommandLine()
- val runner = Partest(args: _*)
- import runner._
-
- normal("Ant options translate to command line: partest " + fromArgs(args))
- printConfigBanner()
-
- val result = launchTestSuite()
- val msg = result.toString
-
- if (result.hasFailures && errorOnFailed) error(msg)
- else log(msg)
- }
-
- override def execute() {
- try antRunTests()
- catch {
- case x =>
- System.err.println("Uncaught exception %s in partest ant ask: aborting." format x)
- x.printStackTrace()
- throw x
- }
- }
-}
diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala
index 3ef4db7cd8..f6d216e379 100644
--- a/src/partest/scala/tools/partest/package.scala
+++ b/src/partest/scala/tools/partest/package.scala
@@ -5,7 +5,6 @@
package scala.tools
import nsc.io.{ File, Path, Process, Directory }
-import nsc.util.CommandLineSpec
import java.nio.charset.CharacterCodingException
package object partest {
@@ -18,13 +17,12 @@ package object partest {
private[partest] def safeLines(f: File) = safeSlurp(f) split """\r\n|\r|\n""" toList
private[partest] def safeArgs(f: File) = toArgs(safeSlurp(f))
- private[partest] def safeToInt(s: String) = try Some(s.toInt) catch { case _: NumberFormatException => None }
private[partest] def isJava(f: Path) = f.isFile && (f hasExtension "java")
private[partest] def isScala(f: Path) = f.isFile && (f hasExtension "scala")
private[partest] def isJavaOrScala(f: Path) = isJava(f) || isScala(f)
- private[partest] def toArgs(line: String) = CommandLineSpec toArgs line
- private[partest] def fromArgs(args: List[String]) = CommandLineSpec fromArgs args
+ private[partest] def toArgs(line: String) = cmd toArgs line
+ private[partest] def fromArgs(args: List[String]) = cmd fromArgs args
/** Strings, argument lists, etc. */
diff --git a/test/partest b/test/partest
index 124c4d605e..87c7961689 100755
--- a/test/partest
+++ b/test/partest
@@ -75,11 +75,11 @@ if $cygwin; then
fi
# Reminder: substitution ${JAVA_OPTS:=-Xmx256M -Xms16M} DO NOT work on Solaris
-[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:MaxPermSize=128M"
+[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xms64M -Xmx1024M -Xss768K -XX:MaxPermSize=96M"
[ -n "$SCALAC_OPTS" ] || SCALAC_OPTS=""
-export SCALAC_OPTS
-export JAVA_OPTS
+# export SCALAC_OPTS
+# export JAVA_OPTS
export JAVACMD
${JAVACMD:=java} $JAVA_OPTS \