summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-03-21 22:25:40 +0000
committerPaul Phillips <paulp@improving.org>2011-03-21 22:25:40 +0000
commit455ee619fbfde17c8a9208d3e2ebf7d867cbd560 (patch)
tree686ccedbf5004eeb1507bbedc3b8c0d4b8d273fd /src/compiler/scala
parent7946facede9482d8a363b6474b163c11ab3a662c (diff)
downloadscala-455ee619fbfde17c8a9208d3e2ebf7d867cbd560.tar.gz
scala-455ee619fbfde17c8a9208d3e2ebf7d867cbd560.tar.bz2
scala-455ee619fbfde17c8a9208d3e2ebf7d867cbd560.zip
[I'm laptop only so there's some chance this wi...
[I'm laptop only so there's some chance this will incur temporary breakage, but it needs committing.] Heading off gratuitous complications which haven't yet shipped, I eliminated the -jar startup option in favor of doing what we already do, figuring it out. So now all these things work. scala foo/bar.scala // if file is a script or has one main method scala foo.Bar // if it has a legal main method scala foo.jar // if it has a legal MainClass attribute Also changed "-savecompiled" to "-save" and given scala source called foo.scala, generate foo.jar rather than foo.scala.jar. Cleaned up a bunch of related code and further polished the scala startup message. And unbroke choice settings and improved that error too, which closes #3849. While trying to write a test for the choice setting, was reminded that partest just discards invalid flags files. Made it fail instead, which closes #3712. Fixed the new failures that revealed. No review.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/GenericRunnerCommand.scala78
-rw-r--r--src/compiler/scala/tools/nsc/GenericRunnerSettings.scala22
-rw-r--r--src/compiler/scala/tools/nsc/MainGenericRunner.scala64
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala19
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala14
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala7
-rw-r--r--src/compiler/scala/tools/nsc/io/Jar.scala25
-rw-r--r--src/compiler/scala/tools/nsc/io/Path.scala27
-rw-r--r--src/compiler/scala/tools/nsc/io/Sources.scala5
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala8
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala1
-rw-r--r--src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala9
12 files changed, 147 insertions, 132 deletions
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala
index 68689a4109..86ab76b59c 100644
--- a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala
+++ b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala
@@ -5,6 +5,8 @@
package scala.tools.nsc
+import GenericRunnerCommand._
+
/** A command for ScriptRunner */
class GenericRunnerCommand(
args: List[String],
@@ -24,30 +26,31 @@ extends CompilerCommand(args, settings) {
// change CompilerCommand behavior
override def shouldProcessArguments: Boolean = false
- /** thingToRun: What to run. If it is None, then the interpreter should be started
- * arguments: Arguments to pass to the object or script to run
- */
- val (_ok, thingToRun, arguments) = {
- val (ok, remaining) = settings.processArguments(args, false)
- val mainClass =
- if (settings.jarfile.isDefault) None
- else new io.Jar(settings.jarfile.value).mainClass
-
- // If there is a jar with a main class, the remaining args are passed to that.
- // Otherwise, the first remaining argument is the program to run, and the rest
- // of the arguments go to it. If remaining is empty, we'll start the repl.
- mainClass match {
- case Some(name) => (ok, Some(name), remaining)
- case _ => (ok, remaining.headOption, remaining drop 1)
+ private lazy val (_ok, targetAndArguments) = settings.processArguments(args, false)
+ override def ok = _ok
+ private def guessHowToRun(target: String): GenericRunnerCommand.HowToRun = {
+ if (!ok) Error
+ else if (io.Jar.isJarOrZip(target)) AsJar
+ else if (util.ScalaClassLoader.classExists(settings.classpathURLs, target)) AsObject
+ else {
+ val f = io.File(target)
+ if (!f.hasExtension("class", "jar", "zip") && f.canRead) AsScript
+ else sys.error("Cannot figure out how to run target: " + target)
}
}
- override def ok = _ok
-
+ /** String with either the jar file, class name, or script file name. */
+ def thingToRun = targetAndArguments.headOption getOrElse ""
+ /** Arguments to thingToRun. */
+ def arguments = targetAndArguments drop 1
+
+ val howToRun = targetAndArguments match {
+ case Nil => AsRepl
+ case hd :: _ => waysToRun find (_.name == settings.howtorun.value) getOrElse guessHowToRun(hd)
+ }
private def interpolate(s: String) = s.trim.replaceAll("@cmd@", cmdName).replaceAll("@compileCmd@", compCmdName) + "\n"
def shortUsageMsg = interpolate("""
-Usage: @cmd@ <options> [<script|class|object> <arguments>]
- or @cmd@ <options> [-jar <jarfile> <arguments>]
+Usage: @cmd@ <options> [<script|class|object|jar> <arguments>]
or @cmd@ -help
All options to @compileCmd@ are also allowed. See @compileCmd@ -help.
@@ -59,26 +62,37 @@ what to run. Runnable targets are:
- a file containing scala source
- the name of a compiled class
- - a runnable jar file with a Main-Class attribute (if -jar is given)
- - if no argument is given, the repl (interactive shell) is started
+ - a runnable jar file with a valid Main-Class attribute
+ - or if no argument is given, the repl (interactive shell) is started
-Options to the runner which reach the java runtime:
+Options to @cmd@ which reach the java runtime:
-Dname=prop passed directly to java to set system properties
-J<arg> -J is stripped and <arg> passed to java as-is
-nobootcp do not put the scala jars on the boot classpath (slower)
-Other scala startup options:
+Other startup options:
- -howtorun specify what to run <script|object|guess> (default: guess)
- -i <file> preload <file> before starting the repl
- -e <string> execute <string> as if entered in the repl
- -nc no compilation daemon: do not use the fsc offline compiler
- -savecompiled save the compiled script in a jar for future use
+ -howtorun what to run <script|object|jar|guess> (default: guess)
+ -i <file> preload <file> before starting the repl
+ -e <string> execute <string> as if entered in the repl
+ -save save the compiled script in a jar for future use
+ -nc no compilation daemon: do not use the fsc offline compiler
-A file argument will be run as a scala script unless it contains only top
-level classes and objects, and exactly one runnable main method. In that
-case the file will be compiled and the main method invoked. This provides
-a bridge between scripts and standard scala source.
+A file argument will be run as a scala script unless it contains only
+self-contained compilation units (classes and objects) and exactly one
+runnable main method. In that case the file will be compiled and the
+main method invoked. This provides a bridge between scripts and standard
+scala source.
""") + "\n"
}
+
+object GenericRunnerCommand {
+ sealed abstract class HowToRun(val name: String) { }
+ case object AsJar extends HowToRun("jar")
+ case object AsObject extends HowToRun("object")
+ case object AsScript extends HowToRun("script")
+ case object AsRepl extends HowToRun("repl")
+ case object Error extends HowToRun("<error>")
+ val waysToRun = List(AsJar, AsObject, AsScript, AsRepl)
+}
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
index bd0ea4a4ba..45f8d1af5f 100644
--- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
+++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
@@ -5,24 +5,17 @@
package scala.tools.nsc
+import scala.tools.util.PathResolver
+
class GenericRunnerSettings(error: String => Unit) extends Settings(error) {
- // A -jar option means the remainder of the command line should be
- // passed to the main program in the jar. If -jar is given, jarfile
- // will be set, but we also need to prepend the jar to the classpath
- // since it may not be there.
- val jarfile =
- StringSetting(
- "-jar",
- "jar",
- "Specify the jarfile in which to look for the main class",
- "").stopProcessing() withPostSetHook (classpath prepend _.value)
+ def classpathURLs = new PathResolver(this) asURLs
val howtorun =
ChoiceSetting(
"-howtorun",
"how",
"how to run the specified code",
- List("guess", "object", "script"),
+ List("object", "script", "jar", "guess"),
"guess")
val loadfiles =
@@ -38,14 +31,15 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) {
"execute a single command",
"")
- val savecompiled =
+ val save =
BooleanSetting(
- "-savecompiled",
- "save the compiled script (assumes the code is a script)")
+ "-save",
+ "save the compiled script (assumes the code is a script)") withAbbreviation "-savecompiled"
val nc = BooleanSetting(
"-nc",
"do not use the fsc compilation daemon") withAbbreviation "-nocompdaemon"
@deprecated("Use `nc` instead") def nocompdaemon = nc
+ @deprecated("Use `save` instead") def savecompiled = save
}
diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
index e40fdea3b9..7ead4cce4a 100644
--- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala
+++ b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
@@ -13,6 +13,7 @@ import io.{ File }
import util.{ ClassPath, ScalaClassLoader }
import Properties.{ versionString, copyrightString }
import interpreter.{ ILoop }
+import GenericRunnerCommand._
/** An object that runs Scala code. It has three possible
* sources for the code to run: pre-compiled code, a script file,
@@ -35,7 +36,7 @@ object MainGenericRunner {
def process(args: Array[String]): Boolean = {
val command = new GenericRunnerCommand(args.toList, (x: String) => errorFn(x))
- import command.settings
+ import command.{ settings, howToRun, thingToRun }
def sampleCompiler = new Global(settings) // def so its not created unless needed
if (!command.ok) return errorFn("\n" + command.shortUsageMsg)
@@ -55,44 +56,35 @@ object MainGenericRunner {
files ++ str mkString "\n\n"
}
- val classpath: List[URL] = new PathResolver(settings) asURLs
+ def runTarget(): Either[Throwable, Boolean] = howToRun match {
+ case AsObject =>
+ ObjectRunner.runAndCatch(settings.classpathURLs, thingToRun, command.arguments)
+ case AsScript =>
+ ScriptRunner.runScriptAndCatch(settings, thingToRun, command.arguments)
+ case AsJar =>
+ ObjectRunner.runAndCatch(
+ File(thingToRun).toURL +: settings.classpathURLs,
+ new io.Jar(thingToRun).mainClass getOrElse sys.error("Cannot find main class for jar: " + thingToRun),
+ command.arguments
+ )
+ case _ =>
+ // We start the repl when no arguments are given.
+ Right(new ILoop process settings)
+ }
- /** Was code given in a -e argument? */
+ /** If -e and -i were both given, we want to execute the -e code after the
+ * -i files have been included, so they are read into strings and prepended to
+ * the code given in -e. The -i option is documented to only make sense
+ * interactively so this is a pretty reasonable assumption.
+ *
+ * This all needs a rewrite though.
+ */
if (isE) {
- /** If a -i argument was also given, we want to execute the code after the
- * files have been included, so they are read into strings and prepended to
- * the code given in -e. The -i option is documented to only make sense
- * interactively so this is a pretty reasonable assumption.
- *
- * This all needs a rewrite though.
- */
- val fullArgs = command.thingToRun.toList ::: command.arguments
-
- return ScriptRunner.runCommand(settings, combinedCode, fullArgs)
+ ScriptRunner.runCommand(settings, combinedCode, thingToRun +: command.arguments)
}
- else command.thingToRun match {
- case None =>
- // We start the repl when no arguments are given.
- new ILoop process settings
-
- case Some(thingToRun) =>
- val isObjectName =
- settings.howtorun.value match {
- case "object" => true
- case "script" => false
- case "guess" => ScalaClassLoader.classExists(classpath, thingToRun)
- }
-
- val result = try {
- if (isObjectName) ObjectRunner.runAndCatch(classpath, thingToRun, command.arguments)
- else ScriptRunner.runScriptAndCatch(settings, thingToRun, command.arguments)
- }
- catch { case ex => Left(ex) }
-
- result match {
- case Left(ex) => errorFn(ex)
- case Right(b) => b
- }
+ else runTarget() match {
+ case Left(ex) => errorFn(ex)
+ case Right(b) => b
}
}
}
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index 07aa62d164..96b7bce885 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -61,13 +61,10 @@ class ScriptRunner extends HasCompileSocket {
def isScript(settings: Settings) = settings.script.value != ""
/** Choose a jar filename to hold the compiled version of a script. */
- private def jarFileFor(scriptFile: String): File = {
- val name =
- if (scriptFile endsWith ".jar") scriptFile
- else scriptFile + ".jar"
-
- File(name)
- }
+ private def jarFileFor(scriptFile: String)= File(
+ if (scriptFile endsWith ".jar") scriptFile
+ else scriptFile.stripSuffix(".scala") + ".jar"
+ )
/** Read the entire contents of a file as a String. */
private def contentsOfFile(filename: String) = File(filename).slurp()
@@ -140,7 +137,7 @@ class ScriptRunner extends HasCompileSocket {
* not take place until there are no non-daemon threads running. Tickets #1955, #2006.
*/
waitingForThreads {
- if (settings.savecompiled.value) {
+ if (settings.save.value) {
val jarFile = jarFileFor(scriptFile)
def jarOK = jarFile.canRead && (jarFile isFresher File(scriptFile))
@@ -179,10 +176,8 @@ class ScriptRunner extends HasCompileSocket {
compiledLocation: String,
scriptArgs: List[String]): Boolean =
{
- val pr = new PathResolver(settings)
- val classpath = File(compiledLocation).toURL +: pr.asURLs
-
- ObjectRunner.runAndCatch(classpath, scriptMain(settings), scriptArgs) match {
+ val cp = File(compiledLocation).toURL +: settings.classpathURLs
+ ObjectRunner.runAndCatch(cp, scriptMain(settings), scriptArgs) match {
case Left(ex) => ex.printStackTrace() ; false
case _ => true
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index 3d4ff7a20b..584b8867b2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -38,7 +38,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
with LoopCommands
{
def this(in0: BufferedReader, out: PrintWriter) = this(Some(in0), out)
- def this() = this(None, new PrintWriter(Console.out))
+ def this() = this(None, new PrintWriter(Console.out, true))
var in: InteractiveReader = _ // the input stream from which commands come
var settings: Settings = _
@@ -162,8 +162,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
|Type in expressions to have them evaluated.
|Type :help for more information.""" .
stripMargin.format(versionString, javaVmName, javaVersion)
+ val addendum = if (isReplDebug) "\n" + new java.util.Date else ""
- plushln(welcomeMsg)
+ plushln(welcomeMsg + addendum)
}
/** Show the history */
@@ -748,7 +749,12 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
}
@deprecated("Use `process` instead")
- def main(args: Array[String]): Unit = process(args)
+ def main(args: Array[String]): Unit = {
+ if (isReplDebug)
+ System.out.println(new java.util.Date)
+
+ process(args)
+ }
@deprecated("Use `process` instead")
def main(settings: Settings): Unit = process(settings)
}
@@ -765,7 +771,7 @@ object ILoop {
stringFromStream { ostream =>
Console.withOut(ostream) {
val input = new BufferedReader(new StringReader(code))
- val output = new PrintWriter(new OutputStreamWriter(ostream))
+ val output = new PrintWriter(new OutputStreamWriter(ostream), true)
val repl = new ILoop(input, output)
val settings = new Settings
settings.classpath.value = sys.props("java.class.path")
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 527a9b153a..d74aa5e6df 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -87,6 +87,8 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
// not sure if we have some motivation to print directly to console
private def echo(msg: String) { Console println msg }
+ // protected def defaultImports: List[String] = List("_root_.scala.sys.exit")
+
/** We're going to go to some trouble to initialize the compiler asynchronously.
* It's critical that nothing call into it until it's been initialized or we will
* run into unrecoverable issues, but the perceived repl startup time goes
@@ -114,6 +116,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
// Can't use printMessage here, it deadlocks
Console.println("Repl compiler initialized.")
}
+ // addImports(defaultImports: _*)
true
}
catch {
@@ -609,6 +612,10 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
quietRun("val %s = %s".format(tempName, name))
quietRun("val %s = %s.asInstanceOf[%s]".format(name, tempName, newType))
}
+ def quietImport(ids: String*): IR.Result = beQuietDuring(addImports(ids: _*))
+ def addImports(ids: String*): IR.Result =
+ if (ids.isEmpty) IR.Success
+ else interpret("import " + ids.mkString(", "))
def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p))
def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala
index 0796742fb6..a9f0acaa00 100644
--- a/src/compiler/scala/tools/nsc/io/Jar.scala
+++ b/src/compiler/scala/tools/nsc/io/Jar.scala
@@ -65,8 +65,29 @@ class JarWriter(file: File, val manifest: Manifest = new Manifest()) {
}
object Jar {
- // CLASS_PATH
- // CONTENT_TYPE
+ // See http://download.java.net/jdk7/docs/api/java/nio/file/Path.html
+ // for some ideas.
+ private val ZipMagicNumber = List[Byte](80, 75, 3, 4)
+ private def magicNumberIsZip(f: Path) = f.isFile && (f.toFile.bytes().take(4).toList == ZipMagicNumber)
+
+ def isJarOrZip(f: Path): Boolean = isJarOrZip(f, true)
+ def isJarOrZip(f: Path, examineFile: Boolean): Boolean =
+ f.hasExtension("zip", "jar") || (examineFile && magicNumberIsZip(f))
+
+ def locateByClass(clazz: Class[_]): Option[File] = {
+ try Some(File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()))
+ catch { case _: Exception => None }
+ }
+ /** Walks upward from wherever the scala library jar is searching for
+ * the given jar name. This approach finds the scala library jar in the
+ * release layout and in trunk builds going up from pack.
+ */
+ def locateByName(name: String): Option[File] = {
+ def toSrc(d: Directory) = d.dirs.toList map (_ / name)
+ def walk(d: Directory) = d.parents flatMap toSrc find (_.isFile) map (_.toFile)
+
+ locateByClass(classOf[ScalaObject]) flatMap (x => walk(x.parent))
+ }
def create(file: File, sourceDir: Directory, mainClass: String): File = {
val writer = new Jar(file).jarWriter()
diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/compiler/scala/tools/nsc/io/Path.scala
index 68e9867dd7..3cfab55aaa 100644
--- a/src/compiler/scala/tools/nsc/io/Path.scala
+++ b/src/compiler/scala/tools/nsc/io/Path.scala
@@ -28,37 +28,12 @@ import scala.util.Random.alphanumeric
*/
object Path {
- // See http://download.java.net/jdk7/docs/api/java/nio/file/Path.html
- // for some ideas.
- private val ZipMagicNumber = List[Byte](80, 75, 3, 4)
- private def magicNumberIsZip(f: Path) = f.isFile && (f.toFile.bytes().take(4).toList == ZipMagicNumber)
-
- /** If examineFile is true, it will look at the first four bytes of the file
- * and see if the magic number indicates it may be a jar or zip.
- */
- def isJarOrZip(f: Path): Boolean = isJarOrZip(f, true)
- def isJarOrZip(f: Path, examineFile: Boolean): Boolean =
- f.hasExtension("zip", "jar") || (examineFile && magicNumberIsZip(f))
+ def isJarOrZip(f: Path, examineFile: Boolean = true) = Jar.isJarOrZip(f, examineFile)
// not certain these won't be problematic, but looks good so far
implicit def string2path(s: String): Path = apply(s)
implicit def jfile2path(jfile: JFile): Path = apply(jfile)
- def locateJarByClass(clazz: Class[_]): Option[File] = {
- try Some(File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()))
- catch { case _: Exception => None }
- }
- /** Walks upward from wherever the scala library jar is searching for
- * the given jar name. This approach finds the scala library jar in the
- * release layout and in trunk builds going up from pack.
- */
- def locateJarByName(name: String): Option[File] = {
- def toSrc(d: Directory) = d.dirs.toList map (_ / name)
- def walk(d: Directory) = d.parents flatMap toSrc find (_.isFile) map (_.toFile)
-
- locateJarByClass(classOf[ScalaObject]) flatMap (x => walk(x.parent))
- }
-
// java 7 style, we don't use it yet
// object AccessMode extends Enumeration("AccessMode") {
// val EXECUTE, READ, WRITE = Value
diff --git a/src/compiler/scala/tools/nsc/io/Sources.scala b/src/compiler/scala/tools/nsc/io/Sources.scala
index 48682e4ad4..c763b04511 100644
--- a/src/compiler/scala/tools/nsc/io/Sources.scala
+++ b/src/compiler/scala/tools/nsc/io/Sources.scala
@@ -4,7 +4,7 @@ package io
import util.ClassPath
import java.util.concurrent.{ Future, ConcurrentHashMap, ExecutionException }
import java.util.zip.ZipException
-import Path.{ isJarOrZip, locateJarByName }
+import Jar.{ isJarOrZip, locateByClass }
import collection.JavaConverters._
import Properties.{ envOrElse, propOrElse }
@@ -62,7 +62,6 @@ trait LowPrioritySourcesImplicits {
implicit def fallbackSources: Sources = defaultSources
}
-
object Sources extends LowPrioritySourcesImplicits {
// Examples of what libraryJar might be, each of which we'd like to find
// the source files automatically:
@@ -70,7 +69,7 @@ object Sources extends LowPrioritySourcesImplicits {
// /scala/trunk/build/pack/lib/scala-library.jar
// /scala/trunk/build/quick/classes/library
// /scala/inst/scala-2.9.0.r24213-b20110206233447/lib/scala-library.jar
- private def libraryJar = Path.locateJarByClass(classOf[ScalaObject]) map (_.toAbsolute.path)
+ private def libraryJar = locateByClass(classOf[ScalaObject]) map (_.toAbsolute.path)
private def autoSourcePaths: List[String] = libraryJar.toList flatMap { lib =>
val markers = List("build/pack/lib", "build/quick/classes", "scala-library.jar")
markers filter (lib contains _) flatMap { m =>
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index 6a357cc08a..b485d4725a 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -527,10 +527,14 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
protected var v: String = default
def indexOfChoice: Int = choices indexOf value
- def tryToSet(args: List[String]) = { value = default ; Some(args) }
+ private def usageErrorMessage = {
+ "Usage: %s:<%s>\n where <%s> choices are %s (default: %s)\n".format(
+ name, helpArg, helpArg, choices mkString ", ", default)
+ }
+ def tryToSet(args: List[String]) = errorAndValue(usageErrorMessage, None)
override def tryToSetColon(args: List[String]) = args match {
- case Nil => errorAndValue("missing " + helpArg, None)
+ case Nil => errorAndValue(usageErrorMessage, None)
case List(x) if choices contains x => value = x ; Some(Nil)
case List(x) => errorAndValue("'" + x + "' is not a valid choice for '" + name + "'", None)
case xs => errorAndValue("'" + name + "' does not accept multiple arguments.", None)
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 1e29dd4fae..bb404480a9 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -83,6 +83,7 @@ object ClassPath {
/** Join the paths as a classpath */
def fromPaths(paths: Path*): String = join(paths map (_.path): _*)
+ def fromURLs(urls: URL*): String = fromPaths(urls map (x => Path(x.getPath)) : _*)
/** Split the classpath and map them into URLs */
def toURLs(cp: String): List[URL] = toPaths(cp) map (_.toURL)
diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
index ee71d04827..be69c39547 100644
--- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
+++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
@@ -93,13 +93,20 @@ object ScalaClassLoader {
with ScalaClassLoader {
private var classloaderURLs = urls.toList
+ private def classpathString = ClassPath.fromURLs(urls: _*)
/** Override to widen to public */
override def addURL(url: URL) = {
classloaderURLs +:= url
super.addURL(url)
}
-
+ override def run(objectName: String, arguments: Seq[String]) {
+ try super.run(objectName, arguments)
+ catch { case x: ClassNotFoundException =>
+ throw new ClassNotFoundException(objectName +
+ " (args = %s, classpath = %s)".format(arguments mkString ", ", classpathString))
+ }
+ }
override def toString = urls.mkString("URLClassLoader(\n ", "\n ", "\n)\n")
}