summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-08-18 18:11:24 +0000
committerPaul Phillips <paulp@improving.org>2009-08-18 18:11:24 +0000
commit1d28a77bf349e8e03a0eb53da554959c80864220 (patch)
tree42a4c13621da73f601d284300e1831e7bcd2f1b9
parent917101fd0de9580e1fd18b69778022f01cb6d29d (diff)
downloadscala-1d28a77bf349e8e03a0eb53da554959c80864220.tar.gz
scala-1d28a77bf349e8e03a0eb53da554959c80864220.tar.bz2
scala-1d28a77bf349e8e03a0eb53da554959c80864220.zip
A bunch of cleanup on scriptrunner and fsc perf...
A bunch of cleanup on scriptrunner and fsc performed in a quest to fix #1889. I understand why #1889 happens now but I believe fixing it is going to require adjusting the logic in SymbolLoaders.
-rw-r--r--src/compiler/scala/tools/nsc/CompileSocket.scala93
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala449
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala9
-rw-r--r--src/compiler/scala/tools/nsc/io/PlainFile.scala6
-rw-r--r--src/compiler/scala/tools/util/SocketServer.scala10
-rw-r--r--src/library/scala/io/File.scala33
7 files changed, 283 insertions, 319 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
index 1a0fc7d877..42b91a59ad 100644
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
@@ -6,10 +6,8 @@
package scala.tools.nsc
-import java.lang.{Thread, System, Runtime}
-import java.lang.NumberFormatException
-import java.io.{File, IOException, PrintWriter, FileOutputStream}
-import java.io.{BufferedReader, FileReader}
+import java.io.{ File, IOException, FileNotFoundException, PrintWriter, FileOutputStream }
+import java.io.{ BufferedReader, FileReader }
import java.util.regex.Pattern
import java.net._
@@ -25,17 +23,13 @@ class CompileSocket {
protected def cmdName = Properties.cmdName //todo: lazy val
/** The vm part of the command to start a new scala compile server */
- protected val vmCommand =
- Properties.scalaHome match {
- case null =>
- cmdName
- case dirname =>
- val trial = new File(new File(dirname, "bin"), cmdName)
- if (trial.canRead)
- trial.getPath
- else
- cmdName
- }
+ protected val vmCommand = Properties.scalaHome match {
+ case null => cmdName
+ case dirname =>
+ val trial = scala.io.File(dirname) / "bin" / cmdName
+ if (trial.canRead) trial.path
+ else cmdName
+ }
/** The class name of the scala compile server */
protected val serverClass = "scala.tools.nsc.CompileServer"
@@ -44,7 +38,7 @@ class CompileSocket {
val errorRegex = ".*(errors? found|don't know|bad option).*"
/** A Pattern object for checking compiler output for errors */
- val errorPattern = Pattern.compile(errorRegex)
+ val errorPattern = Pattern compile errorRegex
protected def error(msg: String) = System.err.println(msg)
@@ -144,14 +138,12 @@ class CompileSocket {
/** Set the port number to which a scala compile server is connected */
def setPort(port: Int) {
- try {
- val f = new PrintWriter(new FileOutputStream(portFile(port)))
- f.println(new java.security.SecureRandom().nextInt.toString)
- f.close()
- } catch {
- case ex: /*FileNotFound+Security*/Exception =>
- fatal("Cannot create file: " +
- portFile(port).getAbsolutePath())
+ val file = scala.io.File(portFile(port))
+ val secret = new java.security.SecureRandom().nextInt.toString
+
+ try file writeAll List(secret) catch {
+ case e @ (_: FileNotFoundException | _: SecurityException) =>
+ fatal("Cannot create file: %s".format(file.absolutePath))
}
}
@@ -162,7 +154,7 @@ class CompileSocket {
* create a new daemon if necessary. Returns null if the connection
* cannot be established.
*/
- def getOrCreateSocket(vmArgs: String, create: Boolean): Socket = {
+ def getOrCreateSocket(vmArgs: String, create: Boolean = true): Socket = {
val nAttempts = 49 // try for about 5 seconds
def getsock(attempts: Int): Socket =
if (attempts == 0) {
@@ -193,45 +185,40 @@ class CompileSocket {
getsock(nAttempts)
}
- /** Same as getOrCreateSocket(vmArgs, true). */
- def getOrCreateSocket(vmArgs: String): Socket =
- getOrCreateSocket(vmArgs, true)
+ // XXX way past time for this to be central
+ def parseInt(x: String): Option[Int] =
+ try { Some(x.toInt) }
+ catch { case _: NumberFormatException => None }
def getSocket(serverAdr: String): Socket = {
- val cpos = serverAdr indexOf ':'
- if (cpos < 0)
- fatal("Malformed server address: " + serverAdr + "; exiting")
- else {
- val hostName = serverAdr.substring(0, cpos)
- val port = try {
- serverAdr.substring(cpos+1).toInt
- } catch {
- case ex: Throwable =>
- fatal("Malformed server address: " + serverAdr + "; exiting")
- }
- getSocket(hostName, port)
+ def fail = fatal("Malformed server address: %s; exiting" format serverAdr)
+ (serverAdr indexOf ':') match {
+ case -1 => fail
+ case cpos =>
+ val hostName: String = serverAdr take cpos
+ parseInt(serverAdr drop (cpos + 1)) match {
+ case Some(port) => getSocket(hostName, port)
+ case _ => fail
+ }
}
}
def getSocket(hostName: String, port: Int): Socket =
- try {
- new Socket(hostName, port)
- } catch {
- case e: /*IO+Security*/Exception =>
- fatal("Unable to establish connection to server " +
- hostName + ":" + port + "; exiting")
+ try new Socket(hostName, port) catch {
+ case e @ (_: IOException | _: SecurityException) =>
+ fatal("Unable to establish connection to server %s:%d; exiting".format(hostName, port))
}
def getPassword(port: Int): String = {
- val ff = portFile(port)
- val f = new BufferedReader(new FileReader(ff))
+ val ff = scala.io.File(portFile(port))
+ val f = ff.bufferedReader()
+
// allow some time for the server to start up
- var retry = 50
- while (ff.length() == 0 && retry > 0) {
- Thread.sleep(100)
- retry -= 1
+ def check = {
+ Thread sleep 100
+ ff.file.length()
}
- if (ff.length() == 0) {
+ if (Iterator continually check take 50 find (_ > 0) isEmpty) {
ff.delete()
fatal("Unable to establish connection to server.")
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 1f2c0a21aa..315d09d54f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -268,7 +268,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
if (forMSIL) inform("[AssemRefs = " + settings.assemrefs.value + "]")
}
- def getSourceFile(f: AbstractFile): SourceFile =
+ def getSourceFile(f: AbstractFile): BatchSourceFile =
new BatchSourceFile(f, reader.read(f))
def getSourceFile(name: String): SourceFile = {
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index e31dcd38f9..0a7b0aeeec 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -6,12 +6,19 @@
package scala.tools.nsc
-import java.io.{BufferedReader, File, FileInputStream, FileOutputStream,
- FileReader, InputStreamReader, PrintWriter,
- FileWriter, IOException}
+import java.io.{
+ InputStream, OutputStream,
+ BufferedReader, FileInputStream, FileOutputStream,
+ FileReader, InputStreamReader, PrintWriter, FileWriter,
+ IOException
+}
+import scala.io.File
+// import scala.io.arm.ManagedResource
+import java.io.{ File => JFile }
import java.lang.reflect.InvocationTargetException
import java.net.URL
-import java.util.jar.{JarEntry, JarOutputStream}
+import java.util.jar.{ JarEntry, JarOutputStream }
+import java.util.regex.Pattern
import scala.tools.nsc.io.PlainFile
import scala.tools.nsc.reporters.{Reporter,ConsoleReporter}
@@ -43,136 +50,123 @@ import scala.tools.nsc.util.{ClassPath, CompoundSourceFile, BatchSourceFile, Sou
* @todo It would be better if error output went to stderr instead
* of stdout...
*/
-object ScriptRunner {
+object ScriptRunner
+{
+ /* While I'm chasing down the fsc and script bugs. */
+ def DBG(msg: Any) {
+ System.err.println(msg.toString)
+ System.err.flush()
+ }
+
/** Default name to use for the wrapped script */
val defaultScriptMain = "Main"
+ private def addShutdownHook(body: => Unit) =
+ Runtime.getRuntime addShutdownHook new Thread { override def run { body } }
+
/** Pick a main object name from the specified settings */
- def scriptMain(settings: Settings) =
- if (settings.script.value == "")
- defaultScriptMain
- else
- settings.script.value
-
- /** Choose a jar filename to hold the compiled version
- * of a script
- */
- private def jarFileFor(scriptFile: String): File = {
- val filename =
- if (scriptFile.matches(".*\\.[^.\\\\/]*"))
- scriptFile.replaceFirst("\\.[^.\\\\/]*$", ".jar")
- else
- scriptFile + ".jar"
-
- new File(filename)
+ def scriptMain(settings: Settings) = settings.script.value match {
+ case "" => defaultScriptMain
+ case x => x
+ }
+
+ /** Choose a jar filename to hold the compiled version of a script. */
+ private def jarFileFor(scriptFile: String): JFile = {
+ val name =
+ if (scriptFile endsWith ".jar") scriptFile
+ else scriptFile + ".jar"
+
+ File(name).file
+ }
+
+ def copyStreams(in: InputStream, out: OutputStream) = {
+ val buf = new Array[Byte](10240)
+
+ def loop: Unit = in.read(buf, 0, buf.length) match {
+ case -1 => in.close()
+ case n => out.write(buf, 0, n) ; loop
+ }
+
+ loop
}
/** Try to create a jar file out of all the contents
* of the directory <code>sourcePath</code>.
*/
- private def tryMakeJar(jarFile: File, sourcePath: File) = {
- try {
- val jarFileStream = new FileOutputStream(jarFile)
- val jar = new JarOutputStream(jarFileStream)
- val buf = new Array[Byte](10240)
-
- def addFromDir(dir: File, prefix: String) {
- for (entry <- dir.listFiles) {
- if (entry.isFile) {
- jar.putNextEntry(new JarEntry(prefix + entry.getName))
-
- val input = new FileInputStream(entry)
- var n = input.read(buf, 0, buf.length)
- while (n >= 0) {
- jar.write (buf, 0, n)
- n = input.read(buf, 0, buf.length)
- }
- jar.closeEntry
- input.close
- } else {
- addFromDir(entry, prefix + entry.getName + "/")
- }
- }
+ private def tryMakeJar(jarFile: JFile, sourcePath: JFile) = {
+ def addFromDir(jar: JarOutputStream, dir: JFile, prefix: String) {
+ def addFileToJar(entry: JFile) = {
+ jar putNextEntry new JarEntry(prefix + entry.getName)
+ copyStreams(new FileInputStream(entry), jar)
+ jar.closeEntry
}
- addFromDir(sourcePath, "")
+ dir.listFiles foreach { entry =>
+ if (entry.isFile) addFileToJar(entry)
+ else addFromDir(jar, entry, prefix + entry.getName + "/")
+ }
+ }
+
+ try {
+ val jar = new JarOutputStream(File(jarFile).outputStream())
+ addFromDir(jar, sourcePath, "")
jar.close
- } catch {
- case _:Error => jarFile.delete // XXX what errors to catch?
+ }
+ catch {
+ case _: Error => jarFile.delete() // XXX what errors to catch?
}
}
-
/** Read the entire contents of a file as a String. */
- private def contentsOfFile(filename: String): String = {
- val strbuf = new StringBuilder
- val reader = new FileReader(filename)
- val cbuf = new Array[Char](1024)
- while(true) {
- val n = reader.read(cbuf)
- if (n <= 0)
- return strbuf.toString
- strbuf.append(cbuf, 0, n)
- }
- throw new Error("impossible")
- }
+ private def contentsOfFile(filename: String) = File(filename).toSource().mkString
/** Find the length of the header in the specified file, if
* there is one. The header part starts with "#!" or "::#!"
* and ends with a line that begins with "!#" or "::!#".
*/
private def headerLength(filename: String): Int = {
- import java.util.regex._
-
+ val headerPattern = Pattern.compile("""^(::)?!#.*(\r|\n|\r\n)""", Pattern.MULTILINE)
val fileContents = contentsOfFile(filename)
+ def isValid = List("#!", "::#!") exists (fileContents startsWith _)
- if (!(fileContents.startsWith("#!") || fileContents.startsWith("::#!")))
- return 0
-
- val matcher =
- (Pattern.compile("^(::)?!#.*(\\r|\\n|\\r\\n)", Pattern.MULTILINE)
- .matcher(fileContents))
- if (!matcher.find)
- throw new IOException("script file does not close its header with !# or ::!#")
- return matcher.end
+ if (!isValid) 0 else {
+ val matcher = headerPattern matcher fileContents
+ if (matcher.find) matcher.end
+ else throw new IOException("script file does not close its header with !# or ::!#")
+ }
}
/** Split a fully qualified object name into a
* package and an unqualified object name */
- private def splitObjectName(fullname: String):
- (Option[String],String) =
- {
- val idx = fullname.lastIndexOf('.')
- if (idx < 0)
- (None, fullname)
- else
- (Some(fullname.substring(0,idx)), fullname.substring(idx+1))
- }
+ private def splitObjectName(fullname: String): (Option[String], String) =
+ (fullname lastIndexOf '.') match {
+ case -1 => (None, fullname)
+ case idx => (Some(fullname take idx), fullname drop (idx + 1))
+ }
/** Code that is added to the beginning of a script file to make
* it a complete Scala compilation unit.
*/
- protected def preambleCode(objectName: String) = {
- val (maybePack, objName) = splitObjectName(objectName)
-
- val packageDecl =
- maybePack match {
- case Some(pack) => "package " + pack + "\n"
- case None => ""
- }
-
- (packageDecl +
- "object " + objName + " {\n" +
- " def main(argv: Array[String]): Unit = {\n" +
- " val args = argv;\n" +
- " new AnyRef {\n")
+ protected def preambleCode(objectName: String): String = {
+ val (maybePack, objName) = splitObjectName(objectName)
+ val packageDecl = maybePack map ("package %s\n" format _) getOrElse ("")
+
+ return """|
+ | object %s {
+ | def main(argv: Array[String]): Unit = {
+ | val args = argv
+ | new AnyRef {
+ |""".stripMargin.format(objName)
}
/** Code that is added to the end of a script file to make
* it a complete Scala compilation unit.
*/
- val endCode = "\n} \n} }\n"
-
+ val endCode = """
+ | }
+ | }
+ | }
+ |""".stripMargin
/** Wrap a script file into a runnable object named
* <code>scala.scripting.Main</code>.
@@ -180,20 +174,12 @@ object ScriptRunner {
def wrappedScript(
objectName: String,
filename: String,
- getSourceFile: PlainFile => SourceFile): SourceFile =
+ getSourceFile: PlainFile => BatchSourceFile): SourceFile =
{
- val preamble =
- new BatchSourceFile("<script preamble>",
- preambleCode(objectName).toCharArray)
-
+ val preamble = new BatchSourceFile("<script preamble>", preambleCode(objectName).toCharArray)
val middle = {
- val f = new File(filename)
- val bsf = getSourceFile(new PlainFile(f)).asInstanceOf[BatchSourceFile]
- new SourceFileFragment(
- bsf,
- headerLength(filename),
- bsf.length)
-// f.length.asInstanceOf[Int])
+ val bsf = getSourceFile(PlainFile fromPath filename)
+ new SourceFileFragment(bsf, headerLength(filename), bsf.length)
}
val end = new BatchSourceFile("<script trailer>", endCode.toCharArray)
@@ -210,53 +196,42 @@ object ScriptRunner {
settings: GenericRunnerSettings,
scriptFileIn: String): Boolean =
{
- val scriptFile = CompileClient.absFileName(scriptFileIn)
- for (setting <- List(
- settings.classpath,
- settings.sourcepath,
- settings.bootclasspath,
- settings.extdirs,
- settings.outdir))
- setting.value = CompileClient.absFileNames(setting.value)
-
- val compSettingNames =
- (new Settings(error)).allSettings.map(_.name)
-
- val compSettings =
- settings.allSettings.filter(stg =>
- compSettingNames.contains(stg.name))
-
- val coreCompArgs =
- compSettings.foldLeft[List[String]](Nil)((args, stg) =>
- stg.unparse ::: args)
-
- val compArgs =
- (coreCompArgs :::
- List("-Xscript", scriptMain(settings), scriptFile))
-
- val socket = CompileSocket.getOrCreateSocket("")
- if (socket eq null)
- return false
-
- val out = new PrintWriter(socket.getOutputStream(), true)
- val in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
+ val scriptFile = CompileClient absFileName scriptFileIn
- out.println(CompileSocket.getPassword(socket.getPort))
- out.println(compArgs.mkString("", "\0", ""))
-
- var compok = true
-
- var fromServer = in.readLine()
- while (fromServer ne null) {
- Console.err.println(fromServer)
- if (CompileSocket.errorPattern.matcher(fromServer).matches)
- compok = false
+ {
+ import settings._
+ for (setting <- List(classpath, sourcepath, bootclasspath, extdirs, outdir)) {
+ // DBG("%s = %s".format(setting.name, setting.value))
+ setting.value = CompileClient absFileName setting.value
+ }
+ }
- fromServer = in.readLine()
+ val compSettingNames = new Settings(error).allSettings map (_.name)
+ val compSettings = settings.allSettings filter (compSettingNames contains _.name)
+ val coreCompArgs = compSettings flatMap (_.unparse)
+ val compArgs = coreCompArgs ::: List("-Xscript", scriptMain(settings), scriptFile)
+ var compok = true
+
+ // XXX temporary as I started using ManagedResource not remembering it wasn't checked in.
+ def ManagedResource[T](x: => T) = Some(x)
+
+ for {
+ socket <- ManagedResource(CompileSocket getOrCreateSocket "")
+ val _ = if (socket == null) return false
+ out <- ManagedResource(new PrintWriter(socket.getOutputStream(), true))
+ in <- ManagedResource(new BufferedReader(new InputStreamReader(socket.getInputStream())))
+ } {
+ out println (CompileSocket getPassword socket.getPort)
+ out println (compArgs mkString "\0")
+
+ for (fromServer <- (Iterator continually in.readLine()) takeWhile (_ != null)) {
+ Console.err println fromServer
+ if (CompileSocket.errorPattern matcher fromServer matches)
+ compok = false
+ }
+ // XXX temp until managed resource is available
+ in.close() ; out.close() ; socket.close()
}
- in.close()
- out.close()
- socket.close()
compok
}
@@ -269,101 +244,82 @@ object ScriptRunner {
*
* @returns true if compilation and the handler succeeds, false otherwise.
*/
- private def withCompiledScript
- (settings: GenericRunnerSettings, scriptFile: String)
- (handler: String => Boolean)
- : Boolean = {
+ private def withCompiledScript(
+ settings: GenericRunnerSettings,
+ scriptFile: String)
+ (handler: String => Boolean): Boolean =
+ {
import Interpreter.deleteRecursively
- /** Compiles the script file, and returns
- * the directory with the compiled class files,
- * if the compilation succeeded.
- */
- def compile: Option[File] = {
- val compiledPath = File.createTempFile("scalascript", "")
- compiledPath.delete // the file is created as a file; make it a directory
- compiledPath.mkdirs
+ /** Compiles the script file, and returns the directory with the compiled
+ * class files, if the compilation succeeded.
+ */
+ def compile: Option[JFile] = {
+ val compiledPath = File tempdir "scalascript"
// delete the directory after the user code has finished
- Runtime.getRuntime.addShutdownHook(new Thread {
- override def run { deleteRecursively(compiledPath) }})
+ addShutdownHook(deleteRecursively(compiledPath.file))
- settings.outdir.value = compiledPath.getPath
+ settings.outdir.value = compiledPath.path
if (settings.nocompdaemon.value) {
val reporter = new ConsoleReporter(settings)
val compiler = newGlobal(settings, reporter)
val cr = new compiler.Run
- val wrapped =
- wrappedScript(
- scriptMain(settings),
- scriptFile,
- compiler.getSourceFile _)
- cr.compileSources(List(wrapped))
- if (!reporter.hasErrors)
- Some(compiledPath)
- else
- None
- } else {
- if (compileWithDaemon(settings, scriptFile))
- Some(compiledPath)
- else
- None
+ val wrapped = wrappedScript(scriptMain(settings), scriptFile, compiler getSourceFile _)
+
+ cr compileSources List(wrapped)
+ if (reporter.hasErrors) None else Some(compiledPath.file)
}
+ else if (compileWithDaemon(settings, scriptFile)) Some(compiledPath.file)
+ else None
}
if (settings.savecompiled.value) {
- val jarFile = jarFileFor(scriptFile)
-
- def jarOK = (jarFile.canRead &&
- (jarFile.lastModified > new File(scriptFile).lastModified))
+ val jarFile = File(jarFileFor(scriptFile))
+ def jarOK = jarFile.canRead && (jarFile isFresher File(scriptFile))
- if (jarOK) {
- // pre-compiled jar is current
- handler(jarFile.getAbsolutePath)
- } else {
- // The pre-compiled jar is old. Recompile the script.
+ def recompile() = {
jarFile.delete
compile match {
case Some(compiledPath) =>
- tryMakeJar(jarFile, compiledPath)
+ tryMakeJar(jarFile.file, compiledPath)
if (jarOK) {
- deleteRecursively(compiledPath) // may as well do it now
- handler(jarFile.getAbsolutePath)
- } else {
- // jar failed; run directly from the class files
- handler(compiledPath.getPath)
+ deleteRecursively(compiledPath)
+ handler(jarFile.absolutePath)
}
- case None => false
+ // jar failed; run directly from the class files
+ else handler(compiledPath.getPath)
+ case _ => false
}
}
- } else {
- // don't use a cache jar at all--just use the class files
- compile match {
- case Some(compiledPath) => handler(compiledPath.getPath)
- case None => false
- }
+
+ if (jarOK) handler(jarFile.absolutePath) // pre-compiled jar is current
+ else recompile() // jar old - recompile the script.
}
+ // don't use a cache jar at all--just use the class files
+ else compile map (cp => handler(cp.getPath)) getOrElse false
}
-
/** Run a script after it has been compiled
*
* @returns true if execution succeeded, false otherwise
*/
- private def runCompiled(settings: GenericRunnerSettings,
- compiledLocation: String,
- scriptArgs: List[String]) : Boolean = {
- def fileToURL(f: File): Option[URL] =
- try { Some(f.toURL) }
- catch { case e => Console.err.println(e); None }
+ private def runCompiled(
+ settings: GenericRunnerSettings,
+ compiledLocation: String,
+ scriptArgs: List[String]): Boolean =
+ {
+ def fileToURL(f: JFile): Option[URL] =
+ try Some(f.toURL) catch { case _: Exception => None }
def paths(str: String, expandStar: Boolean): List[URL] =
- for (
- file <- ClassPath.expandPath(str, expandStar) map (new File(_)) if file.exists;
- val url = fileToURL(file); if !url.isEmpty
- ) yield url.get
+ for {
+ file <- ClassPath.expandPath(str, expandStar) map (new JFile(_))
+ if file.exists
+ url <- fileToURL(file)
+ } yield url
val classpath =
(paths(settings.bootclasspath.value, true) :::
@@ -376,64 +332,47 @@ object ScriptRunner {
scriptMain(settings),
scriptArgs.toArray)
true
- } catch {
- case e: ClassNotFoundException =>
- Console.println(e)
- false
- case e: NoSuchMethodException =>
- Console.println(e)
+ }
+ catch {
+ case e @ (_: ClassNotFoundException | _: NoSuchMethodException) =>
+ Console println e
false
- case e:InvocationTargetException =>
+ case e: InvocationTargetException =>
e.getCause.printStackTrace
false
}
}
-
/** Run a script file with the specified arguments and compilation
* settings.
*
* @returns true if compilation and execution succeeded, false otherwise.
*/
- def runScript(settings: GenericRunnerSettings,
+ def runScript(
+ settings: GenericRunnerSettings,
scriptFile: String,
- scriptArgs: List[String]) : Boolean = {
- val f = new File(scriptFile)
- if (!f.isFile) {
- throw new IOException("no such file: " + scriptFile)
- } else {
- try {
- withCompiledScript(settings, scriptFile){compiledLocation =>
- runCompiled(settings, compiledLocation, scriptArgs)
- }
- } catch {
- case e => throw e
- }
- }
+ scriptArgs: List[String]): Boolean =
+ {
+ if (File(scriptFile).isFile)
+ withCompiledScript(settings, scriptFile) { runCompiled(settings, _, scriptArgs) }
+ else
+ throw new IOException("no such file: " + scriptFile)
}
/** Run a command
*
* @returns true if compilation and execution succeeded, false otherwise.
*/
- def runCommand(settings: GenericRunnerSettings,
- command: String,
- scriptArgs: List[String]) : Boolean = {
- val scriptFile = File.createTempFile("scalacmd", ".scala")
-
+ def runCommand(
+ settings: GenericRunnerSettings,
+ command: String,
+ scriptArgs: List[String]) : Boolean =
+ {
+ val scriptFile = File.tempfile("scalacmd", ".scala")
// save the command to the file
- {
- val str = new FileWriter(scriptFile)
- str.write(command)
- str.close()
- }
+ scriptFile writeAll List(command)
- try {
- withCompiledScript(settings, scriptFile.getPath){compiledLocation =>
- runCompiled(settings, compiledLocation, scriptArgs)
- }
- } catch {
- case e => throw e
- } finally scriptFile.delete() // in case there was a compilation error
+ try withCompiledScript(settings, scriptFile.path) { runCompiled(settings, _, scriptArgs) }
+ finally scriptFile.delete() // in case there was a compilation error
}
}
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index d99644303d..af0e0293fe 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -25,8 +25,9 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
protected def classpathDefault =
syspropopt("env.classpath") orElse syspropopt("java.class.path") getOrElse ""
- protected def bootclasspathDefault =
- concatPath(syspropopt("sun.boot.class.path"), guessedScalaBootClassPath)
+ protected def bootclasspathDefault = syspropopt("sun.boot.class.path") getOrElse ""
+ // XXX scala-library.jar was being added to both boot and regular classpath until 8/18/09
+ // concatPath(syspropopt("sun.boot.class.path"), guessedScalaBootClassPath)
protected def extdirsDefault =
concatPath(syspropopt("java.ext.dirs"), guessedScalaExtDirs)
@@ -216,6 +217,9 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
lazy val PhasesSetting = untupled(tupled(phase _) andThen add[PhasesSetting])
lazy val DefinesSetting = add(defines())
lazy val OutputSetting = untupled(tupled(output _) andThen add[OutputSetting])
+
+ override def toString() =
+ "Settings(\n%s)" format (settingSet filter (s => !s.isDefault) map (" " + _ + "\n") mkString)
}
object Settings {
@@ -403,6 +407,7 @@ object Settings {
def eqValues: List[Any] = List(name, value)
def isEq(other: Setting) = eqValues == other.eqValues
override def hashCode() = name.hashCode
+ override def toString() = "%s = %s".format(name, value)
}
/** A setting represented by a positive integer */
diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala
index a52ec203dc..23082f92fb 100644
--- a/src/compiler/scala/tools/nsc/io/PlainFile.scala
+++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala
@@ -10,14 +10,16 @@ package io
import java.io.{File, FileInputStream, FileOutputStream, IOException}
-object PlainFile {
+object PlainFile
+{
/**
* If the specified File exists, returns an abstract file backed
* by it. Otherwise, returns null.
*/
- def fromFile(file: File): AbstractFile =
+ def fromFile(file: File): PlainFile =
if (file.exists()) new PlainFile(file) else null
+ def fromPath(path: String): PlainFile = fromFile(new File(path))
}
/** This class implements an abstract file backed by a File.
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
index 79c081bdc8..1a1815f02a 100644
--- a/src/compiler/scala/tools/util/SocketServer.scala
+++ b/src/compiler/scala/tools/util/SocketServer.scala
@@ -45,12 +45,10 @@ abstract class SocketServer {
// some cleanup, if any
def timeout() {}
- val serverSocket = try {
- new ServerSocket(0)
- } catch {
- case e: IOException =>
- fatal("Could not listen on any port; exiting.")
- }
+ val serverSocket =
+ try new ServerSocket(0)
+ catch { case e: IOException => fatal("Could not listen on any port; exiting.") }
+
val port: Int = serverSocket.getLocalPort()
def run() {
diff --git a/src/library/scala/io/File.scala b/src/library/scala/io/File.scala
index 6c15152921..6cc37d3825 100644
--- a/src/library/scala/io/File.scala
+++ b/src/library/scala/io/File.scala
@@ -22,6 +22,29 @@ object File
def apply(fileName: String) = new File(new JFile(fileName))
def apply(file: JFile) = new File(file)
+
+ private def randomPrefix = {
+ import scala.util.Random.nextInt
+ import Character.isJavaIdentifierPart
+
+ (Iterator continually nextInt)
+ . map (x => ((x % 60) + 'A').toChar)
+ . filter (isJavaIdentifierPart)
+ . take (6)
+ . mkString
+ }
+ // Create a temporary file
+ def tempfile(prefix: String = randomPrefix, suffix: String = null, dir: JFile = null) =
+ apply(JFile.createTempFile(prefix, suffix, dir))
+
+ // Like tempfile but creates a directory instead
+ def tempdir(prefix: String = randomPrefix, suffix: String = null, dir: JFile = null) = {
+ val file = tempfile(prefix, suffix, dir)
+ file.delete()
+ file.mkdirs()
+ file
+ }
+
}
import File._
@@ -33,6 +56,16 @@ import File._
*/
class File(val file: JFile)(implicit val codec: Codec = Codec.default) extends collection.Iterable[File]
{
+ def path = file.getPath()
+ def absolutePath = file.getAbsolutePath()
+ def delete() = file.delete()
+ def mkdirs() = file.mkdirs()
+ def isFile = file.isFile()
+ def canRead = file.canRead()
+ def canWrite = file.canWrite()
+
+ def isFresher(other: File) = file.lastModified > other.file.lastModified
+
/** If file is a directory, an iterator over its contents.
* If not, an empty iterator.
*/