summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-02-18 18:49:21 +0000
committerPaul Phillips <paulp@improving.org>2010-02-18 18:49:21 +0000
commit388a0c0d1db3e41e3acbebd6e1e4c79f7d176ca3 (patch)
treef1f5df26496c614446cea6b970f48c6659ad803d
parent23e5428008fc88377e59a1a5c20d5476c586d62e (diff)
downloadscala-388a0c0d1db3e41e3acbebd6e1e4c79f7d176ca3.tar.gz
scala-388a0c0d1db3e41e3acbebd6e1e4c79f7d176ca3.tar.bz2
scala-388a0c0d1db3e41e3acbebd6e1e4c79f7d176ca3.zip
The first reasonably satisfying classpath commit.
there with this one. Documentation to come. Review by community.
-rw-r--r--src/compiler/scala/tools/nsc/GenericRunnerSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala4
-rw-r--r--src/compiler/scala/tools/nsc/MainGenericRunner.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala60
-rw-r--r--src/compiler/scala/tools/nsc/backend/JavaPlatform.scala12
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Completion.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala11
-rw-r--r--src/compiler/scala/tools/util/ClassPathSettings.scala37
-rw-r--r--src/compiler/scala/tools/util/PathResolver.scala251
-rw-r--r--src/compiler/scala/tools/util/StringOps.scala66
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala4
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleFileManager.scala62
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleRunner.scala4
-rw-r--r--src/partest/scala/tools/partest/nest/TestFile.scala6
-rw-r--r--src/partest/scala/tools/partest/package.scala14
-rw-r--r--src/scalap/scala/tools/scalap/Main.scala2
-rw-r--r--test/files/run/programmatic-main.scala5
19 files changed, 237 insertions, 315 deletions
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
index 76cb8e608b..6697146a5a 100644
--- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
+++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
@@ -38,6 +38,4 @@ extends Settings(error) {
BooleanSetting(
"-nocompdaemon",
"do not use the fsc compilation daemon")
-
- val defines = DefinesSetting
}
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 3b6b7a1a7f..6e06518a7a 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -192,7 +192,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** the compiler's classpath, as URL's */
/** XXX ignoring codebase for now, but it used to be appended here. */
/** (And one would think it ought to be prepended. */
- lazy val compilerClasspath: List[URL] = new PathResolver(settings) minimalPathAsURLs
+ lazy val compilerClasspath: List[URL] = new PathResolver(settings) asURLs
/* A single class loader is used for all commands interpreted by this Interpreter.
It would also be possible to create a new class loader for each command
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index 7060c14ea2..c04feb9efd 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -112,8 +112,8 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
/** Create a new interpreter. */
def createInterpreter() {
- if (!addedClasspath.isEmpty)
- addedClasspath foreach (settings appendToClasspath _)
+ // if (!addedClasspath.isEmpty)
+ // addedClasspath foreach (settings appendToClasspath _)
interpreter = new Interpreter(settings, out) {
override protected def parentClassLoader = classOf[InterpreterLoop].getClassLoader
diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
index 719425c40c..bb373c69e4 100644
--- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala
+++ b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
@@ -13,7 +13,7 @@ import java.lang.reflect.InvocationTargetException
import java.net.{ URL, MalformedURLException }
import scala.tools.util.PathResolver
-import io.{ File }
+import io.{ File, Process }
import util.{ ClassPath, ScalaClassLoader }
import Properties.{ versionString, copyrightString }
@@ -43,7 +43,7 @@ object MainGenericRunner {
def dashi = settings.loadfiles.value
def slurp = dashi map (file => File(file).slurp()) mkString "\n"
- val classpath: List[URL] = PathResolver urlsFromSettings settings
+ val classpath: List[URL] = new PathResolver(settings) asURLs
/** Was code given in a -e argument? */
if (!settings.execute.isDefault) {
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index 5d5e4c8c43..0cd5fe1f6a 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -300,8 +300,8 @@ object ScriptRunner
compiledLocation: String,
scriptArgs: List[String]): Boolean =
{
- val classpath =
- (PathResolver urlsFromSettings settings) ::: (PathResolver fromPathString compiledLocation asURLs)
+ val pr = new PathResolver(settings)
+ val classpath = pr.asURLs :+ new URL(compiledLocation)
try {
ObjectRunner.run(
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 9585db7c64..39ea8f62c6 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -12,20 +12,13 @@ import io.AbstractFile
import util.{ ClassPath, SourceFile }
import Settings._
import annotation.elidable
-import scala.tools.util.PathResolver
+import scala.tools.util.{ PathResolver, StringOps }
import scala.collection.mutable.ListBuffer
import scala.collection.immutable.TreeSet
class Settings(errorFn: String => Unit) extends ScalacSettings {
def this() = this(Console.println)
- /** It's a hacky situation but there's not much to be done in the
- * face of settings which mutate and semantic significance to the
- * originally given classpath.
- */
- private var _userSuppliedClassPath: String = null
- def userSuppliedClassPath = if (_userSuppliedClassPath == null) "" else _userSuppliedClassPath
-
/** Iterates over the arguments applying them to settings where applicable.
* Then verifies setting dependencies are met.
*
@@ -47,23 +40,13 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
var args = arguments
val residualArgs = new ListBuffer[String]
- /** First time through here we take note of the classpath, if any.
- */
- def finish[T](x: T): T = {
- /** "lazy var" */
- if (_userSuppliedClassPath == null)
- _userSuppliedClassPath = if (classpath.isDefault) "" else classpath.value
-
- x
- }
-
while (args.nonEmpty) {
if (args.head startsWith "-") {
val args0 = args
args = this parseParams args
if (args eq args0) {
errorFn("bad option: '" + args.head + "'")
- return finish((false, args))
+ return ((false, args))
}
}
else if (args.head == "") { // discard empties, sometimes they appear because of ant or etc.
@@ -71,14 +54,14 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
}
else {
if (!processAll)
- return finish((checkDependencies, args))
+ return ((checkDependencies, args))
residualArgs += args.head
args = args.tail
}
}
- finish((checkDependencies, residualArgs.toList))
+ ((checkDependencies, residualArgs.toList))
}
def processArgumentString(params: String) = processArguments(splitParams(params), true)
@@ -124,7 +107,7 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
/** Split the given line into parameters.
*/
- def splitParams(line: String) = PathResolver.splitParams(line, errorFn)
+ def splitParams(line: String) = StringOps.splitParams(line, errorFn)
/** Returns any unprocessed arguments.
*/
@@ -145,19 +128,18 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
// if arg is of form -Xfoo:bar,baz,quux
def parseColonArg(s: String): Option[List[String]] = {
- val idx = s indexWhere (_ == ':')
- val (p, args) = (s.substring(0, idx), s.substring(idx+1).split(",").toList)
+ val (p, args) = StringOps.splitWhere(s, _ == ':', true) getOrElse (return None)
// any non-Nil return value means failure and we return s unmodified
- tryToSetIfExists(p, args, (s: Setting) => s.tryToSetColon _)
+ tryToSetIfExists(p, args split "," toList, (s: Setting) => s.tryToSetColon _)
}
// if arg is of form -Dfoo=bar or -Dfoo (name = "-D")
- def isPropertyArg(s: String) = lookupSetting(s.substring(0, 2)) match {
+ def isPropertyArg(s: String) = lookupSetting(s take 2) match {
case Some(x: DefinesSetting) => true
case _ => false
}
def parsePropertyArg(s: String): Option[List[String]] = {
- val (p, args) = (s.substring(0, 2), s.substring(2))
+ val (p, args) = (s take 2, s drop 2)
tryToSetIfExists(p, List(args), (s: Setting) => s.tryToSetProperty _)
}
@@ -258,8 +240,8 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
lazy val ChoiceSetting = untupled((choice _).tupled andThen add[ChoiceSetting])
lazy val DebugSetting = untupled((sdebug _).tupled andThen add[DebugSetting])
lazy val PhasesSetting = untupled((phase _).tupled andThen add[PhasesSetting])
- lazy val DefinesSetting = add(defines())
lazy val OutputSetting = untupled((output _).tupled andThen add[OutputSetting])
+ lazy val DefinesSetting = () => add(new DefinesSetting())
override def toString() =
"Settings(\n%s)" format (userSetSettings map (" " + _ + "\n") mkString)
@@ -408,8 +390,6 @@ object Settings {
def phase(name: String, descr: String) =
new PhasesSetting(name, descr)
- def defines() = new DefinesSetting()
-
def output(outputDirs: OutputDirs, default: String) =
new OutputSetting(outputDirs, default)
}
@@ -653,7 +633,7 @@ object Settings {
extends Setting(descr + choices.mkString(" (", ",", ")")) {
type T = String
protected var v: String = default
- protected def argument: String = name.substring(1)
+ protected def argument: String = name drop 1
def tryToSet(args: List[String]) = { value = default ; Some(args) }
override def tryToSetColon(args: List[String]) = args match {
@@ -747,12 +727,10 @@ object Settings {
// given foo=bar returns Some(foo, bar), or None if parse fails
def parseArg(s: String): Option[(String, String)] = {
if (s == "") return None
- val regexp = """^(.*)?=(.*)$""".r
+ val idx = s indexOf '='
- regexp.findAllIn(s).matchData.toList match {
- case Nil => Some(s, "")
- case List(md) => md.subgroups match { case List(a,b) => Some(a,b) }
- }
+ if (idx < 0) Some(s, "")
+ else Some(s take idx, s drop (idx + 1))
}
private[Settings] override def tryToSetProperty(args: List[String]): Option[List[String]] =
@@ -815,12 +793,14 @@ trait ScalacSettings {
*/
val bootclasspath = StringSetting ("-bootclasspath", "path", "Override location of bootstrap class files", "")
- val classpath = StringSetting ("-classpath", "path", "Specify where to find user class files", "") .
- withAbbreviation("-cp") .
- withPostSetHook(self => if (Ylogcp.value) Console.println("Updated classpath to '%s'".format(self.value)))
+ val classpath = StringSetting ("-classpath", "path", "Specify where to find user class files", "") withAbbreviation ("-cp")
val extdirs = StringSetting ("-extdirs", "dirs", "Override location of installed extensions", "")
val javabootclasspath = StringSetting ("-javabootclasspath", "path", "Override java boot classpath.", "")
+ val javabootAppend = StringSetting ("-javabootclasspath/a", "path", "Append to java boot classpath", "")
+ val javabootPrepend = StringSetting ("-javabootclasspath/p", "path", "Prepend to java boot classpath", "")
val javaextdirs = StringSetting ("-javaextdirs", "path", "Override java extdirs classpath.", "")
+
+ val outdir = OutputSetting (outputDirs, ".")
val sourcepath = StringSetting ("-sourcepath", "path", "Specify where to find input source files", "")
val Ycodebase = StringSetting ("-Ycodebase", "codebase", "Specify the URL containing the Scala libraries", "")
val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.")
@@ -830,7 +810,7 @@ trait ScalacSettings {
*/
// argfiles is only for the help message
val argfiles = BooleanSetting ("@<file>", "A text file containing compiler arguments (options and source files)")
- val outdir = OutputSetting (outputDirs, ".")
+ val defines = DefinesSetting()
val dependenciesFile = StringSetting ("-dependencyfile", "file", "Specify the file in which dependencies are tracked", ".scala_dependencies")
val deprecation = BooleanSetting ("-deprecation", "Output source locations where deprecated APIs are used")
val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files", Properties.sourceEncoding)
diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
index b6dd06f83f..88651220f6 100644
--- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
+++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
@@ -14,17 +14,7 @@ import scala.tools.util.PathResolver
trait JavaPlatform extends Platform[AbstractFile] {
import global._
- lazy val classPath: JavaClassPath = {
- val context =
- if (isInlinerOn) new JavaContext
- else DefaultJavaContext
-
- val cp = PathResolver.fromSettings(settings, context)
- if (settings.Ylogcp.value)
- Console.println("Created Global has classpath: " + cp.asClasspathString)
-
- cp
- }
+ lazy val classPath = new PathResolver(settings).result
def rootLoader = new loaders.JavaPackageLoader(classPath)
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
index 65a6da7c07..b62de995c2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
@@ -53,7 +53,7 @@ import Completion._
class Completion(repl: Interpreter) {
self =>
- private lazy val classPath = PathResolver.fromSettings(repl.settings).asURLs
+ private lazy val classPath = repl.compilerClasspath
// the unqualified vals/defs/etc visible in the repl
val ids = new IdentCompletion(repl)
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 013cd89a44..0e9c4f27fa 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -213,6 +213,13 @@ abstract class ClassPath[T] {
case Some(ClassRep(Some(x: AbstractFile), _)) => Some(x)
case _ => None
}
+
+ def sortString = asURLs map (_.toString) sorted
+ override def equals(that: Any) = that match {
+ case x: ClassPath[_] => this.sortString == x.sortString
+ case _ => false
+ }
+ override def hashCode = sortString.hashCode
}
/**
@@ -311,6 +318,10 @@ extends ClassPath[T] {
case x: DirectoryClassPath => x.dir.path
case x: MergedClassPath[_] => x.asClasspathString
})
+ def show {
+ println("ClassPath %s has %d entries and results in:\n".format(name, entries.size))
+ asClasspathString split ':' foreach (x => println(" " + x))
+ }
override def toString() = "merged classpath "+ entries.mkString("(", "\n", ")")
}
diff --git a/src/compiler/scala/tools/util/ClassPathSettings.scala b/src/compiler/scala/tools/util/ClassPathSettings.scala
new file mode 100644
index 0000000000..49c01d19df
--- /dev/null
+++ b/src/compiler/scala/tools/util/ClassPathSettings.scala
@@ -0,0 +1,37 @@
+/* NSC -- new Scala compiler
+ * Copyright 2006-2010 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package util
+
+trait ClassPathSettings {
+ def javabootclasspath: String // -javabootclasspath
+ def javabootPrepend: String // -javabootclasspath/p
+ def javabootAppend: String // -javabootclasspath/a
+ def javaextdirs: String // -javaextdirs
+
+ def bootclasspath: String // -bootclasspath
+ def extdirs: String // -extdirs
+ def classpath: String // -classpath
+ def sourcepath: String // -sourcepath
+
+ def codebase: String // -Ycodebase
+}
+
+// val debugLogger = {
+// val f = File("/tmp/path-resolve-log.txt")
+// if (f.exists) f.truncate()
+// else f.createFile()
+//
+// val res = f.bufferedWriter()
+// res write ("Started debug log: %s\n".format(new java.util.Date))
+// res
+// }
+// def log(msg: Any) = {
+// Console println msg
+// debugLogger.write(msg.toString + "\n")
+// debugLogger flush
+// }
+
diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala
index 9feb61e0a3..c86c6ffe74 100644
--- a/src/compiler/scala/tools/util/PathResolver.scala
+++ b/src/compiler/scala/tools/util/PathResolver.scala
@@ -13,29 +13,13 @@ import nsc.io.{ File, Directory, Path }
import ClassPath.{ JavaContext, DefaultJavaContext, join, split }
import PartialFunction.condOpt
-// Mostly based on the specification at:
+// Loosely based on the draft specification at:
// https://lampsvn.epfl.ch/trac/scala/wiki/Classpath
-//
object PathResolver {
- // val debugLogger = {
- // val f = File("/tmp/path-resolve-log.txt")
- // if (f.exists) f.truncate()
- // else f.createFile()
- //
- // val res = f.bufferedWriter()
- // res write ("Started debug log: %s\n".format(new java.util.Date))
- // res
- // }
- // def log(msg: Any) = {
- // Console println msg
- // debugLogger.write(msg.toString + "\n")
- // debugLogger flush
- // }
-
- private def propOrElse(name: String, alt: String) = System.getProperty(name, alt)
- private def envOrElse(name: String, alt: String) = Option(System getenv name) getOrElse alt
- private def firstNonEmpty(xs: String*) = xs find (_ != "") getOrElse ""
+ def propOrElse(name: String, alt: String) = System.getProperty(name, alt)
+ def envOrElse(name: String, alt: String) = Option(System getenv name) getOrElse alt
+ def firstNonEmpty(xs: String*) = xs find (_ != "") getOrElse ""
private def fileOpt(f: Path): Option[String] = f ifFile (_.path)
private def dirOpt(d: Path): Option[String] = d ifDirectory (_.path)
@@ -60,15 +44,21 @@ object PathResolver {
import scala.collection.JavaConversions._
System.getProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse ""
}
+ private def searchForScalaHome = {
+ for (url <- ScalaClassLoader originOfClass classOf[ScalaObject] ; if url.getProtocol == "file") yield
+ File(url.getFile).parent.path
+ } getOrElse ""
def classPathEnv = envOrElse("CLASSPATH", "")
def sourcePathEnv = envOrElse("SOURCEPATH", "") // not used
+ def scalaHomeEnv = envOrElse("SCALA_HOME", "") // not used
def javaBootClassPath = propOrElse("sun.boot.class.path", searchForBootClasspath)
def javaUserClassPath = propOrElse("java.class.path", "")
def javaExtDirs = propOrElse("java.ext.dirs", "")
def userHome = propOrElse("user.home", "")
def scalaHome = propOrElse("scala.home", "")
def scalaExtDirs = propOrElse("scala.ext.dirs", "")
+ def scalaHomeGuessed = searchForScalaHome
override def toString = """
|object Environment {
@@ -88,17 +78,13 @@ object PathResolver {
* to the path resolution specification.
*/
object Defaults {
- private lazy val guessedScalaHome = {
- for (url <- ScalaClassLoader originOfClass classOf[ScalaObject] ; if url.getProtocol == "file") yield
- File(url.getFile).parent.path
- } getOrElse ""
-
- // XXX review these semantics
- def javaBootClassPath = join(Seq(Environment.javaBootClassPath, Environment.javaUserClassPath)) // ... ignoring Environment.classPathEnv
+ def javaBootClassPath = Environment.javaBootClassPath
+ def javaUserClassPath = firstNonEmpty(Environment.javaUserClassPath, Environment.classPathEnv)
def javaExtDirs = Environment.javaExtDirs
- def scalaHome = firstNonEmpty(Environment.scalaHome, guessedScalaHome)
+ def scalaHome = Environment.scalaHome
def scalaHomeDir = Directory(scalaHome)
+ def scalaHomeExists = scalaHomeDir.isDirectory
def scalaLibDir = Directory(scalaHomeDir / "lib")
def scalaClassesDir = Directory(scalaHomeDir / "classes")
@@ -115,31 +101,15 @@ object PathResolver {
else if (scalaLibAsDir.isDirectory) scalaLibAsDir.path
else ""
- // This attempt to duplicate the original logic of MainGenericRunner
- // was causing the issue described in r20878. Obviously it's past time
- // to establish with certainty what each of these paths should contain.
- def scalaBootClassPath = ""
- // scalaLibDirFound match {
- // case Some(dir) => join(ClassPath expandDir dir.path)
- // case _ => ""
- // }
+ def scalaBootClassPath = scalaLibDirFound match {
+ case Some(dir) if scalaHomeExists => join(ClassPath expandDir dir.path)
+ case _ => ""
+ }
def scalaExtDirs = Environment.scalaExtDirs
def scalaPluginDirs = List("misc", "scala-devel", "plugins")
def scalaPluginPath = join(scalaPluginDirs map (scalaHomeDir / _ path))
- // The class path that a runner script uses to interpret a program is called the “execution class path”.
- // The execution class path is the concatenation of the following sub-path.
- // If a class is available in multiple locations, it must be loaded from that with the lowest number.
- def executionPath = List(
- // 1. The Java bootstrap class path.
- javaBootClassPath,
- // 2. The Java extension class path.
- javaExtDirs,
- // 3. The class path formed by all JAR and ZIP files and all folders in Scala's home lib folder.
- scalaBootClassPath
- )
-
override def toString = """
|object Defaults {
| javaBootClassPath = %s
@@ -155,60 +125,10 @@ object PathResolver {
)
}
- def executionPath = join(Defaults.executionPath)
- def executionPathURLs = fromPathString(executionPath).asURLs
-
- private def classPathContainersFromSettings(settings: Settings, context: JavaContext) = {
- val pr = new PathResolver(settings)
- import context._
- import pr.Calculated._
-
- // XXX how should the contents of lib/* break down between bootclasspath and extdirs?
- // XXX what exactly is codebase for?
- val sources = List(
- classesInPath(javaBootClassPath), // -javabootclasspath multiple entries, no expansion
- contentsOfDirsInPath(scalaBootClassPath), // -bootclasspath ???
- contentsOfDirsInPath(javaExtDirs), // -javaextdirs multiple dirs, each expands to contents
- contentsOfDirsInPath(scalaExtDirs), // -extdirs ???
- classesInExpandedPath(userClassPath), // -classpath multiple entries, first expanding *s
- classesAtAllURLS(codeBase), // -Ycodebase ??? multiple URLs
- sourcesInPath(sourcePath) // -sourcepath multiple source entries, no expansion
- )
-
- if (settings.Ylogcp.value)
- Console.println("PathResolver calculated classpath:\n" + pr.Calculated)
-
- sources.flatten
- }
- def urlsFromSettings(settings: Settings): List[URL] = urlsFromSettings(settings, DefaultJavaContext)
- def urlsFromSettings(settings: Settings, context: JavaContext): List[URL] =
- classPathContainersFromSettings(settings, context) flatMap (_.asURLs) distinct
-
- private def contextFromSettings(s: Settings) =
- if (s.inline.value) new JavaContext else DefaultJavaContext
-
- def fromArgumentString(argString: String): JavaClassPath =
- fromArgumentList(splitParams(argString, _ => ()))
-
- def fromArgumentList(args: List[String]): JavaClassPath = {
- val settings = new Settings()
- settings.processArguments(args, false)
- fromSettings(settings, contextFromSettings(settings))
- }
-
- def fromSettings(settings: Settings): JavaClassPath =
- fromSettings(settings, contextFromSettings(settings))
-
- def fromSettings(settings: Settings, context: JavaContext): JavaClassPath = {
- val containers = classPathContainersFromSettings(settings, context)
- new JavaClassPath(containers, context)
- }
-
- def fromPathString(path: String): JavaClassPath = fromPathString(path, DefaultJavaContext)
- def fromPathString(path: String, context: JavaContext): JavaClassPath = {
+ def fromPathString(path: String, context: JavaContext = DefaultJavaContext): JavaClassPath = {
val s = new Settings()
s.classpath.value = path
- fromSettings(s, context)
+ new PathResolver(s, context) result
}
/** With no arguments, show the interesting values in Environment and Defaults.
@@ -226,76 +146,15 @@ object PathResolver {
val pr = new PathResolver(settings)
println(" COMMAND: 'scala %s'".format(args.mkString(" ")))
println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" ")))
- println(pr.Calculated)
+ pr.result.show
}
}
-
- /**
- * Split command line parameters by space, properly process quoted parameter
- */
- def splitParams(line: String, errorFn: String => Unit): List[String] = {
- def parse(from: Int, i: Int, args: List[String]): List[String] = {
- if (i < line.length) {
- line.charAt(i) match {
- case ' ' =>
- val args1 = fetchArg(from, i) :: args
- val j = skipS(i + 1)
- if (j >= 0) {
- parse(j, j, args1)
- } else args1
- case '"' =>
- val j = skipTillQuote(i + 1)
- if (j > 0) {
- parse(from, j + 1, args)
- } else {
- errorFn("Parameters '" + line + "' with unmatched quote at " + i + ".")
- Nil
- }
- case _ => parse(from, i + 1, args)
- }
- } else { // done
- if (i > from) {
- fetchArg(from, i) :: args
- } else args
- }
- }
-
- def fetchArg(from: Int, until: Int) = {
- if (line.charAt(from) == '"') {
- line.substring(from + 1, until - 1)
- } else {
- line.substring(from, until)
- }
- }
-
- def skipTillQuote(i: Int): Int = {
- if (i < line.length) {
- line.charAt(i) match {
- case '"' => i
- case _ => skipTillQuote(i + 1)
- }
- } else -1
- }
-
- def skipS(i: Int): Int = {
- if (i < line.length) {
- line.charAt(i) match {
- case ' ' => skipS(i + 1)
- case _ => i
- }
- } else -1
- }
-
- // begin split
- val j = skipS(0)
- if (j >= 0) {
- parse(j, j, Nil).reverse
- } else Nil
- }
}
import PathResolver.{ Defaults, Environment, firstNonEmpty, ppcp }
-class PathResolver(settings: Settings) {
+class PathResolver(settings: Settings, context: JavaContext) {
+ def this(settings: Settings) = this(settings, if (settings.inline.value) new JavaContext else DefaultJavaContext)
+
private def cmdLineOrElse(name: String, alt: String) = {
(commandLineFor(name) match {
case Some("") => None
@@ -319,56 +178,58 @@ class PathResolver(settings: Settings) {
object Calculated {
def scalaHome = Defaults.scalaHome
def javaBootClassPath = cmdLineOrElse("javabootclasspath", Defaults.javaBootClassPath)
- def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath)
def javaExtDirs = cmdLineOrElse("javaextdirs", Defaults.javaExtDirs)
+ def javaUserClassPath = Defaults.javaUserClassPath
+ def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath)
def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs)
- def userClassPath = cmdLineOrElse("classpath", "")
+ def userClassPath = cmdLineOrElse("classpath", ".")
def sourcePath = cmdLineOrElse("sourcepath", "")
def codeBase = cmdLineOrElse("Ycodebase", "")
- def dotPath = if (settings.userSuppliedClassPath == "") "." else ""
- def referencePath = List(
- // 1. The value of -javabootclasspath if it is set, or the Java bootstrap class path.
- javaBootClassPath,
- // 2. The value of -bootclasspath if it is set,
- // or the lib/scala-library.jar file of Scala's home if it is available,
- // or the classes/library folder of Scala's home if it is available.
- scalaBootClassPath,
- // 3. All JAR and ZIP files present in any folder listed by the value of -javaextdirs, if it is set,
- // or the Java extension class path.
- javaExtDirs,
- // 4. All JAR and ZIP files present in any folder listed by the value of -extdirs, if it is set.
- scalaExtDirs,
- // 5. The first available path below.
- // * The value of -classpath or -cp.
- // * ---> XXX what about java.class.path?
- // * The value of the CLASSPATH environment variable.
- // * The current directory (that is the location of ".").
- userClassPath,
- dotPath
+ import context._
+
+ // Assemble the elements!
+ def basis = List(
+ classesInPath(javaBootClassPath), // 1. The Java bootstrap class path.
+ contentsOfDirsInPath(javaExtDirs), // 2. The Java extension class path.
+ classesInExpandedPath(javaUserClassPath), // 3. The Java application class path.
+ classesInPath(scalaBootClassPath), // 4. The Scala boot class path.
+ contentsOfDirsInPath(scalaExtDirs), // 5. The Scala extension class path.
+ classesInExpandedPath(userClassPath), // 6. The Scala application class path.
+ sourcesInPath(sourcePath) // 7. The Scala source path.
)
+ lazy val containers = basis.flatten.distinct
+
override def toString = """
|object Calculated {
| scalaHome = %s
| javaBootClassPath = %s
+ | javaUserClassPath = %s
| scalaBootClassPath = %s
| javaExtDirs = %s
| scalaExtDirs = %s
| userClassPath = %s
| sourcePath = %s
- | referencePath = %s
|}""".trim.stripMargin.format(
scalaHome,
- ppcp(javaBootClassPath), ppcp(scalaBootClassPath),
+ ppcp(javaBootClassPath), ppcp(javaUserClassPath), ppcp(scalaBootClassPath),
ppcp(javaExtDirs), ppcp(scalaExtDirs),
- ppcp(userClassPath), ppcp(sourcePath),
- ppcp(PathResolver.this.referencePath)
+ ppcp(userClassPath), ppcp(sourcePath)
)
}
- def referencePath = join(Calculated.referencePath)
- def referencePathAsURLs = ClassPath toURLs referencePath
- def minimalPath = join(Seq(Calculated.scalaBootClassPath, Calculated.userClassPath))
- def minimalPathAsURLs = ClassPath toURLs minimalPath
+ def containers = Calculated.containers
+
+ lazy val result = {
+ val cp = new JavaClassPath(containers, context)
+ if (settings.Ylogcp.value) {
+ Console.println("Classpath built from settings: " + settings)
+ Console.println("And Environment: " + PathResolver.Environment)
+ cp.show
+ }
+ cp
+ }
+
+ def asURLs = result.asURLs
}
diff --git a/src/compiler/scala/tools/util/StringOps.scala b/src/compiler/scala/tools/util/StringOps.scala
index 77fc6f8700..b98ab38d89 100644
--- a/src/compiler/scala/tools/util/StringOps.scala
+++ b/src/compiler/scala/tools/util/StringOps.scala
@@ -11,13 +11,75 @@
package scala.tools
package util
-/** This objects provides methods to extract elements from
- * a string according to some defined character separator.
+/** This object provides utility methods to extract elements
+ * from Strings.
*
* @author Martin Odersky
* @version 1.0
*/
object StringOps {
+ /**
+ * Split command line parameters by space, properly process quoted parameter
+ */
+ def splitParams(line: String, errorFn: String => Unit): List[String] = {
+ def parse(from: Int, i: Int, args: List[String]): List[String] = {
+ if (i < line.length) {
+ line.charAt(i) match {
+ case ' ' =>
+ val args1 = fetchArg(from, i) :: args
+ val j = skipS(i + 1)
+ if (j >= 0) {
+ parse(j, j, args1)
+ } else args1
+ case '"' =>
+ val j = skipTillQuote(i + 1)
+ if (j > 0) {
+ parse(from, j + 1, args)
+ } else {
+ errorFn("Parameters '" + line + "' with unmatched quote at " + i + ".")
+ Nil
+ }
+ case _ => parse(from, i + 1, args)
+ }
+ } else { // done
+ if (i > from) {
+ fetchArg(from, i) :: args
+ } else args
+ }
+ }
+
+ def fetchArg(from: Int, until: Int) = {
+ if (line.charAt(from) == '"') {
+ line.substring(from + 1, until - 1)
+ } else {
+ line.substring(from, until)
+ }
+ }
+
+ def skipTillQuote(i: Int): Int = {
+ if (i < line.length) {
+ line.charAt(i) match {
+ case '"' => i
+ case _ => skipTillQuote(i + 1)
+ }
+ } else -1
+ }
+
+ def skipS(i: Int): Int = {
+ if (i < line.length) {
+ line.charAt(i) match {
+ case ' ' => skipS(i + 1)
+ case _ => i
+ }
+ } else -1
+ }
+
+ // begin split
+ val j = skipS(0)
+ if (j >= 0) {
+ parse(j, j, Nil).reverse
+ } else Nil
+ }
def decompose(str: String, sep: Char): List[String] = {
def ws(start: Int): List[String] =
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index 3ef5a0f723..63acf654e2 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -45,7 +45,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
settings.deprecation.value = true
settings.nowarnings.value = false
settings.encoding.value = "iso-8859-1"
- settings.classpath.value += fileManager.LATEST_LIB
+ settings.classpath.value += (pathSeparator + fileManager.LATEST_LIB)
// XXX
// settings.javabootAppend.value = fileManager.LATEST_LIB
@@ -113,7 +113,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
out map { outDir =>
command.settings.outdir.value = outDir.getAbsolutePath
- command.settings appendToClasspath outDir.getAbsolutePath
+ command.settings.classpath.value += (pathSeparator + outDir.getAbsolutePath)
}
val toCompile = files map (_.getPath)
diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
index cd5023573b..258651e0ce 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
@@ -14,6 +14,7 @@ import scala.tools.util.PathResolver
import scala.tools.nsc.io
import io.{ Path, Directory }
import File.pathSeparator
+import PathResolver.{ propOrElse }
class ConsoleFileManager extends FileManager {
implicit private def tempPathConversion(x: Path): File = x.jfile
@@ -47,17 +48,11 @@ class ConsoleFileManager extends FileManager {
NestUI.verbose("CLASSPATH: "+CLASSPATH)
- var JAVACMD = System.getProperty("scalatest.javacmd", "java")
- var JAVAC_CMD = System.getProperty("scalatest.javac_cmd", "javac")
+ var JAVACMD = propOrElse("scalatest.javacmd", "java")
+ var JAVAC_CMD = propOrElse("scalatest.javac_cmd", "javac")
- val prefixFile = {
- val cwd = System.getProperty("user.dir")
- if (cwd != null)
- (new File(cwd)).getCanonicalFile
- else
- error("user.dir property not set")
- }
- val PREFIX = prefixFile.getAbsolutePath
+ val prefixDir = Directory.Current map (_.normalize.toDirectory) getOrElse error("user.dir property not set")
+ val PREFIX = prefixDir.toAbsolute.path
/*
if [ -d "$PREFIX/test" ]; then
@@ -68,38 +63,31 @@ else
abort "Test directory not found";
*/
- val testRootFile = {
- val testRootProp = System.getProperty("scalatest.root")
- val testroot =
- if (testRootProp != null)
- new File(testRootProp)
- else {
- // case 1: cwd is `test`
- if (prefixFile.getName == "test" && (new File(prefixFile, "files")).exists)
- prefixFile
- else {
- // case 2: cwd is `test/..`
- val test = new File(prefixFile, "test")
- val scalaTest = new File(new File(prefixFile, "misc"), "scala-test")
- if (test.isDirectory)
- test
- else if (scalaTest.isDirectory)
- scalaTest
- else
- error("Test directory not found")
- }
- }
- testroot.getCanonicalFile
+ val testRootDir = {
+ val testRootProp = Option(propOrElse("scalatest.root", null)) map (x => Directory(x))
+ def isTestDir(d: Directory) = d.name == "test" && (d / "files" isDirectory)
+
+ (
+ testRootProp orElse (
+ if (isTestDir(prefixDir)) Some(prefixDir) else None // cwd is `test`
+ ) orElse (
+ (prefixDir / "test") ifDirectory (x => x) // cwd is `test/..`
+ ) orElse (
+ (prefixDir / "misc" / "scala-test") ifDirectory (x => x)
+ ) getOrElse (
+ error("Test directory not found")
+ )
+ ).normalize
}
- val TESTROOT = testRootFile.getAbsolutePath
+ val TESTROOT = testRootDir.toAbsolute.path
- def testParent = Path(testRootFile).parent
+ def testParent = testRootDir.parent
var srcDirName: String = ""
val srcDir: io.Directory = {
srcDirName = Option(System.getProperty("partest.srcdir")) getOrElse "files"
- val src = Path(testRootFile) / srcDirName
+ val src = testRootDir / srcDirName
if (src.isDirectory) src.toDirectory
else {
@@ -108,7 +96,7 @@ else
}
}
- LIB_DIR = (Path(testRootFile.getParentFile) / "lib").normalize.toAbsolute.path
+ LIB_DIR = (testParent / "lib").normalize.toAbsolute.path
CLASSPATH = {
val libs = (srcDir / Directory("lib")).files filter (_ hasExtension "jar") map (_.normalize.toAbsolute.path)
@@ -177,7 +165,7 @@ else
val dists = testParent / "dists"
val build = testParent / "build"
- // in case of an installed dist, testRootFile is one level deeper
+ // in case of an installed dist, testRootDir is one level deeper
val bin = testParent.parent / "bin"
def mostRecentOf(base: String, names: String*) =
diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
index 373da5e3db..1ba2ce61a4 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -128,8 +128,8 @@ class ConsoleRunner extends DirectRunner with RunnerUtils {
val dir =
if (!fileManager.testClasses.isEmpty)
fileManager.testClassesDir
- else if (fileManager.testBuild != null)
- fileManager.testBuildFile
+ else if (fileManager.testBuildFile.isDefined)
+ fileManager.testBuildFile.get
else
fileManager.latestCompFile.getParentFile.getParentFile.getCanonicalFile
NestUI.outline("Scala compiler classes in: "+dir+"\n")
diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala
index 90d8db936f..e4f1d98c06 100644
--- a/src/partest/scala/tools/partest/nest/TestFile.scala
+++ b/src/partest/scala/tools/partest/nest/TestFile.scala
@@ -22,8 +22,7 @@ abstract class TestFile(kind: String) {
val fileBase: String = basename(file.getName)
def objDir = fileBase + "-" + kind + ".obj"
- // @mutates settings
- protected def baseSettings(settings: Settings) {
+ def defineSettings(settings: Settings) {
settings appendToClasspath dirpath
if (createOutDir) {
@@ -34,10 +33,7 @@ abstract class TestFile(kind: String) {
// add additional flags found in 'testname.flags'
def flagsPath = Path(dir) / (fileBase + ".flags")
flagsPath ifFile { _.slurp().trim } foreach (settings processArgumentString _)
- }
- def defineSettings(settings: Settings) {
- baseSettings(settings)
settings appendToClasspath fileManager.CLASSPATH
}
diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala
index 017974c232..d814fc4fc7 100644
--- a/src/partest/scala/tools/partest/package.scala
+++ b/src/partest/scala/tools/partest/package.scala
@@ -7,23 +7,21 @@ package scala.tools
package object partest {
import nest.NestUI
- def showVMArgs {
+ def vmArgString = {
import scala.tools.nsc.io.Process
val str = Process.javaVmArguments mkString " "
- NestUI.verbose("Java VM started with arguments: '%s'" format str)
+ "Java VM started with arguments: '%s'" format str
}
- def showAllProperties {
+ def allPropertiesString = {
import collection.JavaConversions._
- for ((k, v) <- System.getProperties.toList.sorted) {
- NestUI.verbose("%s -> %s".format(k, v))
- }
+ System.getProperties.toList.sorted map { case (k, v) => "%s -> %s\n".format(k, v) } mkString
}
def showAllJVMInfo {
- showVMArgs
- showAllProperties
+ NestUI.verbose(vmArgString)
+ NestUI.verbose(allPropertiesString)
}
def isPartestDebug = {
diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala
index b9c2ab0cc8..eee689c189 100644
--- a/src/scalap/scala/tools/scalap/Main.scala
+++ b/src/scalap/scala/tools/scalap/Main.scala
@@ -12,7 +12,7 @@ package scala.tools.scalap
import java.io.{File, PrintStream, OutputStreamWriter, ByteArrayOutputStream}
import scalax.rules.scalasig._
import tools.nsc.io.AbstractFile
-import tools.nsc.util.{ ClassPath, JavaClassPath }
+import tools.nsc.util.{ ClassPath }
import tools.util.PathResolver
import ClassPath.DefaultJavaContext
diff --git a/test/files/run/programmatic-main.scala b/test/files/run/programmatic-main.scala
index b6fbdb9d30..0e91d219a7 100644
--- a/test/files/run/programmatic-main.scala
+++ b/test/files/run/programmatic-main.scala
@@ -3,8 +3,9 @@ import io.Path
object Test
{
- val basedir = (Path(System.getProperty("scalatest.cwd")).parent / "lib").path
- val baseargs = Array("-bootclasspath", basedir + "scala-library.jar", "-cp", basedir + "scala-compiler.jar")
+ val cwd = Option(System.getProperty("scalatest.cwd")) getOrElse "."
+ val basedir = (Path(cwd).parent / "lib").path
+ val baseargs = Array("-bootclasspath", basedir + "/scala-library.jar", "-cp", basedir + "/scala-compiler.jar")
def main(args: Array[String]): Unit = {
Main process (baseargs ++ Array("-Xshow-phases"))