summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala10
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugin.scala91
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala146
-rw-r--r--src/library/scala/io/File.scala2
4 files changed, 100 insertions, 149 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 02d65d7e05..56b8253fa7 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -623,18 +623,12 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
buildCompilerFromPhasesSet() // PhaseAssembly.scala
}
- /* Simple option value to hold the compiler phase chain */
- private var phasesCache: Option[List[SubComponent]] = None
+ /* The phase descriptor list */
+ lazy val phaseDescriptors: List[SubComponent] = computePhaseDescriptors
/* The set of phase objects that is the basis for the compiler phase chain */
protected val phasesSet : HashSet[SubComponent] = new HashSet[SubComponent]
- /** A accessor for the phase descriptor list (List of SubComponents), Only calculate the list once */
- def phaseDescriptors = {
- if (phasesCache.isEmpty) phasesCache = Some(computePhaseDescriptors)
- phasesCache.get
- }
-
/** A description of the phases that will run */
def phaseDescriptions: String = {
new Run // force some initialization
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
index 3013199c36..a7b686e750 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc
package plugins
-import java.io.File
+import scala.io.{ File, Path }
import java.net.URLClassLoader
import java.util.jar.JarFile
import java.util.zip.ZipException
@@ -63,39 +63,44 @@ abstract class Plugin {
* @author Lex Spoon
* @version 1.0, 2007-5-21
*/
-object Plugin {
+object Plugin
+{
+ private val PluginXML = "scalac-plugin.xml"
+
/** Create a class loader with the specified file plus
* the loader that loaded the Scala compiler.
*/
- private def loaderFor(jarfiles: Seq[File]): ClassLoader = {
+ private def loaderFor(jarfiles: Seq[Path]): ClassLoader = {
val compilerLoader = classOf[Plugin].getClassLoader
- val jarurls = jarfiles.map(_.toURL).toArray
- new URLClassLoader(jarurls, compilerLoader)
+ val jarurls = jarfiles map (_.toURL)
+
+ new URLClassLoader(jarurls.toArray, compilerLoader)
}
/** Try to load a plugin description from the specified
* file, returning None if it does not work. */
- private def loadDescription(jarfile: File): Option[PluginDescription] = {
- if (!jarfile.exists) return None
+ private def loadDescription(jarfile: Path): Option[PluginDescription] =
+ // XXX Return to this once we have some ARM support
+ if (!jarfile.exists) None
+ else try {
+ val jar = new JarFile(jarfile.jfile)
- try {
- val jar = new JarFile(jarfile)
try {
- val ent = jar.getEntry("scalac-plugin.xml")
- if (ent == null) return None
-
- val inBytes = jar.getInputStream(ent)
- val packXML = XML.load(inBytes)
- inBytes.close()
-
- PluginDescription.fromXML(packXML)
- } finally {
- jar.close()
+ (jar getEntry PluginXML) match {
+ case null => None
+ case entry =>
+ val in = jar getInputStream entry
+ val packXML = XML load in
+ in.close()
+
+ PluginDescription fromXML packXML
+ }
}
- } catch {
+ finally jar.close()
+ }
+ catch {
case _: ZipException => None
}
- }
type AnyClass = Class[_]
@@ -103,16 +108,13 @@ object Plugin {
* if the jar file has no plugin in it or if the plugin
* is badly formed.
*/
- def loadFrom(jarfile: File, loader: ClassLoader): Option[AnyClass] = {
+ def loadFrom(jarfile: Path, loader: ClassLoader): Option[AnyClass] = {
val pluginInfo = loadDescription(jarfile).get
- try {
- Some(loader.loadClass(pluginInfo.classname))
- } catch {
- case _:ClassNotFoundException =>
- println("Warning: class not found for plugin in " + jarfile +
- " (" + pluginInfo.classname + ")")
- None
+ try Some(loader loadClass pluginInfo.classname) catch {
+ case _: ClassNotFoundException =>
+ println("Warning: class not found for plugin in %s (%s)".format(jarfile, pluginInfo.classname))
+ None
}
}
@@ -121,35 +123,28 @@ object Plugin {
* directories specified. Skips all plugins in <code>ignoring</code>.
* A single classloader is created and used to load all of them.
*/
- def loadAllFrom(jars: List[File],
- dirs: List[File],
- ignoring: List[String]): List[AnyClass] =
+ def loadAllFrom(
+ jars: List[Path],
+ dirs: List[Path],
+ ignoring: List[String]): List[AnyClass] =
{
- val alljars = new ListBuffer[File]
-
- alljars ++= jars
-
- for {
+ val alljars = jars ::: (for {
dir <- dirs if dir.isDirectory
- entries = dir.listFiles
- if entries ne null
- entry <- entries.toList.sort(_.getName <= _.getName)
- if entry.toString.toLowerCase endsWith ".jar"
+ entry <- dir.toDirectory.files.toList sortWith (_.name <= _.name)
+ if entry.name.toLowerCase endsWith ".jar"
pdesc <- loadDescription(entry)
if !(ignoring contains pdesc.name)
- } alljars += entry
+ } yield entry)
- val loader = loaderFor(alljars.toList)
- alljars.toList.map(f => loadFrom(f,loader)).flatMap(x => x)
+ val loader = loaderFor(alljars)
+ alljars map (loadFrom(_, loader)) flatten
}
/** Instantiate a plugin class, given the class and
* the compiler it is to be used in.
*/
def instantiate(clazz: AnyClass, global: Global): Plugin = {
- //println("instantiating "+clazz)
- //println(clazz.getDeclaredConstructors)
- val constructor = clazz.getConstructor(classOf[Global])
- constructor.newInstance(global).asInstanceOf[Plugin]
+ val constructor = clazz getConstructor classOf[Global]
+ (constructor newInstance global).asInstanceOf[Plugin]
}
}
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
index 1163ae5a6a..a67218ee01 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
@@ -8,7 +8,7 @@
package scala.tools.nsc
package plugins
-import java.io.File
+import scala.io.{ File, Path }
/** Support for run-time loading of compiler plugins.
*
@@ -16,7 +16,9 @@ import java.io.File
* @version 1.1, 2009/1/2
* Updated 2009/1/2 by Anders Bach Nielsen: Added features to implement SIP 00002
*/
-trait Plugins { self: Global =>
+trait Plugins
+{
+ self: Global =>
/** Load a rough list of the plugins. For speed, it
* does not instantiate a compiler run. Therefore it cannot
@@ -24,24 +26,17 @@ trait Plugins { self: Global =>
* filtered from the final list of plugins.
*/
protected def loadRoughPluginsList(): List[Plugin] = {
- val jars = settings.plugin.value.map(new File(_))
- val dirs =
- for (name <- settings.pluginsDir.value.split(File.pathSeparator).toList)
- yield new File(name)
+ val jars = settings.plugin.value map Path.apply
+ val dirs = (settings.pluginsDir.value split File.pathSeparator).toList map Path.apply
+ val classes = Plugin.loadAllFrom(jars, dirs, settings.disable.value)
+
+ classes foreach (c => Plugin.instantiate(c, this))
for (plugClass <- Plugin.loadAllFrom(jars, dirs, settings.disable.value))
yield Plugin.instantiate(plugClass, this)
}
- private var roughPluginsListCache: Option[List[Plugin]] = None
-
- protected def roughPluginsList: List[Plugin] =
- roughPluginsListCache match {
- case Some(list) => list
- case None =>
- roughPluginsListCache = Some(loadRoughPluginsList)
- roughPluginsListCache.get
- }
+ protected lazy val roughPluginsList: List[Plugin] = loadRoughPluginsList
/** Load all available plugins. Skips plugins that
* either have the same name as another one, or which
@@ -54,105 +49,70 @@ trait Plugins { self: Global =>
plugNames: Set[String],
phaseNames: Set[String]): List[Plugin] =
{
- plugins match {
- case Nil => Nil
- case plug :: rest =>
- val plugPhaseNames = Set.empty ++ plug.components.map(_.phaseName)
- def withoutPlug = pick(rest, plugNames, plugPhaseNames)
- def withPlug =
- (plug ::
- pick(rest,
- plugNames+plug.name,
- phaseNames++plugPhaseNames))
-
- if (plugNames.contains(plug.name)) {
- if (settings.verbose.value)
- inform("[skipping a repeated plugin: " + plug.name + "]")
- withoutPlug
- } else if (settings.disable.value contains(plug.name)) {
- if (settings.verbose.value)
- inform("[disabling plugin: " + plug.name + "]")
- withoutPlug
- } else {
- val commonPhases = phaseNames.intersect(plugPhaseNames)
- if (!commonPhases.isEmpty) {
- if (settings.verbose.value)
- inform("[skipping plugin " + plug.name +
- "because it repeats phase names: " +
- commonPhases.mkString(", ") + "]")
- withoutPlug
- } else {
- if (settings.verbose.value)
- inform("[loaded plugin " + plug.name + "]")
- withPlug
- }
- }
+ if (plugins.isEmpty) return Nil // early return
+
+ val plug :: tail = plugins
+ val plugPhaseNames = Set(plug.components map (_.phaseName): _*)
+ def withoutPlug = pick(tail, plugNames, plugPhaseNames)
+ def withPlug = plug :: pick(tail, plugNames + plug.name, phaseNames ++ plugPhaseNames)
+ lazy val commonPhases = phaseNames intersect plugPhaseNames
+
+ def note(msg: String): Unit = if (settings.verbose.value) inform(msg format plug.name)
+ def fail(msg: String) = { note(msg) ; withoutPlug }
+
+ if (plugNames contains plug.name)
+ fail("[skipping a repeated plugin: %s]")
+ else if (settings.disable.value contains plug.name)
+ fail("[disabling plugin: %s]")
+ else if (!commonPhases.isEmpty)
+ fail("[skipping plugin %s because it repeats phase names: " + (commonPhases mkString ", ") + "]")
+ else {
+ note("[loaded plugin %s]")
+ withPlug
}
}
- val plugs =
- pick(roughPluginsList,
- Set.empty,
- Set.empty ++ phasesSet.map(_.phaseName))
+ val plugs = pick(roughPluginsList, Set(), phasesSet map (_.phaseName) toSet)
- for (req <- settings.require.value; if !plugs.exists(p => p.name==req))
+ /** Verify requirements are present. */
+ for (req <- settings.require.value ; if !(plugs exists (_.name == req)))
error("Missing required plugin: " + req)
+ /** Process plugin options. */
+ def namec(plug: Plugin) = plug.name + ":"
+ def optList(xs: List[String], p: Plugin) = xs filter (_ startsWith namec(p))
+ def doOpts(p: Plugin): List[String] =
+ optList(settings.pluginOptions.value, p) map (_ stripPrefix namec(p))
- for (plug <- plugs) {
- val nameColon = plug.name + ":"
- val opts = for {
- raw <- settings.pluginOptions.value
- if raw.startsWith(nameColon)
- } yield raw.substring(nameColon.length)
-
+ for (p <- plugs) {
+ val opts = doOpts(p)
if (!opts.isEmpty)
- plug.processOptions(opts, error)
+ p.processOptions(opts, error)
}
- for {
- opt <- settings.pluginOptions.value
- if !plugs.exists(p => opt.startsWith(p.name + ":"))
- } error("bad option: -P:" + opt)
+ /** Verify no non-existent plugin given with -P */
+ for (opt <- settings.pluginOptions.value ; if plugs forall (p => optList(List(opt), p).isEmpty))
+ error("bad option: -P:" + opt)
plugs
}
- private var pluginsCache: Option[List[Plugin]] = None
-
- def plugins: List[Plugin] = {
- if (pluginsCache.isEmpty)
- pluginsCache = Some(loadPlugins)
- pluginsCache.get
- }
+ lazy val plugins: List[Plugin] = loadPlugins
/** A description of all the plugins that are loaded */
- def pluginDescriptions: String = {
- val messages =
- for (plugin <- roughPluginsList)
- yield plugin.name + " - " + plugin.description
- messages.mkString("\n")
- }
+ def pluginDescriptions: String =
+ roughPluginsList map (x => "%s - %s".format(x.name, x.description)) mkString "\n"
/**
* Extract all phases supplied by plugins and add them to the phasesSet.
* @see phasesSet
*/
- protected def computePluginPhases() {
- val plugPhases = plugins.flatMap(_.components)
- for (pPhase <- plugPhases) {
- phasesSet += pPhase
- }
- }
+ protected def computePluginPhases(): Unit =
+ phasesSet ++= (plugins flatMap (_.components))
/** Summary of the options for all loaded plugins */
- def pluginOptionsHelp: String = {
- val buf = new StringBuffer
- for (plug <- roughPluginsList; help <- plug.optionsHelp) {
- buf append ("Options for plugin " + plug.name + ":\n")
- buf append help
- buf append "\n"
- }
- buf.toString
- }
+ def pluginOptionsHelp: String =
+ (for (plug <- roughPluginsList ; help <- plug.optionsHelp) yield {
+ "Options for plugin %s:\n%s\n".format(plug.name, help)
+ }) mkString
}
diff --git a/src/library/scala/io/File.scala b/src/library/scala/io/File.scala
index b4131d7e57..74a66492ec 100644
--- a/src/library/scala/io/File.scala
+++ b/src/library/scala/io/File.scala
@@ -18,6 +18,8 @@ import collection.Traversable
object File
{
+ def pathSeparator = JFile.pathSeparator
+
def apply(path: Path)(implicit codec: Codec = null) =
if (codec != null) new File(path.jfile)(codec)
else path.toFile