Some 11th hour modifications with the dual purpose of a smooth
console life for sbt and so the repl can be used on google app engine. Although this patch may look largish to be entering at RC4, there isn't a lot going on. It's trying to make these dangerous things: - property and environment variable accesses - thread creation - signal handler installation happpen in a sufficiently uniform way that people who don't want them and places who don't allow them are not left with an unfixable situation where things blow up inside private methods. Also, the (ahem) lower than usual elegance levels are due to it being intended for 2.9.x as well. Review by harrah. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@25549 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
c8630fa0da
commit
a978f24ba3
|
@ -119,7 +119,6 @@ abstract class SymbolTable extends api.Universe
|
||||||
|
|
||||||
object perRunCaches {
|
object perRunCaches {
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import scala.tools.util.Signallable
|
|
||||||
import scala.runtime.ScalaRunTime.stringOf
|
import scala.runtime.ScalaRunTime.stringOf
|
||||||
|
|
||||||
// We can allow ourselves a structural type, these methods
|
// We can allow ourselves a structural type, these methods
|
||||||
|
@ -143,9 +142,9 @@ abstract class SymbolTable extends api.Universe
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (settings.debug.value) {
|
// if (settings.debug.value) {
|
||||||
println(Signallable("dump compiler caches")(dumpCaches()))
|
// println(Signallable("dump compiler caches")(dumpCaches()))
|
||||||
}
|
// }
|
||||||
|
|
||||||
def recordCache[T <: Clearable](cache: T): T = {
|
def recordCache[T <: Clearable](cache: T): T = {
|
||||||
caches += new WeakReference(cache)
|
caches += new WeakReference(cache)
|
||||||
|
|
|
@ -66,7 +66,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
|
||||||
|
|
||||||
// Install a signal handler so we can be prodded.
|
// Install a signal handler so we can be prodded.
|
||||||
private val signallable =
|
private val signallable =
|
||||||
if (isReplDebug) Signallable("Dump repl state.")(dumpCommand())
|
if (isReplDebug && !settings.Yreplsync.value)
|
||||||
|
Signallable("Dump repl state.")(dumpCommand())
|
||||||
else null
|
else null
|
||||||
|
|
||||||
// classpath entries added via :cp
|
// classpath entries added via :cp
|
||||||
|
@ -95,19 +96,21 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
|
||||||
override lazy val formatting = new Formatting {
|
override lazy val formatting = new Formatting {
|
||||||
def prompt = ILoop.this.prompt
|
def prompt = ILoop.this.prompt
|
||||||
}
|
}
|
||||||
override protected def createLineManager() = new Line.Manager {
|
override protected def createLineManager(): Line.Manager =
|
||||||
override def onRunaway(line: Line[_]): Unit = {
|
if (ReplPropsKludge.noThreadCreation(settings)) null else new Line.Manager {
|
||||||
val template = """
|
override def onRunaway(line: Line[_]): Unit = {
|
||||||
|// She's gone rogue, captain! Have to take her out!
|
val template = """
|
||||||
|// Calling Thread.stop on runaway %s with offending code:
|
|// She's gone rogue, captain! Have to take her out!
|
||||||
|// scala> %s""".stripMargin
|
|// Calling Thread.stop on runaway %s with offending code:
|
||||||
|
|// scala> %s""".stripMargin
|
||||||
|
|
||||||
echo(template.format(line.thread, line.code))
|
echo(template.format(line.thread, line.code))
|
||||||
// XXX no way to suppress the deprecation warning
|
// XXX no way to suppress the deprecation warning
|
||||||
line.thread.stop()
|
line.thread.stop()
|
||||||
in.redrawLine()
|
in.redrawLine()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
override protected def parentClassLoader =
|
override protected def parentClassLoader =
|
||||||
settings.explicitParentLoader.getOrElse( classOf[ILoop].getClassLoader )
|
settings.explicitParentLoader.getOrElse( classOf[ILoop].getClassLoader )
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ trait ILoopInit {
|
||||||
}
|
}
|
||||||
ignoring(classOf[Exception]) {
|
ignoring(classOf[Exception]) {
|
||||||
SignalManager("INT") = {
|
SignalManager("INT") = {
|
||||||
if (intp == null)
|
if (intp == null || intp.lineManager == null)
|
||||||
onExit()
|
onExit()
|
||||||
else if (intp.lineManager.running)
|
else if (intp.lineManager.running)
|
||||||
intp.lineManager.cancel()
|
intp.lineManager.cancel()
|
||||||
|
|
|
@ -62,7 +62,7 @@ import IMain._
|
||||||
*/
|
*/
|
||||||
class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports {
|
class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports {
|
||||||
imain =>
|
imain =>
|
||||||
|
|
||||||
private var currentSettings: Settings = initialSettings
|
private var currentSettings: Settings = initialSettings
|
||||||
def settings = currentSettings
|
def settings = currentSettings
|
||||||
def savingSettings[T](fn: Settings => Unit)(body: => T): T = {
|
def savingSettings[T](fn: Settings => Unit)(body: => T): T = {
|
||||||
|
@ -265,7 +265,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
|
||||||
|
|
||||||
/** Create a line manager. Overridable. */
|
/** Create a line manager. Overridable. */
|
||||||
protected def createLineManager(): Line.Manager =
|
protected def createLineManager(): Line.Manager =
|
||||||
if (replProps.noThreads) null else new Line.Manager
|
if (ReplPropsKludge.noThreadCreation(settings)) null else new Line.Manager
|
||||||
|
|
||||||
/** Instantiate a compiler. Overridable. */
|
/** Instantiate a compiler. Overridable. */
|
||||||
protected def newCompiler(settings: Settings, reporter: Reporter) = {
|
protected def newCompiler(settings: Settings, reporter: Reporter) = {
|
||||||
|
@ -967,7 +967,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
|
||||||
|
|
||||||
/** load and run the code using reflection */
|
/** load and run the code using reflection */
|
||||||
def loadAndRun: (String, Boolean) = {
|
def loadAndRun: (String, Boolean) = {
|
||||||
if (replProps.noThreads) return {
|
if (lineManager == null) return {
|
||||||
try { ("" + (lineRep call sessionNames.print), true) }
|
try { ("" + (lineRep call sessionNames.print), true) }
|
||||||
catch { case ex => (lineRep.bindError(ex), false) }
|
catch { case ex => (lineRep.bindError(ex), false) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,3 +24,9 @@ class ReplProps {
|
||||||
val powerInitCode = Prop[JFile]("scala.repl.power.initcode")
|
val powerInitCode = Prop[JFile]("scala.repl.power.initcode")
|
||||||
val powerBanner = Prop[JFile]("scala.repl.power.banner")
|
val powerBanner = Prop[JFile]("scala.repl.power.banner")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object ReplPropsKludge {
|
||||||
|
// !!! short term binary compatibility hack for 2.9.1 to put this
|
||||||
|
// here - needed a not previously existing object.
|
||||||
|
def noThreadCreation(settings: Settings) = replProps.noThreads || settings.Yreplsync.value
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2006-2011 LAMP/EPFL
|
||||||
|
* @author Paul Phillips
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools
|
||||||
|
package reflect
|
||||||
|
|
||||||
|
import scala.util.PropertiesTrait
|
||||||
|
import java.security.AccessControlException
|
||||||
|
|
||||||
|
/** For placing a wrapper function around property functions.
|
||||||
|
* Motivated by places like google app engine throwing exceptions
|
||||||
|
* on property lookups.
|
||||||
|
*/
|
||||||
|
trait WrappedProperties extends PropertiesTrait {
|
||||||
|
def wrap[T](body: => T): Option[T]
|
||||||
|
|
||||||
|
protected def propCategory = "wrapped"
|
||||||
|
protected def pickJarBasedOn = this.getClass
|
||||||
|
|
||||||
|
override def propIsSet(name: String) = wrap(super.propIsSet(name)) exists (x => x)
|
||||||
|
override def propOrElse(name: String, alt: String) = wrap(super.propOrElse(name, alt)) getOrElse alt
|
||||||
|
override def setProp(name: String, value: String) = wrap(super.setProp(name, value)) orNull
|
||||||
|
override def clearProp(name: String) = wrap(super.clearProp(name)) orNull
|
||||||
|
override def envOrElse(name: String, alt: String) = wrap(super.envOrElse(name, alt)) getOrElse alt
|
||||||
|
override def envOrNone(name: String) = wrap(super.envOrNone(name)).flatten
|
||||||
|
|
||||||
|
def systemProperties: Iterator[(String, String)] = {
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
wrap(System.getProperties.asScala.iterator) getOrElse Iterator.empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object WrappedProperties {
|
||||||
|
object AccessControl extends WrappedProperties {
|
||||||
|
def wrap[T](body: => T) = try Some(body) catch { case _: AccessControlException => None }
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ package scala.tools
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import java.net.{ URL, MalformedURLException }
|
import java.net.{ URL, MalformedURLException }
|
||||||
import scala.util.Properties._
|
import scala.tools.reflect.WrappedProperties.AccessControl
|
||||||
import nsc.{ Settings, GenericRunnerSettings }
|
import nsc.{ Settings, GenericRunnerSettings }
|
||||||
import nsc.util.{ ClassPath, JavaClassPath, ScalaClassLoader }
|
import nsc.util.{ ClassPath, JavaClassPath, ScalaClassLoader }
|
||||||
import nsc.io.{ File, Directory, Path, AbstractFile }
|
import nsc.io.{ File, Directory, Path, AbstractFile }
|
||||||
|
@ -18,6 +18,10 @@ import PartialFunction.condOpt
|
||||||
// https://wiki.scala-lang.org/display/SW/Classpath
|
// https://wiki.scala-lang.org/display/SW/Classpath
|
||||||
|
|
||||||
object PathResolver {
|
object PathResolver {
|
||||||
|
// Imports property/environment functions which suppress
|
||||||
|
// security exceptions.
|
||||||
|
import AccessControl._
|
||||||
|
|
||||||
def firstNonEmpty(xs: String*) = xs find (_ != "") getOrElse ""
|
def firstNonEmpty(xs: String*) = xs find (_ != "") getOrElse ""
|
||||||
|
|
||||||
/** Map all classpath elements to absolute paths and reconstruct the classpath.
|
/** Map all classpath elements to absolute paths and reconstruct the classpath.
|
||||||
|
@ -34,10 +38,9 @@ object PathResolver {
|
||||||
/** Values found solely by inspecting environment or property variables.
|
/** Values found solely by inspecting environment or property variables.
|
||||||
*/
|
*/
|
||||||
object Environment {
|
object Environment {
|
||||||
private def searchForBootClasspath = {
|
private def searchForBootClasspath = (
|
||||||
import scala.collection.JavaConversions._
|
systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse ""
|
||||||
System.getProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse ""
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/** Environment variables which java pays attention to so it
|
/** Environment variables which java pays attention to so it
|
||||||
* seems we do as well.
|
* seems we do as well.
|
||||||
|
|
|
@ -6,11 +6,17 @@
|
||||||
package scala.tools
|
package scala.tools
|
||||||
package util
|
package util
|
||||||
|
|
||||||
|
import java.security.AccessControlException
|
||||||
|
|
||||||
/** A class for things which are signallable.
|
/** A class for things which are signallable.
|
||||||
*/
|
*/
|
||||||
abstract class Signallable[T] private (val signal: String, val description: String) {
|
abstract class Signallable[T] private (val signal: String, val description: String) {
|
||||||
private var last: Option[T] = None
|
private var last: Option[T] = None
|
||||||
private def lastString = last filterNot (_ == ()) map (_.toString) getOrElse ""
|
private def lastString = last match {
|
||||||
|
case Some(()) => ""
|
||||||
|
case Some(x) => "" + x
|
||||||
|
case _ => ""
|
||||||
|
}
|
||||||
|
|
||||||
/** The most recent result from the signal handler. */
|
/** The most recent result from the signal handler. */
|
||||||
def lastResult: Option[T] = last
|
def lastResult: Option[T] = last
|
||||||
|
@ -29,8 +35,9 @@ abstract class Signallable[T] private (val signal: String, val description: Stri
|
||||||
object Signallable {
|
object Signallable {
|
||||||
/** Same as the other apply, but an open signal is found for you.
|
/** Same as the other apply, but an open signal is found for you.
|
||||||
*/
|
*/
|
||||||
def apply[T](description: String)(body: => T): Signallable[T] =
|
def apply[T](description: String)(body: => T): Signallable[T] = wrap {
|
||||||
apply(SignalManager.findOpenSignal().name, description)(body)
|
apply(SignalManager.findOpenSignal().name, description)(body)
|
||||||
|
}
|
||||||
|
|
||||||
/** Given a signal name, a description, and a handler body, this
|
/** Given a signal name, a description, and a handler body, this
|
||||||
* registers a signal handler and returns the Signallable instance.
|
* registers a signal handler and returns the Signallable instance.
|
||||||
|
@ -38,16 +45,21 @@ object Signallable {
|
||||||
* SignalManager.info(), or sending SIGINFO to the manager will
|
* SignalManager.info(), or sending SIGINFO to the manager will
|
||||||
* dump it to console.
|
* dump it to console.
|
||||||
*/
|
*/
|
||||||
def apply[T](signal: String, description: String)(body: => T): Signallable[T] = {
|
def apply[T](signal: String, description: String)(body: => T): Signallable[T] = wrap {
|
||||||
val result = new Signallable[T](signal, description) {
|
val result = create[T](signal, description, body)
|
||||||
def onSignal(): T = {
|
SignalManager.public(signal, description)(result.onSignal())
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
private def wrap[T](body: => Signallable[T]): Signallable[T] =
|
||||||
|
try body catch { case _: AccessControlException => null }
|
||||||
|
|
||||||
|
private def create[T](signal: String, description: String, body: => T): Signallable[T] =
|
||||||
|
new Signallable[T](signal, description) {
|
||||||
|
def onSignal = {
|
||||||
val result = body
|
val result = body
|
||||||
last = Some(result)
|
last = Some(result)
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SignalManager.public(signal, description)(result.onSignal())
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ package nest
|
||||||
import java.io.{ File }
|
import java.io.{ File }
|
||||||
import java.util.StringTokenizer
|
import java.util.StringTokenizer
|
||||||
import scala.util.Properties.{ setProp }
|
import scala.util.Properties.{ setProp }
|
||||||
import scala.tools.util.Signallable
|
|
||||||
import scala.tools.nsc.util.ScalaClassLoader
|
import scala.tools.nsc.util.ScalaClassLoader
|
||||||
import scala.tools.nsc.io.Path
|
import scala.tools.nsc.io.Path
|
||||||
import scala.collection.{ mutable, immutable }
|
import scala.collection.{ mutable, immutable }
|
||||||
|
|
Loading…
Reference in New Issue