summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/util/ClassPath.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/util/ClassPath.scala')
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala225
1 files changed, 122 insertions, 103 deletions
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 40c3316e09..e1cf6e55d9 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc
package util
import java.net.URL
-import scala.collection.mutable.ListBuffer
+import scala.collection.mutable
import io.{ File, Directory, Path, Jar, AbstractFile, ClassAndJarInfo }
import scala.tools.util.StringOps.splitWhere
import Jar.isJarOrZip
@@ -55,21 +55,21 @@ object ClassPath {
* (name, list of origins)
* in the order they occur on the path.
*/
- def findDuplicates(cp: ClassPath[_]) = {
- def toFullName(x: (String, _, cp.AnyClassRep)) = x._1 + "." + x._3.name
- def toOriginString(x: ClassPath[_]) = x.origin getOrElse x.name
-
- /** Flatten everything into tuples, recombine grouped by name, filter down to 2+ entries. */
- val flattened = (
- for ((pkgName, pkg) <- cp.allPackagesWithNames ; clazz <- pkg.classes) yield
- (pkgName, pkg, clazz)
- )
- val multipleAppearingEntries = flattened groupBy toFullName filter (_._2.size > 1)
-
- /** Extract results. */
- for (name <- flattened map toFullName distinct ; dups <- multipleAppearingEntries get name) yield
- (name, dups map { case (_, cp, _) => toOriginString(cp) })
- }
+ // def findDuplicates(cp: ClassPath[_]) = {
+ // def toFullName(x: (String, _, cp.AnyClassRep)) = x._1 + "." + x._3.name
+ // def toOriginString(x: ClassPath[_]) = x.origin getOrElse x.name
+ //
+ // /** Flatten everything into tuples, recombine grouped by name, filter down to 2+ entries. */
+ // val flattened = (
+ // for ((pkgName, pkg) <- cp.allPackagesWithNames ; clazz <- pkg.classes) yield
+ // (pkgName, pkg, clazz)
+ // )
+ // val multipleAppearingEntries = flattened groupBy toFullName filter (_._2.size > 1)
+ //
+ // /** Extract results. */
+ // for (name <- flattened map toFullName distinct ; dups <- multipleAppearingEntries get name) yield
+ // (name, dups map { case (_, cp, _) => toOriginString(cp) })
+ // }
/** Split classpath using platform-dependent path separator */
def split(path: String): List[String] = (path split pathSeparator).toList filterNot (_ == "") distinct
@@ -149,7 +149,9 @@ object ClassPath {
for (url <- specToURL(spec).toList ; location <- Option(AbstractFile getURL url)) yield
newClassPath(location)
- def classesInExpandedPath(path: String) = classesInPathImpl(path, true)
+ def classesInExpandedPath(path: String): IndexedSeq[ClassPath[T]] =
+ classesInPathImpl(path, true).toIndexedSeq
+
def classesInPath(path: String) = classesInPathImpl(path, false)
// Internal
@@ -160,8 +162,9 @@ object ClassPath {
class JavaContext extends ClassPathContext[AbstractFile] {
def toBinaryName(rep: AbstractFile) = {
- assert(rep.name endsWith ".class", rep.name)
- rep.name dropRight 6
+ val name = rep.name
+ assert(name.length > 6 && name.substring(name.length - 6) == ".class", name)
+ name.substring(0, name.length - 6)
}
def newClassPath(dir: AbstractFile) = new DirectoryClassPath(dir, this)
}
@@ -173,13 +176,13 @@ object ClassPath {
/** From the source file to its identifier.
*/
def toSourceName(f: AbstractFile): String = {
- val nme = f.name
- if (nme.endsWith(".scala"))
- nme dropRight 6
- else if (nme.endsWith(".java"))
- nme dropRight 5
+ val name = f.name
+ if (name.length > 6 && name.substring(name.length - 6) == ".scala")
+ name.substring(0, name.length - 6)
+ else if (name.length > 5 && name.substring(name.length - 5) == ".java")
+ name.substring(0, name.length - 5)
else
- throw new FatalError("Unexpected source file ending: " + nme)
+ throw new FatalError("Unexpected source file ending: " + name)
}
}
import ClassPath._
@@ -215,29 +218,29 @@ abstract class ClassPath[T] {
/** Lists of entities.
*/
- def classes: List[AnyClassRep]
- def packages: List[ClassPath[T]]
- def sourcepaths: List[AbstractFile]
+ def classes: IndexedSeq[AnyClassRep]
+ def packages: IndexedSeq[ClassPath[T]]
+ def sourcepaths: IndexedSeq[AbstractFile]
/** Information which entails walking the tree. This is probably only
* necessary for tracking down problems - it's normally not used.
*/
- def allPackages: List[ClassPath[T]] = packages ::: (packages flatMap (_.allPackages))
- def allPackageNames: List[String] = {
- def subpackages(prefix: String, cp: ClassPath[T]): List[String] = (
- (cp.packages map (prefix + _.name)) :::
- (cp.packages flatMap (x => subpackages(prefix + x.name + ".", x)))
- )
- subpackages("", this)
- }
- def allPackagesWithNames: List[(String, ClassPath[T])] = {
- val root = packages map (p => p.name -> p)
- val subs =
- for ((prefix, p) <- root ; (k, v) <- p.allPackagesWithNames) yield
- (prefix + "." + k, v)
-
- root ::: subs
- }
+ // def allPackages: List[ClassPath[T]] = packages ::: (packages flatMap (_.allPackages))
+ // def allPackageNames: List[String] = {
+ // def subpackages(prefix: String, cp: ClassPath[T]): List[String] = (
+ // (cp.packages map (prefix + _.name)) :::
+ // (cp.packages flatMap (x => subpackages(prefix + x.name + ".", x)))
+ // )
+ // subpackages("", this)
+ // }
+ // def allPackagesWithNames: List[(String, ClassPath[T])] = {
+ // val root = packages map (p => p.name -> p)
+ // val subs =
+ // for ((prefix, p) <- root ; (k, v) <- p.allPackagesWithNames) yield
+ // (prefix + "." + k, v)
+ //
+ // root ::: subs
+ // }
/**
* Represents classes which can be loaded with a ClassfileLoader/MSILTypeLoader
@@ -297,17 +300,17 @@ class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends
override def origin = dir.underlyingSource map (_.path)
def asURLs = dir.sfile.toList map (_.toURL)
def asClasspathString = dir.path
- val sourcepaths: List[AbstractFile] = List(dir)
+ val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq(dir)
- lazy val classes: List[ClassRep] = dir flatMap { f =>
+ lazy val classes: IndexedSeq[ClassRep] = dir flatMap { f =>
if (f.isDirectory || !validSourceFile(f.name)) Nil
else List(ClassRep(None, Some(f)))
- } toList
+ } toIndexedSeq
- lazy val packages: List[SourcePath[T]] = dir flatMap { f =>
+ lazy val packages: IndexedSeq[SourcePath[T]] = dir flatMap { f =>
if (f.isDirectory && validPackage(f.name)) List(new SourcePath[T](f, context))
else Nil
- } toList
+ } toIndexedSeq
override def toString() = "sourcepath: "+ dir.toString()
}
@@ -320,17 +323,17 @@ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[Ab
override def origin = dir.underlyingSource map (_.path)
def asURLs = dir.sfile.toList map (_.toURL)
def asClasspathString = dir.path
- val sourcepaths: List[AbstractFile] = Nil
+ val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq()
- lazy val classes: List[ClassRep] = dir flatMap { f =>
+ lazy val classes: IndexedSeq[ClassRep] = dir flatMap { f =>
if (f.isDirectory || !validClassFile(f.name)) Nil
else List(ClassRep(Some(f), None))
- } toList
+ } toIndexedSeq
- lazy val packages: List[DirectoryClassPath] = dir flatMap { f =>
+ lazy val packages: IndexedSeq[DirectoryClassPath] = dir flatMap { f =>
if (f.isDirectory && validPackage(f.name)) List(new DirectoryClassPath(f, context))
else Nil
- } toList
+ } toIndexedSeq
override def toString() = "directory classpath: "+ dir
}
@@ -339,90 +342,106 @@ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[Ab
* A classpath unifying multiple class- and sourcepath entries.
*/
class MergedClassPath[T](
- val entries: List[ClassPath[T]],
+ val entries: IndexedSeq[ClassPath[T]],
val context: ClassPathContext[T])
extends ClassPath[T] {
+ def this(entries: TraversableOnce[ClassPath[T]], context: ClassPathContext[T]) =
+ this(entries.toIndexedSeq, context)
+
def name = entries.head.name
- def asURLs = entries flatMap (_.asURLs)
- lazy val sourcepaths: List[AbstractFile] = entries flatMap (_.sourcepaths)
+ def asURLs = entries flatMap (_.asURLs) toList
+ lazy val sourcepaths: IndexedSeq[AbstractFile] = entries flatMap (_.sourcepaths)
override def origin = Some(entries map (x => x.origin getOrElse x.name) mkString ("Merged(", ", ", ")"))
override def asClasspathString: String = join(entries map (_.asClasspathString) : _*)
- lazy val classes: List[AnyClassRep] = {
- val cls = new ListBuffer[AnyClassRep]
+ lazy val classes: IndexedSeq[AnyClassRep] = {
+ var count = 0
+ val indices = mutable.HashMap[String, Int]()
+ val cls = new mutable.ArrayBuffer[AnyClassRep](1024)
+
for (e <- entries; c <- e.classes) {
val name = c.name
- val idx = cls.indexWhere(_.name == name)
- if (idx >= 0) {
+ if (indices contains name) {
+ val idx = indices(name)
val existing = cls(idx)
+
if (existing.binary.isEmpty && c.binary.isDefined)
cls(idx) = existing.copy(binary = c.binary)
if (existing.source.isEmpty && c.source.isDefined)
cls(idx) = existing.copy(source = c.source)
- } else {
+ }
+ else {
+ indices(name) = count
cls += c
+ count += 1
}
}
- cls.toList
+ cls.toIndexedSeq
}
- lazy val packages: List[ClassPath[T]] = {
- val pkg = new ListBuffer[ClassPath[T]]
+ lazy val packages: IndexedSeq[ClassPath[T]] = {
+ var count = 0
+ val indices = mutable.HashMap[String, Int]()
+ val pkg = new mutable.ArrayBuffer[ClassPath[T]](256)
+
for (e <- entries; p <- e.packages) {
val name = p.name
- val idx = pkg.indexWhere(_.name == name)
- if (idx >= 0) {
+ if (indices contains name) {
+ val idx = indices(name)
pkg(idx) = addPackage(pkg(idx), p)
- } else {
+ }
+ else {
+ indices(name) = count
pkg += p
+ count += 1
}
}
- pkg.toList
+ pkg.toIndexedSeq
}
private def addPackage(to: ClassPath[T], pkg: ClassPath[T]) = {
- val newEntries = to match {
+ val newEntries: IndexedSeq[ClassPath[T]] = to match {
case cp: MergedClassPath[_] => cp.entries :+ pkg
- case _ => List(to, pkg)
+ case _ => IndexedSeq(to, pkg)
}
new MergedClassPath[T](newEntries, context)
}
-
- override def allPackages: List[ClassPath[T]] = entries flatMap (_.allPackages)
- override def allPackageNames = entries flatMap (_.allPackageNames)
- override def allPackagesWithNames = entries flatMap (_.allPackagesWithNames)
-
- def duplicatedClasses = {
- def toFullName(x: (String, _, AnyClassRep)) = x._1 + "." + x._3.name
-
- /** Flatten everything into tuples, recombine grouped by name, filter down to 2+ entries. */
- val flattened = (
- for ((pkgName, pkg) <- allPackagesWithNames ; clazz <- pkg.classes) yield
- (pkgName, pkg, clazz)
- )
- val multipleAppearingEntries = flattened groupBy toFullName filter (_._2.size > 1)
-
- /** Using original name list as reference point, return duplicated entries as
- * (name, list of origins)
- * in the order they occur on the path.
- */
- for (name <- flattened map toFullName distinct ; dups <- multipleAppearingEntries get name) yield
- (name, dups map {
- case (_, cp, _) if cp.origin.isDefined => cp.origin.get
- case (_, cp, _) => cp.asURLs.mkString
- })
- }
-
+ //
+ // override def allPackages: List[ClassPath[T]] = entries flatMap (_.allPackages)
+ // override def allPackageNames = entries flatMap (_.allPackageNames)
+ // override def allPackagesWithNames = entries flatMap (_.allPackagesWithNames)
+ //
+ // def duplicatedClasses = {
+ // def toFullName(x: (String, _, AnyClassRep)) = x._1 + "." + x._3.name
+ //
+ // /** Flatten everything into tuples, recombine grouped by name, filter down to 2+ entries. */
+ // val flattened = (
+ // for ((pkgName, pkg) <- allPackagesWithNames ; clazz <- pkg.classes) yield
+ // (pkgName, pkg, clazz)
+ // )
+ // val multipleAppearingEntries = flattened groupBy toFullName filter (_._2.size > 1)
+ //
+ // /** Using original name list as reference point, return duplicated entries as
+ // * (name, list of origins)
+ // * in the order they occur on the path.
+ // */
+ // for (name <- flattened map toFullName distinct ; dups <- multipleAppearingEntries get name) yield
+ // (name, dups map {
+ // case (_, cp, _) if cp.origin.isDefined => cp.origin.get
+ // case (_, cp, _) => cp.asURLs.mkString
+ // })
+ // }
+ //
def show() {
println("ClassPath %s has %d entries and results in:\n".format(name, entries.size))
asClasspathString split ':' foreach (x => println(" " + x))
}
- def showDuplicates() =
- ClassPath findDuplicates this foreach {
- case (name, xs) => println(xs.mkString(name + ":\n ", "\n ", "\n"))
- }
-
+ // def showDuplicates() =
+ // ClassPath findDuplicates this foreach {
+ // case (name, xs) => println(xs.mkString(name + ":\n ", "\n ", "\n"))
+ // }
+ //
override def toString() = "merged classpath "+ entries.mkString("(", "\n", ")")
}
@@ -431,7 +450,7 @@ extends ClassPath[T] {
* as AbstractFile. nsc.io.ZipArchive is used to view zip/jar archives as directories.
*/
class JavaClassPath(
- containers: List[ClassPath[AbstractFile]],
+ containers: IndexedSeq[ClassPath[AbstractFile]],
context: JavaContext)
extends MergedClassPath[AbstractFile](containers, context) {
}