From 30d6fce50aba1d73173339b0add4808bc13b1c40 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Apr 2016 21:26:17 +0200 Subject: Remove abstraction layer in classpath implementation --- build.sbt | 2 +- .../scala/tools/nsc/GenericRunnerSettings.scala | 4 +- src/compiler/scala/tools/nsc/Global.scala | 56 +++--- src/compiler/scala/tools/nsc/ScriptRunner.scala | 5 +- .../scala/tools/nsc/backend/JavaPlatform.scala | 24 ++- .../scala/tools/nsc/backend/Platform.scala | 7 +- .../nsc/backend/jvm/opt/ByteCodeRepository.scala | 5 +- .../tools/nsc/classpath/AggregateClassPath.scala | 139 ++++++++++++++ .../nsc/classpath/AggregateFlatClassPath.scala | 138 -------------- .../scala/tools/nsc/classpath/ClassPath.scala | 60 ++++++ .../tools/nsc/classpath/ClassPathFactory.scala | 63 +++++-- .../tools/nsc/classpath/DirectoryClassPath.scala | 145 ++++++++++++++ .../nsc/classpath/DirectoryFlatClassPath.scala | 146 -------------- .../scala/tools/nsc/classpath/FlatClassPath.scala | 98 ---------- .../tools/nsc/classpath/FlatClassPathFactory.scala | 44 ----- .../tools/nsc/classpath/PackageNameUtils.scala | 2 +- .../nsc/classpath/VirtualDirectoryClassPath.scala | 40 ++++ .../classpath/VirtualDirectoryFlatClassPath.scala | 39 ---- .../nsc/classpath/ZipAndJarFileLookupFactory.scala | 45 ++--- .../tools/nsc/classpath/ZipArchiveFileLookup.scala | 9 +- .../scala/tools/nsc/settings/ScalaSettings.scala | 5 - .../scala/tools/nsc/symtab/SymbolLoaders.scala | 16 +- .../nsc/symtab/classfile/ClassfileParser.scala | 20 +- .../scala/tools/nsc/util/ClassFileLookup.scala | 55 ------ src/compiler/scala/tools/nsc/util/ClassPath.scala | 57 +++++- src/compiler/scala/tools/reflect/ReflectMain.scala | 4 +- src/compiler/scala/tools/util/PathResolver.scala | 41 ++-- .../scala/tools/partest/BytecodeTest.scala | 10 +- src/repl/scala/tools/nsc/interpreter/IMain.scala | 16 +- .../nsc/interpreter/PresentationCompilation.scala | 7 +- src/scalap/scala/tools/scalap/Main.scala | 17 +- test/files/run/t6502.scala | 1 - test/files/run/various-flat-classpath-types.scala | 2 +- .../nsc/classpath/AggregateClassPathTest.scala | 209 +++++++++++++++++++++ .../nsc/classpath/AggregateFlatClassPathTest.scala | 208 -------------------- .../nsc/classpath/FlatClassPathResolverTest.scala | 113 ----------- .../tools/nsc/classpath/PathResolverBaseTest.scala | 110 +++++++++++ .../nsc/symtab/SymbolTableForUnitTesting.scala | 13 +- 38 files changed, 937 insertions(+), 1038 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala delete mode 100644 src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala create mode 100644 src/compiler/scala/tools/nsc/classpath/ClassPath.scala create mode 100644 src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala delete mode 100644 src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala delete mode 100644 src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala delete mode 100644 src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala create mode 100644 src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala delete mode 100644 src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala delete mode 100644 src/compiler/scala/tools/nsc/util/ClassFileLookup.scala create mode 100644 test/junit/scala/tools/nsc/classpath/AggregateClassPathTest.scala delete mode 100644 test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala delete mode 100644 test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala create mode 100644 test/junit/scala/tools/nsc/classpath/PathResolverBaseTest.scala diff --git a/build.sbt b/build.sbt index 4962e4e41c..546b3e7099 100644 --- a/build.sbt +++ b/build.sbt @@ -4,7 +4,7 @@ * What you see below is very much work-in-progress. The following features are implemented: * - Compiling all classses for the compiler and library ("compile" in the respective subprojects) * - Running JUnit tests ("test") and partest ("test/it:test") - * - Creating build/quick with all compiled classes and launcher scripts ("dist/mkQuick") + * - Creating build/quick with all compiled classes and launcher scripts ("˜") * - Creating build/pack with all JARs and launcher scripts ("dist/mkPack") * - Building all scaladoc sets ("doc") * - Publishing ("publishDists" and standard sbt tasks like "publish" and "publishLocal") diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala index e99cce9186..c82ed68da8 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala @@ -6,10 +6,10 @@ package scala.tools.nsc import java.net.URL -import scala.tools.util.PathResolverFactory +import scala.tools.util.PathResolver class GenericRunnerSettings(error: String => Unit) extends Settings(error) { - lazy val classpathURLs: Seq[URL] = PathResolverFactory.create(this).resultAsURLs + lazy val classpathURLs: Seq[URL] = new PathResolver(this).resultAsURLs val howtorun = ChoiceSetting( diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 7509437e79..de6fd6266e 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -13,7 +13,7 @@ import java.nio.charset.{Charset, CharsetDecoder, IllegalCharsetNameException, U import scala.collection.{immutable, mutable} import io.{AbstractFile, Path, SourceReader} import reporters.Reporter -import util.{ClassFileLookup, StatisticsInfo, returning} +import util.{ClassPath, StatisticsInfo, returning} import scala.reflect.ClassTag import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, ScalaClassLoader, ScriptSourceFile, SourceFile} import scala.reflect.internal.pickling.PickleBuffer @@ -30,7 +30,6 @@ import backend.jvm.GenBCode import scala.language.postfixOps import scala.tools.nsc.ast.{TreeGen => AstTreeGen} import scala.tools.nsc.classpath._ -import scala.tools.nsc.settings.ClassPathRepresentationType class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable @@ -54,7 +53,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) class GlobalMirror extends Roots(NoSymbol) { val universe: self.type = self - def rootLoader: LazyType = new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) + def rootLoader: LazyType = new loaders.PackageLoader(ClassPath.RootPackage, classPath) override def toString = "compiler mirror" } implicit val MirrorTag: ClassTag[Mirror] = ClassTag[Mirror](classOf[GlobalMirror]) @@ -97,9 +96,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) type ThisPlatform = JavaPlatform { val global: Global.this.type } lazy val platform: ThisPlatform = new GlobalPlatform - def classPath: ClassFileLookup = platform.flatClassPath - - private def flatClassPath: FlatClassPath = platform.flatClassPath + def classPath: ClassPath = platform.classPath // sub-components -------------------------------------------------- @@ -758,9 +755,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Extend classpath of `platform` and rescan updated packages. */ def extendCompilerClassPath(urls: URL*): Unit = { - val urlClasspaths = urls.map(u => FlatClassPathFactory.newClassPath(AbstractFile.getURL(u), settings)) - val newClassPath = AggregateFlatClassPath.createAggregate(platform.flatClassPath +: urlClasspaths : _*) - platform.currentFlatClassPath = Some(newClassPath) + val urlClasspaths = urls.map(u => ClassPathFactory.newClassPath(AbstractFile.getURL(u), settings)) + val newClassPath = AggregateClassPath.createAggregate(platform.classPath +: urlClasspaths : _*) + platform.currentClassPath = Some(newClassPath) invalidateClassPathEntries(urls.map(_.getPath): _*) } @@ -793,26 +790,26 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * entries on the classpath. */ def invalidateClassPathEntries(paths: String*): Unit = { - implicit object ClassPathOrdering extends Ordering[FlatClassPath] { - def compare(a: FlatClassPath, b: FlatClassPath): Int = a.asClassPathString compareTo b.asClassPathString + implicit object ClassPathOrdering extends Ordering[ClassPath] { + def compare(a: ClassPath, b: ClassPath): Int = a.asClassPathString compareTo b.asClassPathString } val invalidated, failed = new mutable.ListBuffer[ClassSymbol] - def assoc(path: String): Option[(FlatClassPath, FlatClassPath)] = { - def origin(lookup: ClassFileLookup): Option[String] = lookup match { + def assoc(path: String): Option[(ClassPath, ClassPath)] = { + def origin(lookup: ClassPath): Option[String] = lookup match { case cp: JFileDirectoryLookup[_] => Some(cp.dir.getPath) case cp: ZipArchiveFileLookup[_] => Some(cp.zipFile.getPath) case _ => None } - def entries(lookup: ClassFileLookup): Seq[FlatClassPath] = lookup match { - case cp: AggregateFlatClassPath => cp.aggregates - case cp: FlatClassPath => Seq(cp) + def entries(lookup: ClassPath): Seq[ClassPath] = lookup match { + case cp: AggregateClassPath => cp.aggregates + case cp: ClassPath => Seq(cp) } val dir = AbstractFile.getDirectory(path) // if path is a `jar`, this is a FileZipArchive (isDirectory is true) val canonical = dir.canonicalPath // this is the canonical path of the .jar - def matchesCanonical(e: ClassFileLookup) = origin(e) match { + def matchesCanonical(e: ClassPath) = origin(e) match { case Some(opath) => AbstractFile.getDirectory(opath).canonicalPath == canonical case None => @@ -820,7 +817,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } entries(classPath) find matchesCanonical match { case Some(oldEntry) => - Some(oldEntry -> FlatClassPathFactory.newClassPath(dir, settings)) + Some(oldEntry -> ClassPathFactory.newClassPath(dir, settings)) case None => error(s"Error adding entry to classpath. During invalidation, no entry named $path in classpath $classPath") None @@ -830,15 +827,15 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (subst.nonEmpty) { platform updateClassPath subst informProgress(s"classpath updated on entries [${subst.keys mkString ","}]") - def mkClassPath(elems: Iterable[FlatClassPath]): FlatClassPath = + def mkClassPath(elems: Iterable[ClassPath]): ClassPath = if (elems.size == 1) elems.head - else AggregateFlatClassPath.createAggregate(elems.toSeq: _*) + else AggregateClassPath.createAggregate(elems.toSeq: _*) val oldEntries = mkClassPath(subst.keys) val newEntries = mkClassPath(subst.values) classPath match { - case fcp: FlatClassPath => mergeNewEntriesFlat( + case cp: ClassPath => mergeNewEntries( RootClass, "", - oldEntries, newEntries, fcp, + oldEntries, newEntries, cp, invalidated, failed) } } @@ -867,20 +864,19 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * Otherwise, sub-packages in newEntries are looked up in the symbol table (created if * non-existent) and the merge function is called recursively. */ - private def mergeNewEntriesFlat( - packageClass: ClassSymbol, fullPackageName: String, - oldEntries: FlatClassPath, newEntries: FlatClassPath, fullClasspath: FlatClassPath, - invalidated: mutable.ListBuffer[ClassSymbol], failed: mutable.ListBuffer[ClassSymbol]): Unit = { + private def mergeNewEntries(packageClass: ClassSymbol, fullPackageName: String, + oldEntries: ClassPath, newEntries: ClassPath, fullClasspath: ClassPath, + invalidated: mutable.ListBuffer[ClassSymbol], failed: mutable.ListBuffer[ClassSymbol]): Unit = { ifDebug(informProgress(s"syncing $packageClass, $oldEntries -> $newEntries")) - def packageExists(cp: FlatClassPath): Boolean = { + def packageExists(cp: ClassPath): Boolean = { val (parent, _) = PackageNameUtils.separatePkgAndClassNames(fullPackageName) cp.packages(parent).exists(_.name == fullPackageName) } def invalidateOrRemove(pkg: ClassSymbol) = { if (packageExists(fullClasspath)) - pkg setInfo new loaders.PackageLoaderUsingFlatClassPath(fullPackageName, fullClasspath) + pkg setInfo new loaders.PackageLoader(fullPackageName, fullClasspath) else pkg.owner.info.decls unlink pkg.sourceModule invalidated += pkg @@ -898,9 +894,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val (_, subPackageName) = PackageNameUtils.separatePkgAndClassNames(p.name) val subPackage = packageClass.info.decl(newTermName(subPackageName)) orElse { // package does not exist in symbol table, create a new symbol - loaders.enterPackage(packageClass, subPackageName, new loaders.PackageLoaderUsingFlatClassPath(p.name, fullClasspath)) + loaders.enterPackage(packageClass, subPackageName, new loaders.PackageLoader(p.name, fullClasspath)) } - mergeNewEntriesFlat( + mergeNewEntries( subPackage.moduleClass.asClass, p.name, oldEntries, newEntries, fullClasspath, invalidated, failed) diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index fed335daef..1f66657d8d 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -8,9 +8,8 @@ package tools.nsc import io.{ AbstractFile, Directory, File, Path } import java.io.IOException -import scala.tools.nsc.classpath.DirectoryFlatClassPath +import scala.tools.nsc.classpath.DirectoryClassPath import scala.tools.nsc.reporters.{Reporter,ConsoleReporter} -import scala.tools.nsc.settings.ClassPathRepresentationType import util.Exceptional.unwrap /** An object that runs Scala code in script files. @@ -114,7 +113,7 @@ class ScriptRunner extends HasCompileSocket { } def hasClassToRun(d: Directory): Boolean = { - val cp = DirectoryFlatClassPath(d.jfile) + val cp = DirectoryClassPath(d.jfile) cp.findClass(mainClass).isDefined } diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala index 1e4ea99509..dc63b335cc 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -7,11 +7,9 @@ package scala.tools.nsc package backend import io.AbstractFile -import scala.tools.nsc.classpath.{AggregateFlatClassPath, FlatClassPath} -import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.nsc.util.ClassFileLookup -import scala.tools.util.FlatClassPathResolver +import scala.tools.nsc.classpath.AggregateClassPath import scala.tools.util.PathResolver +import scala.tools.nsc.util.ClassPath trait JavaPlatform extends Platform { val global: Global @@ -19,20 +17,20 @@ trait JavaPlatform extends Platform { import global._ import definitions._ - private[nsc] var currentFlatClassPath: Option[FlatClassPath] = None + private[nsc] var currentClassPath: Option[ClassPath] = None - private[nsc] def flatClassPath: FlatClassPath = { - if (currentFlatClassPath.isEmpty) currentFlatClassPath = Some(new FlatClassPathResolver(settings).result) - currentFlatClassPath.get + private[nsc] def classPath: ClassPath = { + if (currentClassPath.isEmpty) currentClassPath = Some(new PathResolver(settings).result) + currentClassPath.get } /** Update classpath with a substituted subentry */ - def updateClassPath(subst: Map[FlatClassPath, FlatClassPath]): Unit = global.classPath match { - case AggregateFlatClassPath(entries) => - currentFlatClassPath = Some(AggregateFlatClassPath(entries map (e => subst.getOrElse(e, e)))) + def updateClassPath(subst: Map[ClassPath, ClassPath]): Unit = global.classPath match { + case AggregateClassPath(entries) => + currentClassPath = Some(AggregateClassPath(entries map (e => subst.getOrElse(e, e)))) - case cp: FlatClassPath => - currentFlatClassPath = Some(subst.getOrElse(cp, cp)) + case cp: ClassPath => + currentClassPath = Some(subst.getOrElse(cp, cp)) } def platformPhases = List( diff --git a/src/compiler/scala/tools/nsc/backend/Platform.scala b/src/compiler/scala/tools/nsc/backend/Platform.scala index 5279901b21..e464768bb3 100644 --- a/src/compiler/scala/tools/nsc/backend/Platform.scala +++ b/src/compiler/scala/tools/nsc/backend/Platform.scala @@ -6,9 +6,8 @@ package scala.tools.nsc package backend -import util.{ClassFileLookup, ClassPath} import io.AbstractFile -import scala.tools.nsc.classpath.FlatClassPath +import scala.tools.nsc.util.ClassPath /** The platform dependent pieces of Global. */ @@ -17,10 +16,10 @@ trait Platform { import symbolTable._ /** The new implementation of compiler classpath. */ - private[nsc] def flatClassPath: FlatClassPath + private[nsc] def classPath: ClassPath /** Update classpath with a substitution that maps entries to entries */ - def updateClassPath(subst: Map[FlatClassPath, FlatClassPath]) + def updateClassPath(subst: Map[ClassPath, ClassPath]) /** Any platform-specific phases. */ def platformPhases: List[SubComponent] diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala index c5259aa433..e1c311494d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala @@ -13,8 +13,7 @@ import scala.collection.convert.decorateAsScala._ import scala.collection.concurrent import scala.tools.asm.Attribute import scala.tools.nsc.backend.jvm.BackendReporting._ -import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.util.ClassFileLookup +import scala.tools.nsc.util.ClassPath import BytecodeUtils._ import ByteCodeRepository._ import BTypes.InternalName @@ -26,7 +25,7 @@ import java.util.concurrent.atomic.AtomicLong * * @param classPath The compiler classpath where classfiles are searched and read from. */ -class ByteCodeRepository[BT <: BTypes](val classPath: ClassFileLookup, val btypes: BT) { +class ByteCodeRepository[BT <: BTypes](val classPath: ClassPath, val btypes: BT) { import btypes._ /** diff --git a/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala b/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala new file mode 100644 index 0000000000..6b435542a3 --- /dev/null +++ b/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import java.net.URL +import scala.annotation.tailrec +import scala.collection.mutable.ArrayBuffer +import scala.reflect.io.AbstractFile +import scala.tools.nsc.util.ClassPath +import scala.tools.nsc.util.ClassRepresentation + +/** + * A classpath unifying multiple class- and sourcepath entries. + * The Classpath can obtain entries for classes and sources independently + * so it tries to do operations quite optimally - iterating only these collections + * which are needed in the given moment and only as far as it's necessary. + * + * @param aggregates classpath instances containing entries which this class processes + */ +case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath { + override def findClassFile(className: String): Option[AbstractFile] = { + @tailrec + def find(aggregates: Seq[ClassPath]): Option[AbstractFile] = + if (aggregates.nonEmpty) { + val classFile = aggregates.head.findClassFile(className) + if (classFile.isDefined) classFile + else find(aggregates.tail) + } else None + + find(aggregates) + } + + override def findClass(className: String): Option[ClassRepresentation] = { + @tailrec + def findEntry(aggregates: Seq[ClassPath], isSource: Boolean): Option[ClassRepresentation] = + if (aggregates.nonEmpty) { + val entry = aggregates.head.findClass(className) match { + case s @ Some(_: SourceFileEntry) if isSource => s + case s @ Some(_: ClassFileEntry) if !isSource => s + case _ => None + } + if (entry.isDefined) entry + else findEntry(aggregates.tail, isSource) + } else None + + val classEntry = findEntry(aggregates, isSource = false) + val sourceEntry = findEntry(aggregates, isSource = true) + + (classEntry, sourceEntry) match { + case (Some(c: ClassFileEntry), Some(s: SourceFileEntry)) => Some(ClassAndSourceFilesEntry(c.file, s.file)) + case (c @ Some(_), _) => c + case (_, s) => s + } + } + + override def asURLs: Seq[URL] = aggregates.flatMap(_.asURLs) + + override def asClassPathStrings: Seq[String] = aggregates.map(_.asClassPathString).distinct + + override def asSourcePathString: String = ClassPath.join(aggregates map (_.asSourcePathString): _*) + + override private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { + val aggregatedPackages = aggregates.flatMap(_.packages(inPackage)).distinct + aggregatedPackages + } + + override private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = + getDistinctEntries(_.classes(inPackage)) + + override private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = + getDistinctEntries(_.sources(inPackage)) + + override private[nsc] def list(inPackage: String): ClassPathEntries = { + val (packages, classesAndSources) = aggregates.map(_.list(inPackage)).unzip + val distinctPackages = packages.flatten.distinct + val distinctClassesAndSources = mergeClassesAndSources(classesAndSources: _*) + ClassPathEntries(distinctPackages, distinctClassesAndSources) + } + + /** + * Returns only one entry for each name. If there's both a source and a class entry, it + * creates an entry containing both of them. If there would be more than one class or source + * entries for the same class it always would use the first entry of each type found on a classpath. + */ + private def mergeClassesAndSources(entries: Seq[ClassRepresentation]*): Seq[ClassRepresentation] = { + // based on the implementation from MergedClassPath + var count = 0 + val indices = collection.mutable.HashMap[String, Int]() + val mergedEntries = new ArrayBuffer[ClassRepresentation](1024) + + for { + partOfEntries <- entries + entry <- partOfEntries + } { + val name = entry.name + if (indices contains name) { + val index = indices(name) + val existing = mergedEntries(index) + + if (existing.binary.isEmpty && entry.binary.isDefined) + mergedEntries(index) = ClassAndSourceFilesEntry(entry.binary.get, existing.source.get) + if (existing.source.isEmpty && entry.source.isDefined) + mergedEntries(index) = ClassAndSourceFilesEntry(existing.binary.get, entry.source.get) + } + else { + indices(name) = count + mergedEntries += entry + count += 1 + } + } + mergedEntries.toIndexedSeq + } + + private def getDistinctEntries[EntryType <: ClassRepresentation](getEntries: ClassPath => Seq[EntryType]): Seq[EntryType] = { + val seenNames = collection.mutable.HashSet[String]() + val entriesBuffer = new ArrayBuffer[EntryType](1024) + for { + cp <- aggregates + entry <- getEntries(cp) if !seenNames.contains(entry.name) + } { + entriesBuffer += entry + seenNames += entry.name + } + entriesBuffer.toIndexedSeq + } +} + +object AggregateClassPath { + def createAggregate(parts: ClassPath*): ClassPath = { + val elems = new ArrayBuffer[ClassPath]() + parts foreach { + case AggregateClassPath(ps) => elems ++= ps + case p => elems += p + } + if (elems.size == 1) elems.head + else AggregateClassPath(elems.toIndexedSeq) + } +} diff --git a/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala deleted file mode 100644 index 91026d0e13..0000000000 --- a/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.classpath - -import java.net.URL -import scala.annotation.tailrec -import scala.collection.mutable.ArrayBuffer -import scala.reflect.io.AbstractFile -import scala.tools.nsc.util.ClassPath -import scala.tools.nsc.util.ClassRepresentation - -/** - * A classpath unifying multiple class- and sourcepath entries. - * Flat classpath can obtain entries for classes and sources independently - * so it tries to do operations quite optimally - iterating only these collections - * which are needed in the given moment and only as far as it's necessary. - * @param aggregates classpath instances containing entries which this class processes - */ -case class AggregateFlatClassPath(aggregates: Seq[FlatClassPath]) extends FlatClassPath { - override def findClassFile(className: String): Option[AbstractFile] = { - @tailrec - def find(aggregates: Seq[FlatClassPath]): Option[AbstractFile] = - if (aggregates.nonEmpty) { - val classFile = aggregates.head.findClassFile(className) - if (classFile.isDefined) classFile - else find(aggregates.tail) - } else None - - find(aggregates) - } - - override def findClass(className: String): Option[ClassRepresentation] = { - @tailrec - def findEntry(aggregates: Seq[FlatClassPath], isSource: Boolean): Option[ClassRepresentation] = - if (aggregates.nonEmpty) { - val entry = aggregates.head.findClass(className) match { - case s @ Some(_: SourceFileEntry) if isSource => s - case s @ Some(_: ClassFileEntry) if !isSource => s - case _ => None - } - if (entry.isDefined) entry - else findEntry(aggregates.tail, isSource) - } else None - - val classEntry = findEntry(aggregates, isSource = false) - val sourceEntry = findEntry(aggregates, isSource = true) - - (classEntry, sourceEntry) match { - case (Some(c: ClassFileEntry), Some(s: SourceFileEntry)) => Some(ClassAndSourceFilesEntry(c.file, s.file)) - case (c @ Some(_), _) => c - case (_, s) => s - } - } - - override def asURLs: Seq[URL] = aggregates.flatMap(_.asURLs) - - override def asClassPathStrings: Seq[String] = aggregates.map(_.asClassPathString).distinct - - override def asSourcePathString: String = ClassPath.join(aggregates map (_.asSourcePathString): _*) - - override private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { - val aggregatedPackages = aggregates.flatMap(_.packages(inPackage)).distinct - aggregatedPackages - } - - override private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = - getDistinctEntries(_.classes(inPackage)) - - override private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = - getDistinctEntries(_.sources(inPackage)) - - override private[nsc] def list(inPackage: String): FlatClassPathEntries = { - val (packages, classesAndSources) = aggregates.map(_.list(inPackage)).unzip - val distinctPackages = packages.flatten.distinct - val distinctClassesAndSources = mergeClassesAndSources(classesAndSources: _*) - FlatClassPathEntries(distinctPackages, distinctClassesAndSources) - } - - /** - * Returns only one entry for each name. If there's both a source and a class entry, it - * creates an entry containing both of them. If there would be more than one class or source - * entries for the same class it always would use the first entry of each type found on a classpath. - */ - private def mergeClassesAndSources(entries: Seq[ClassRepClassPathEntry]*): Seq[ClassRepClassPathEntry] = { - // based on the implementation from MergedClassPath - var count = 0 - val indices = collection.mutable.HashMap[String, Int]() - val mergedEntries = new ArrayBuffer[ClassRepClassPathEntry](1024) - - for { - partOfEntries <- entries - entry <- partOfEntries - } { - val name = entry.name - if (indices contains name) { - val index = indices(name) - val existing = mergedEntries(index) - - if (existing.binary.isEmpty && entry.binary.isDefined) - mergedEntries(index) = ClassAndSourceFilesEntry(entry.binary.get, existing.source.get) - if (existing.source.isEmpty && entry.source.isDefined) - mergedEntries(index) = ClassAndSourceFilesEntry(existing.binary.get, entry.source.get) - } - else { - indices(name) = count - mergedEntries += entry - count += 1 - } - } - mergedEntries.toIndexedSeq - } - - private def getDistinctEntries[EntryType <: ClassRepClassPathEntry](getEntries: FlatClassPath => Seq[EntryType]): Seq[EntryType] = { - val seenNames = collection.mutable.HashSet[String]() - val entriesBuffer = new ArrayBuffer[EntryType](1024) - for { - cp <- aggregates - entry <- getEntries(cp) if !seenNames.contains(entry.name) - } { - entriesBuffer += entry - seenNames += entry.name - } - entriesBuffer.toIndexedSeq - } -} - -object AggregateFlatClassPath { - def createAggregate(parts: FlatClassPath*): FlatClassPath = { - val elems = new ArrayBuffer[FlatClassPath]() - parts foreach { - case AggregateFlatClassPath(ps) => elems ++= ps - case p => elems += p - } - if (elems.size == 1) elems.head - else AggregateFlatClassPath(elems.toIndexedSeq) - } -} diff --git a/src/compiler/scala/tools/nsc/classpath/ClassPath.scala b/src/compiler/scala/tools/nsc/classpath/ClassPath.scala new file mode 100644 index 0000000000..08bd98b1d8 --- /dev/null +++ b/src/compiler/scala/tools/nsc/classpath/ClassPath.scala @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import scala.reflect.io.AbstractFile +import scala.tools.nsc.util.ClassRepresentation + +case class ClassPathEntries(packages: Seq[PackageEntry], classesAndSources: Seq[ClassRepresentation]) + +object ClassPathEntries { + import scala.language.implicitConversions + // to have working unzip method + implicit def entry2Tuple(entry: ClassPathEntries): (Seq[PackageEntry], Seq[ClassRepresentation]) = (entry.packages, entry.classesAndSources) +} + +trait ClassFileEntry extends ClassRepresentation { + def file: AbstractFile +} + +trait SourceFileEntry extends ClassRepresentation { + def file: AbstractFile +} + +trait PackageEntry { + def name: String +} + +private[nsc] case class ClassFileEntryImpl(file: AbstractFile) extends ClassFileEntry { + override def name = FileUtils.stripClassExtension(file.name) // class name + + override def binary: Option[AbstractFile] = Some(file) + override def source: Option[AbstractFile] = None +} + +private[nsc] case class SourceFileEntryImpl(file: AbstractFile) extends SourceFileEntry { + override def name = FileUtils.stripSourceExtension(file.name) + + override def binary: Option[AbstractFile] = None + override def source: Option[AbstractFile] = Some(file) +} + +private[nsc] case class ClassAndSourceFilesEntry(classFile: AbstractFile, srcFile: AbstractFile) extends ClassRepresentation { + override def name = FileUtils.stripClassExtension(classFile.name) + + override def binary: Option[AbstractFile] = Some(classFile) + override def source: Option[AbstractFile] = Some(srcFile) +} + +private[nsc] case class PackageEntryImpl(name: String) extends PackageEntry + +private[nsc] trait NoSourcePaths { + def asSourcePathString: String = "" + private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = Seq.empty +} + +private[nsc] trait NoClassPaths { + def findClassFile(className: String): Option[AbstractFile] = None + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = Seq.empty +} diff --git a/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala b/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala index 04477c11d4..3a29f1ba11 100644 --- a/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala +++ b/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala @@ -3,47 +3,49 @@ */ package scala.tools.nsc.classpath -import scala.reflect.io.AbstractFile +import scala.reflect.io.{AbstractFile, VirtualDirectory} +import scala.tools.nsc.Settings +import FileUtils.AbstractFileOps import scala.tools.nsc.util.ClassPath /** - * A trait that contains factory methods for classpath elements of type T. - * - * The logic has been abstracted from ClassPath#ClassPathContext so it's possible - * to have common trait that supports both recursive and flat classpath representations. - * - * Therefore, we expect that T will FlatClassPath. + * Provides factory methods for classpath. When creating classpath instances for a given path, + * it uses proper type of classpath depending on a types of particular files containing sources or classes. */ -trait ClassPathFactory[T] { - +class ClassPathFactory(settings: Settings) { /** - * Create a new classpath based on the abstract file. - */ - def newClassPath(file: AbstractFile): T + * Create a new classpath based on the abstract file. + */ + def newClassPath(file: AbstractFile): ClassPath = ClassPathFactory.newClassPath(file, settings) /** - * Creators for sub classpaths which preserve this context. - */ - def sourcesInPath(path: String): List[T] + * Creators for sub classpaths which preserve this context. + */ + def sourcesInPath(path: String): List[ClassPath] = + for { + file <- expandPath(path, expandStar = false) + dir <- Option(AbstractFile getDirectory file) + } yield createSourcePath(dir) + - def expandPath(path: String, expandStar: Boolean = true): List[String] = ClassPath.expandPath(path, expandStar) + def expandPath(path: String, expandStar: Boolean = true): List[String] = scala.tools.nsc.util.ClassPath.expandPath(path, expandStar) - def expandDir(extdir: String): List[String] = ClassPath.expandDir(extdir) + def expandDir(extdir: String): List[String] = scala.tools.nsc.util.ClassPath.expandDir(extdir) - def contentsOfDirsInPath(path: String): List[T] = + def contentsOfDirsInPath(path: String): List[ClassPath] = for { dir <- expandPath(path, expandStar = false) name <- expandDir(dir) entry <- Option(AbstractFile.getDirectory(name)) } yield newClassPath(entry) - def classesInExpandedPath(path: String): IndexedSeq[T] = + def classesInExpandedPath(path: String): IndexedSeq[ClassPath] = classesInPathImpl(path, expand = true).toIndexedSeq def classesInPath(path: String) = classesInPathImpl(path, expand = false) def classesInManifest(useManifestClassPath: Boolean) = - if (useManifestClassPath) ClassPath.manifests.map(url => newClassPath(AbstractFile getResources url)) + if (useManifestClassPath) scala.tools.nsc.util.ClassPath.manifests.map(url => newClassPath(AbstractFile getResources url)) else Nil // Internal @@ -52,4 +54,25 @@ trait ClassPathFactory[T] { file <- expandPath(path, expand) dir <- Option(AbstractFile.getDirectory(file)) } yield newClassPath(dir) + + private def createSourcePath(file: AbstractFile): ClassPath = + if (file.isJarOrZip) + ZipAndJarSourcePathFactory.create(file, settings) + else if (file.isDirectory) + new DirectorySourcePath(file.file) + else + sys.error(s"Unsupported sourcepath element: $file") +} + +object ClassPathFactory { + def newClassPath(file: AbstractFile, settings: Settings): ClassPath = file match { + case vd: VirtualDirectory => VirtualDirectoryClassPath(vd) + case _ => + if (file.isJarOrZip) + ZipAndJarClassPathFactory.create(file, settings) + else if (file.isDirectory) + new DirectoryClassPath(file.file) + else + sys.error(s"Unsupported classpath element: $file") + } } diff --git a/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala b/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala new file mode 100644 index 0000000000..aba941e043 --- /dev/null +++ b/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import java.io.File +import java.net.URL +import scala.reflect.io.{AbstractFile, PlainFile} +import scala.tools.nsc.util.{ClassPath, ClassRepresentation} +import FileUtils._ + +/** + * A trait allowing to look for classpath entries in directories. It provides common logic for + * classes handling class and source files. + * It makes use of the fact that in the case of nested directories it's easy to find a file + * when we have a name of a package. + * It abstracts over the file representation to work with both JFile and AbstractFile. + */ +trait DirectoryLookup[FileEntryType <: ClassRepresentation] extends ClassPath { + type F + + val dir: F + + protected def emptyFiles: Array[F] // avoids reifying ClassTag[F] + protected def getSubDir(dirName: String): Option[F] + protected def listChildren(dir: F, filter: Option[F => Boolean] = None): Array[F] + protected def getName(f: F): String + protected def toAbstractFile(f: F): AbstractFile + protected def isPackage(f: F): Boolean + + protected def createFileEntry(file: AbstractFile): FileEntryType + protected def isMatchingFile(f: F): Boolean + + private def getDirectory(forPackage: String): Option[F] = { + if (forPackage == ClassPath.RootPackage) { + Some(dir) + } else { + val packageDirName = FileUtils.dirPath(forPackage) + getSubDir(packageDirName) + } + } + + private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { + val dirForPackage = getDirectory(inPackage) + val nestedDirs: Array[F] = dirForPackage match { + case None => emptyFiles + case Some(directory) => listChildren(directory, Some(isPackage)) + } + val prefix = PackageNameUtils.packagePrefix(inPackage) + nestedDirs.map(f => PackageEntryImpl(prefix + getName(f))) + } + + protected def files(inPackage: String): Seq[FileEntryType] = { + val dirForPackage = getDirectory(inPackage) + val files: Array[F] = dirForPackage match { + case None => emptyFiles + case Some(directory) => listChildren(directory, Some(isMatchingFile)) + } + files.map(f => createFileEntry(toAbstractFile(f))) + } + + private[nsc] def list(inPackage: String): ClassPathEntries = { + val dirForPackage = getDirectory(inPackage) + val files: Array[F] = dirForPackage match { + case None => emptyFiles + case Some(directory) => listChildren(directory) + } + val packagePrefix = PackageNameUtils.packagePrefix(inPackage) + val packageBuf = collection.mutable.ArrayBuffer.empty[PackageEntry] + val fileBuf = collection.mutable.ArrayBuffer.empty[FileEntryType] + for (file <- files) { + if (isPackage(file)) + packageBuf += PackageEntryImpl(packagePrefix + getName(file)) + else if (isMatchingFile(file)) + fileBuf += createFileEntry(toAbstractFile(file)) + } + ClassPathEntries(packageBuf, fileBuf) + } +} + +trait JFileDirectoryLookup[FileEntryType <: ClassRepresentation] extends DirectoryLookup[FileEntryType] { + type F = File + + protected def emptyFiles: Array[File] = Array.empty + protected def getSubDir(packageDirName: String): Option[File] = { + val packageDir = new File(dir, packageDirName) + if (packageDir.exists && packageDir.isDirectory) Some(packageDir) + else None + } + protected def listChildren(dir: File, filter: Option[File => Boolean]): Array[File] = filter match { + case Some(f) => dir.listFiles(mkFileFilter(f)) + case None => dir.listFiles() + } + protected def getName(f: File): String = f.getName + protected def toAbstractFile(f: File): AbstractFile = new PlainFile(new scala.reflect.io.File(f)) + protected def isPackage(f: File): Boolean = f.isPackage + + assert(dir != null, "Directory file in DirectoryFileLookup cannot be null") + + def asURLs: Seq[URL] = Seq(dir.toURI.toURL) + def asClassPathStrings: Seq[String] = Seq(dir.getPath) +} + +case class DirectoryClassPath(dir: File) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { + override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl + + def findClassFile(className: String): Option[AbstractFile] = { + val relativePath = FileUtils.dirPath(className) + val classFile = new File(s"$dir/$relativePath.class") + if (classFile.exists) { + val wrappedClassFile = new scala.reflect.io.File(classFile) + val abstractClassFile = new PlainFile(wrappedClassFile) + Some(abstractClassFile) + } else None + } + + protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) + protected def isMatchingFile(f: File): Boolean = f.isClass + + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) +} + +case class DirectorySourcePath(dir: File) extends JFileDirectoryLookup[SourceFileEntryImpl] with NoClassPaths { + def asSourcePathString: String = asClassPathString + + protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file) + protected def isMatchingFile(f: File): Boolean = endsScalaOrJava(f.getName) + + override def findClass(className: String): Option[ClassRepresentation] = findSourceFile(className) map SourceFileEntryImpl + + private def findSourceFile(className: String): Option[AbstractFile] = { + val relativePath = FileUtils.dirPath(className) + val sourceFile = Stream("scala", "java") + .map(ext => new File(s"$dir/$relativePath.$ext")) + .collectFirst { case file if file.exists() => file } + + sourceFile.map { file => + val wrappedSourceFile = new scala.reflect.io.File(file) + val abstractSourceFile = new PlainFile(wrappedSourceFile) + abstractSourceFile + } + } + + private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = files(inPackage) +} diff --git a/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala deleted file mode 100644 index ed38915cb6..0000000000 --- a/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.classpath - -import java.io.File -import java.net.URL -import scala.reflect.io.AbstractFile -import scala.reflect.io.PlainFile -import scala.tools.nsc.util.ClassRepresentation -import FileUtils._ - -/** - * A trait allowing to look for classpath entries in directories. It provides common logic for - * classes handling class and source files. - * It makes use of the fact that in the case of nested directories it's easy to find a file - * when we have a name of a package. - * It abstracts over the file representation to work with both JFile and AbstractFile. - */ -trait DirectoryLookup[FileEntryType <: ClassRepClassPathEntry] extends FlatClassPath { - type F - - val dir: F - - protected def emptyFiles: Array[F] // avoids reifying ClassTag[F] - protected def getSubDir(dirName: String): Option[F] - protected def listChildren(dir: F, filter: Option[F => Boolean] = None): Array[F] - protected def getName(f: F): String - protected def toAbstractFile(f: F): AbstractFile - protected def isPackage(f: F): Boolean - - protected def createFileEntry(file: AbstractFile): FileEntryType - protected def isMatchingFile(f: F): Boolean - - private def getDirectory(forPackage: String): Option[F] = { - if (forPackage == FlatClassPath.RootPackage) { - Some(dir) - } else { - val packageDirName = FileUtils.dirPath(forPackage) - getSubDir(packageDirName) - } - } - - private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { - val dirForPackage = getDirectory(inPackage) - val nestedDirs: Array[F] = dirForPackage match { - case None => emptyFiles - case Some(directory) => listChildren(directory, Some(isPackage)) - } - val prefix = PackageNameUtils.packagePrefix(inPackage) - nestedDirs.map(f => PackageEntryImpl(prefix + getName(f))) - } - - protected def files(inPackage: String): Seq[FileEntryType] = { - val dirForPackage = getDirectory(inPackage) - val files: Array[F] = dirForPackage match { - case None => emptyFiles - case Some(directory) => listChildren(directory, Some(isMatchingFile)) - } - files.map(f => createFileEntry(toAbstractFile(f))) - } - - private[nsc] def list(inPackage: String): FlatClassPathEntries = { - val dirForPackage = getDirectory(inPackage) - val files: Array[F] = dirForPackage match { - case None => emptyFiles - case Some(directory) => listChildren(directory) - } - val packagePrefix = PackageNameUtils.packagePrefix(inPackage) - val packageBuf = collection.mutable.ArrayBuffer.empty[PackageEntry] - val fileBuf = collection.mutable.ArrayBuffer.empty[FileEntryType] - for (file <- files) { - if (isPackage(file)) - packageBuf += PackageEntryImpl(packagePrefix + getName(file)) - else if (isMatchingFile(file)) - fileBuf += createFileEntry(toAbstractFile(file)) - } - FlatClassPathEntries(packageBuf, fileBuf) - } -} - -trait JFileDirectoryLookup[FileEntryType <: ClassRepClassPathEntry] extends DirectoryLookup[FileEntryType] { - type F = File - - protected def emptyFiles: Array[File] = Array.empty - protected def getSubDir(packageDirName: String): Option[File] = { - val packageDir = new File(dir, packageDirName) - if (packageDir.exists && packageDir.isDirectory) Some(packageDir) - else None - } - protected def listChildren(dir: File, filter: Option[File => Boolean]): Array[File] = filter match { - case Some(f) => dir.listFiles(mkFileFilter(f)) - case None => dir.listFiles() - } - protected def getName(f: File): String = f.getName - protected def toAbstractFile(f: File): AbstractFile = new PlainFile(new scala.reflect.io.File(f)) - protected def isPackage(f: File): Boolean = f.isPackage - - assert(dir != null, "Directory file in DirectoryFileLookup cannot be null") - - def asURLs: Seq[URL] = Seq(dir.toURI.toURL) - def asClassPathStrings: Seq[String] = Seq(dir.getPath) -} - -case class DirectoryFlatClassPath(dir: File) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { - override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl - - def findClassFile(className: String): Option[AbstractFile] = { - val relativePath = FileUtils.dirPath(className) - val classFile = new File(s"$dir/$relativePath.class") - if (classFile.exists) { - val wrappedClassFile = new scala.reflect.io.File(classFile) - val abstractClassFile = new PlainFile(wrappedClassFile) - Some(abstractClassFile) - } else None - } - - protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) - protected def isMatchingFile(f: File): Boolean = f.isClass - - private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) -} - -case class DirectoryFlatSourcePath(dir: File) extends JFileDirectoryLookup[SourceFileEntryImpl] with NoClassPaths { - def asSourcePathString: String = asClassPathString - - protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file) - protected def isMatchingFile(f: File): Boolean = endsScalaOrJava(f.getName) - - override def findClass(className: String): Option[ClassRepresentation] = findSourceFile(className) map SourceFileEntryImpl - - private def findSourceFile(className: String): Option[AbstractFile] = { - val relativePath = FileUtils.dirPath(className) - val sourceFile = Stream("scala", "java") - .map(ext => new File(s"$dir/$relativePath.$ext")) - .collectFirst { case file if file.exists() => file } - - sourceFile.map { file => - val wrappedSourceFile = new scala.reflect.io.File(file) - val abstractSourceFile = new PlainFile(wrappedSourceFile) - abstractSourceFile - } - } - - private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = files(inPackage) -} diff --git a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala deleted file mode 100644 index 758071443d..0000000000 --- a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.classpath - -import scala.reflect.io.AbstractFile -import scala.tools.nsc.util.{ ClassFileLookup, ClassPath, ClassRepresentation } - -/** - * A base trait for the particular flat classpath representation implementations. - * - * We call this variant of a classpath representation flat because it's possible to - * query the whole classpath using just single instance extending this trait. - * - * This is an alternative design compared to scala.tools.nsc.util.ClassPath - */ -trait FlatClassPath extends ClassFileLookup { - /** Empty string represents root package */ - private[nsc] def packages(inPackage: String): Seq[PackageEntry] - private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] - private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] - - /** Allows to get entries for packages and classes merged with sources possibly in one pass. */ - private[nsc] def list(inPackage: String): FlatClassPathEntries - - // A default implementation which should be overridden, if we can create the more efficient - // solution for a given type of FlatClassPath - override def findClass(className: String): Option[ClassRepresentation] = { - val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) - - val foundClassFromClassFiles = classes(pkg).find(_.name == simpleClassName) - def findClassInSources = sources(pkg).find(_.name == simpleClassName) - - foundClassFromClassFiles orElse findClassInSources - } - - override def asClassPathString: String = ClassPath.join(asClassPathStrings: _*) - def asClassPathStrings: Seq[String] -} - -object FlatClassPath { - val RootPackage = "" -} - -case class FlatClassPathEntries(packages: Seq[PackageEntry], classesAndSources: Seq[ClassRepClassPathEntry]) - -object FlatClassPathEntries { - import scala.language.implicitConversions - // to have working unzip method - implicit def entry2Tuple(entry: FlatClassPathEntries): (Seq[PackageEntry], Seq[ClassRepClassPathEntry]) = (entry.packages, entry.classesAndSources) -} - -sealed trait ClassRepClassPathEntry extends ClassRepresentation - -trait ClassFileEntry extends ClassRepClassPathEntry { - def file: AbstractFile -} - -trait SourceFileEntry extends ClassRepClassPathEntry { - def file: AbstractFile -} - -trait PackageEntry { - def name: String -} - -private[nsc] case class ClassFileEntryImpl(file: AbstractFile) extends ClassFileEntry { - override def name = FileUtils.stripClassExtension(file.name) // class name - - override def binary: Option[AbstractFile] = Some(file) - override def source: Option[AbstractFile] = None -} - -private[nsc] case class SourceFileEntryImpl(file: AbstractFile) extends SourceFileEntry { - override def name = FileUtils.stripSourceExtension(file.name) - - override def binary: Option[AbstractFile] = None - override def source: Option[AbstractFile] = Some(file) -} - -private[nsc] case class ClassAndSourceFilesEntry(classFile: AbstractFile, srcFile: AbstractFile) extends ClassRepClassPathEntry { - override def name = FileUtils.stripClassExtension(classFile.name) - - override def binary: Option[AbstractFile] = Some(classFile) - override def source: Option[AbstractFile] = Some(srcFile) -} - -private[nsc] case class PackageEntryImpl(name: String) extends PackageEntry - -private[nsc] trait NoSourcePaths { - def asSourcePathString: String = "" - private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = Seq.empty -} - -private[nsc] trait NoClassPaths { - def findClassFile(className: String): Option[AbstractFile] = None - private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = Seq.empty -} diff --git a/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala b/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala deleted file mode 100644 index 463301696e..0000000000 --- a/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.classpath - -import scala.reflect.io.VirtualDirectory -import scala.tools.nsc.Settings -import scala.tools.nsc.io.AbstractFile -import FileUtils.AbstractFileOps - -/** - * Provides factory methods for flat classpath. When creating classpath instances for a given path, - * it uses proper type of classpath depending on a types of particular files containing sources or classes. - */ -class FlatClassPathFactory(settings: Settings) extends ClassPathFactory[FlatClassPath] { - def newClassPath(file: AbstractFile): FlatClassPath = FlatClassPathFactory.newClassPath(file, settings) - - def sourcesInPath(path: String): List[FlatClassPath] = - for { - file <- expandPath(path, expandStar = false) - dir <- Option(AbstractFile getDirectory file) - } yield createSourcePath(dir) - - private def createSourcePath(file: AbstractFile): FlatClassPath = - if (file.isJarOrZip) - ZipAndJarFlatSourcePathFactory.create(file, settings) - else if (file.isDirectory) - new DirectoryFlatSourcePath(file.file) - else - sys.error(s"Unsupported sourcepath element: $file") -} - -object FlatClassPathFactory { - def newClassPath(file: AbstractFile, settings: Settings): FlatClassPath = file match { - case vd: VirtualDirectory => VirtualDirectoryFlatClassPath(vd) - case _ => - if (file.isJarOrZip) - ZipAndJarFlatClassPathFactory.create(file, settings) - else if (file.isDirectory) - new DirectoryFlatClassPath(file.file) - else - sys.error(s"Unsupported classpath element: $file") - } -} diff --git a/src/compiler/scala/tools/nsc/classpath/PackageNameUtils.scala b/src/compiler/scala/tools/nsc/classpath/PackageNameUtils.scala index c907d565d2..39b0d78135 100644 --- a/src/compiler/scala/tools/nsc/classpath/PackageNameUtils.scala +++ b/src/compiler/scala/tools/nsc/classpath/PackageNameUtils.scala @@ -3,7 +3,7 @@ */ package scala.tools.nsc.classpath -import scala.tools.nsc.classpath.FlatClassPath.RootPackage +import scala.tools.nsc.util.ClassPath.RootPackage /** * Common methods related to package names represented as String diff --git a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala new file mode 100644 index 0000000000..8df0c3743d --- /dev/null +++ b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala @@ -0,0 +1,40 @@ +package scala.tools.nsc.classpath + +import scala.tools.nsc.util.ClassRepresentation +import scala.reflect.io.{Path, PlainFile, VirtualDirectory, AbstractFile} +import FileUtils._ +import java.net.URL +import scala.tools.nsc.util.ClassPath + +case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath with DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { + type F = AbstractFile + + protected def emptyFiles: Array[AbstractFile] = Array.empty + protected def getSubDir(packageDirName: String): Option[AbstractFile] = + Option(dir.lookupName(packageDirName, directory = true)) + protected def listChildren(dir: AbstractFile, filter: Option[AbstractFile => Boolean] = None): Array[F] = filter match { + case Some(f) => dir.iterator.filter(f).toArray + case _ => dir.toArray + } + def getName(f: AbstractFile): String = f.name + def toAbstractFile(f: AbstractFile): AbstractFile = f + def isPackage(f: AbstractFile): Boolean = f.isPackage + + // mimic the behavior of the old nsc.util.DirectoryClassPath + def asURLs: Seq[URL] = Seq(new URL(dir.name)) + def asClassPathStrings: Seq[String] = Seq(dir.path) + + override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl + + def findClassFile(className: String): Option[AbstractFile] = { + val relativePath = FileUtils.dirPath(className) + val classFile = new PlainFile(Path(s"$dir/$relativePath.class")) + if (classFile.exists) Some(classFile) + else None + } + + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) + + protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) + protected def isMatchingFile(f: AbstractFile): Boolean = f.isClass +} diff --git a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala deleted file mode 100644 index 3d418139de..0000000000 --- a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala +++ /dev/null @@ -1,39 +0,0 @@ -package scala.tools.nsc.classpath - -import scala.tools.nsc.util.ClassRepresentation -import scala.reflect.io.{Path, PlainFile, VirtualDirectory, AbstractFile} -import FileUtils._ -import java.net.URL - -case class VirtualDirectoryFlatClassPath(dir: VirtualDirectory) extends FlatClassPath with DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { - type F = AbstractFile - - protected def emptyFiles: Array[AbstractFile] = Array.empty - protected def getSubDir(packageDirName: String): Option[AbstractFile] = - Option(dir.lookupName(packageDirName, directory = true)) - protected def listChildren(dir: AbstractFile, filter: Option[AbstractFile => Boolean] = None): Array[F] = filter match { - case Some(f) => dir.iterator.filter(f).toArray - case _ => dir.toArray - } - def getName(f: AbstractFile): String = f.name - def toAbstractFile(f: AbstractFile): AbstractFile = f - def isPackage(f: AbstractFile): Boolean = f.isPackage - - // mimic the behavior of the old nsc.util.DirectoryClassPath - def asURLs: Seq[URL] = Seq(new URL(dir.name)) - def asClassPathStrings: Seq[String] = Seq(dir.path) - - override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl - - def findClassFile(className: String): Option[AbstractFile] = { - val relativePath = FileUtils.dirPath(className) - val classFile = new PlainFile(Path(s"$dir/$relativePath.class")) - if (classFile.exists) Some(classFile) - else None - } - - private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) - - protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) - protected def isMatchingFile(f: AbstractFile): Boolean = f.isClass -} diff --git a/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala b/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala index 6ec3805d8b..fe74e5f874 100644 --- a/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala +++ b/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala @@ -6,7 +6,8 @@ package scala.tools.nsc.classpath import java.io.File import java.net.URL import scala.annotation.tailrec -import scala.reflect.io.{ AbstractFile, FileZipArchive, ManifestResources } +import scala.reflect.io.{AbstractFile, FileZipArchive, ManifestResources} +import scala.tools.nsc.util.ClassPath import scala.tools.nsc.Settings import FileUtils._ @@ -19,16 +20,16 @@ import FileUtils._ * when there are a lot of projects having a lot of common dependencies. */ sealed trait ZipAndJarFileLookupFactory { - private val cache = collection.mutable.Map.empty[AbstractFile, FlatClassPath] + private val cache = collection.mutable.Map.empty[AbstractFile, ClassPath] - def create(zipFile: AbstractFile, settings: Settings): FlatClassPath = { + def create(zipFile: AbstractFile, settings: Settings): ClassPath = { if (settings.YdisableFlatCpCaching) createForZipFile(zipFile) else createUsingCache(zipFile, settings) } - protected def createForZipFile(zipFile: AbstractFile): FlatClassPath + protected def createForZipFile(zipFile: AbstractFile): ClassPath - private def createUsingCache(zipFile: AbstractFile, settings: Settings): FlatClassPath = cache.synchronized { + private def createUsingCache(zipFile: AbstractFile, settings: Settings): ClassPath = cache.synchronized { def newClassPathInstance = { if (settings.verbose || settings.Ylogcp) println(s"$zipFile is not yet in the classpath cache") @@ -39,11 +40,11 @@ sealed trait ZipAndJarFileLookupFactory { } /** - * Manages creation of flat classpath for class files placed in zip and jar files. + * Manages creation of classpath for class files placed in zip and jar files. * It should be the only way of creating them as it provides caching. */ -object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { - private case class ZipArchiveFlatClassPath(zipFile: File) +object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory { + private case class ZipArchiveClassPath(zipFile: File) extends ZipArchiveFileLookup[ClassFileEntryImpl] with NoSourcePaths { @@ -65,7 +66,7 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { * with a particularly prepared scala-library.jar. It should have all classes listed in the manifest like e.g. this entry: * Name: scala/Function2$mcFJD$sp.class */ - private case class ManifestResourcesFlatClassPath(file: ManifestResources) extends FlatClassPath with NoSourcePaths { + private case class ManifestResourcesClassPath(file: ManifestResources) extends ClassPath with NoSourcePaths { override def findClassFile(className: String): Option[AbstractFile] = { val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) classes(pkg).find(_.name == simpleClassName).map(_.file) @@ -75,8 +76,8 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { override def asURLs: Seq[URL] = file.toURLs() - import ManifestResourcesFlatClassPath.PackageFileInfo - import ManifestResourcesFlatClassPath.PackageInfo + import ManifestResourcesClassPath.PackageFileInfo + import ManifestResourcesClassPath.PackageInfo /** * A cache mapping package name to abstract file for package directory and subpackages of given package. @@ -114,8 +115,8 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { } val subpackages = getSubpackages(file) - packages.put(FlatClassPath.RootPackage, PackageFileInfo(file, subpackages)) - traverse(FlatClassPath.RootPackage, subpackages, collection.mutable.Queue()) + packages.put(ClassPath.RootPackage, PackageFileInfo(file, subpackages)) + traverse(ClassPath.RootPackage, subpackages, collection.mutable.Queue()) packages } @@ -132,21 +133,21 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { (for (file <- pkg if file.isClass) yield ClassFileEntryImpl(file))(collection.breakOut) } - override private[nsc] def list(inPackage: String): FlatClassPathEntries = FlatClassPathEntries(packages(inPackage), classes(inPackage)) + override private[nsc] def list(inPackage: String): ClassPathEntries = ClassPathEntries(packages(inPackage), classes(inPackage)) } - private object ManifestResourcesFlatClassPath { + private object ManifestResourcesClassPath { case class PackageFileInfo(packageFile: AbstractFile, subpackages: Seq[AbstractFile]) case class PackageInfo(packageName: String, subpackages: List[AbstractFile]) } - override protected def createForZipFile(zipFile: AbstractFile): FlatClassPath = + override protected def createForZipFile(zipFile: AbstractFile): ClassPath = if (zipFile.file == null) createWithoutUnderlyingFile(zipFile) - else ZipArchiveFlatClassPath(zipFile.file) + else ZipArchiveClassPath(zipFile.file) private def createWithoutUnderlyingFile(zipFile: AbstractFile) = zipFile match { case manifestRes: ManifestResources => - ManifestResourcesFlatClassPath(manifestRes) + ManifestResourcesClassPath(manifestRes) case _ => val errorMsg = s"Abstract files which don't have an underlying file and are not ManifestResources are not supported. There was $zipFile" throw new IllegalArgumentException(errorMsg) @@ -154,11 +155,11 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { } /** - * Manages creation of flat classpath for source files placed in zip and jar files. + * Manages creation of classpath for source files placed in zip and jar files. * It should be the only way of creating them as it provides caching. */ -object ZipAndJarFlatSourcePathFactory extends ZipAndJarFileLookupFactory { - private case class ZipArchiveFlatSourcePath(zipFile: File) +object ZipAndJarSourcePathFactory extends ZipAndJarFileLookupFactory { + private case class ZipArchiveSourcePath(zipFile: File) extends ZipArchiveFileLookup[SourceFileEntryImpl] with NoClassPaths { @@ -170,5 +171,5 @@ object ZipAndJarFlatSourcePathFactory extends ZipAndJarFileLookupFactory { override protected def isRequiredFileType(file: AbstractFile): Boolean = file.isScalaOrJavaSource } - override protected def createForZipFile(zipFile: AbstractFile): FlatClassPath = ZipArchiveFlatSourcePath(zipFile.file) + override protected def createForZipFile(zipFile: AbstractFile): ClassPath = ZipArchiveSourcePath(zipFile.file) } diff --git a/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala b/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala index a24d989306..9c147cf8cc 100644 --- a/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala +++ b/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala @@ -9,13 +9,14 @@ import scala.collection.Seq import scala.reflect.io.AbstractFile import scala.reflect.io.FileZipArchive import FileUtils.AbstractFileOps +import scala.tools.nsc.util.{ClassPath, ClassRepresentation} /** * A trait allowing to look for classpath entries of given type in zip and jar files. * It provides common logic for classes handling class and source files. * It's aware of things like e.g. META-INF directory which is correctly skipped. */ -trait ZipArchiveFileLookup[FileEntryType <: ClassRepClassPathEntry] extends FlatClassPath { +trait ZipArchiveFileLookup[FileEntryType <: ClassRepresentation] extends ClassPath { val zipFile: File assert(zipFile != null, "Zip file in ZipArchiveFileLookup cannot be null") @@ -39,7 +40,7 @@ trait ZipArchiveFileLookup[FileEntryType <: ClassRepClassPathEntry] extends Flat entry <- dirEntry.iterator if isRequiredFileType(entry) } yield createFileEntry(entry) - override private[nsc] def list(inPackage: String): FlatClassPathEntries = { + override private[nsc] def list(inPackage: String): ClassPathEntries = { val foundDirEntry = findDirEntry(inPackage) foundDirEntry map { dirEntry => @@ -53,8 +54,8 @@ trait ZipArchiveFileLookup[FileEntryType <: ClassRepClassPathEntry] extends Flat else if (isRequiredFileType(entry)) fileBuf += createFileEntry(entry) } - FlatClassPathEntries(pkgBuf, fileBuf) - } getOrElse FlatClassPathEntries(Seq.empty, Seq.empty) + ClassPathEntries(pkgBuf, fileBuf) + } getOrElse ClassPathEntries(Seq.empty, Seq.empty) } private def findDirEntry(pkg: String): Option[archive.DirEntry] = { diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 15925edeeb..9a0d86a94d 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -388,8 +388,3 @@ trait ScalaSettings extends AbsScalaSettings None } } - -object ClassPathRepresentationType { - val Flat = "flat" - val Recursive = "recursive" -} diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index e5c8e64347..b36d5d4ef1 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -10,10 +10,8 @@ import classfile.ClassfileParser import java.io.IOException import scala.reflect.internal.MissingRequirementError import scala.reflect.internal.util.Statistics -import scala.reflect.io.{ AbstractFile, NoAbstractFile } -import scala.tools.nsc.classpath.FlatClassPath -import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.nsc.util.{ ClassPath, ClassRepresentation } +import scala.reflect.io.{AbstractFile, NoAbstractFile} +import scala.tools.nsc.util.{ClassPath, ClassRepresentation} /** This class ... * @@ -249,9 +247,9 @@ abstract class SymbolLoaders { /** * Loads contents of a package */ - class PackageLoaderUsingFlatClassPath(packageName: String, classPath: FlatClassPath) extends SymbolLoader with FlagAgnosticCompleter { + class PackageLoader(packageName: String, classPath: ClassPath) extends SymbolLoader with FlagAgnosticCompleter { protected def description = { - val shownPackageName = if (packageName == FlatClassPath.RootPackage) "" else packageName + val shownPackageName = if (packageName == ClassPath.RootPackage) "" else packageName s"package loader $shownPackageName" } @@ -268,9 +266,9 @@ abstract class SymbolLoaders { val fullName = pkg.name val name = - if (packageName == FlatClassPath.RootPackage) fullName + if (packageName == ClassPath.RootPackage) fullName else fullName.substring(packageName.length + 1) - val packageLoader = new PackageLoaderUsingFlatClassPath(fullName, classPath) + val packageLoader = new PackageLoader(fullName, classPath) enterPackage(root, name, packageLoader) } @@ -299,7 +297,7 @@ abstract class SymbolLoaders { val loaders = SymbolLoaders.this.asInstanceOf[SymbolLoadersRefined] - override def classFileLookup: util.ClassFileLookup = platform.flatClassPath + override def classPath: ClassPath = platform.classPath } protected def description = "class file "+ classfile.toString diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index e10c847597..0533d420cd 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -8,16 +8,16 @@ package tools.nsc package symtab package classfile -import java.io.{ File, IOException } +import java.io.{File, IOException} import java.lang.Integer.toHexString -import scala.collection.{ mutable, immutable } -import scala.collection.mutable.{ ListBuffer, ArrayBuffer } +import scala.collection.{immutable, mutable} +import scala.collection.mutable.{ArrayBuffer, ListBuffer} import scala.annotation.switch -import scala.reflect.internal.{ JavaAccFlags } -import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs} +import scala.reflect.internal.JavaAccFlags +import scala.reflect.internal.pickling.{ByteCodecs, PickleBuffer} import scala.reflect.io.NoAbstractFile +import scala.tools.nsc.util.ClassPath import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.util.ClassFileLookup /** This abstract class implements a class file parser. * @@ -43,8 +43,8 @@ abstract class ClassfileParser { */ protected def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol - /** The way of the class file lookup used by the compiler. */ - def classFileLookup: ClassFileLookup + /** The compiler classpath. */ + def classPath: ClassPath import definitions._ import scala.reflect.internal.ClassfileConstants._ @@ -357,7 +357,7 @@ abstract class ClassfileParser { } private def loadClassSymbol(name: Name): Symbol = { - val file = classFileLookup findClassFile name.toString getOrElse { + val file = classPath findClassFile name.toString getOrElse { // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects // that are not in their correct place (see bug for details) @@ -1079,7 +1079,7 @@ abstract class ClassfileParser { for (entry <- innerClasses.entries) { // create a new class member for immediate inner classes if (entry.outerName == currentClass) { - val file = classFileLookup.findClassFile(entry.externalName.toString) + val file = classPath.findClassFile(entry.externalName.toString) enterClassAndModule(entry, file.getOrElse(NoAbstractFile)) } } diff --git a/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala b/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala deleted file mode 100644 index f47765d248..0000000000 --- a/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.util - -import scala.tools.nsc.Settings -import scala.tools.nsc.classpath.{AggregateFlatClassPath, FlatClassPath, FlatClassPathFactory} -import scala.tools.nsc.io.AbstractFile -import java.net.URL - -/** - * Simple interface that allows us to abstract over how class file lookup is performed - * in different classpath representations. - */ -trait ClassFileLookup { - def findClassFile(name: String): Option[AbstractFile] - - /** - * It returns both classes from class file and source files (as our base ClassRepresentation). - * So note that it's not so strictly related to findClassFile. - */ - def findClass(name: String): Option[ClassRepresentation] - - /** - * A sequence of URLs representing this classpath. - */ - def asURLs: Seq[URL] - - /** The whole classpath in the form of one String. - */ - def asClassPathString: String - - // for compatibility purposes - @deprecated("Use asClassPathString instead of this one", "2.11.5") - def asClasspathString: String = asClassPathString - - /** The whole sourcepath in the form of one String. - */ - def asSourcePathString: String -} - -/** - * Represents classes which can be loaded with a ClassfileLoader and/or SourcefileLoader. - */ -trait ClassRepresentation { - def binary: Option[AbstractFile] - def source: Option[AbstractFile] - - def name: String -} - -object ClassRepresentation { - def unapply[T](classRep: ClassRepresentation): Option[(Option[AbstractFile], Option[AbstractFile])] = - Some((classRep.binary, classRep.source)) -} diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 822396d4cf..50ed6c4cba 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package util -import io.{ AbstractFile, Directory, File, Jar } +import io.{AbstractFile, Directory, File, Jar} import java.net.MalformedURLException import java.net.URL import java.util.regex.PatternSyntaxException @@ -15,7 +15,54 @@ import java.util.regex.PatternSyntaxException import File.pathSeparator import Jar.isJarOrZip +/** + * A representation of the compiler's class- or sourcepath. + */ +trait ClassPath { + import scala.tools.nsc.classpath._ + def asURLs: Seq[URL] + + /** Empty string represents root package */ + private[nsc] def packages(inPackage: String): Seq[PackageEntry] + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] + private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] + + /** Allows to get entries for packages and classes merged with sources possibly in one pass. */ + private[nsc] def list(inPackage: String): ClassPathEntries + + /** + * It returns both classes from class file and source files (as our base ClassRepresentation). + * So note that it's not so strictly related to findClassFile. + */ + def findClass(className: String): Option[ClassRepresentation] = { + // A default implementation which should be overridden, if we can create the more efficient + // solution for a given type of ClassPath + val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) + + val foundClassFromClassFiles = classes(pkg).find(_.name == simpleClassName) + def findClassInSources = sources(pkg).find(_.name == simpleClassName) + + foundClassFromClassFiles orElse findClassInSources + } + def findClassFile(className: String): Option[AbstractFile] + + def asClassPathStrings: Seq[String] + + /** The whole classpath in the form of one String. + */ + def asClassPathString: String = ClassPath.join(asClassPathStrings: _*) + // for compatibility purposes + @deprecated("Use asClassPathString instead of this one", "2.11.5") + def asClasspathString: String = asClassPathString + + /** The whole sourcepath in the form of one String. + */ + def asSourcePathString: String +} + object ClassPath { + val RootPackage = "" + /** Expand single path entry */ private def expandS(pattern: String): List[String] = { val wildSuffix = File.separator + "*" @@ -54,7 +101,7 @@ object ClassPath { def expandDir(extdir: String): List[String] = { AbstractFile getDirectory extdir match { case null => Nil - case dir => dir filter (_.isClassContainer) map (x => new java.io.File(dir.file, x.name) getPath) toList + case dir => dir.filter(_.isClassContainer).map(x => new java.io.File(dir.file, x.name).getPath).toList } } @@ -89,6 +136,12 @@ object ClassPath { sealed abstract class JavaContext } +trait ClassRepresentation { + def name: String + def binary: Option[AbstractFile] + def source: Option[AbstractFile] +} + @deprecated("Shim for sbt's compiler interface", since = "2.12") sealed abstract class DirectoryClassPath diff --git a/src/compiler/scala/tools/reflect/ReflectMain.scala b/src/compiler/scala/tools/reflect/ReflectMain.scala index 8d8418945a..7d82910699 100644 --- a/src/compiler/scala/tools/reflect/ReflectMain.scala +++ b/src/compiler/scala/tools/reflect/ReflectMain.scala @@ -5,12 +5,12 @@ import scala.reflect.internal.util.ScalaClassLoader import scala.tools.nsc.Driver import scala.tools.nsc.Global import scala.tools.nsc.Settings -import scala.tools.util.PathResolverFactory +import scala.tools.util.PathResolver object ReflectMain extends Driver { private def classloaderFromSettings(settings: Settings) = { - val classPathURLs = PathResolverFactory.create(settings).resultAsURLs + val classPathURLs = new PathResolver(settings).resultAsURLs ScalaClassLoader.fromURLs(classPathURLs, getClass.getClassLoader) } diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 11b9766da4..c351b6ace1 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -10,11 +10,10 @@ package util import java.net.URL import scala.tools.reflect.WrappedProperties.AccessControl import scala.tools.nsc.Settings -import scala.tools.nsc.util.{ClassFileLookup, ClassPath} -import scala.reflect.io.{ File, Directory, Path, AbstractFile } +import scala.tools.nsc.util.ClassPath +import scala.reflect.io.{Directory, File, Path} import PartialFunction.condOpt -import scala.tools.nsc.classpath.{ AggregateFlatClassPath, ClassPathFactory, FlatClassPath, FlatClassPathFactory } -import scala.tools.nsc.settings.ClassPathRepresentationType +import scala.tools.nsc.classpath._ // Loosely based on the draft specification at: // https://wiki.scala-lang.org/display/SIW/Classpath @@ -174,26 +173,19 @@ object PathResolver { } else { val settings = new Settings() val rest = settings.processArguments(args.toList, processAll = false)._2 - val pr = PathResolverFactory.create(settings) + val pr = new PathResolver(settings) println("COMMAND: 'scala %s'".format(args.mkString(" "))) println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" "))) pr.result match { - case cp: AggregateFlatClassPath => + case cp: AggregateClassPath => println(s"ClassPath has ${cp.aggregates.size} entries and results in:\n${cp.asClassPathStrings}") } } } -trait PathResolverResult { - def result: ClassFileLookup - - def resultAsURLs: Seq[URL] = result.asURLs -} - -abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup, ResultClassPathType <: BaseClassPathType] -(settings: Settings, classPathFactory: ClassPathFactory[BaseClassPathType]) - extends PathResolverResult { +final class PathResolver(settings: Settings) { + private val classPathFactory = new ClassPathFactory(settings) import PathResolver.{ AsLines, Defaults, ppcp } @@ -241,7 +233,7 @@ abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup, ResultClas import classPathFactory._ // Assemble the elements! - def basis = List[Traversable[BaseClassPathType]]( + def basis = List[Traversable[ClassPath]]( classesInPath(javaBootClassPath), // 1. The Java bootstrap class path. contentsOfDirsInPath(javaExtDirs), // 2. The Java extension class path. classesInExpandedPath(javaUserClassPath), // 3. The Java application class path. @@ -272,7 +264,7 @@ abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup, ResultClas import PathResolver.MkLines - def result: ResultClassPathType = { + def result: ClassPath = { val cp = computeResult() if (settings.Ylogcp) { Console print f"Classpath built from ${settings.toConciseString} %n" @@ -285,20 +277,11 @@ abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup, ResultClas cp } + def resultAsURLs: Seq[URL] = result.asURLs + @deprecated("Use resultAsURLs instead of this one", "2.11.5") def asURLs: List[URL] = resultAsURLs.toList - protected def computeResult(): ResultClassPathType + private def computeResult(): ClassPath = AggregateClassPath(containers.toIndexedSeq) } -class FlatClassPathResolver(settings: Settings, flatClassPathFactory: ClassPathFactory[FlatClassPath]) - extends PathResolverBase[FlatClassPath, AggregateFlatClassPath](settings, flatClassPathFactory) { - - def this(settings: Settings) = this(settings, new FlatClassPathFactory(settings)) - - override protected def computeResult(): AggregateFlatClassPath = AggregateFlatClassPath(containers.toIndexedSeq) -} - -object PathResolverFactory { - def create(settings: Settings): PathResolverResult = new FlatClassPathResolver(settings) -} diff --git a/src/partest-extras/scala/tools/partest/BytecodeTest.scala b/src/partest-extras/scala/tools/partest/BytecodeTest.scala index bdb82605b6..532dfd2a73 100644 --- a/src/partest-extras/scala/tools/partest/BytecodeTest.scala +++ b/src/partest-extras/scala/tools/partest/BytecodeTest.scala @@ -1,6 +1,5 @@ package scala.tools.partest -import scala.tools.nsc.util.ClassFileLookup import scala.collection.JavaConverters._ import scala.tools.asm.{ClassReader, ClassWriter} import scala.tools.asm.tree._ @@ -126,15 +125,16 @@ abstract class BytecodeTest { cn } - protected lazy val classpath: ClassFileLookup = { - import scala.tools.nsc.classpath.{FlatClassPathFactory, AggregateFlatClassPath} + protected lazy val classpath: scala.tools.nsc.util.ClassPath = { + import scala.tools.nsc.classpath.AggregateClassPath + import scala.tools.nsc.classpath.ClassPathFactory import scala.tools.util.PathResolver.Defaults import scala.tools.nsc.Settings // logic inspired by scala.tools.util.PathResolver implementation // `Settings` is used to check YdisableFlatCpCaching in ZipArchiveFlatClassPath - val factory = new FlatClassPathFactory(new Settings()) + val factory = new ClassPathFactory(new Settings()) val containers = factory.classesInExpandedPath(Defaults.javaUserClassPath) - new AggregateFlatClassPath(containers) + new AggregateClassPath(containers) } } diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 893bde42ab..8c91242b36 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -11,18 +11,18 @@ import PartialFunction.cond import scala.language.implicitConversions import scala.beans.BeanProperty import scala.collection.mutable -import scala.concurrent.{ Future, ExecutionContext } -import scala.reflect.runtime.{ universe => ru } -import scala.reflect.{ ClassTag, classTag } -import scala.reflect.internal.util.{ BatchSourceFile, SourceFile } -import scala.tools.util.PathResolverFactory +import scala.concurrent.{ExecutionContext, Future} +import scala.reflect.runtime.{universe => ru} +import scala.reflect.{ClassTag, classTag} +import scala.reflect.internal.util.{BatchSourceFile, SourceFile} import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings } +import scala.tools.nsc.typechecker.{StructuredTypeStrings, TypeStrings} import scala.tools.nsc.util._ import ScalaClassLoader.URLClassLoader import scala.tools.nsc.util.Exceptional.unwrap -import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException, CompiledScript, Compilable} +import javax.script.{AbstractScriptEngine, Bindings, Compilable, CompiledScript, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException} import java.net.URL +import scala.tools.util.PathResolver /** An interpreter for Scala code. * @@ -91,7 +91,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def compilerClasspath: Seq[java.net.URL] = ( if (isInitializeComplete) global.classPath.asURLs - else PathResolverFactory.create(settings).resultAsURLs // the compiler's classpath + else new PathResolver(settings).resultAsURLs // the compiler's classpath ) def settings = initialSettings // Run the code body with the given boolean settings flipped to true. diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala index cfefc3419c..b9a4054ffc 100644 --- a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala +++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala @@ -7,7 +7,6 @@ package scala.tools.nsc.interpreter import scala.reflect.internal.util.RangePosition import scala.reflect.io.AbstractFile import scala.tools.nsc.backend.JavaPlatform -import scala.tools.nsc.settings.ClassPathRepresentationType import scala.tools.nsc.util.ClassPath import scala.tools.nsc.{interactive, Settings} import scala.tools.nsc.reporters.StoreReporter @@ -57,8 +56,8 @@ trait PresentationCompilation { */ def newPresentationCompiler(): interactive.Global = { def mergedFlatClasspath = { - val replOutClasspath = FlatClassPathFactory.newClassPath(replOutput.dir, settings) - AggregateFlatClassPath(replOutClasspath :: global.platform.flatClassPath :: Nil) + val replOutClasspath = ClassPathFactory.newClassPath(replOutput.dir, settings) + AggregateClassPath(replOutClasspath :: global.platform.classPath :: Nil) } def copySettings: Settings = { val s = new Settings(_ => () /* ignores "bad option -nc" errors, etc */) @@ -71,7 +70,7 @@ trait PresentationCompilation { override lazy val platform: ThisPlatform = { new JavaPlatform { val global: self.type = self - override private[nsc] lazy val flatClassPath: FlatClassPath = mergedFlatClasspath + override private[nsc] lazy val classPath: ClassPath = mergedFlatClasspath } } } diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 2ae43306a7..6a37bbc270 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -8,15 +8,12 @@ package scala package tools.scalap -import java.io.{ PrintStream, OutputStreamWriter, ByteArrayOutputStream } +import java.io.{ByteArrayOutputStream, OutputStreamWriter, PrintStream} import scala.reflect.NameTransformer import scala.tools.nsc.Settings -import scala.tools.nsc.classpath.AggregateFlatClassPath -import scala.tools.nsc.classpath.FlatClassPathFactory -import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.nsc.util.ClassFileLookup -import scala.tools.util.PathResolverFactory +import scala.tools.nsc.classpath.{AggregateClassPath, ClassPathFactory} +import scala.tools.nsc.util.ClassPath +import scala.tools.util.PathResolver import scalax.rules.scalasig._ /**The main object used to execute scalap on the command-line. @@ -99,7 +96,7 @@ class Main { /** Executes scalap with the given arguments and classpath for the * class denoted by `classname`. */ - def process(args: Arguments, path: ClassFileLookup)(classname: String): Unit = { + def process(args: Arguments, path: ClassPath)(classname: String): Unit = { // find the classfile val encName = classname match { case "scala.AnyRef" => "java.lang.Object" @@ -208,9 +205,9 @@ object Main extends Main { private def createClassPath(cpArg: Option[String], settings: Settings) = cpArg match { case Some(cp) => - AggregateFlatClassPath(new FlatClassPathFactory(settings).classesInExpandedPath(cp)) + AggregateClassPath(new ClassPathFactory(settings).classesInExpandedPath(cp)) case _ => settings.classpath.value = "." // include '.' in the default classpath SI-6669 - PathResolverFactory.create(settings).result + new PathResolver(settings).result } } diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala index 2a52474e5d..cb2b3ff449 100644 --- a/test/files/run/t6502.scala +++ b/test/files/run/t6502.scala @@ -1,6 +1,5 @@ import scala.tools.nsc.Settings import scala.tools.nsc.interpreter.{ ILoop, replProps } -import scala.tools.nsc.settings.ClassPathRepresentationType import scala.tools.partest._ object Test extends StoreReporterDirectTest { diff --git a/test/files/run/various-flat-classpath-types.scala b/test/files/run/various-flat-classpath-types.scala index 527f22fc8b..bc54ffb6cc 100644 --- a/test/files/run/various-flat-classpath-types.scala +++ b/test/files/run/various-flat-classpath-types.scala @@ -5,7 +5,7 @@ import java.io.{File => JFile, FileInputStream, FileOutputStream} import java.util.zip.{ZipEntry, ZipOutputStream} import scala.reflect.io.{Directory, File} -import scala.tools.nsc.classpath.FlatClassPath.RootPackage +import scala.tools.nsc.util.ClassPath.RootPackage import scala.tools.nsc.classpath.PackageNameUtils import scala.tools.nsc.io.Jar diff --git a/test/junit/scala/tools/nsc/classpath/AggregateClassPathTest.scala b/test/junit/scala/tools/nsc/classpath/AggregateClassPathTest.scala new file mode 100644 index 0000000000..a7aca31ee3 --- /dev/null +++ b/test/junit/scala/tools/nsc/classpath/AggregateClassPathTest.scala @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import java.net.URL +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.reflect.io.VirtualFile +import scala.tools.nsc.io.AbstractFile +import scala.tools.nsc.util.ClassPath + +/** + * Tests whether AggregateFlatClassPath returns correct entries taken from + * cp instances used during creating it and whether it preserves the ordering + * (in the case of the repeated entry for a class or a source it returns the first one). + */ +@RunWith(classOf[JUnit4]) +class AggregateClassPathTest { + + private abstract class TestClassPathBase extends ClassPath { + override def packages(inPackage: String): Seq[PackageEntry] = unsupported + override def sources(inPackage: String): Seq[SourceFileEntry] = unsupported + override def classes(inPackage: String): Seq[ClassFileEntry] = unsupported + + override def list(inPackage: String): ClassPathEntries = unsupported + override def findClassFile(name: String): Option[AbstractFile] = unsupported + + override def asClassPathStrings: Seq[String] = unsupported + override def asSourcePathString: String = unsupported + override def asURLs: Seq[URL] = unsupported + } + + private case class TestClassPath(virtualPath: String, classesInPackage: EntryNamesInPackage*) extends TestClassPathBase { + + override def classes(inPackage: String): Seq[ClassFileEntry] = + for { + entriesWrapper <- classesInPackage if entriesWrapper.inPackage == inPackage + name <- entriesWrapper.names + } yield classFileEntry(virtualPath, inPackage, name) + + override def sources(inPackage: String): Seq[SourceFileEntry] = Nil + + // we'll ignore packages + override def list(inPackage: String): ClassPathEntries = ClassPathEntries(Nil, classes(inPackage)) + } + + private case class TestSourcePath(virtualPath: String, sourcesInPackage: EntryNamesInPackage*) extends TestClassPathBase { + + override def sources(inPackage: String): Seq[SourceFileEntry] = + for { + entriesWrapper <- sourcesInPackage if entriesWrapper.inPackage == inPackage + name <- entriesWrapper.names + } yield sourceFileEntry(virtualPath, inPackage, name) + + override def classes(inPackage: String): Seq[ClassFileEntry] = Nil + + // we'll ignore packages + override def list(inPackage: String): ClassPathEntries = ClassPathEntries(Nil, sources(inPackage)) + } + + private case class EntryNamesInPackage(inPackage: String)(val names: String*) + + private val dir1 = "./dir1" + private val dir2 = "./dir2" + private val dir3 = "./dir3" + private val dir4 = "" + + private val pkg1 = "pkg1" + private val pkg2 = "pkg2" + private val pkg3 = "pkg1.nested" + private val nonexistingPkg = "nonexisting" + + private def unsupported = throw new UnsupportedOperationException + + private def classFileEntry(pathPrefix: String, inPackage: String, fileName: String) = + ClassFileEntryImpl(classFile(pathPrefix, inPackage, fileName)) + + private def sourceFileEntry(pathPrefix: String, inPackage: String, fileName: String) = + SourceFileEntryImpl(sourceFile(pathPrefix, inPackage, fileName)) + + private def classFile(pathPrefix: String, inPackage: String, fileName: String) = + virtualFile(pathPrefix, inPackage, fileName, ".class") + + private def sourceFile(pathPrefix: String, inPackage: String, fileName: String) = + virtualFile(pathPrefix, inPackage, fileName, ".scala") + + private def virtualFile(pathPrefix: String, inPackage: String, fileName: String, extension: String) = { + val packageDirs = + if (inPackage == ClassPath.RootPackage) "" + else inPackage.split('.').mkString("/", "/", "") + new VirtualFile(fileName + extension, s"$pathPrefix$packageDirs/$fileName$extension") + } + + private def createDefaultTestClasspath() = { + val partialClassPaths = Seq(TestSourcePath(dir1, EntryNamesInPackage(pkg1)("F", "A", "G")), + TestClassPath(dir2, EntryNamesInPackage(pkg1)("C", "B", "A"), EntryNamesInPackage(pkg2)("D", "A", "E")), + TestClassPath(dir3, EntryNamesInPackage(pkg1)("A", "D", "F")), + TestSourcePath(dir4, EntryNamesInPackage(pkg2)("A", "H", "I"), EntryNamesInPackage(pkg1)("A")), + TestSourcePath(dir2, EntryNamesInPackage(pkg3)("J", "K", "L")) + ) + + AggregateClassPath(partialClassPaths) + } + + @Test + def testGettingPackages: Unit = { + case class ClassPathWithPackages(packagesInPackage: EntryNamesInPackage*) extends TestClassPathBase { + override def packages(inPackage: String): Seq[PackageEntry] = + packagesInPackage.find(_.inPackage == inPackage).map(_.names).getOrElse(Nil) map PackageEntryImpl + } + + val partialClassPaths = Seq(ClassPathWithPackages(EntryNamesInPackage(pkg1)("pkg1.a", "pkg1.d", "pkg1.f")), + ClassPathWithPackages(EntryNamesInPackage(pkg1)("pkg1.c", "pkg1.b", "pkg1.a"), + EntryNamesInPackage(pkg2)("pkg2.d", "pkg2.a", "pkg2.e")) + ) + val cp = AggregateClassPath(partialClassPaths) + + val packagesInPkg1 = Seq("pkg1.a", "pkg1.d", "pkg1.f", "pkg1.c", "pkg1.b") + assertEquals(packagesInPkg1, cp.packages(pkg1).map(_.name)) + + val packagesInPkg2 = Seq("pkg2.d", "pkg2.a", "pkg2.e") + assertEquals(packagesInPkg2, cp.packages(pkg2).map(_.name)) + + assertEquals(Seq.empty, cp.packages(nonexistingPkg)) + } + + @Test + def testGettingClasses: Unit = { + val cp = createDefaultTestClasspath() + + val classesInPkg1 = Seq(classFileEntry(dir2, pkg1, "C"), + classFileEntry(dir2, pkg1, "B"), + classFileEntry(dir2, pkg1, "A"), + classFileEntry(dir3, pkg1, "D"), + classFileEntry(dir3, pkg1, "F") + ) + assertEquals(classesInPkg1, cp.classes(pkg1)) + + val classesInPkg2 = Seq(classFileEntry(dir2, pkg2, "D"), + classFileEntry(dir2, pkg2, "A"), + classFileEntry(dir2, pkg2, "E") + ) + assertEquals(classesInPkg2, cp.classes(pkg2)) + + assertEquals(Seq.empty, cp.classes(pkg3)) + assertEquals(Seq.empty, cp.classes(nonexistingPkg)) + } + + @Test + def testGettingSources: Unit = { + val partialClassPaths = Seq(TestClassPath(dir1, EntryNamesInPackage(pkg1)("F", "A", "G")), + TestSourcePath(dir2, EntryNamesInPackage(pkg1)("C", "B", "A"), EntryNamesInPackage(pkg2)("D", "A", "E")), + TestSourcePath(dir3, EntryNamesInPackage(pkg1)("A", "D", "F")), + TestClassPath(dir4, EntryNamesInPackage(pkg2)("A", "H", "I")), + TestClassPath(dir2, EntryNamesInPackage(pkg3)("J", "K", "L")) + ) + val cp = AggregateClassPath(partialClassPaths) + + val sourcesInPkg1 = Seq(sourceFileEntry(dir2, pkg1, "C"), + sourceFileEntry(dir2, pkg1, "B"), + sourceFileEntry(dir2, pkg1, "A"), + sourceFileEntry(dir3, pkg1, "D"), + sourceFileEntry(dir3, pkg1, "F") + ) + assertEquals(sourcesInPkg1, cp.sources(pkg1)) + + val sourcesInPkg2 = Seq(sourceFileEntry(dir2, pkg2, "D"), + sourceFileEntry(dir2, pkg2, "A"), + sourceFileEntry(dir2, pkg2, "E") + ) + assertEquals(sourcesInPkg2, cp.sources(pkg2)) + + assertEquals(Seq.empty, cp.sources(pkg3)) + assertEquals(Seq.empty, cp.sources(nonexistingPkg)) + } + + @Test + def testList: Unit = { + val cp = createDefaultTestClasspath() + + val classesAndSourcesInPkg1 = Seq( + ClassAndSourceFilesEntry(classFile(dir3, pkg1, "F"), sourceFile(dir1, pkg1, "F")), + ClassAndSourceFilesEntry(classFile(dir2, pkg1, "A"), sourceFile(dir1, pkg1, "A")), + sourceFileEntry(dir1, pkg1, "G"), + classFileEntry(dir2, pkg1, "C"), + classFileEntry(dir2, pkg1, "B"), + classFileEntry(dir3, pkg1, "D") + ) + assertEquals(classesAndSourcesInPkg1, cp.list(pkg1).classesAndSources) + + assertEquals(ClassPathEntries(Nil, Nil), cp.list(nonexistingPkg)) + } + + @Test + def testFindClass: Unit = { + val cp = createDefaultTestClasspath() + + assertEquals( + Some(ClassAndSourceFilesEntry(classFile(dir2, pkg1, "A"), sourceFile(dir1, pkg1, "A"))), + cp.findClass(s"$pkg1.A") + ) + assertEquals(Some(classFileEntry(dir3, pkg1, "D")), cp.findClass(s"$pkg1.D")) + assertEquals(Some(sourceFileEntry(dir2, pkg3, "L")), cp.findClass(s"$pkg3.L")) + assertEquals(None, cp.findClass("Nonexisting")) + } +} diff --git a/test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala b/test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala deleted file mode 100644 index 9a004d5e0e..0000000000 --- a/test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.classpath - -import java.net.URL -import org.junit.Assert._ -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import scala.reflect.io.VirtualFile -import scala.tools.nsc.io.AbstractFile - -/** - * Tests whether AggregateFlatClassPath returns correct entries taken from - * cp instances used during creating it and whether it preserves the ordering - * (in the case of the repeated entry for a class or a source it returns the first one). - */ -@RunWith(classOf[JUnit4]) -class AggregateFlatClassPathTest { - - private class TestFlatClassPath extends FlatClassPath { - override def packages(inPackage: String): Seq[PackageEntry] = unsupported - override def sources(inPackage: String): Seq[SourceFileEntry] = unsupported - override def classes(inPackage: String): Seq[ClassFileEntry] = unsupported - - override def list(inPackage: String): FlatClassPathEntries = unsupported - override def findClassFile(name: String): Option[AbstractFile] = unsupported - - override def asClassPathStrings: Seq[String] = unsupported - override def asSourcePathString: String = unsupported - override def asURLs: Seq[URL] = unsupported - } - - private case class TestClassPath(virtualPath: String, classesInPackage: EntryNamesInPackage*) extends TestFlatClassPath { - - override def classes(inPackage: String): Seq[ClassFileEntry] = - for { - entriesWrapper <- classesInPackage if entriesWrapper.inPackage == inPackage - name <- entriesWrapper.names - } yield classFileEntry(virtualPath, inPackage, name) - - override def sources(inPackage: String): Seq[SourceFileEntry] = Nil - - // we'll ignore packages - override def list(inPackage: String): FlatClassPathEntries = FlatClassPathEntries(Nil, classes(inPackage)) - } - - private case class TestSourcePath(virtualPath: String, sourcesInPackage: EntryNamesInPackage*) extends TestFlatClassPath { - - override def sources(inPackage: String): Seq[SourceFileEntry] = - for { - entriesWrapper <- sourcesInPackage if entriesWrapper.inPackage == inPackage - name <- entriesWrapper.names - } yield sourceFileEntry(virtualPath, inPackage, name) - - override def classes(inPackage: String): Seq[ClassFileEntry] = Nil - - // we'll ignore packages - override def list(inPackage: String): FlatClassPathEntries = FlatClassPathEntries(Nil, sources(inPackage)) - } - - private case class EntryNamesInPackage(inPackage: String)(val names: String*) - - private val dir1 = "./dir1" - private val dir2 = "./dir2" - private val dir3 = "./dir3" - private val dir4 = "" - - private val pkg1 = "pkg1" - private val pkg2 = "pkg2" - private val pkg3 = "pkg1.nested" - private val nonexistingPkg = "nonexisting" - - private def unsupported = throw new UnsupportedOperationException - - private def classFileEntry(pathPrefix: String, inPackage: String, fileName: String) = - ClassFileEntryImpl(classFile(pathPrefix, inPackage, fileName)) - - private def sourceFileEntry(pathPrefix: String, inPackage: String, fileName: String) = - SourceFileEntryImpl(sourceFile(pathPrefix, inPackage, fileName)) - - private def classFile(pathPrefix: String, inPackage: String, fileName: String) = - virtualFile(pathPrefix, inPackage, fileName, ".class") - - private def sourceFile(pathPrefix: String, inPackage: String, fileName: String) = - virtualFile(pathPrefix, inPackage, fileName, ".scala") - - private def virtualFile(pathPrefix: String, inPackage: String, fileName: String, extension: String) = { - val packageDirs = - if (inPackage == FlatClassPath.RootPackage) "" - else inPackage.split('.').mkString("/", "/", "") - new VirtualFile(fileName + extension, s"$pathPrefix$packageDirs/$fileName$extension") - } - - private def createDefaultTestClasspath() = { - val partialClassPaths = Seq(TestSourcePath(dir1, EntryNamesInPackage(pkg1)("F", "A", "G")), - TestClassPath(dir2, EntryNamesInPackage(pkg1)("C", "B", "A"), EntryNamesInPackage(pkg2)("D", "A", "E")), - TestClassPath(dir3, EntryNamesInPackage(pkg1)("A", "D", "F")), - TestSourcePath(dir4, EntryNamesInPackage(pkg2)("A", "H", "I"), EntryNamesInPackage(pkg1)("A")), - TestSourcePath(dir2, EntryNamesInPackage(pkg3)("J", "K", "L")) - ) - - AggregateFlatClassPath(partialClassPaths) - } - - @Test - def testGettingPackages: Unit = { - case class ClassPathWithPackages(packagesInPackage: EntryNamesInPackage*) extends TestFlatClassPath { - override def packages(inPackage: String): Seq[PackageEntry] = - packagesInPackage.find(_.inPackage == inPackage).map(_.names).getOrElse(Nil) map PackageEntryImpl - } - - val partialClassPaths = Seq(ClassPathWithPackages(EntryNamesInPackage(pkg1)("pkg1.a", "pkg1.d", "pkg1.f")), - ClassPathWithPackages(EntryNamesInPackage(pkg1)("pkg1.c", "pkg1.b", "pkg1.a"), - EntryNamesInPackage(pkg2)("pkg2.d", "pkg2.a", "pkg2.e")) - ) - val cp = AggregateFlatClassPath(partialClassPaths) - - val packagesInPkg1 = Seq("pkg1.a", "pkg1.d", "pkg1.f", "pkg1.c", "pkg1.b") - assertEquals(packagesInPkg1, cp.packages(pkg1).map(_.name)) - - val packagesInPkg2 = Seq("pkg2.d", "pkg2.a", "pkg2.e") - assertEquals(packagesInPkg2, cp.packages(pkg2).map(_.name)) - - assertEquals(Seq.empty, cp.packages(nonexistingPkg)) - } - - @Test - def testGettingClasses: Unit = { - val cp = createDefaultTestClasspath() - - val classesInPkg1 = Seq(classFileEntry(dir2, pkg1, "C"), - classFileEntry(dir2, pkg1, "B"), - classFileEntry(dir2, pkg1, "A"), - classFileEntry(dir3, pkg1, "D"), - classFileEntry(dir3, pkg1, "F") - ) - assertEquals(classesInPkg1, cp.classes(pkg1)) - - val classesInPkg2 = Seq(classFileEntry(dir2, pkg2, "D"), - classFileEntry(dir2, pkg2, "A"), - classFileEntry(dir2, pkg2, "E") - ) - assertEquals(classesInPkg2, cp.classes(pkg2)) - - assertEquals(Seq.empty, cp.classes(pkg3)) - assertEquals(Seq.empty, cp.classes(nonexistingPkg)) - } - - @Test - def testGettingSources: Unit = { - val partialClassPaths = Seq(TestClassPath(dir1, EntryNamesInPackage(pkg1)("F", "A", "G")), - TestSourcePath(dir2, EntryNamesInPackage(pkg1)("C", "B", "A"), EntryNamesInPackage(pkg2)("D", "A", "E")), - TestSourcePath(dir3, EntryNamesInPackage(pkg1)("A", "D", "F")), - TestClassPath(dir4, EntryNamesInPackage(pkg2)("A", "H", "I")), - TestClassPath(dir2, EntryNamesInPackage(pkg3)("J", "K", "L")) - ) - val cp = AggregateFlatClassPath(partialClassPaths) - - val sourcesInPkg1 = Seq(sourceFileEntry(dir2, pkg1, "C"), - sourceFileEntry(dir2, pkg1, "B"), - sourceFileEntry(dir2, pkg1, "A"), - sourceFileEntry(dir3, pkg1, "D"), - sourceFileEntry(dir3, pkg1, "F") - ) - assertEquals(sourcesInPkg1, cp.sources(pkg1)) - - val sourcesInPkg2 = Seq(sourceFileEntry(dir2, pkg2, "D"), - sourceFileEntry(dir2, pkg2, "A"), - sourceFileEntry(dir2, pkg2, "E") - ) - assertEquals(sourcesInPkg2, cp.sources(pkg2)) - - assertEquals(Seq.empty, cp.sources(pkg3)) - assertEquals(Seq.empty, cp.sources(nonexistingPkg)) - } - - @Test - def testList: Unit = { - val cp = createDefaultTestClasspath() - - val classesAndSourcesInPkg1 = Seq( - ClassAndSourceFilesEntry(classFile(dir3, pkg1, "F"), sourceFile(dir1, pkg1, "F")), - ClassAndSourceFilesEntry(classFile(dir2, pkg1, "A"), sourceFile(dir1, pkg1, "A")), - sourceFileEntry(dir1, pkg1, "G"), - classFileEntry(dir2, pkg1, "C"), - classFileEntry(dir2, pkg1, "B"), - classFileEntry(dir3, pkg1, "D") - ) - assertEquals(classesAndSourcesInPkg1, cp.list(pkg1).classesAndSources) - - assertEquals(FlatClassPathEntries(Nil, Nil), cp.list(nonexistingPkg)) - } - - @Test - def testFindClass: Unit = { - val cp = createDefaultTestClasspath() - - assertEquals( - Some(ClassAndSourceFilesEntry(classFile(dir2, pkg1, "A"), sourceFile(dir1, pkg1, "A"))), - cp.findClass(s"$pkg1.A") - ) - assertEquals(Some(classFileEntry(dir3, pkg1, "D")), cp.findClass(s"$pkg1.D")) - assertEquals(Some(sourceFileEntry(dir2, pkg3, "L")), cp.findClass(s"$pkg3.L")) - assertEquals(None, cp.findClass("Nonexisting")) - } -} diff --git a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala deleted file mode 100644 index 97c3200fc2..0000000000 --- a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.classpath - -import java.io.File -import org.junit.Assert._ -import org.junit._ -import org.junit.rules.TemporaryFolder -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import scala.annotation.tailrec -import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.util.ClassPath -import scala.tools.nsc.Settings -import scala.tools.util.FlatClassPathResolver -import scala.tools.util.PathResolver - -@RunWith(classOf[JUnit4]) -class FlatClassPathResolverTest { - - val tempDir = new TemporaryFolder() - - private val packagesToTest = List(FlatClassPath.RootPackage, "scala", "scala.reflect", "scala.reflect.io") - private val classFilesToFind = List("scala.tools.util.FlatClassPathResolver", - "scala.reflect.io.AbstractFile", - "scala.collection.immutable.List", - "scala.Option", - "scala.collection.immutable.Vector", - "scala.util.hashing.MurmurHash3", - "java.lang.Object", - "java.util.Date") - - private val classesToFind = classFilesToFind ++ List("TestSourceInRootPackage", - "scala.reflect.io.TestScalaSource", - "scala.reflect.io.TestJavaSource") - - private val settings = new Settings - - @Before - def initTempDirAndSourcePath: Unit = { - // In Java TemporaryFolder in JUnit is managed automatically using @Rule. - // It would work also in Scala after adding and extending a class like - // TestWithTempFolder.java containing it. But in this case it doesn't work when running tests - // from the command line - java class is not compiled due to some, mysterious reasons. - // That's why such dirs are here created and deleted manually. - tempDir.create() - tempDir.newFile("TestSourceInRootPackage.scala") - val ioDir = tempDir.newFolder("scala", "reflect", "io") - new File(ioDir, "AbstractFile.scala").createNewFile() - new File(ioDir, "ZipArchive.java").createNewFile() - new File(ioDir, "TestScalaSource.scala").createNewFile() - new File(ioDir, "TestJavaSource.java").createNewFile() - - settings.usejavacp.value = true - settings.sourcepath.value = tempDir.getRoot.getAbsolutePath - } - - @After - def deleteTempDir: Unit = tempDir.delete() - - private def createFlatClassPath(settings: Settings) = - new FlatClassPathResolver(settings).result - - @Test - def testEntriesFromListOperationAgainstSeparateMethods: Unit = { - val classPath = createFlatClassPath(settings) - - def compareEntriesInPackage(inPackage: String): Unit = { - val packages = classPath.packages(inPackage) - val classes = classPath.classes(inPackage) - val sources = classPath.sources(inPackage) - val FlatClassPathEntries(packagesFromList, classesAndSourcesFromList) = classPath.list(inPackage) - - val packageNames = packages.map(_.name).sorted - val packageNamesFromList = packagesFromList.map(_.name).sorted - assertEquals(s"Methods list and packages for package '$inPackage' should return the same packages", - packageNames, packageNamesFromList) - - val classFileNames = classes.map(_.name).sorted - val classFileNamesFromList = classesAndSourcesFromList.filter(_.binary.isDefined).map(_.name).sorted - assertEquals(s"Methods list and classes for package '$inPackage' should return entries for the same class files", - classFileNames, classFileNamesFromList) - - val sourceFileNames = sources.map(_.name).sorted - val sourceFileNamesFromList = classesAndSourcesFromList.filter(_.source.isDefined).map(_.name).sorted - assertEquals(s"Methods list and sources for package '$inPackage' should return entries for the same source files", - sourceFileNames, sourceFileNamesFromList) - - val uniqueNamesOfClassAndSourceFiles = (classFileNames ++ sourceFileNames).toSet - assertEquals(s"Class and source entries with the same name obtained via list for package '$inPackage' should be merged into one containing both files", - uniqueNamesOfClassAndSourceFiles.size, classesAndSourcesFromList.length) - } - - packagesToTest foreach compareEntriesInPackage - } - - @Test - def testFindClassFile: Unit = { - val classPath = createFlatClassPath(settings) - classFilesToFind foreach { className => - assertTrue(s"File for $className should be found", classPath.findClassFile(className).isDefined) - } - } - - @Test - def testFindClass: Unit = { - val classPath = createFlatClassPath(settings) - classesToFind foreach { className => - assertTrue(s"File for $className should be found", classPath.findClass(className).isDefined) - } - } -} diff --git a/test/junit/scala/tools/nsc/classpath/PathResolverBaseTest.scala b/test/junit/scala/tools/nsc/classpath/PathResolverBaseTest.scala new file mode 100644 index 0000000000..d3d4289d8b --- /dev/null +++ b/test/junit/scala/tools/nsc/classpath/PathResolverBaseTest.scala @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import java.io.File +import org.junit.Assert._ +import org.junit._ +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.tools.nsc.util.ClassPath +import scala.tools.nsc.Settings +import scala.tools.util.PathResolver + +@RunWith(classOf[JUnit4]) +class PathResolverBaseTest { + + val tempDir = new TemporaryFolder() + + private val packagesToTest = List(ClassPath.RootPackage, "scala", "scala.reflect", "scala.reflect.io") + private val classFilesToFind = List("scala.tools.util.PathResolver", + "scala.reflect.io.AbstractFile", + "scala.collection.immutable.List", + "scala.Option", + "scala.collection.immutable.Vector", + "scala.util.hashing.MurmurHash3", + "java.lang.Object", + "java.util.Date") + + private val classesToFind = classFilesToFind ++ List("TestSourceInRootPackage", + "scala.reflect.io.TestScalaSource", + "scala.reflect.io.TestJavaSource") + + private val settings = new Settings + + @Before + def initTempDirAndSourcePath: Unit = { + // In Java TemporaryFolder in JUnit is managed automatically using @Rule. + // It would work also in Scala after adding and extending a class like + // TestWithTempFolder.java containing it. But in this case it doesn't work when running tests + // from the command line - java class is not compiled due to some, mysterious reasons. + // That's why such dirs are here created and deleted manually. + tempDir.create() + tempDir.newFile("TestSourceInRootPackage.scala") + val ioDir = tempDir.newFolder("scala", "reflect", "io") + new File(ioDir, "AbstractFile.scala").createNewFile() + new File(ioDir, "ZipArchive.java").createNewFile() + new File(ioDir, "TestScalaSource.scala").createNewFile() + new File(ioDir, "TestJavaSource.java").createNewFile() + + settings.usejavacp.value = true + settings.sourcepath.value = tempDir.getRoot.getAbsolutePath + } + + @After + def deleteTempDir: Unit = tempDir.delete() + + private def createFlatClassPath(settings: Settings) = + new PathResolver(settings).result + + @Test + def testEntriesFromListOperationAgainstSeparateMethods: Unit = { + val classPath = createFlatClassPath(settings) + + def compareEntriesInPackage(inPackage: String): Unit = { + val packages = classPath.packages(inPackage) + val classes = classPath.classes(inPackage) + val sources = classPath.sources(inPackage) + val ClassPathEntries(packagesFromList, classesAndSourcesFromList) = classPath.list(inPackage) + + val packageNames = packages.map(_.name).sorted + val packageNamesFromList = packagesFromList.map(_.name).sorted + assertEquals(s"Methods list and packages for package '$inPackage' should return the same packages", + packageNames, packageNamesFromList) + + val classFileNames = classes.map(_.name).sorted + val classFileNamesFromList = classesAndSourcesFromList.filter(_.binary.isDefined).map(_.name).sorted + assertEquals(s"Methods list and classes for package '$inPackage' should return entries for the same class files", + classFileNames, classFileNamesFromList) + + val sourceFileNames = sources.map(_.name).sorted + val sourceFileNamesFromList = classesAndSourcesFromList.filter(_.source.isDefined).map(_.name).sorted + assertEquals(s"Methods list and sources for package '$inPackage' should return entries for the same source files", + sourceFileNames, sourceFileNamesFromList) + + val uniqueNamesOfClassAndSourceFiles = (classFileNames ++ sourceFileNames).toSet + assertEquals(s"Class and source entries with the same name obtained via list for package '$inPackage' should be merged into one containing both files", + uniqueNamesOfClassAndSourceFiles.size, classesAndSourcesFromList.length) + } + + packagesToTest foreach compareEntriesInPackage + } + + @Test + def testFindClassFile: Unit = { + val classPath = createFlatClassPath(settings) + classFilesToFind foreach { className => + assertTrue(s"File for $className should be found", classPath.findClassFile(className).isDefined) + } + } + + @Test + def testFindClass: Unit = { + val classPath = createFlatClassPath(settings) + classesToFind foreach { className => + assertTrue(s"File for $className should be found", classPath.findClass(className).isDefined) + } + } +} diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala index 45cded6d43..8cc7aefdd3 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala @@ -3,11 +3,8 @@ package symtab import scala.reflect.ClassTag import scala.reflect.internal.{NoPhase, Phase, SomePhase} -import scala.tools.nsc.classpath.FlatClassPath -import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.util.FlatClassPathResolver import scala.tools.util.PathResolver -import util.{ClassFileLookup, ClassPath} +import util.ClassPath import io.AbstractFile /** @@ -30,7 +27,7 @@ class SymbolTableForUnitTesting extends SymbolTable { override def isCompilerUniverse: Boolean = true - def flatClassPath: FlatClassPath = platform.flatClassPath + def classPath: ClassPath = platform.classPath object platform extends backend.Platform { val symbolTable: SymbolTableForUnitTesting.this.type = SymbolTableForUnitTesting.this @@ -38,12 +35,12 @@ class SymbolTableForUnitTesting extends SymbolTable { def platformPhases: List[SubComponent] = Nil - private[nsc] lazy val flatClassPath: FlatClassPath = new FlatClassPathResolver(settings).result + private[nsc] lazy val classPath: ClassPath = new PathResolver(settings).result def isMaybeBoxed(sym: Symbol): Boolean = ??? def needCompile(bin: AbstractFile, src: AbstractFile): Boolean = ??? def externalEquals: Symbol = ??? - def updateClassPath(subst: Map[FlatClassPath, FlatClassPath]): Unit = ??? + def updateClassPath(subst: Map[ClassPath, ClassPath]): Unit = ??? } object loaders extends symtab.SymbolLoaders { @@ -58,7 +55,7 @@ class SymbolTableForUnitTesting extends SymbolTable { class GlobalMirror extends Roots(NoSymbol) { val universe: SymbolTableForUnitTesting.this.type = SymbolTableForUnitTesting.this - def rootLoader: LazyType = new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) + def rootLoader: LazyType = new loaders.PackageLoader(ClassPath.RootPackage, classPath) override def toString = "compiler mirror" } -- cgit v1.2.3