diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-07-01 11:29:34 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-07-01 11:29:34 -0700 |
commit | 7e833bcc75b382cecc4b6e8f33b8def68037af82 (patch) | |
tree | ea00f9602770f40e3efc7d53dd129e94249c993c /src | |
parent | e2fbbb28fa0200d4799ed81a4c93dcb224f6564b (diff) | |
parent | 609070953cfce003fbfcf232ffbfb7fb284cda54 (diff) | |
download | scala-7e833bcc75b382cecc4b6e8f33b8def68037af82.tar.gz scala-7e833bcc75b382cecc4b6e8f33b8def68037af82.tar.bz2 scala-7e833bcc75b382cecc4b6e8f33b8def68037af82.zip |
Merge pull request #2692 from soc/SI-7591
SI-7591 Migrate command-line parsing to s.t.cmd
Diffstat (limited to 'src')
10 files changed, 96 insertions, 266 deletions
diff --git a/src/compiler/scala/tools/cmd/Demo.scala b/src/compiler/scala/tools/cmd/Demo.scala deleted file mode 100644 index fc90140f8f..0000000000 --- a/src/compiler/scala/tools/cmd/Demo.scala +++ /dev/null @@ -1,85 +0,0 @@ -/* NEST (New Scala Test) - * Copyright 2007-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala -package 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 --self-update 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 --self-update --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.Info("demo", "Usage: demo [<options>]", "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 errorFn(msg: String) = { println("Error: " + msg) ; sys.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/Spec.scala b/src/compiler/scala/tools/cmd/Spec.scala index b761601167..a1cb31f911 100644 --- a/src/compiler/scala/tools/cmd/Spec.scala +++ b/src/compiler/scala/tools/cmd/Spec.scala @@ -15,7 +15,7 @@ trait Spec { def programInfo: Spec.Info protected def help(str: => String): Unit - protected def heading(str: => String): Unit = help("\n " + str) + protected def heading(str: => String): Unit = help(s"\n $str") type OptionMagic <: Opt.Implicit protected implicit def optionMagicAdditions(s: String): OptionMagic diff --git a/src/compiler/scala/tools/nsc/util/CommandLine.scala b/src/compiler/scala/tools/nsc/util/CommandLine.scala deleted file mode 100644 index ef28f6dc53..0000000000 --- a/src/compiler/scala/tools/nsc/util/CommandLine.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* NEST (New Scala Test) - * Copyright 2007-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools -package nsc.util - -import scala.collection.mutable.ListBuffer - -/** - * XXX Note this has been completely obsolesced by scala.tools.cmd. - * I checked it back in as part of rolling partest back a month - * rather than go down the rabbit hole of unravelling dependencies. - */ -case class CommandLine( - args: List[String], - unaryArguments: List[String], - binaryArguments: 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(cmd.CommandLineParser tokenize line, Nil, Nil) - - def withUnaryArgs(xs: List[String]) = copy(unaryArguments = xs) - def withBinaryArgs(xs: List[String]) = copy(binaryArguments = xs) - - 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 || (unaryArguments contains s) || (binaryArguments contains s) - def isOption(s: String) = (s startsWith "-") && (isValidOption(s) || { unknownOption(s) ; false }) - def isUnary(s: String) = isOption(s) && (unaryArguments contains s) - def isBinary(s: String) = isOption(s) && !isUnary(s) && (assumeBinary || (binaryArguments 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 apply(arg: String) = argMap(arg) - - override def toString() = "CommandLine(\n%s)\n" format (args map (" " + _ + "\n") mkString) -} diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala index 4602c3cc53..16754646fd 100644 --- a/src/library/scala/util/parsing/combinator/Parsers.scala +++ b/src/library/scala/util/parsing/combinator/Parsers.scala @@ -531,10 +531,6 @@ trait Parsers { } } - /*trait ElemFun - case class EFCons(hd: Elem => ElemFun, tl: ElemFun) extends ElemFun - case class EFNil(res: Boolean) extends ElemFun*/ - /** A parser matching input elements that satisfy a given predicate. * * `elem(kind, p)` succeeds if the input starts with an element `e` for which `p(e)` is true. diff --git a/src/partest/scala/tools/partest/TestKinds.scala b/src/partest/scala/tools/partest/TestKinds.scala index ec682690ca..b4e8afd0d2 100644 --- a/src/partest/scala/tools/partest/TestKinds.scala +++ b/src/partest/scala/tools/partest/TestKinds.scala @@ -4,8 +4,7 @@ package partest import nest.PathSettings.srcDir object TestKinds { - val standardKinds = "pos neg run jvm res buildmanager scalacheck scalap specialized instrumented presentation ant" split "\\s+" toList - val standardArgs = standardKinds map ("--" + _) + val standardKinds = ("pos neg run jvm res scalacheck scalap specialized instrumented presentation ant" split "\\s+").toList def denotesTestFile(p: Path) = p.isFile && p.hasExtension("scala", "res", "xml") def denotesTestDir(p: Path) = kindOf(p) match { diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala index 33bf836a7b..332131ca3a 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala @@ -9,13 +9,15 @@ package nest import utils.Properties._ import scala.tools.nsc.Properties.{ versionMsg, setProp } -import scala.tools.nsc.util.CommandLine import scala.collection.{ mutable, immutable } import PathSettings.srcDir import TestKinds._ import scala.reflect.internal.util.Collections.distinctBy +import scala.tools.cmd.{ CommandLine, CommandLineParser, Instance } -class ConsoleRunner extends DirectRunner { +class ConsoleRunner(argstr: String) extends { + val parsed = ConsoleRunnerSpec.creator(CommandLineParser tokenize argstr) +} with DirectRunner with ConsoleRunnerSpec with Instance { import NestUI._ import NestUI.color._ @@ -86,27 +88,15 @@ class ConsoleRunner extends DirectRunner { } } - private val unaryArgs = List( - "--pack", "--all", - "--terse", "--verbose", "--show-diff", "--show-log", "--self-test", - "--failed", "--update-check", "--version", "--ansi", "--debug", "--help" - ) ::: standardArgs - - private val binaryArgs = List( - "--grep", "--srcpath", "--buildpath", "--classpath", "--timeout" - ) - - def main(argstr: String) { - val parsed = (new CommandLine(argstr)) withUnaryArgs unaryArgs withBinaryArgs binaryArgs - - if (parsed isSet "--debug") NestUI.setDebug() - if (parsed isSet "--verbose") NestUI.setVerbose() - if (parsed isSet "--terse") NestUI.setTerse() - if (parsed isSet "--show-diff") NestUI.setDiffOnFail() + def run(): Unit = { + if (optDebug) NestUI.setDebug() + if (optVerbose) NestUI.setVerbose() + if (optTerse) NestUI.setTerse() + if (optShowDiff) NestUI.setDiffOnFail() // Early return on no args, version, or invalid args - if (parsed isSet "--version") return echo(versionMsg) - if ((argstr == "") || (parsed isSet "--help")) return NestUI.usage() + if (optVersion) return echo(versionMsg) + if ((argstr == "") || optHelp) return NestUI.usage() val (individualTests, invalid) = parsed.residualArgs map (p => Path(p)) partition denotesTestPath if (invalid.nonEmpty) { @@ -116,27 +106,26 @@ class ConsoleRunner extends DirectRunner { echoWarning(s"Discarding ${invalid.size} invalid test paths") } - parsed get "--srcpath" foreach (x => setProp("partest.srcdir", x)) - parsed get "--timeout" foreach (x => setProp("partest.timeout", x)) + optSourcePath foreach (x => setProp("partest.srcdir", x)) + optTimeout foreach (x => setProp("partest.timeout", x)) fileManager = - if (parsed isSet "--buildpath") new ConsoleFileManager(parsed("--buildpath")) - else if (parsed isSet "--classpath") new ConsoleFileManager(parsed("--classpath"), true) - else if (parsed isSet "--pack") new ConsoleFileManager("build/pack") + if (optBuildPath.isDefined) new ConsoleFileManager(optBuildPath.get) + else if (optClassPath.isDefined) new ConsoleFileManager(optClassPath.get, true) + else if (optPack) new ConsoleFileManager("build/pack") else new ConsoleFileManager // auto detection, see ConsoleFileManager.findLatest - fileManager.updateCheck = parsed isSet "--update-check" - fileManager.failed = parsed isSet "--failed" + fileManager.updateCheck = optUpdateCheck + fileManager.failed = optFailed val partestTests = ( - if (parsed isSet "--self-test") TestKinds.testsForPartest + if (optSelfTest) TestKinds.testsForPartest else Nil ) - val grepExpr = parsed get "--grep" getOrElse "" + val grepExpr = optGrep getOrElse "" // If --grep is given we suck in every file it matches. - var grepMessage = "" val greppedTests = if (grepExpr == "") Nil else { val paths = grepFor(grepExpr) if (paths.isEmpty) @@ -145,14 +134,14 @@ class ConsoleRunner extends DirectRunner { paths.sortBy(_.toString) } - val isRerun = parsed isSet "--failed" + val isRerun = optFailed val rerunTests = if (isRerun) TestKinds.failedTests else Nil def miscTests = partestTests ++ individualTests ++ greppedTests ++ rerunTests - val givenKinds = standardArgs filter parsed.isSet + val givenKinds = standardKinds filter parsed.isSet val kinds = ( - if (parsed isSet "--all") standardKinds - else if (givenKinds.nonEmpty) givenKinds map (_ stripPrefix "--") + if (optAll) standardKinds + else if (givenKinds.nonEmpty) givenKinds else if (invalid.isEmpty && miscTests.isEmpty && !isRerun) standardKinds // If no kinds, --grep, or individual tests were given, assume --all else Nil ) @@ -223,4 +212,13 @@ class ConsoleRunner extends DirectRunner { issueSummaryReport() System exit ( if (isSuccess) 0 else 1 ) } + + run() } + +object ConsoleRunner { + def main(args: Array[String]): Unit = { + new ConsoleRunner(args mkString " ") + } +} + diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunnerSpec.scala b/src/partest/scala/tools/partest/nest/ConsoleRunnerSpec.scala new file mode 100644 index 0000000000..f9143013e9 --- /dev/null +++ b/src/partest/scala/tools/partest/nest/ConsoleRunnerSpec.scala @@ -0,0 +1,54 @@ +package scala.tools.partest.nest + +import language.postfixOps + +import scala.tools.cmd.{ CommandLine, Interpolation, Meta, Reference, Spec } + +trait ConsoleRunnerSpec extends Spec with Meta.StdOpts with Interpolation { + def referenceSpec = ConsoleRunnerSpec + def programInfo = Spec.Info( + "console-runner", + "Usage: NestRunner [options] [test test ...]", + "scala.tools.partest.nest.ConsoleRunner") + + heading("Test categories:") + val optAll = "all" / "run all tests" --? + val optPos = "pos" / "run compilation tests (success)" --? + val optNeg = "neg" / "run compilation tests (failure)" --? + val optRun = "run" / "run interpreter and backend tests" --? + val optJvm = "jvm" / "run JVM backend tests" --? + val optRes = "res" / "run resident compiler tests" --? + val optAnt = "ant" / "run Ant tests" --? + val optScalap = "scalap" / "run scalap tests" --? + val optSpecialized = "specialized" / "run specialization tests" --? + val optScalacheck = "scalacheck" / "run ScalaCheck tests" --? + val optInstrumented = "instrumented" / "run instrumented tests" --? + val optPresentation = "presentation" / "run presentation compiler tests" --? + + heading("Test runner options:") + val optFailed = "failed" / "run only those tests that failed during the last run" --? + val optTimeout = "timeout" / "aborts the test suite after the given amount of time" --| + val optPack = "pack" / "pick compiler/reflect/library in build/pack, and run all tests" --? + val optGrep = "grep" / "run all tests whose source file contains the expression given to grep" --| + val optUpdateCheck = "update-check" / "instead of failing tests with output change, update checkfile (use with care!)" --? + val optBuildPath = "buildpath" / "set (relative) path to build jars (ex.: --buildpath build/pack)" --| + val optClassPath = "classpath" / "set (absolute) path to build classes" --| + val optSourcePath = "srcpath" / "set (relative) path to test source files (ex.: --srcpath pending)" --| + + heading("Test output options:") + val optShowDiff = "show-diff" / "show diffs for failed tests" --? + val optVerbose = "verbose" / "show verbose progress information" --? + val optTerse = "terse" / "show terse progress information" --? + val optDebug = "debug" / "enable debugging output" --? + + heading("Other options:") + val optVersion = "version" / "show Scala version and exit" --? + val optSelfTest = "self-test" / "run tests for partest itself" --? + val optHelp = "help" / "show this page and exit" --? + +} + +object ConsoleRunnerSpec extends ConsoleRunnerSpec with Reference { + type ThisCommandLine = CommandLine + def creator(args: List[String]): ThisCommandLine = new CommandLine(ConsoleRunnerSpec, args) +} diff --git a/src/partest/scala/tools/partest/nest/NestUI.scala b/src/partest/scala/tools/partest/nest/NestUI.scala index 564270e531..5148115905 100644 --- a/src/partest/scala/tools/partest/nest/NestUI.scala +++ b/src/partest/scala/tools/partest/nest/NestUI.scala @@ -144,34 +144,8 @@ object NestUI { } def usage() { - println("Usage: NestRunner [options] [test test ...]") - println - println(" Test categories:") - println(" --all run all tests") - println(" --pos run compilation tests (success)") - println(" --neg run compilation tests (failure)") - println(" --run run interpreter and backend tests") - println(" --jvm run JVM backend tests") - println(" --res run resident compiler tests") - println(" --scalacheck run ScalaCheck tests") - println(" --instrumented run instrumented tests") - println(" --presentation run presentation compiler tests") - println - println(" Other options:") - println(" --pack pick compiler/reflect/library in build/pack, and run all tests") - println(" --grep <expr> run all tests whose source file contains <expr>") - println(" --failed run only those tests that failed during the last run") - println(" --update-check instead of failing tests with output change, update checkfile. (Use with care!)") - println(" --verbose show progress information") - println(" --buildpath set (relative) path to build jars") - println(" ex.: --buildpath build/pack") - println(" --classpath set (absolute) path to build classes") - println(" --srcpath set (relative) path to test source files") - println(" ex.: --srcpath pending") - println(" --debug enable debugging output") - println - println(utils.Properties.versionString) - println("maintained by Philipp Haller (EPFL)") + println(ConsoleRunnerSpec.programInfo.usage) + println(ConsoleRunnerSpec.helpMsg) sys.exit(1) } diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index 734affa153..3c77a03f1e 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -85,10 +85,9 @@ class ReflectiveRunner { try { val sepRunnerClass = sepLoader loadClass sepRunnerClassName - val sepRunner = sepRunnerClass.newInstance() - val sepMainMethod = sepRunnerClass.getMethod("main", Array(classOf[String]): _*) - val cargs: Array[AnyRef] = Array(args) - sepMainMethod.invoke(sepRunner, cargs: _*) + val sepMainMethod = sepRunnerClass.getMethod("main", classOf[Array[String]]) + val cargs: Array[AnyRef] = Array(Array(args)) + sepMainMethod.invoke(null, cargs: _*) } catch { case cnfe: ClassNotFoundException => diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala index a53698eb77..d7d87bdcf5 100644 --- a/src/partest/scala/tools/partest/nest/Runner.scala +++ b/src/partest/scala/tools/partest/nest/Runner.scala @@ -772,15 +772,8 @@ trait DirectRunner { import PartestDefaults.{ numThreads, waitTime } - Thread.setDefaultUncaughtExceptionHandler( - new Thread.UncaughtExceptionHandler { - def uncaughtException(thread: Thread, t: Throwable) { - val t1 = Exceptional unwrap t - System.err.println(s"Uncaught exception on thread $thread: $t1") - t1.printStackTrace() - } - } - ) + setUncaughtHandler + def runTestsForFiles(kindFiles: List[File], kind: String): List[TestState] = { NestUI.resetTestNumber(kindFiles.size) |