summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-02-01 08:27:18 +0000
committerPaul Phillips <paulp@improving.org>2011-02-01 08:27:18 +0000
commitee4e09235afa578a7a33267061179ca338e396c0 (patch)
tree52ff21a786e84f0a3c47ef5666746591301cc47c /src
parentd59d7f928d8a71d73d198690ab5816af3be90d6b (diff)
downloadscala-ee4e09235afa578a7a33267061179ca338e396c0.tar.gz
scala-ee4e09235afa578a7a33267061179ca338e396c0.tar.bz2
scala-ee4e09235afa578a7a33267061179ca338e396c0.zip
Eliminating duplication and trying to outrun ob...
Eliminating duplication and trying to outrun obsolescence in the exciting world of fsc. No review.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/CompileClient.scala42
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala47
-rw-r--r--src/compiler/scala/tools/nsc/CompileSocket.scala33
-rw-r--r--src/compiler/scala/tools/nsc/CompilerCommand.scala18
-rw-r--r--src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala19
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala46
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala7
-rw-r--r--src/compiler/scala/tools/util/SocketServer.scala31
8 files changed, 118 insertions, 125 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
index b15aab7714..41b96bfcdd 100644
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
@@ -14,8 +14,8 @@ import util.ClassPath
/** The client part of the fsc offline compiler. Instead of compiling
* things itself, it send requests to a CompileServer.
*/
-class StandardCompileClient {
- def compileSocket: CompileSocket = CompileSocket // todo: should be lazy val
+class StandardCompileClient extends CompileSocketShared {
+ lazy val compileSocket: CompileSocket = CompileSocket
val versionMsg = "Fast " + Properties.versionMsg
var verbose = false
@@ -85,37 +85,19 @@ class StandardCompileClient {
if (serverAdr == "") compileSocket.getOrCreateSocket(vmArgs, !shutdown)
else Some(compileSocket.getSocket(serverAdr))
- val sawerror: Boolean = socket match {
- case None =>
- val msg = if (shutdown) "[No compilation server running.]" else "Compilation failed."
- Console println msg
- !shutdown
-
- case Some(sock) =>
- var wasError = false
-
- sock.applyReaderAndWriter { (in, out) =>
- out println compileSocket.getPassword(sock.getPort())
- out println args.mkString("\0")
- def loop: Unit = in.readLine() match {
- case null => ()
- case fromServer =>
- if (compileSocket.errorPattern matcher fromServer matches)
- wasError = true
-
- Console println fromServer
- loop
- }
- loop
- }
- wasError
+ val success = socket match {
+ case Some(sock) => fscCompile(sock, args)
+ case _ =>
+ Console.println(
+ if (shutdown) "[No compilation server running.]" else "Compilation failed."
+ )
+ shutdown
}
- if (sawerror) 1 else 0
+ if (success) 1 else 0
}
+}
+object CompileClient extends StandardCompileClient {
def main(args: Array[String]): Unit =
sys.exit(try main0(args) catch { case e: Exception => 1 })
}
-
-
-object CompileClient extends StandardCompileClient
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index 8998b8065e..5296432519 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -21,7 +21,7 @@ import scala.tools.util.SocketServer
* @version 1.0
*/
class StandardCompileServer extends SocketServer {
- def compileSocket: CompileSocket = CompileSocket // todo: make this a lazy val
+ lazy val compileSocket: CompileSocket = CompileSocket
val versionMsg = "Fast Scala compiler " +
Properties.versionString + " -- " +
@@ -75,27 +75,25 @@ class StandardCompileServer extends SocketServer {
val guessedPassword = in.readLine()
val input = in.readLine()
+ def fscError(msg: String): Unit = out println (
+ FakePos("fsc"),
+ msg + "\n fsc -help gives more information"
+ )
if (input == null || password != guessedPassword)
return
val args = input.split("\0", -1).toList
- if (args contains "-shutdown") {
- out.println("[Compile server exited]")
+ val command = newOfflineCompilerCommand(args, new Settings(fscError))
+
+ if (command.fscShutdown.value) {
shutDown = true
- return
+ return out.println("[Compile server exited]")
}
- if (args contains "-reset") {
- out.println("[Compile server was reset]")
+ if (command.fscReset.value) {
compiler = null
- return
+ return out.println("[Compile server was reset]")
}
- def fscError(msg: String) {
- out.println(FakePos("fsc"), msg + "\n fsc -help gives more information")
- }
-
- val command = newOfflineCompilerCommand(args, new Settings(fscError))
-
reporter = new ConsoleReporter(command.settings, in, out) {
// disable prompts, so that compile server cannot block
override def displayPrompt = ()
@@ -112,7 +110,7 @@ class StandardCompileServer extends SocketServer {
compiler.reporter = reporter
}
else {
- if (args contains "-verbose") {
+ if (command.verbose) {
val reason = if (compiler == null) "compiler is null" else "settings not equal"
out.println("[Starting new compile server instance because %s]".format(reason))
}
@@ -124,14 +122,15 @@ class StandardCompileServer extends SocketServer {
}
catch {
case ex @ FatalError(msg) =>
- if (command.settings.debug.value)
- ex.printStackTrace(out);
- reporter.error(null, "fatal error: " + msg)
- compiler = null
+ if (command.debug)
+ ex.printStackTrace(out)
+
+ reporter.error(null, "fatal error: " + msg)
+ compiler = null
case ex: Throwable =>
ex.printStackTrace(out);
- reporter.error(null, "fatal error (server aborted): " + ex.getMessage())
- shutDown = true
+ reporter.error(null, "fatal error (server aborted): " + ex.getMessage())
+ shutDown = true
}
}
@@ -139,7 +138,10 @@ class StandardCompileServer extends SocketServer {
if (isMemoryFullEnough)
compiler = null
}
+}
+
+object CompileServer extends StandardCompileServer {
/** A directory holding redirected output */
private val redirectDir = (compileSocket.tmpDir / "output-redirects").createDirectory()
@@ -151,12 +153,11 @@ class StandardCompileServer extends SocketServer {
redirect(System.setErr, "scala-compile-server-err.log")
System.err.println("...starting server on socket "+port+"...")
System.err.flush()
+
compileSocket.setPort(port)
run()
+
compileSocket.deletePort(port)
exit(0)
}
}
-
-
-object CompileServer extends StandardCompileServer
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
index 19ba822231..1e4b37b3bc 100644
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
@@ -16,9 +16,33 @@ import scala.util.control.Exception.catching
import scala.tools.util.StringOps.splitWhere
import scala.sys.process._
+trait CompileSocketShared {
+ def compileSocket: CompileSocket
+ def fscCompile(sock: Socket, args: Seq[String]): Boolean = {
+ var noErrors = true
+
+ sock.applyReaderAndWriter { (in, out) =>
+ out println (compileSocket getPassword sock.getPort())
+ out println (args mkString "\0")
+
+ def loop(): Boolean = in.readLine() match {
+ case null => noErrors
+ case line =>
+ if (compileSocket.errorPattern matcher line matches)
+ noErrors = false
+
+ Console.err println line
+ loop()
+ }
+ try loop()
+ finally sock.close()
+ }
+ }
+}
+
/** This class manages sockets for the fsc offline compiler. */
class CompileSocket {
- protected def compileClient: StandardCompileClient = CompileClient //todo: lazy val
+ protected lazy val compileClient: StandardCompileClient = CompileClient
/** The prefix of the port identification file, which is followed
* by the port number.
@@ -141,9 +165,9 @@ class CompileSocket {
* cannot be established.
*/
def getOrCreateSocket(vmArgs: String, create: Boolean = true): Option[Socket] = {
- // try for 5 seconds
+ // try for 10 seconds
val retryDelay = 100
- val maxAttempts = (5 * 1000) / retryDelay
+ val maxAttempts = (10 * 1000) / retryDelay
def getsock(attempts: Int): Option[Socket] = attempts match {
case 0 => fscError("Unable to establish connection to compilation daemon") ; None
@@ -202,4 +226,5 @@ class CompileSocket {
}
-object CompileSocket extends CompileSocket
+object CompileSocket extends CompileSocket {
+}
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala
index 86579a4e94..2e3bc32007 100644
--- a/src/compiler/scala/tools/nsc/CompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala
@@ -17,17 +17,21 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
/** file extensions of files that the compiler can process */
lazy val fileEndings = Properties.fileEndings
+ val (ok, files) =
+ if (shouldProcessArguments) processArguments
+ else (true, Nil)
+
/** The name of the command */
def cmdName = "scalac"
- private val helpSyntaxColumnWidth: Int =
+ private def helpSyntaxColumnWidth: Int =
(settings.visibleSettings map (_.helpSyntax.length)) max
private def format(s: String): String =
if (s.length >= helpSyntaxColumnWidth) s
else s + (" " * (helpSyntaxColumnWidth - s.length))
- private val explainAdvanced = "\n" + """
+ private def explainAdvanced = "\n" + """
|-- Notes on option parsing --
|Boolean settings are always false unless set.
|Where multiple values are accepted, they should be comma-separated.
@@ -58,11 +62,7 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
}
/** Messages explaining usage and options */
- def usageMsg =
- if (cmdName == "fsc")
- createUsageMsg("where possible standard", false, st => st.isStandard || st.name == "-shutdown")
- else
- createUsageMsg("where possible standard", false, _.isStandard)
+ def usageMsg = createUsageMsg("where possible standard", false, _.isStandard)
def xusageMsg = createUsageMsg("Possible advanced", true, _.isAdvanced)
def yusageMsg = createUsageMsg("Possible private", true, _.isPrivate)
@@ -108,8 +108,4 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
settings.processArguments(expandedArguments, true)
}
-
- val (ok, files) =
- if (shouldProcessArguments) processArguments
- else (true, Nil)
}
diff --git a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
index 34ec62a6e5..c04ce45d6c 100644
--- a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
@@ -9,18 +9,19 @@ package scala.tools.nsc
*
* @author Martin Odersky and Lex Spoon
*/
-class OfflineCompilerCommand(
- arguments: List[String],
- settings: Settings)
-extends CompilerCommand(arguments, settings) {
- override val cmdName = "fsc"
+class OfflineCompilerCommand(arguments: List[String], _settings: Settings)
+ extends CompilerCommand(arguments, _settings)
+{
+ override def cmdName = "fsc"
import settings._
disable(prompt)
disable(resident)
- BooleanSetting("-reset", "Reset compile server caches")
- BooleanSetting("-shutdown", "Shutdown compile server")
- StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
- BooleanSetting("-J<flag>", "Pass <flag> directly to runtime system")
+ def verbose = settings.verbose.value
+ def debug = settings.debug.value
+
+ val fscReset = BooleanSetting("-reset", "Reset compile server caches")
+ val fscShutdown = BooleanSetting("-shutdown", "Shutdown compile server")
+ val fscServer = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
}
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index 0733254356..fcfb827089 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -47,7 +47,9 @@ import util.Exceptional.unwrap
* @todo It would be better if error output went to stderr instead
* of stdout...
*/
-object ScriptRunner {
+class ScriptRunner extends CompileSocketShared {
+ lazy val compileSocket = CompileSocket
+
/* While I'm chasing down the fsc and script bugs. */
def DBG(msg: Any) {
System.err.println(msg.toString)
@@ -124,38 +126,18 @@ object ScriptRunner {
}
/** Compile a script using the fsc compilation daemon.
- *
- * @param settings ...
- * @param scriptFileIn ...
- * @return ...
*/
- private def compileWithDaemon(
- settings: GenericRunnerSettings,
- scriptFileIn: String): Boolean =
- {
- val scriptFile = Path(scriptFileIn).toAbsolute.path
- val compSettingNames = new Settings(sys.error).visibleSettings.toList map (_.name)
- val compSettings = settings.visibleSettings.toList filter (compSettingNames contains _.name)
- val coreCompArgs = compSettings flatMap (_.unparse)
- val compArgs = coreCompArgs ::: List("-Xscript", scriptMain(settings), scriptFile)
- var compok = true
-
- val socket = CompileSocket getOrCreateSocket "" getOrElse (return false)
- socket.applyReaderAndWriter { (in, out) =>
- out println (CompileSocket getPassword socket.getPort)
- out println (compArgs mkString "\0")
-
- try {
- for (fromServer <- (Iterator continually in.readLine()) takeWhile (_ != null)) {
- Console.err println fromServer
- if (CompileSocket.errorPattern matcher fromServer matches)
- compok = false
- }
- }
- finally socket.close()
+ private def compileWithDaemon(settings: GenericRunnerSettings, scriptFileIn: String) = {
+ val scriptFile = Path(scriptFileIn).toAbsolute.path
+ val compSettingNames = new Settings(sys.error).visibleSettings.toList map (_.name)
+ val compSettings = settings.visibleSettings.toList filter (compSettingNames contains _.name)
+ val coreCompArgs = compSettings flatMap (_.unparse)
+ val compArgs = coreCompArgs ++ List("-Xscript", scriptMain(settings), scriptFile)
+
+ CompileSocket getOrCreateSocket "" match {
+ case Some(sock) => fscCompile(sock, compArgs)
+ case _ => false
}
-
- compok
}
protected def newGlobal(settings: Settings, reporter: Reporter) =
@@ -293,3 +275,5 @@ object ScriptRunner {
finally scriptFile.delete() // in case there was a compilation error
}
}
+
+object ScriptRunner extends ScriptRunner { } \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 8025254fc5..3539251a2c 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -23,6 +23,9 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
/** Disable a setting */
def disable(s: Setting) = allSettings -= s
+ BooleanSetting("-J<flag>", "Pass <flag> directly to runtime system")
+ BooleanSetting("-Dprop=value", "Pass -Dprop=value directly to runtime system")
+
/**
* Standard settings
*/
@@ -156,10 +159,6 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
val YpresentationLog = StringSetting("-Ypresentation-log", "file", "Log presentation compiler events into file", "")
val YpresentationReplay = StringSetting("-Ypresentation-replay", "file", "Replay presentation compiler events from file", "")
- /**
- * "fsc-specific" settings.
- */
- val fscShutdown = BooleanSetting ("-shutdown", "Shutdown the fsc daemon")
/**
* -P "Plugin" settings
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
index e9a837fb04..5f5cb28c4c 100644
--- a/src/compiler/scala/tools/util/SocketServer.scala
+++ b/src/compiler/scala/tools/util/SocketServer.scala
@@ -12,13 +12,7 @@ package scala.tools.util
import java.io.{ PrintWriter, BufferedOutputStream, BufferedReader, InputStreamReader, IOException }
import java.net.{ Socket, ServerSocket, SocketException, SocketTimeoutException }
-object SocketServer
-{
- // After 30 idle minutes, politely exit.
- // Should the port file disappear, and the clients
- // therefore unable to contact this server instance,
- // the process will just eventually terminate by itself.
- val IdleTimeout = 1800000
+object SocketServer {
val BufferSize = 10240
def bufferedReader(s: Socket) = new BufferedReader(new InputStreamReader(s.getInputStream()))
@@ -32,8 +26,19 @@ import SocketServer._
* @author Martin Odersky
* @version 1.0
*/
-abstract class SocketServer
-{
+abstract class SocketServer {
+ // After some number of idle minutes, politely exit.
+ // Should the port file disappear, and the clients
+ // therefore unable to contact this server instance,
+ // the process will just eventually terminate by itself.
+ def fscIdleMinutes = {
+ sys.props("scala.fsc.idle.minutes") match {
+ case null => 30
+ case str => try str.toInt catch { case _: Exception => 30 }
+ }
+ }
+ def fscIdleMillis = fscIdleMinutes * 60 * 1000
+
def shutDown: Boolean
def session()
@@ -75,9 +80,9 @@ abstract class SocketServer
def run() {
def fail(s: String) = fatal(s format port)
-
- try serverSocket setSoTimeout IdleTimeout catch {
- case e: SocketException => fail("Could not set timeout on port: %d; exiting.")
+ Console.println("Setting timeout to " + fscIdleMillis)
+ try serverSocket setSoTimeout fscIdleMillis catch {
+ case e: SocketException => fatal("Could not set timeout on server socket; exiting.")
}
try {
@@ -94,6 +99,6 @@ abstract class SocketServer
warn("Timeout elapsed with no requests from clients on port %d; exiting" format port)
timeout()
}
- serverSocket.close()
+ finally serverSocket.close()
}
}