summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-03-26 19:42:25 +0000
committerPaul Phillips <paulp@improving.org>2011-03-26 19:42:25 +0000
commit3e5cd92cbb455f046f70552f1dd127404b32f4b2 (patch)
tree1eb91e77e931d2d9dec86a8d9e5b28358a0b9467
parentf84a12bfbba20d043800fb8b4af9b2bcf79f9d27 (diff)
downloadscala-3e5cd92cbb455f046f70552f1dd127404b32f4b2.tar.gz
scala-3e5cd92cbb455f046f70552f1dd127404b32f4b2.tar.bz2
scala-3e5cd92cbb455f046f70552f1dd127404b32f4b2.zip
Some accumulated work and polish on classpath a...
Some accumulated work and polish on classpath and jars. No review.
-rw-r--r--src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala39
-rw-r--r--src/compiler/scala/tools/nsc/io/Jar.scala41
-rw-r--r--src/compiler/scala/tools/nsc/io/Sources.scala26
-rw-r--r--src/compiler/scala/tools/nsc/settings/AestheticSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala4
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala12
-rw-r--r--src/library/scala/sys/SystemProperties.scala16
7 files changed, 94 insertions, 46 deletions
diff --git a/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala b/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala
new file mode 100644
index 0000000000..88efe1e0b5
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala
@@ -0,0 +1,39 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package io
+
+import java.net.URL
+import collection.JavaConverters._
+
+/** A convenience class for finding the jar with the bytecode for
+ * a given Class object and similar common tasks.
+ */
+class ClassAndJarInfo[T: ClassManifest] {
+ val man = classManifest[T]
+ def clazz = man.erasure
+
+ def baseOfPath(path: String) = path indexOf '!' match {
+ case -1 => path stripSuffix internalClassName
+ case idx => path take idx
+ }
+
+ def classUrl = clazz getResource simpleClassName + ".class"
+ def codeSource = protectionDomain.getCodeSource()
+ def internalClassName = internalName + ".class"
+ def internalName = clazz.getName.replace('.', '/')
+ def jarManifest = new JManifest(jarManifestUrl.openStream())
+ def jarManifestMainAttrs = jarManifest.getMainAttributes().asScala
+ def jarManifestUrl = new URL(baseOfPath("" + classUrl) + "!/META-INF/MANIFEST.MF")
+ def locationFile = File(locationUrl.toURI.getPath())
+ def locationUrl = if (codeSource == null) new URL("file:///") else codeSource.getLocation()
+ def protectionDomain = clazz.getProtectionDomain()
+ def rootClasspath = rootPossibles find (_.exists)
+ def rootFromLocation = Path(locationUrl.toURI.getPath())
+ def rootFromResource = Path(baseOfPath(classUrl.getPath) stripPrefix "file:")
+ def rootPossibles = Iterator(rootFromResource, rootFromLocation)
+ def simpleClassName = clazz.getName split """[$.]""" last
+}
diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala
index a9f0acaa00..bd7dbde5ec 100644
--- a/src/compiler/scala/tools/nsc/io/Jar.scala
+++ b/src/compiler/scala/tools/nsc/io/Jar.scala
@@ -1,3 +1,8 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
package scala.tools.nsc
package io
@@ -5,6 +10,27 @@ import java.io.{ InputStream, OutputStream, IOException, FileNotFoundException,
import java.util.jar._
import collection.JavaConverters._
import Attributes.Name
+import util.ClassPath
+
+// Attributes.Name instances:
+//
+// static Attributes.Name CLASS_PATH
+// static Attributes.Name CONTENT_TYPE
+// static Attributes.Name EXTENSION_INSTALLATION
+// static Attributes.Name EXTENSION_LIST
+// static Attributes.Name EXTENSION_NAME
+// static Attributes.Name IMPLEMENTATION_TITLE
+// static Attributes.Name IMPLEMENTATION_URL
+// static Attributes.Name IMPLEMENTATION_VENDOR
+// static Attributes.Name IMPLEMENTATION_VENDOR_ID
+// static Attributes.Name IMPLEMENTATION_VERSION
+// static Attributes.Name MAIN_CLASS
+// static Attributes.Name MANIFEST_VERSION
+// static Attributes.Name SEALED
+// static Attributes.Name SIGNATURE_VERSION
+// static Attributes.Name SPECIFICATION_TITLE
+// static Attributes.Name SPECIFICATION_VENDOR
+// static Attributes.Name SPECIFICATION_VERSION
class Jar(file: File) extends Iterable[JarEntry] {
def this(path: String) = this(File(path))
@@ -74,21 +100,6 @@ object Jar {
def isJarOrZip(f: Path, examineFile: Boolean): Boolean =
f.hasExtension("zip", "jar") || (examineFile && magicNumberIsZip(f))
- def locateByClass(clazz: Class[_]): Option[File] = {
- try Some(File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()))
- catch { case _: Exception => None }
- }
- /** Walks upward from wherever the scala library jar is searching for
- * the given jar name. This approach finds the scala library jar in the
- * release layout and in trunk builds going up from pack.
- */
- def locateByName(name: String): Option[File] = {
- def toSrc(d: Directory) = d.dirs.toList map (_ / name)
- def walk(d: Directory) = d.parents flatMap toSrc find (_.isFile) map (_.toFile)
-
- locateByClass(classOf[ScalaObject]) flatMap (x => walk(x.parent))
- }
-
def create(file: File, sourceDir: Directory, mainClass: String): File = {
val writer = new Jar(file).jarWriter()
writer.manifest(Name.MANIFEST_VERSION) = "1.0"
diff --git a/src/compiler/scala/tools/nsc/io/Sources.scala b/src/compiler/scala/tools/nsc/io/Sources.scala
index c763b04511..35c7a504a5 100644
--- a/src/compiler/scala/tools/nsc/io/Sources.scala
+++ b/src/compiler/scala/tools/nsc/io/Sources.scala
@@ -4,7 +4,6 @@ package io
import util.ClassPath
import java.util.concurrent.{ Future, ConcurrentHashMap, ExecutionException }
import java.util.zip.ZipException
-import Jar.{ isJarOrZip, locateByClass }
import collection.JavaConverters._
import Properties.{ envOrElse, propOrElse }
@@ -20,7 +19,7 @@ class Sources(val path: String) {
private val partitioned = ClassPath toPaths expandedPath partition (_.isDirectory)
val dirs = partitioned._1 map (_.toDirectory)
- val jars = partitioned._2 filter isJarOrZip map (_.toFile)
+ val jars = partitioned._2 filter Jar.isJarOrZip map (_.toFile)
val (isDone, force) = {
val f1 = spawn(calculateDirs())
val f2 = spawn(calculateJars())
@@ -63,25 +62,12 @@ trait LowPrioritySourcesImplicits {
}
object Sources extends LowPrioritySourcesImplicits {
- // Examples of what libraryJar might be, each of which we'd like to find
- // the source files automatically:
- //
- // /scala/trunk/build/pack/lib/scala-library.jar
- // /scala/trunk/build/quick/classes/library
- // /scala/inst/scala-2.9.0.r24213-b20110206233447/lib/scala-library.jar
- private def libraryJar = locateByClass(classOf[ScalaObject]) map (_.toAbsolute.path)
- private def autoSourcePaths: List[String] = libraryJar.toList flatMap { lib =>
- val markers = List("build/pack/lib", "build/quick/classes", "scala-library.jar")
- markers filter (lib contains _) flatMap { m =>
- val dir = Path(lib take lib.indexOf(m)) / "src"
-
- if (dir.exists) ClassPath.expandDir(dir.path)
- else Nil
- }
- }
+ private def libraryInits = ClassPath.scalaLibrary.toList flatMap (_.toAbsolute.parents)
+ private def librarySourceDir = libraryInits map (_ / "src") find (_.isDirectory)
+ private def expandedSourceDir = librarySourceDir.toList flatMap (ClassPath expandDir _.path)
- val sourcePathEnv = envOrElse("SOURCEPATH", "")
- val defaultSources = apply(autoSourcePaths :+ sourcePathEnv: _*)
+ val sourcePathProp = sys.props.traceSourcePath.value
+ val defaultSources = apply(expandedSourceDir :+ sourcePathProp: _*)
def apply(paths: String*): Sources = new Sources(ClassPath.join(paths: _*))
}
diff --git a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
index d7bec764b3..0908ea60b6 100644
--- a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
@@ -25,7 +25,7 @@ trait AestheticSettings {
def fatalWarnings = settings.Xwarnfatal.value
def logClasspath = settings.Ylogcp.value
def printStats = settings.Ystatistics.value
- def richExes = settings.YrichExes.value
+ def richExes = settings.YrichExes.value || sys.props.traceSourcePath.isSet
def target = settings.target.value
def unchecked = settings.unchecked.value
def verbose = settings.verbose.value
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 7405ca0b3d..14915da9ba 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -134,7 +134,9 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
ChoiceSetting ("-Ystruct-dispatch", "policy", "structural method dispatch policy",
List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache")
val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.")
- val YrichExes = BooleanSetting ("-Yrich-exceptions", "More revealing exceptions. Set SOURCEPATH to java/scala source jars.")
+ val YrichExes = BooleanSetting ("-Yrich-exceptions",
+ "Fancier exceptions. Set source search path with -D" +
+ sys.SystemProperties.traceSourcePath.key)
val Yidedebug = BooleanSetting ("-Yide-debug", "Generate, validate and output trees using the interactive compiler.")
val Ybuilderdebug = ChoiceSetting ("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
val Ybuildmanagerdebug =
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index bb404480a9..962062eb2d 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -9,9 +9,9 @@ package util
import java.net.URL
import scala.collection.mutable.ListBuffer
-import io.{ File, Directory, Path, AbstractFile }
+import io.{ File, Directory, Path, Jar, AbstractFile, ClassAndJarInfo }
import scala.tools.util.StringOps.splitWhere
-import Path.isJarOrZip
+import Jar.isJarOrZip
import File.pathSeparator
/** <p>
@@ -22,6 +22,14 @@ import File.pathSeparator
* @author Stepan Koltsov
*/
object ClassPath {
+ def scalaLibrary = locate[ScalaObject]
+ def scalaCompiler = locate[Global]
+
+ def info[T: ClassManifest] = new ClassAndJarInfo[T]
+ def locate[T: ClassManifest] = info[T] rootClasspath
+ def locateJar[T: ClassManifest] = info[T].rootPossibles find (x => isJarOrZip(x)) map (x => File(x))
+ def locateDir[T: ClassManifest] = info[T].rootPossibles find (_.isDirectory) map (_.toDirectory)
+
/** Expand single path entry */
private def expandS(pattern: String): List[String] = {
val wildSuffix = File.separator + "*"
diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala
index 228ca6315e..296db9e469 100644
--- a/src/library/scala/sys/SystemProperties.scala
+++ b/src/library/scala/sys/SystemProperties.scala
@@ -55,14 +55,15 @@ object SystemProperties {
implicit def systemPropertiesToCompanion(p: SystemProperties): SystemProperties.type = this
private lazy val propertyHelp = mutable.Map[String, String]()
- private def bool(key: String, helpText: String): BooleanProp = {
- val prop = (
- if (key startsWith "java.") BooleanProp.valueIsTrue(key)
- else BooleanProp.keyExists(key)
- )
- propertyHelp(key) = helpText
- prop
+ private def addHelp[P <: Prop[_]](p: P, helpText: String): P = {
+ propertyHelp(p.key) = helpText
+ p
}
+ private def str(key: String, helpText: String) = addHelp(Prop[String](key), helpText)
+ private def bool(key: String, helpText: String): BooleanProp = addHelp[BooleanProp](
+ if (key startsWith "java.") BooleanProp.valueIsTrue(key) else BooleanProp.keyExists(key),
+ helpText
+ )
def help(key: String) = propertyHelp.getOrElse(key, "")
// Todo: bring some sanity to the intersection of system properties aka "mutable
@@ -72,5 +73,6 @@ object SystemProperties {
lazy val preferIPv4Stack = bool("java.net.preferIPv4Stack", "system should prefer IPv4 sockets")
lazy val preferIPv6Addresses = bool("java.net.preferIPv6Addresses", "system should prefer IPv6 addresses")
lazy val noTraceSupression = bool("scala.control.noTraceSuppression", "scala should not suppress any stack trace creation")
+ lazy val traceSourcePath = str("scala.control.sourcepath", "sourcepath for looking up stack trace elements")
}