diff options
Diffstat (limited to 'src')
7 files changed, 108 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala b/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala index 50b9f12dcc..aa60231b86 100644 --- a/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala +++ b/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala @@ -14,12 +14,15 @@ package sabbus import java.io.File import java.io.FileWriter import org.apache.tools.ant.Project -import org.apache.tools.ant.taskdefs.{MatchingTask, Java} -import org.apache.tools.ant.util.{GlobPatternMapper, SourceFileScanner} +import org.apache.tools.ant.taskdefs.{ MatchingTask, Java } +import org.apache.tools.ant.util.{ GlobPatternMapper, SourceFileScanner } import scala.tools.nsc.io +import scala.tools.nsc.util.ScalaClassLoader class ScalacFork extends MatchingTask with TaskArgs { val MainClass = "scala.tools.nsc.Main" + private def originOfThis: String = + ScalaClassLoader.originOfClass(classOf[ScalacFork]) map (_.toString) getOrElse "<unknown>" def setSrcdir(input: File) { sourceDir = Some(input) @@ -59,6 +62,8 @@ class ScalacFork extends MatchingTask with TaskArgs { override def execute() { def plural(x: Int) = if (x > 1) "s" else "" + log("Executing ant task scalacfork, origin: %s".format(originOfThis), Project.MSG_VERBOSE) + val compilerPath = this.compilerPath getOrElse error("Mandatory attribute 'compilerpath' is not set.") val sourceDir = this.sourceDir getOrElse error("Mandatory attribute 'srcdir' is not set.") val destinationDir = this.destinationDir getOrElse error("Mandatory attribute 'destdir' is not set.") diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala index 216579e376..1f9e6c55f0 100644 --- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala +++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala @@ -102,7 +102,10 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { /** Returns the underlying File if any and null otherwise. */ def file: JFile - def sfile = File(file) // XXX + def sfile = Option(file) map (x => File(x)) // XXX + + /** An underlying source, if known. Mostly, a zip/jar file. */ + def underlyingSource: Option[AbstractFile] = None /** Does this abstract file denote an existing file? */ def exists: Boolean = @@ -110,7 +113,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { else true /** Does this abstract file represent something which can contain classfiles? */ - def isClassContainer = isDirectory || (file != null && Path.isJarOrZip(sfile)) + def isClassContainer = isDirectory || (sfile exists (Path isJarOrZip _)) /** Create a file on disk, if one does not exist already. */ def create: Unit @@ -229,7 +232,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { */ def fileNamed(name: String): AbstractFile = { assert(isDirectory) - Option(lookupName(name, false)) getOrElse new PlainFile((sfile / name).createFile()) + Option(lookupName(name, false)) getOrElse new PlainFile((sfile.get / name).createFile()) } /** @@ -238,7 +241,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] { */ def subdirectoryNamed(name: String): AbstractFile = { assert (isDirectory) - Option(lookupName(name, true)) getOrElse new PlainFile((sfile / name).createDirectory()) + Option(lookupName(name, true)) getOrElse new PlainFile((sfile.get / name).createDirectory()) } /** Returns the path of this abstract file. */ diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala index 5336c4d04d..df24880f32 100644 --- a/src/compiler/scala/tools/nsc/io/PlainFile.scala +++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala @@ -27,6 +27,8 @@ class PlainFile(val givenPath: Path) extends AbstractFile { assert(path ne null) val file = givenPath.jfile + override def underlyingSource = Some(this) + private val fpath = try givenPath.normalize catch { case _: IOException => givenPath.toAbsolute } /** Returns the name of this abstract file. */ diff --git a/src/compiler/scala/tools/nsc/io/SourceReader.scala b/src/compiler/scala/tools/nsc/io/SourceReader.scala index bb5e662ab7..ccd946d0b6 100644 --- a/src/compiler/scala/tools/nsc/io/SourceReader.scala +++ b/src/compiler/scala/tools/nsc/io/SourceReader.scala @@ -65,7 +65,7 @@ class SourceReader(decoder: CharsetDecoder, reporter: Reporter) { case p:PlainFile => read(p.file) // bq: (!!!) case z:ZipArchive#FileEntry => - val c = Channels.newChannel(z.getArchive.getInputStream(z.entry)) + val c = Channels.newChannel(z.archive.getInputStream(z.entry)) read(c) case _ => val b = ByteBuffer.wrap(file.toByteArray) diff --git a/src/compiler/scala/tools/nsc/io/VirtualFile.scala b/src/compiler/scala/tools/nsc/io/VirtualFile.scala index edbcde1ff3..256d02c5a5 100644 --- a/src/compiler/scala/tools/nsc/io/VirtualFile.scala +++ b/src/compiler/scala/tools/nsc/io/VirtualFile.scala @@ -62,7 +62,7 @@ class VirtualFile(val name: String, _path: String) extends AbstractFile } } - def container : AbstractFile = throw new Error("not supported") + def container: AbstractFile = throw new Error("not supported") /** Is this abstract file a directory? */ def isDirectory: Boolean = false diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/compiler/scala/tools/nsc/io/ZipArchive.scala index 62f1491fdf..aa92b896db 100644 --- a/src/compiler/scala/tools/nsc/io/ZipArchive.scala +++ b/src/compiler/scala/tools/nsc/io/ZipArchive.scala @@ -207,9 +207,9 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) path: String ) extends VirtualFile(name, path) { - final override def path = "%s(%s)".format(self, pathInArchive) - final def getArchive = self.archive - def pathInArchive = super.path + override def underlyingSource = Some(self) + final override def path = "%s(%s)".format(self, super.path) + final def archive = self.archive override def hashCode = super.hashCode + container.hashCode override def equals(that : Any) = @@ -234,7 +234,6 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) val entry: ZipEntry ) extends Entry(container, name, path) with FileEntryInterface { - def archive = self.archive override def input = archive getInputStream entry } @@ -282,6 +281,7 @@ final class URLZipArchive(url: URL) extends AbstractFile with ZipContainer abstract class Entry(name: String, path: String) extends VirtualFile(name, path) { final override def path = "%s(%s)".format(URLZipArchive.this, super.path) + override def container = URLZipArchive.this } final class DirEntry(name: String, path: String) extends Entry(name, path) with DirEntryInterface { def source = input diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 0e9c4f27fa..59fc790bf1 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -47,6 +47,26 @@ object ClassPath { else List(pattern) } + /** Return duplicated classpath entries as + * (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) }) + } + /** Split classpath using platform-dependent path separator */ def split(path: String): List[String] = (path split pathSeparator).toList filterNot (_ == "") distinct @@ -67,7 +87,7 @@ object ClassPath { /** Expand dir out to contents, a la extdir */ def expandDir(extdir: String): List[String] = { val dir = Option(AbstractFile getDirectory extdir) getOrElse (return Nil) - dir filter (_.isClassContainer) map (dir.sfile / _.name path) toList + dir filter (_.isClassContainer) map (dir.sfile.get / _.name path) toList } /** A useful name filter. */ @@ -158,7 +178,13 @@ abstract class ClassPath[T] { */ def name: String - /** An URL representing this classpath. + /** + * A String representing the origin of this classpath element, if known. + * For example, the path of the directory or jar. + */ + def origin: Option[String] = None + + /** A list of URLs representing this classpath. */ def asURLs: List[URL] @@ -168,9 +194,29 @@ abstract class ClassPath[T] { /** Lists of entities. */ - val classes: List[AnyClassRep] - val packages: List[ClassPath[T]] - val sourcepaths: List[AbstractFile] + def classes: List[AnyClassRep] + def packages: List[ClassPath[T]] + def sourcepaths: List[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 + } /** * Represents classes which can be loaded with a ClassfileLoader/MSILTypeLoader @@ -227,7 +273,8 @@ abstract class ClassPath[T] { */ class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends ClassPath[T] { def name = dir.name - def asURLs = List(dir.sfile.toURL) + override def origin = dir.underlyingSource map (_.path) + def asURLs = dir.sfile.toList map (_.toURL) val sourcepaths: List[AbstractFile] = List(dir) lazy val classes: List[ClassRep] = dir partialMap { @@ -247,7 +294,8 @@ class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends */ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[AbstractFile]) extends ClassPath[AbstractFile] { def name = dir.name - def asURLs = List(dir.sfile.toURL) + override def origin = dir.underlyingSource map (_.path) + def asURLs = dir.sfile.toList map (_.toURL) val sourcepaths: List[AbstractFile] = Nil lazy val classes: List[ClassRep] = dir partialMap { @@ -266,11 +314,11 @@ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[Ab * A classpath unifying multiple class- and sourcepath entries. */ class MergedClassPath[T]( - protected val entries: List[ClassPath[T]], + val entries: List[ClassPath[T]], val context: ClassPathContext[T]) extends ClassPath[T] { - def name = entries.head.name + override def origin = Some(entries map (x => x.origin getOrElse x.name) mkString ("Merged(", ", ", ")")) def asURLs = entries flatMap (_.asURLs) lazy val sourcepaths: List[AbstractFile] = entries flatMap (_.sourcepaths) @@ -314,6 +362,31 @@ extends ClassPath[T] { 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 + }) + } + def asClasspathString: String = ClassPath.join(entries partialMap { case x: DirectoryClassPath => x.dir.path case x: MergedClassPath[_] => x.asClasspathString @@ -322,6 +395,10 @@ extends ClassPath[T] { 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")) + } override def toString() = "merged classpath "+ entries.mkString("(", "\n", ")") } |