summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2012-09-26 11:36:01 -0700
committerSom Snytt <som.snytt@gmail.com>2012-12-18 10:34:14 -0800
commitfadb306fdf3d37284fd29c50aa3956cabe79480d (patch)
tree7389f4155de0aae885d6ade1bc82c80e99c8b52c
parente14917528e1c080a7f10785e21de36f3a7769718 (diff)
downloadscala-fadb306fdf3d37284fd29c50aa3956cabe79480d.tar.gz
scala-fadb306fdf3d37284fd29c50aa3956cabe79480d.tar.bz2
scala-fadb306fdf3d37284fd29c50aa3956cabe79480d.zip
PluginComponent contributes description to -Xshow-phases.
In Global, SubComponent is called a phase descriptor, but it doesn't actually have a description. (Phase itself does.) This fix adds a description to PluginComponent so that plugins can describe what they do in -Xshow-phases. Elliptical descriptions Exploded archives Plugged-in partest Roundup at the Little h!
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala40
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/io/Jar.scala14
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugin.scala128
-rw-r--r--src/compiler/scala/tools/nsc/plugins/PluginComponent.scala8
-rw-r--r--src/compiler/scala/tools/nsc/plugins/PluginDescription.scala47
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala15
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala3
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala2
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala43
-rw-r--r--src/partest/scala/tools/partest/nest/ReflectiveRunner.scala3
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala17
-rwxr-xr-xtest/files/neg/t6446-additional.check31
-rw-r--r--test/files/neg/t6446-additional/ploogin_1.scala31
-rw-r--r--test/files/neg/t6446-additional/sample_2.flags1
-rw-r--r--test/files/neg/t6446-additional/sample_2.scala6
-rw-r--r--test/files/neg/t6446-additional/scalac-plugin.xml4
-rwxr-xr-xtest/files/neg/t6446-list.check1
-rw-r--r--test/files/neg/t6446-list/ploogin_1.scala31
-rw-r--r--test/files/neg/t6446-list/sample_2.flags1
-rw-r--r--test/files/neg/t6446-list/sample_2.scala6
-rw-r--r--test/files/neg/t6446-list/scalac-plugin.xml4
-rwxr-xr-xtest/files/neg/t6446-missing.check31
-rw-r--r--test/files/neg/t6446-missing/sample_2.flags1
-rw-r--r--test/files/neg/t6446-missing/sample_2.scala6
-rw-r--r--test/files/neg/t6446-missing/scalac-plugin.xml4
-rw-r--r--test/files/neg/t6446-show-phases.check30
-rw-r--r--test/files/neg/t6446-show-phases.flags1
-rw-r--r--test/files/neg/t6446-show-phases.scala3
-rw-r--r--test/files/run/inline-ex-handlers.scala2
-rw-r--r--test/files/run/programmatic-main.check60
-rw-r--r--test/files/run/t4351.check (renamed from test/files/pos/t4351.check)0
-rw-r--r--test/files/run/t4351.scala (renamed from test/files/pos/t4351.scala)3
33 files changed, 422 insertions, 157 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 34d5d10cbf..7ea49a5c86 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -572,7 +572,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val runsRightAfter = None
} with Inliners
- // phaseName = "inlineExceptionHandlers"
+ // phaseName = "inlinehandlers"
object inlineExceptionHandlers extends {
val global: Global.this.type = Global.this
val runsAfter = List("inliner")
@@ -582,7 +582,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// phaseName = "closelim"
object closureElimination extends {
val global: Global.this.type = Global.this
- val runsAfter = List("inlineExceptionHandlers")
+ val runsAfter = List("inlinehandlers")
val runsRightAfter = None
} with ClosureElimination
@@ -724,13 +724,41 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** A description of the phases that will run */
def phaseDescriptions: String = {
- val width = phaseNames map (_.length) max
- val fmt = "%" + width + "s %2s %s\n"
+ val Limit = 16 // phase names should not be absurdly long
+ val MaxCol = 80 // because some of us edit on green screens
+ val maxName = (0 /: phaseNames)(_ max _.length)
+ val width = maxName min Limit
+ val maxDesc = MaxCol - (width + 6) // descriptions not novels
+ val fmt = if (settings.verbose.value) s"%${maxName}s %2s %s%n"
+ else s"%${width}.${width}s %2s %.${maxDesc}s%n"
val line1 = fmt.format("phase name", "id", "description")
val line2 = fmt.format("----------", "--", "-----------")
+
+ // built-in string precision merely truncates
+ import java.util.{ Formattable, FormattableFlags, Formatter }
+ def fmtable(s: String) = new Formattable {
+ override def formatTo(formatter: Formatter, flags: Int, width: Int, precision: Int) {
+ val p = elliptically(s, precision)
+ val w = if (width > 0 && p.length < width) {
+ import FormattableFlags.LEFT_JUSTIFY
+ val leftly = (flags & LEFT_JUSTIFY) == LEFT_JUSTIFY
+ val sb = new StringBuilder
+ def pad() = 1 to width - p.length foreach (_ => sb.append(' '))
+ if (!leftly) pad()
+ sb.append(p)
+ if (leftly) pad()
+ sb.toString
+ } else p
+ formatter.out.append(w)
+ }
+ }
+ def elliptically(s: String, max: Int) =
+ if (max < 0 || s.length <= max) s
+ else if (max < 4) s.take(max)
+ else s.take(max - 3) + "..."
val descs = phaseDescriptors.zipWithIndex map {
- case (ph, idx) => fmt.format(ph.phaseName, idx + 1, phasesDescMap(ph))
+ case (ph, idx) => fmt.format(fmtable(ph.phaseName), idx + 1, fmtable(phasesDescMap(ph)))
}
line1 :: line2 :: descs mkString
}
@@ -1302,7 +1330,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val cleanupPhase = phaseNamed("cleanup")
val icodePhase = phaseNamed("icode")
val inlinerPhase = phaseNamed("inliner")
- val inlineExceptionHandlersPhase = phaseNamed("inlineExceptionHandlers")
+ val inlineExceptionHandlersPhase = phaseNamed("inlinehandlers")
val closelimPhase = phaseNamed("closelim")
val dcePhase = phaseNamed("dce")
// val jvmPhase = phaseNamed("jvm")
diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
index c534c2230c..4e65c72b0b 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
@@ -52,7 +52,7 @@ abstract class InlineExceptionHandlers extends SubComponent {
import icodes._
import icodes.opcodes._
- val phaseName = "inlineExceptionHandlers"
+ val phaseName = "inlinehandlers"
/** Create a new phase */
override def newPhase(p: Phase) = new InlineExceptionHandlersPhase(p)
diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala
index 49a1ff114f..0dca75dab9 100644
--- a/src/compiler/scala/tools/nsc/io/Jar.scala
+++ b/src/compiler/scala/tools/nsc/io/Jar.scala
@@ -47,6 +47,20 @@ class Jar(file: File) extends Iterable[JarEntry] {
case _ => Nil
}
+ /** Invoke f with input for named jar entry (or None). */
+ def withEntryStream[A](name: String)(f: Option[InputStream] => A) = {
+ val jarFile = new JarFile(file.jfile)
+ def apply() =
+ jarFile getEntry name match {
+ case null => f(None)
+ case entry =>
+ val in = Some(jarFile getInputStream entry)
+ try f(in)
+ finally in map (_.close())
+ }
+ try apply() finally jarFile.close()
+ }
+
def withJarInput[T](f: JarInputStream => T): T = {
val in = new JarInputStream(file.inputStream())
try f(in)
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
index 093f8285e1..b0113f7696 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
@@ -6,10 +6,14 @@
package scala.tools.nsc
package plugins
-import io.{ Path, Jar }
-import java.net.URLClassLoader
-import java.util.jar.JarFile
+import scala.tools.nsc.io.{ Jar }
+import scala.tools.nsc.util.ScalaClassLoader
+import scala.reflect.io.{ Directory, File, Path }
+import java.io.InputStream
import java.util.zip.ZipException
+
+import scala.collection.mutable.ListBuffer
+import scala.util.{ Try, Success, Failure }
import scala.xml.XML
/** Information about a plugin loaded from a jar file.
@@ -34,11 +38,13 @@ abstract class Plugin {
val description: String
/** The compiler that this plugin uses. This is normally equated
- * to a constructor parameter in the concrete subclass. */
+ * to a constructor parameter in the concrete subclass.
+ */
val global: Global
/** Handle any plugin-specific options. The `-P:plugname:` part
- * will not be present. */
+ * will not be present.
+ */
def processOptions(options: List[String], error: String => Unit) {
if (!options.isEmpty)
error("Error: " + name + " has no options")
@@ -60,90 +66,86 @@ object Plugin {
private val PluginXML = "scalac-plugin.xml"
- /** Create a class loader with the specified file plus
+ /** Create a class loader with the specified locations plus
* the loader that loaded the Scala compiler.
*/
- private def loaderFor(jarfiles: Seq[Path]): ClassLoader = {
+ private def loaderFor(locations: Seq[Path]): ScalaClassLoader = {
val compilerLoader = classOf[Plugin].getClassLoader
- val jarurls = jarfiles map (_.toURL)
+ val urls = locations map (_.toURL)
- new URLClassLoader(jarurls.toArray, compilerLoader)
+ ScalaClassLoader fromURLs (urls, compilerLoader)
}
- /** Try to load a plugin description from the specified
- * file, returning `None` if it does not work.
+ /** Try to load a plugin description from the specified location.
*/
- 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 {
- jar getEntry PluginXML match {
- case null => None
- case entry =>
- val in = jar getInputStream entry
- val packXML = XML load in
- in.close()
-
- PluginDescription fromXML packXML
- }
- }
- finally jar.close()
- }
- catch {
- case _: ZipException => None
+ private def loadDescriptionFromJar(jarp: Path): Try[PluginDescription] = {
+ // XXX Return to this once we have more ARM support
+ def read(is: Option[InputStream]) = is match {
+ case None => throw new RuntimeException(s"Missing $PluginXML in $jarp")
+ case _ => PluginDescription fromXML (XML load is.get)
}
+ Try(new Jar(jarp.jfile).withEntryStream(PluginXML)(read))
+ }
+
+ private def loadDescriptionFromFile(f: Path): Try[PluginDescription] =
+ Try(XML loadFile f.jfile) map (PluginDescription fromXML _)
type AnyClass = Class[_]
- /** Loads a plugin class from the named jar file.
+ /** Use a class loader to load the plugin class.
*
- * @return `None` if the jar file has no plugin in it or
- * if the plugin is badly formed.
+ * @return `None` on failure
*/
- def loadFrom(jarfile: Path, loader: ClassLoader): Option[AnyClass] =
- loadDescription(jarfile) match {
- case None =>
- println("Warning: could not load descriptor for plugin %s".format(jarfile))
- None
- case Some(pdesc) =>
- try Some(loader loadClass pdesc.classname) catch {
- case _: Exception =>
- println("Warning: class not found for plugin in %s (%s)".format(jarfile, pdesc.classname))
- None
- }
+ def load(pd: PluginDescription, loader: ClassLoader): Try[AnyClass] = {
+ Try[AnyClass] {
+ loader loadClass pd.classname
+ } recoverWith {
+ case _: Exception =>
+ Failure(new RuntimeException(s"Warning: class not found: ${pd.classname}"))
}
+ }
- /** Load all plugins found in the argument list, both in the
- * jar files explicitly listed, and in the jar files in the
- * directories specified. Skips all plugins in `ignoring`.
+ /** Load all plugins specified by the arguments.
+ * Each of `jars` must be a valid plugin archive or exploded archive.
+ * Each of `dirs` may be a directory containing arbitrary plugin archives.
+ * Skips all plugins named in `ignoring`.
* A single classloader is created and used to load all of them.
*/
def loadAllFrom(
jars: List[Path],
dirs: List[Path],
- ignoring: List[String]): List[AnyClass] =
+ ignoring: List[String]): List[Try[AnyClass]] =
{
- val alljars = (jars ::: (for {
- dir <- dirs if dir.isDirectory
- entry <- dir.toDirectory.files.toList sortBy (_.name)
-// was: if Path.isJarOrZip(entry)
- if Jar.isJarOrZip(entry)
- pdesc <- loadDescription(entry)
- if !(ignoring contains pdesc.name)
- } yield entry)).distinct
-
- val loader = loaderFor(alljars)
- (alljars map (loadFrom(_, loader))).flatten
+ // List[(jar, Success(descriptor))] in dir
+ def scan(d: Directory) = for {
+ f <- d.files.toList sortBy (_.name)
+ if Jar isJarOrZip f
+ pd = loadDescriptionFromJar(f)
+ if pd.isSuccess
+ } yield (f, pd)
+ // (dir, Try(descriptor))
+ def explode(d: Directory) = d -> loadDescriptionFromFile(d / PluginXML)
+ // (j, Try(descriptor))
+ def required(j: Path) = j -> loadDescriptionFromJar(j)
+
+ type Paired = Pair[Path, Try[PluginDescription]]
+ val included: List[Paired] = (dirs flatMap (_ ifDirectory scan)).flatten
+ val exploded: List[Paired] = jars flatMap (_ ifDirectory explode)
+ val explicit: List[Paired] = jars flatMap (_ ifFile required)
+ def ignored(p: Paired) = p match {
+ case (path, Success(pd)) => ignoring contains pd.name
+ case _ => false
+ }
+ val (locs, pds) = ((explicit ::: exploded ::: included) filterNot ignored).unzip
+
+ val loader = loaderFor(locs.distinct)
+ pds filter (_.isSuccess) map (_.get) map (Plugin load (_, loader))
}
/** Instantiate a plugin class, given the class and
* the compiler it is to be used in.
*/
def instantiate(clazz: AnyClass, global: Global): Plugin = {
- val constructor = clazz getConstructor classOf[Global]
- (constructor newInstance global).asInstanceOf[Plugin]
+ (clazz getConstructor classOf[Global] newInstance global).asInstanceOf[Plugin]
}
}
diff --git a/src/compiler/scala/tools/nsc/plugins/PluginComponent.scala b/src/compiler/scala/tools/nsc/plugins/PluginComponent.scala
index 4d98b2563c..c6e1af7ea4 100644
--- a/src/compiler/scala/tools/nsc/plugins/PluginComponent.scala
+++ b/src/compiler/scala/tools/nsc/plugins/PluginComponent.scala
@@ -18,8 +18,12 @@ abstract class PluginComponent extends SubComponent {
/** Internal flag to tell external from internal phases */
final override val internal = false
- /** Phases supplied by plugins should not have give the runsRightAfter constraint,
- * but can override it */
+ /** Phases supplied by plugins should not have to supply the
+ * runsRightAfter constraint, but can override it.
+ */
val runsRightAfter: Option[String] = None
+ /** Useful for -Xshow-phases. */
+ def description: String = ""
+
}
diff --git a/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala b/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala
index f77123ba11..27693d1a45 100644
--- a/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala
+++ b/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala
@@ -13,17 +13,12 @@ import scala.xml.Node
*
* @author Lex Spoon
* @version 1.0, 2007-5-21
+ * @param name A short name of the plugin, used to identify it in
+ * various contexts. The phase defined by the plugin
+ * should have the same name.
+ * @param classname The name of the main Plugin class.
*/
-abstract class PluginDescription {
-
- /** A short name of the compiler, used to identify it in
- * various contexts. The phase defined by the plugin
- * should have the same name.
- */
- val name: String
-
- /** The name of the main class for the plugin */
- val classname: String
+case class PluginDescription(name: String, classname: String) {
/** An XML representation of this description. It can be
* read back using `PluginDescription.fromXML`.
@@ -44,32 +39,24 @@ abstract class PluginDescription {
*/
object PluginDescription {
- def fromXML(xml: Node): Option[PluginDescription] = {
- // check the top-level tag
- xml match {
- case <plugin>{_*}</plugin> => ()
- case _ => return None
- }
+ def fromXML(xml: Node): PluginDescription = {
// extract one field
def getField(field: String): Option[String] = {
val text = (xml \\ field).text.trim
if (text == "") None else Some(text)
}
-
- // extract the required fields
- val name1 = getField("name") match {
- case None => return None
- case Some(str) => str
+ def extracted = {
+ val name = "name"
+ val claas = "classname"
+ val vs = Map(name -> getField(name), claas -> getField(claas))
+ if (vs.values exists (_.isEmpty)) fail()
+ else PluginDescription(name = vs(name).get, classname = vs(claas).get)
}
- val classname1 = getField("classname") match {
- case None => return None
- case Some(str) => str
+ def fail() = throw new RuntimeException("Bad plugin descriptor.")
+ // check the top-level tag
+ xml match {
+ case <plugin>{_*}</plugin> => extracted
+ case _ => fail()
}
-
- Some(new PluginDescription {
- val name = name1
- val classname = classname1
- })
}
-
}
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
index 736bd826e4..bb7d54d8f6 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
@@ -7,7 +7,8 @@
package scala.tools.nsc
package plugins
-import io.{ File, Path }
+import scala.reflect.io.{ File, Path }
+import scala.tools.util.PathResolver.Defaults
/** Support for run-time loading of compiler plugins.
*
@@ -25,8 +26,14 @@ trait Plugins {
*/
protected def loadRoughPluginsList(): List[Plugin] = {
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)
+ def injectDefault(s: String) = if (s.isEmpty) Defaults.scalaPluginPath else s
+ val dirs = (settings.pluginsDir.value split File.pathSeparator).toList map injectDefault map Path.apply
+ val maybes = Plugin.loadAllFrom(jars, dirs, settings.disable.value)
+ val (goods, errors) = maybes partition (_.isSuccess)
+ errors foreach (_ recover {
+ case e: Exception => inform(e.getMessage)
+ })
+ val classes = goods map (_.get) // flatten
// Each plugin must only be instantiated once. A common pattern
// is to register annotation checkers during object construction, so
@@ -106,7 +113,7 @@ trait Plugins {
* @see phasesSet
*/
protected def computePluginPhases(): Unit =
- phasesSet ++= (plugins flatMap (_.components))
+ for (p <- plugins; c <- p.components) addToPhasesSet(c, c.description)
/** Summary of the options for all loaded plugins */
def pluginOptionsHelp: String =
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index f62eebaaa0..36f0253243 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -17,13 +17,14 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
import definitions._ // standard classes and methods
import typer.atOwner // methods to type trees
+ override def description = "ANF pre-transform for @cps"
+
/** the following two members override abstract members in Transform */
val phaseName: String = "selectiveanf"
protected def newTransformer(unit: CompilationUnit): Transformer =
new ANFTransformer(unit)
-
class ANFTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
implicit val _unit = unit // allow code in CPSUtils.scala to report errors
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 801c328177..f61828debc 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -17,6 +17,8 @@ abstract class SelectiveCPSTransform extends PluginComponent with
import definitions._ // standard classes and methods
import typer.atOwner // methods to type trees
+ override def description = "@cps-driven transform of selectiveanf assignments"
+
/** the following two members override abstract members in Transform */
val phaseName: String = "selectivecps"
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index 3f005d143e..9a48c5ce2b 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -9,7 +9,7 @@ package scala.tools.partest
package nest
import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError, io }
-import scala.tools.nsc.io.{ File => SFile }
+import scala.reflect.io.{ Directory, File => SFile, FileOperationException }
import scala.tools.nsc.interactive.RangePositions
import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
import scala.tools.nsc.util.{ ClassPath, FakePos }
@@ -70,10 +70,27 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
s
}
- private def updatePluginPath(options: String): String = {
- def absolutize(path: String) = Path(path) match {
+ implicit class Copier(f: SFile) {
+ // But what if f is bigger than CHUNK?!
+ def copyTo(dest: Path) {
+ dest.toFile writeAll f.slurp
+ }
+ }
+
+ // plugin path can be relative to test root, or cwd is out
+ private def updatePluginPath(options: String, out: Option[File], srcdir: Directory): String = {
+ val dir = fileManager.testRootDir
+ def pathOrCwd(p: String) =
+ if (p == "." && out.isDefined) {
+ val plugxml = "scalac-plugin.xml"
+ val pout = Path(out.get)
+ val pd = (srcdir / plugxml).toFile
+ if (pd.exists) pd copyTo (pout / plugxml)
+ pout
+ } else Path(p)
+ def absolutize(path: String) = pathOrCwd(path) match {
case x if x.isAbsolute => x.path
- case x => (fileManager.testRootDir / x).toAbsolute.path
+ case x => (dir / x).toAbsolute.path
}
val (opt1, opt2) = (options split "\\s").toList partition (_ startsWith "-Xplugin:")
@@ -90,17 +107,21 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
}
val logWriter = new FileWriter(log)
+ // this api has no notion of srcdir, so fake it
+ val fstFile = SFile(files(0))
+ val srcdir = fstFile.parent
+
// check whether there is a ".flags" file
+ def convertFlags(f: SFile) = updatePluginPath(f.slurp(), out, srcdir)
val logFile = basename(log.getName)
val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-")))
- val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
+ val argString = (SFile(log).parent / flagsFileName) ifFile (convertFlags) getOrElse ""
// slurp local flags (e.g., "A_1.flags")
- val fstFile = SFile(files(0))
def isInGroup(num: Int) = fstFile.stripExtension endsWith ("_" + num)
val inGroup = (1 to 9) flatMap (group => if (isInGroup(group)) List(group) else List())
val localFlagsList = if (inGroup.nonEmpty) {
- val localArgString = (fstFile.parent / (fstFile.stripExtension + ".flags")) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
+ val localArgString = (srcdir / (fstFile.stripExtension + ".flags")) ifFile (convertFlags) getOrElse ""
localArgString.split(' ').toList.filter(_.length > 0)
} else List()
@@ -140,8 +161,10 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
NestUI.verbose("compiling "+toCompile)
NestUI.verbose("with classpath: "+global.classPath.toString)
NestUI.verbose("and java classpath: "+ propOrEmpty("java.class.path"))
- try new global.Run compile toCompile
- catch {
+ try {
+ if (command.shouldStopWithInfo) logWriter append (command getInfoMessage global)
+ else new global.Run compile toCompile
+ } catch {
case FatalError(msg) =>
testRep.error(null, "fatal error: " + msg)
return CompilerCrashed
@@ -152,7 +175,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
}
finally logWriter.close()
- if (testRep.hasErrors) CompileFailed
+ if (testRep.hasErrors || command.shouldStopWithInfo) CompileFailed
else CompileSuccess
}
}
diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
index d3a40718c6..3446dd0f72 100644
--- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
@@ -81,6 +81,9 @@ class ReflectiveRunner {
val newClasspath = ClassPath.join(paths: _*)
setProp("java.class.path", newClasspath)
+
+ // don't let partest find pluginsdir; in ant build, standard plugin has dedicated test suite
+ //setProp("scala.home", latestLibFile.parent.parent.path)
setProp("scala.home", "")
if (isPartestDebug)
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index f2ce19a950..fbef97dab4 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -344,21 +344,22 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP
* compiler expects and how to implement them. (see SI-1240 for the full story)
*
* In practice, this happens in 3 steps:
- * STEP1: feed all the files to scalac
- * it will parse java files and obtain their expected signatures and generate bytecode for scala files
- * STEP2: feed the java files to javac
- * it will generate the bytecode for the java files and link to the scalac-generated bytecode for scala
- * STEP3: only if there are both scala and java files, recompile the scala sources so they link to the correct
+ * STEP1: Feed all the files to scalac if there are also non-Scala sources.
+ * It will parse java files and obtain their expected signatures and generate bytecode for scala files
+ * STEP2: Feed the java files to javac if there are any.
+ * It will generate the bytecode for the java files and link to the scalac-generated bytecode for scala
+ * STEP3: (Re-)compile the scala sources so they link to the correct
* java signatures, in case the signatures deduced by scalac from the source files were wrong. Since the
* bytecode for java is already in place, we only feed the scala files to scalac so it will take the
- * java signatures from the existing javac-generated bytecode
+ * java signatures from the existing javac-generated bytecode.
+ * Note that no artifacts are deleted before this step.
*/
List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) {
- case (CompileSuccess, 1) if scalaFiles.nonEmpty =>
+ case (CompileSuccess, 1) if scalaFiles.nonEmpty && javaFiles.nonEmpty =>
compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile)
case (CompileSuccess, 2) if javaFiles.nonEmpty =>
javac(outDir, javaFiles, logFile)
- case (CompileSuccess, 3) if scalaFiles.nonEmpty && javaFiles.nonEmpty =>
+ case (CompileSuccess, 3) if scalaFiles.nonEmpty =>
// TODO: Do we actually need this? SI-1240 is known to require this, but we don't know if other tests
// require it: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/rFDKAcOKciU
compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile)
diff --git a/test/files/neg/t6446-additional.check b/test/files/neg/t6446-additional.check
new file mode 100755
index 0000000000..53dd383941
--- /dev/null
+++ b/test/files/neg/t6446-additional.check
@@ -0,0 +1,31 @@
+ phase name id description
+ ---------- -- -----------
+ parser 1 parse source into ASTs, perform simple desugaring
+ namer 2 resolve names, attach symbols to named trees
+packageobjects 3 load package objects
+ typer 4 the meat and potatoes: type the trees
+ patmat 5 translate match expressions
+superaccessors 6 add super accessors in traits and nested classes
+ extmethods 7 add extension methods for inline classes
+ pickler 8 serialize symbol tables
+ refchecks 9 reference/override checking, translate nested objects
+ uncurry 10 uncurry, translate function values to anonymous classes
+ tailcalls 11 replace tail calls by jumps
+ specialize 12 @specialized-driven class and method specialization
+ explicitouter 13 this refs to outer pointers, translate patterns
+ erasure 14 erase types, add interfaces for traits
+ posterasure 15 clean up erased inline classes
+ lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ icode 22 generate portable intermediate code
+ inliner 23 optimization: do inlining
+inlinehandlers 24 optimization: inline exception handlers
+ closelim 25 optimization: eliminate uncalled closures
+ dce 26 optimization: eliminate dead code
+ jvm 27 generate JVM bytecode
+ ploogin 28 A sample phase that does so many things it's kind of hard...
+ terminal 29 The last phase in the compiler chain
diff --git a/test/files/neg/t6446-additional/ploogin_1.scala b/test/files/neg/t6446-additional/ploogin_1.scala
new file mode 100644
index 0000000000..ed6adfc1cf
--- /dev/null
+++ b/test/files/neg/t6446-additional/ploogin_1.scala
@@ -0,0 +1,31 @@
+
+package t6446
+
+import scala.tools.nsc.{ Global, Phase }
+import scala.tools.nsc.plugins.{ Plugin, PluginComponent }
+import scala.reflect.io.Path
+import scala.reflect.io.File
+
+/** A test plugin. */
+class Ploogin(val global: Global) extends Plugin {
+ import global._
+
+ val name = "ploogin"
+ val description = "A sample plugin for testing."
+ val components = List[PluginComponent](TestComponent)
+
+ private object TestComponent extends PluginComponent {
+ val global: Ploogin.this.global.type = Ploogin.this.global
+ //override val runsBefore = List("refchecks")
+ val runsAfter = List("jvm")
+ val phaseName = Ploogin.this.name
+ override def description = "A sample phase that does so many things it's kind of hard to describe briefly."
+ def newPhase(prev: Phase) = new TestPhase(prev)
+ class TestPhase(prev: Phase) extends StdPhase(prev) {
+ override def description = TestComponent.this.description
+ def apply(unit: CompilationUnit) {
+ // kewl kode
+ }
+ }
+ }
+}
diff --git a/test/files/neg/t6446-additional/sample_2.flags b/test/files/neg/t6446-additional/sample_2.flags
new file mode 100644
index 0000000000..4d518c2286
--- /dev/null
+++ b/test/files/neg/t6446-additional/sample_2.flags
@@ -0,0 +1 @@
+-Xplugin:. -Xshow-phases
diff --git a/test/files/neg/t6446-additional/sample_2.scala b/test/files/neg/t6446-additional/sample_2.scala
new file mode 100644
index 0000000000..73cdc64e40
--- /dev/null
+++ b/test/files/neg/t6446-additional/sample_2.scala
@@ -0,0 +1,6 @@
+
+package sample
+
+// just a sample that is compiled with the sample plugin enabled
+object Sample extends App {
+}
diff --git a/test/files/neg/t6446-additional/scalac-plugin.xml b/test/files/neg/t6446-additional/scalac-plugin.xml
new file mode 100644
index 0000000000..e849bb5919
--- /dev/null
+++ b/test/files/neg/t6446-additional/scalac-plugin.xml
@@ -0,0 +1,4 @@
+<plugin>
+<name>sample-plugin</name>
+<classname>t6446.Ploogin</classname>
+</plugin>
diff --git a/test/files/neg/t6446-list.check b/test/files/neg/t6446-list.check
new file mode 100755
index 0000000000..fa5c581941
--- /dev/null
+++ b/test/files/neg/t6446-list.check
@@ -0,0 +1 @@
+ploogin - A sample plugin for testing.
diff --git a/test/files/neg/t6446-list/ploogin_1.scala b/test/files/neg/t6446-list/ploogin_1.scala
new file mode 100644
index 0000000000..ed6adfc1cf
--- /dev/null
+++ b/test/files/neg/t6446-list/ploogin_1.scala
@@ -0,0 +1,31 @@
+
+package t6446
+
+import scala.tools.nsc.{ Global, Phase }
+import scala.tools.nsc.plugins.{ Plugin, PluginComponent }
+import scala.reflect.io.Path
+import scala.reflect.io.File
+
+/** A test plugin. */
+class Ploogin(val global: Global) extends Plugin {
+ import global._
+
+ val name = "ploogin"
+ val description = "A sample plugin for testing."
+ val components = List[PluginComponent](TestComponent)
+
+ private object TestComponent extends PluginComponent {
+ val global: Ploogin.this.global.type = Ploogin.this.global
+ //override val runsBefore = List("refchecks")
+ val runsAfter = List("jvm")
+ val phaseName = Ploogin.this.name
+ override def description = "A sample phase that does so many things it's kind of hard to describe briefly."
+ def newPhase(prev: Phase) = new TestPhase(prev)
+ class TestPhase(prev: Phase) extends StdPhase(prev) {
+ override def description = TestComponent.this.description
+ def apply(unit: CompilationUnit) {
+ // kewl kode
+ }
+ }
+ }
+}
diff --git a/test/files/neg/t6446-list/sample_2.flags b/test/files/neg/t6446-list/sample_2.flags
new file mode 100644
index 0000000000..9cb3232964
--- /dev/null
+++ b/test/files/neg/t6446-list/sample_2.flags
@@ -0,0 +1 @@
+-Xplugin:. -Xplugin-list
diff --git a/test/files/neg/t6446-list/sample_2.scala b/test/files/neg/t6446-list/sample_2.scala
new file mode 100644
index 0000000000..73cdc64e40
--- /dev/null
+++ b/test/files/neg/t6446-list/sample_2.scala
@@ -0,0 +1,6 @@
+
+package sample
+
+// just a sample that is compiled with the sample plugin enabled
+object Sample extends App {
+}
diff --git a/test/files/neg/t6446-list/scalac-plugin.xml b/test/files/neg/t6446-list/scalac-plugin.xml
new file mode 100644
index 0000000000..e849bb5919
--- /dev/null
+++ b/test/files/neg/t6446-list/scalac-plugin.xml
@@ -0,0 +1,4 @@
+<plugin>
+<name>sample-plugin</name>
+<classname>t6446.Ploogin</classname>
+</plugin>
diff --git a/test/files/neg/t6446-missing.check b/test/files/neg/t6446-missing.check
new file mode 100755
index 0000000000..f976bf480e
--- /dev/null
+++ b/test/files/neg/t6446-missing.check
@@ -0,0 +1,31 @@
+Warning: class not found: t6446.Ploogin
+ phase name id description
+ ---------- -- -----------
+ parser 1 parse source into ASTs, perform simple desugaring
+ namer 2 resolve names, attach symbols to named trees
+packageobjects 3 load package objects
+ typer 4 the meat and potatoes: type the trees
+ patmat 5 translate match expressions
+superaccessors 6 add super accessors in traits and nested classes
+ extmethods 7 add extension methods for inline classes
+ pickler 8 serialize symbol tables
+ refchecks 9 reference/override checking, translate nested objects
+ uncurry 10 uncurry, translate function values to anonymous classes
+ tailcalls 11 replace tail calls by jumps
+ specialize 12 @specialized-driven class and method specialization
+ explicitouter 13 this refs to outer pointers, translate patterns
+ erasure 14 erase types, add interfaces for traits
+ posterasure 15 clean up erased inline classes
+ lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ icode 22 generate portable intermediate code
+ inliner 23 optimization: do inlining
+inlinehandlers 24 optimization: inline exception handlers
+ closelim 25 optimization: eliminate uncalled closures
+ dce 26 optimization: eliminate dead code
+ jvm 27 generate JVM bytecode
+ terminal 28 The last phase in the compiler chain
diff --git a/test/files/neg/t6446-missing/sample_2.flags b/test/files/neg/t6446-missing/sample_2.flags
new file mode 100644
index 0000000000..4d518c2286
--- /dev/null
+++ b/test/files/neg/t6446-missing/sample_2.flags
@@ -0,0 +1 @@
+-Xplugin:. -Xshow-phases
diff --git a/test/files/neg/t6446-missing/sample_2.scala b/test/files/neg/t6446-missing/sample_2.scala
new file mode 100644
index 0000000000..73cdc64e40
--- /dev/null
+++ b/test/files/neg/t6446-missing/sample_2.scala
@@ -0,0 +1,6 @@
+
+package sample
+
+// just a sample that is compiled with the sample plugin enabled
+object Sample extends App {
+}
diff --git a/test/files/neg/t6446-missing/scalac-plugin.xml b/test/files/neg/t6446-missing/scalac-plugin.xml
new file mode 100644
index 0000000000..9c34d63f83
--- /dev/null
+++ b/test/files/neg/t6446-missing/scalac-plugin.xml
@@ -0,0 +1,4 @@
+<plugin>
+<name>missing-plugin</name>
+<classname>t6446.Ploogin</classname>
+</plugin>
diff --git a/test/files/neg/t6446-show-phases.check b/test/files/neg/t6446-show-phases.check
new file mode 100644
index 0000000000..5bbe43990c
--- /dev/null
+++ b/test/files/neg/t6446-show-phases.check
@@ -0,0 +1,30 @@
+ phase name id description
+ ---------- -- -----------
+ parser 1 parse source into ASTs, perform simple desugaring
+ namer 2 resolve names, attach symbols to named trees
+packageobjects 3 load package objects
+ typer 4 the meat and potatoes: type the trees
+ patmat 5 translate match expressions
+superaccessors 6 add super accessors in traits and nested classes
+ extmethods 7 add extension methods for inline classes
+ pickler 8 serialize symbol tables
+ refchecks 9 reference/override checking, translate nested objects
+ uncurry 10 uncurry, translate function values to anonymous classes
+ tailcalls 11 replace tail calls by jumps
+ specialize 12 @specialized-driven class and method specialization
+ explicitouter 13 this refs to outer pointers, translate patterns
+ erasure 14 erase types, add interfaces for traits
+ posterasure 15 clean up erased inline classes
+ lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ icode 22 generate portable intermediate code
+ inliner 23 optimization: do inlining
+inlinehandlers 24 optimization: inline exception handlers
+ closelim 25 optimization: eliminate uncalled closures
+ dce 26 optimization: eliminate dead code
+ jvm 27 generate JVM bytecode
+ terminal 28 The last phase in the compiler chain
diff --git a/test/files/neg/t6446-show-phases.flags b/test/files/neg/t6446-show-phases.flags
new file mode 100644
index 0000000000..845666e100
--- /dev/null
+++ b/test/files/neg/t6446-show-phases.flags
@@ -0,0 +1 @@
+-Xshow-phases
diff --git a/test/files/neg/t6446-show-phases.scala b/test/files/neg/t6446-show-phases.scala
new file mode 100644
index 0000000000..a9afb042d2
--- /dev/null
+++ b/test/files/neg/t6446-show-phases.scala
@@ -0,0 +1,3 @@
+
+// testing compiler flag output only
+object Test extends App
diff --git a/test/files/run/inline-ex-handlers.scala b/test/files/run/inline-ex-handlers.scala
index a96b938e13..33e794b940 100644
--- a/test/files/run/inline-ex-handlers.scala
+++ b/test/files/run/inline-ex-handlers.scala
@@ -1,7 +1,7 @@
import scala.tools.partest.IcodeTest
object Test extends IcodeTest {
- override def printIcodeAfterPhase = "inlineExceptionHandlers"
+ override def printIcodeAfterPhase = "inlinehandlers"
}
import scala.util.Random._
diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check
index bdf76ddce1..d472c569d2 100644
--- a/test/files/run/programmatic-main.check
+++ b/test/files/run/programmatic-main.check
@@ -1,31 +1,31 @@
- phase name id description
- ---------- -- -----------
- parser 1 parse source into ASTs, perform simple desugaring
- namer 2 resolve names, attach symbols to named trees
- packageobjects 3 load package objects
- typer 4 the meat and potatoes: type the trees
- patmat 5 translate match expressions
- superaccessors 6 add super accessors in traits and nested classes
- extmethods 7 add extension methods for inline classes
- pickler 8 serialize symbol tables
- refchecks 9 reference/override checking, translate nested objects
- uncurry 10 uncurry, translate function values to anonymous classes
- tailcalls 11 replace tail calls by jumps
- specialize 12 @specialized-driven class and method specialization
- explicitouter 13 this refs to outer pointers, translate patterns
- erasure 14 erase types, add interfaces for traits
- posterasure 15 clean up erased inline classes
- lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 17 move nested functions to top level
- constructors 18 move field definitions into constructors
- flatten 19 eliminate inner classes
- mixin 20 mixin composition
- cleanup 21 platform-specific cleanups, generate reflective calls
- icode 22 generate portable intermediate code
- inliner 23 optimization: do inlining
-inlineExceptionHandlers 24 optimization: inline exception handlers
- closelim 25 optimization: eliminate uncalled closures
- dce 26 optimization: eliminate dead code
- jvm 27 generate JVM bytecode
- terminal 28 The last phase in the compiler chain
+ phase name id description
+ ---------- -- -----------
+ parser 1 parse source into ASTs, perform simple desugaring
+ namer 2 resolve names, attach symbols to named trees
+packageobjects 3 load package objects
+ typer 4 the meat and potatoes: type the trees
+ patmat 5 translate match expressions
+superaccessors 6 add super accessors in traits and nested classes
+ extmethods 7 add extension methods for inline classes
+ pickler 8 serialize symbol tables
+ refchecks 9 reference/override checking, translate nested objects
+ uncurry 10 uncurry, translate function values to anonymous classes
+ tailcalls 11 replace tail calls by jumps
+ specialize 12 @specialized-driven class and method specialization
+ explicitouter 13 this refs to outer pointers, translate patterns
+ erasure 14 erase types, add interfaces for traits
+ posterasure 15 clean up erased inline classes
+ lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ icode 22 generate portable intermediate code
+ inliner 23 optimization: do inlining
+inlinehandlers 24 optimization: inline exception handlers
+ closelim 25 optimization: eliminate uncalled closures
+ dce 26 optimization: eliminate dead code
+ jvm 27 generate JVM bytecode
+ terminal 28 The last phase in the compiler chain
diff --git a/test/files/pos/t4351.check b/test/files/run/t4351.check
index cb5d407e13..cb5d407e13 100644
--- a/test/files/pos/t4351.check
+++ b/test/files/run/t4351.check
diff --git a/test/files/pos/t4351.scala b/test/files/run/t4351.scala
index 2d57588793..d954d748b7 100644
--- a/test/files/pos/t4351.scala
+++ b/test/files/run/t4351.scala
@@ -1,7 +1,8 @@
object Test {
def main(args: Array[String]): Unit = {
- try new BooleanPropImpl() value
+ try new BooleanPropImpl().value
catch {
+ // was: StackOverflowError
case e: RuntimeException => println("runtime exception")
}
}