From 43f7a86e931045c30575e4f0e5a6cd542dc0a380 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 21 Apr 2016 20:31:04 +0200 Subject: remove recursive classpath implementation --- src/compiler/scala/tools/nsc/Global.scala | 120 ++------ src/compiler/scala/tools/nsc/ScriptRunner.scala | 6 +- .../scala/tools/nsc/backend/JavaPlatform.scala | 26 +- .../scala/tools/nsc/backend/Platform.scala | 5 +- .../nsc/backend/jvm/opt/ByteCodeRepository.scala | 2 +- .../nsc/classpath/AggregateFlatClassPath.scala | 2 +- .../tools/nsc/classpath/ClassPathFactory.scala | 2 +- .../nsc/classpath/DirectoryFlatClassPath.scala | 4 +- .../scala/tools/nsc/classpath/FlatClassPath.scala | 6 +- .../classpath/VirtualDirectoryFlatClassPath.scala | 2 +- .../scala/tools/nsc/settings/ScalaSettings.scala | 1 - .../scala/tools/nsc/symtab/SymbolLoaders.scala | 37 +-- .../nsc/symtab/classfile/ClassfileParser.scala | 2 +- .../scala/tools/nsc/util/ClassFileLookup.scala | 33 +-- src/compiler/scala/tools/nsc/util/ClassPath.scala | 318 +-------------------- src/compiler/scala/tools/util/PathResolver.scala | 34 +-- .../scala/tools/partest/BytecodeTest.scala | 18 +- .../nsc/interpreter/PresentationCompilation.scala | 20 +- src/scalap/scala/tools/scalap/Main.scala | 17 +- test/files/run/t6502.scala | 17 +- test/files/run/various-flat-classpath-types.scala | 7 +- .../nsc/classpath/FlatClassPathResolverTest.scala | 46 --- .../nsc/symtab/SymbolTableForUnitTesting.scala | 20 +- .../tools/nsc/util/ClassPathImplComparator.scala | 143 --------- 24 files changed, 85 insertions(+), 803 deletions(-) delete mode 100644 test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 847c4cb2d1..7509437e79 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, ClassPath, StatisticsInfo, returning} +import util.{ClassFileLookup, StatisticsInfo, returning} import scala.reflect.ClassTag import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, ScalaClassLoader, ScriptSourceFile, SourceFile} import scala.reflect.internal.pickling.PickleBuffer @@ -54,12 +54,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) class GlobalMirror extends Roots(NoSymbol) { val universe: self.type = self - def rootLoader: LazyType = { - settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Flat => new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) - case ClassPathRepresentationType.Recursive => new loaders.PackageLoader(recursiveClassPath) - } - } + def rootLoader: LazyType = new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) override def toString = "compiler mirror" } implicit val MirrorTag: ClassTag[Mirror] = ClassTag[Mirror](classOf[GlobalMirror]) @@ -102,12 +97,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[AbstractFile] = settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Flat => flatClassPath - case ClassPathRepresentationType.Recursive => recursiveClassPath - } - - private def recursiveClassPath: ClassPath[AbstractFile] = platform.classPath + def classPath: ClassFileLookup = platform.flatClassPath private def flatClassPath: FlatClassPath = platform.flatClassPath @@ -768,17 +758,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Extend classpath of `platform` and rescan updated packages. */ def extendCompilerClassPath(urls: URL*): Unit = { - if (settings.YclasspathImpl.value == ClassPathRepresentationType.Flat) { - val urlClasspaths = urls.map(u => FlatClassPathFactory.newClassPath(AbstractFile.getURL(u), settings)) - val newClassPath = AggregateFlatClassPath.createAggregate(platform.flatClassPath +: urlClasspaths : _*) - platform.currentFlatClassPath = Some(newClassPath) - invalidateClassPathEntries(urls.map(_.getPath): _*) - } else { - val newClassPath = platform.classPath.mergeUrlsIntoClassPath(urls: _*) - platform.currentClassPath = Some(newClassPath) - // Reload all specified jars into this compiler instance - invalidateClassPathEntries(urls.map(_.getPath): _*) - } + val urlClasspaths = urls.map(u => FlatClassPathFactory.newClassPath(AbstractFile.getURL(u), settings)) + val newClassPath = AggregateFlatClassPath.createAggregate(platform.flatClassPath +: urlClasspaths : _*) + platform.currentFlatClassPath = Some(newClassPath) + invalidateClassPathEntries(urls.map(_.getPath): _*) } // ------------ Invalidations --------------------------------- @@ -810,28 +793,26 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * entries on the classpath. */ def invalidateClassPathEntries(paths: String*): Unit = { - implicit object ClassPathOrdering extends Ordering[ClassFileLookup[AbstractFile]] { - def compare(a:ClassFileLookup[AbstractFile], b:ClassFileLookup[AbstractFile]) = a.asClassPathString compare b.asClassPathString + implicit object ClassPathOrdering extends Ordering[FlatClassPath] { + def compare(a: FlatClassPath, b: FlatClassPath): Int = a.asClassPathString compareTo b.asClassPathString } val invalidated, failed = new mutable.ListBuffer[ClassSymbol] - def assoc(path: String): Option[(ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile])] = { - def origin(lookup: ClassFileLookup[AbstractFile]): Option[String] = lookup match { - case cp: ClassPath[_] => cp.origin + def assoc(path: String): Option[(FlatClassPath, FlatClassPath)] = { + def origin(lookup: ClassFileLookup): Option[String] = lookup match { case cp: JFileDirectoryLookup[_] => Some(cp.dir.getPath) case cp: ZipArchiveFileLookup[_] => Some(cp.zipFile.getPath) case _ => None } - def entries(lookup: ClassFileLookup[AbstractFile]): Seq[ClassFileLookup[AbstractFile]] = lookup match { - case cp: ClassPath[_] => cp.entries + def entries(lookup: ClassFileLookup): Seq[FlatClassPath] = lookup match { case cp: AggregateFlatClassPath => cp.aggregates case cp: FlatClassPath => 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[AbstractFile]) = origin(e) match { + def matchesCanonical(e: ClassFileLookup) = origin(e) match { case Some(opath) => AbstractFile.getDirectory(opath).canonicalPath == canonical case None => @@ -839,7 +820,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } entries(classPath) find matchesCanonical match { case Some(oldEntry) => - Some(oldEntry -> ClassFileLookup.createForFile(dir, classPath, settings)) + Some(oldEntry -> FlatClassPathFactory.newClassPath(dir, settings)) case None => error(s"Error adding entry to classpath. During invalidation, no entry named $path in classpath $classPath") None @@ -849,19 +830,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[ClassFileLookup[AbstractFile]]): ClassFileLookup[AbstractFile] = + def mkClassPath(elems: Iterable[FlatClassPath]): FlatClassPath = if (elems.size == 1) elems.head - else ClassFileLookup.createAggregate(elems, classPath) + else AggregateFlatClassPath.createAggregate(elems.toSeq: _*) val oldEntries = mkClassPath(subst.keys) val newEntries = mkClassPath(subst.values) classPath match { - case rcp: ClassPath[_] => mergeNewEntriesRecursive( - newEntries.asInstanceOf[ClassPath[AbstractFile]], RootClass, Some(rcp), Some(oldEntries.asInstanceOf[ClassPath[AbstractFile]]), - invalidated, failed) - case fcp: FlatClassPath => mergeNewEntriesFlat( RootClass, "", - oldEntries.asInstanceOf[FlatClassPath], newEntries.asInstanceOf[FlatClassPath], fcp, + oldEntries, newEntries, fcp, invalidated, failed) } } @@ -872,69 +849,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) show("could not invalidate system packages", failed) } - /** Merges new classpath entries into the symbol table - * - * @param newEntries The new classpath entries - * @param root The root symbol to be resynced (a package class) - * @param allEntries Optionally, the corresponding package in the complete current classpath - * @param oldEntries Optionally, the corresponding package in the old classpath entries - * @param invalidated A listbuffer collecting the invalidated package classes - * @param failed A listbuffer collecting system package classes which could not be invalidated - * - * The merging strategy is determined by the absence or presence of classes and packages. - * - * If either oldEntries or newEntries contains classes, root is invalidated provided that a corresponding package - * exists in allEntries. Otherwise it is removed. - * Otherwise, the action is determined by the following matrix, with columns: - * - * old sym action - * + + recurse into all child packages of newEntries - * - + invalidate root - * - - create and enter root - * - * Here, old means classpath, and sym means symboltable. + is presence of an entry in its column, - is absence. - */ - private def mergeNewEntriesRecursive(newEntries: ClassPath[AbstractFile], root: ClassSymbol, - allEntries: Option[ClassPath[AbstractFile]], oldEntries: Option[ClassPath[AbstractFile]], - invalidated: mutable.ListBuffer[ClassSymbol], failed: mutable.ListBuffer[ClassSymbol]) { - ifDebug(informProgress(s"syncing $root, $oldEntries -> $newEntries")) - - val getPackageName: ClassPath[AbstractFile] => String = _.name - def hasClasses(cp: Option[ClassPath[AbstractFile]]) = cp.isDefined && cp.get.classes.nonEmpty - def invalidateOrRemove(root: ClassSymbol) = { - allEntries match { - case Some(cp) => root setInfo new loaders.PackageLoader(cp) - case None => root.owner.info.decls unlink root.sourceModule - } - invalidated += root - } - def subPackage(cp: ClassPath[AbstractFile], name: String): Option[ClassPath[AbstractFile]] = - cp.packages find (cp1 => getPackageName(cp1) == name) - - val classesFound = hasClasses(oldEntries) || newEntries.classes.nonEmpty - if (classesFound && !isSystemPackageClass(root)) { - invalidateOrRemove(root) - } else { - if (classesFound) { - if (root.isRoot) invalidateOrRemove(EmptyPackageClass) - else failed += root - } - if (oldEntries.isEmpty) invalidateOrRemove(root) - else - for (pstr <- newEntries.packages.map(getPackageName)) { - val pname = newTermName(pstr) - val pkg = (root.info decl pname) orElse { - // package does not exist in symbol table, create symbol to track it - assert(subPackage(oldEntries.get, pstr).isEmpty) - loaders.enterPackage(root, pstr, new loaders.PackageLoader(allEntries.get)) - } - mergeNewEntriesRecursive(subPackage(newEntries, pstr).get, pkg.moduleClass.asClass, - subPackage(allEntries.get, pstr), subPackage(oldEntries.get, pstr), - invalidated, failed) - } - } - } - /** * Merges new classpath entries into the symbol table * diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index bf93ad30bc..fed335daef 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -11,7 +11,6 @@ import java.io.IOException import scala.tools.nsc.classpath.DirectoryFlatClassPath import scala.tools.nsc.reporters.{Reporter,ConsoleReporter} import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.nsc.util.ClassPath.DefaultJavaContext import util.Exceptional.unwrap /** An object that runs Scala code in script files. @@ -115,10 +114,7 @@ class ScriptRunner extends HasCompileSocket { } def hasClassToRun(d: Directory): Boolean = { - val cp = settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Recursive => DefaultJavaContext.newClassPath(AbstractFile.getDirectory(d)) - case ClassPathRepresentationType.Flat => DirectoryFlatClassPath(d.jfile) - } + val cp = DirectoryFlatClassPath(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 0e2f059a36..1e4ea99509 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -9,7 +9,7 @@ package backend import io.AbstractFile import scala.tools.nsc.classpath.{AggregateFlatClassPath, FlatClassPath} import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.nsc.util.{ClassFileLookup, ClassPath, MergedClassPath} +import scala.tools.nsc.util.ClassFileLookup import scala.tools.util.FlatClassPathResolver import scala.tools.util.PathResolver @@ -19,38 +19,20 @@ trait JavaPlatform extends Platform { import global._ import definitions._ - private[nsc] var currentClassPath: Option[MergedClassPath[AbstractFile]] = None - - def classPath: ClassPath[AbstractFile] = { - assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Recursive, - "To use recursive classpath representation you must enable it with -YclasspathImpl:recursive compiler option.") - - if (currentClassPath.isEmpty) currentClassPath = Some(new PathResolver(settings).result) - currentClassPath.get - } - private[nsc] var currentFlatClassPath: Option[FlatClassPath] = None private[nsc] def flatClassPath: FlatClassPath = { - assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Flat, - "To use flat classpath representation you must enable it with -YclasspathImpl:flat compiler option.") - if (currentFlatClassPath.isEmpty) currentFlatClassPath = Some(new FlatClassPathResolver(settings).result) currentFlatClassPath.get } /** Update classpath with a substituted subentry */ - def updateClassPath(subst: Map[ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile]]) = global.classPath match { - case cp: ClassPath[AbstractFile] => - val s = subst.asInstanceOf[Map[ClassPath[AbstractFile], ClassPath[AbstractFile]]] - currentClassPath = Some(new MergedClassPath(cp.entries map (e => s.getOrElse(e, e)), cp.context)) - + def updateClassPath(subst: Map[FlatClassPath, FlatClassPath]): Unit = global.classPath match { case AggregateFlatClassPath(entries) => - val s = subst.asInstanceOf[Map[FlatClassPath, FlatClassPath]] - currentFlatClassPath = Some(AggregateFlatClassPath(entries map (e => s.getOrElse(e, e)))) + currentFlatClassPath = Some(AggregateFlatClassPath(entries map (e => subst.getOrElse(e, e)))) case cp: FlatClassPath => - currentFlatClassPath = Some(subst.getOrElse(cp, cp).asInstanceOf[FlatClassPath]) + currentFlatClassPath = 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 369bcc44ed..5279901b21 100644 --- a/src/compiler/scala/tools/nsc/backend/Platform.scala +++ b/src/compiler/scala/tools/nsc/backend/Platform.scala @@ -16,14 +16,11 @@ trait Platform { val symbolTable: symtab.SymbolTable import symbolTable._ - /** The old, recursive implementation of compiler classpath. */ - def classPath: ClassPath[AbstractFile] - /** The new implementation of compiler classpath. */ private[nsc] def flatClassPath: FlatClassPath /** Update classpath with a substitution that maps entries to entries */ - def updateClassPath(subst: Map[ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile]]) + def updateClassPath(subst: Map[FlatClassPath, FlatClassPath]) /** 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 4492d0baf5..c5259aa433 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala @@ -26,7 +26,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[AbstractFile], val btypes: BT) { +class ByteCodeRepository[BT <: BTypes](val classPath: ClassFileLookup, val btypes: BT) { import btypes._ /** diff --git a/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala index f97d97548e..3768ed19ac 100644 --- a/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala @@ -30,7 +30,7 @@ case class AggregateFlatClassPath(aggregates: Seq[FlatClassPath]) extends FlatCl find(aggregates) } - override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = { + override def findClass(className: String): Option[ClassRepresentation] = { val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) @tailrec diff --git a/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala b/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala index 9bf4e3f779..04477c11d4 100644 --- a/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala +++ b/src/compiler/scala/tools/nsc/classpath/ClassPathFactory.scala @@ -12,7 +12,7 @@ import scala.tools.nsc.util.ClassPath * 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 be either ClassPath[U] or FlatClassPath. + * Therefore, we expect that T will FlatClassPath. */ trait ClassPathFactory[T] { diff --git a/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala index e3964dfa78..ed38915cb6 100644 --- a/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala @@ -103,7 +103,7 @@ trait JFileDirectoryLookup[FileEntryType <: ClassRepClassPathEntry] extends Dire } case class DirectoryFlatClassPath(dir: File) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { - override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = findClassFile(className) map ClassFileEntryImpl + override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl def findClassFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) @@ -127,7 +127,7 @@ case class DirectoryFlatSourcePath(dir: File) extends JFileDirectoryLookup[Sourc protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file) protected def isMatchingFile(f: File): Boolean = endsScalaOrJava(f.getName) - override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = findSourceFile(className) map SourceFileEntryImpl + override def findClass(className: String): Option[ClassRepresentation] = findSourceFile(className) map SourceFileEntryImpl private def findSourceFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) diff --git a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala index e95ffe02e3..758071443d 100644 --- a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala @@ -14,7 +14,7 @@ import scala.tools.nsc.util.{ ClassFileLookup, ClassPath, ClassRepresentation } * * This is an alternative design compared to scala.tools.nsc.util.ClassPath */ -trait FlatClassPath extends ClassFileLookup[AbstractFile] { +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] @@ -25,7 +25,7 @@ trait FlatClassPath extends ClassFileLookup[AbstractFile] { // 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[AbstractFile]] = { + override def findClass(className: String): Option[ClassRepresentation] = { val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) val foundClassFromClassFiles = classes(pkg).find(_.name == simpleClassName) @@ -50,7 +50,7 @@ object FlatClassPathEntries { implicit def entry2Tuple(entry: FlatClassPathEntries): (Seq[PackageEntry], Seq[ClassRepClassPathEntry]) = (entry.packages, entry.classesAndSources) } -sealed trait ClassRepClassPathEntry extends ClassRepresentation[AbstractFile] +sealed trait ClassRepClassPathEntry extends ClassRepresentation trait ClassFileEntry extends ClassRepClassPathEntry { def file: AbstractFile diff --git a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala index 06cdab583c..3d418139de 100644 --- a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala @@ -23,7 +23,7 @@ case class VirtualDirectoryFlatClassPath(dir: VirtualDirectory) extends FlatClas def asURLs: Seq[URL] = Seq(new URL(dir.name)) def asClassPathStrings: Seq[String] = Seq(dir.path) - override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = findClassFile(className) map ClassFileEntryImpl + override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl def findClassFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 7b98011759..15925edeeb 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -200,7 +200,6 @@ trait ScalaSettings extends AbsScalaSettings val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overridden methods.") val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212) val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212) - val YclasspathImpl = ChoiceSetting ("-YclasspathImpl", "implementation", "Choose classpath scanning method.", List(ClassPathRepresentationType.Recursive, ClassPathRepresentationType.Flat), ClassPathRepresentationType.Flat) val YdisableFlatCpCaching = BooleanSetting ("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.") val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 4f5589fd7c..e5c8e64347 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -154,7 +154,7 @@ abstract class SymbolLoaders { /** Initialize toplevel class and module symbols in `owner` from class path representation `classRep` */ - def initializeFromClassPath(owner: Symbol, classRep: ClassRepresentation[AbstractFile]) { + def initializeFromClassPath(owner: Symbol, classRep: ClassRepresentation) { ((classRep.binary, classRep.source) : @unchecked) match { case (Some(bin), Some(src)) if platform.needCompile(bin, src) && !binaryOnly(owner, classRep.name) => @@ -246,36 +246,6 @@ abstract class SymbolLoaders { resPhase } - /** - * Load contents of a package - */ - class PackageLoader(classpath: ClassPath[AbstractFile]) extends SymbolLoader with FlagAgnosticCompleter { - protected def description = s"package loader ${classpath.name}" - - protected def doComplete(root: Symbol) { - assert(root.isPackageClass, root) - // Time travel to a phase before refchecks avoids an initialization issue. `openPackageModule` - // creates a module symbol and invokes invokes `companionModule` while the `infos` field is - // still null. This calls `isModuleNotMethod`, which forces the `info` if run after refchecks. - enteringPhase(phaseBeforeRefchecks) { - root.setInfo(new PackageClassInfoType(newScope, root)) - - if (!root.isRoot) { - for (classRep <- classpath.classes) { - initializeFromClassPath(root, classRep) - } - } - if (!root.isEmptyPackageClass) { - for (pkg <- classpath.packages) { - enterPackage(root, pkg.name, new PackageLoader(pkg)) - } - - openPackageModule(root) - } - } - } - } - /** * Loads contents of a package */ @@ -329,10 +299,7 @@ abstract class SymbolLoaders { val loaders = SymbolLoaders.this.asInstanceOf[SymbolLoadersRefined] - override def classFileLookup: util.ClassFileLookup[AbstractFile] = settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Recursive => platform.classPath - case ClassPathRepresentationType.Flat => platform.flatClassPath - } + override def classFileLookup: util.ClassFileLookup = platform.flatClassPath } 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 fffd48d145..e10c847597 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -44,7 +44,7 @@ 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[AbstractFile] + def classFileLookup: ClassFileLookup import definitions._ import scala.reflect.internal.ClassfileConstants._ diff --git a/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala b/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala index 5d8831a607..f47765d248 100644 --- a/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala +++ b/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala @@ -12,16 +12,14 @@ import java.net.URL * Simple interface that allows us to abstract over how class file lookup is performed * in different classpath representations. */ -// TODO at the end, after the possible removal of the old classpath representation, this class shouldn't be generic -// T should be just changed to AbstractFile -trait ClassFileLookup[T] { +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[T]] + def findClass(name: String): Option[ClassRepresentation] /** * A sequence of URLs representing this classpath. @@ -41,38 +39,17 @@ trait ClassFileLookup[T] { def asSourcePathString: String } -object ClassFileLookup { - def createForFile(f: AbstractFile, current: ClassFileLookup[AbstractFile], settings: Settings): ClassFileLookup[AbstractFile] = current match { - case cp: ClassPath[_] => cp.context.newClassPath(f) - case _: FlatClassPath => FlatClassPathFactory.newClassPath(f, settings) - } - - def createAggregate(elems: Iterable[ClassFileLookup[AbstractFile]], current: ClassFileLookup[AbstractFile]): ClassFileLookup[AbstractFile] = { - assert(elems.nonEmpty) - if (elems.size == 1) elems.head - else current match { - case cp: ClassPath[_] => - new MergedClassPath(elems.asInstanceOf[Iterable[ClassPath[AbstractFile]]], cp.context) - - case _: FlatClassPath => - AggregateFlatClassPath.createAggregate(elems.asInstanceOf[Iterable[FlatClassPath]].toSeq : _*) - } - } -} - /** * Represents classes which can be loaded with a ClassfileLoader and/or SourcefileLoader. */ -// TODO at the end, after the possible removal of the old classpath implementation, this class shouldn't be generic -// T should be just changed to AbstractFile -trait ClassRepresentation[T] { - def binary: Option[T] +trait ClassRepresentation { + def binary: Option[AbstractFile] def source: Option[AbstractFile] def name: String } object ClassRepresentation { - def unapply[T](classRep: ClassRepresentation[T]): Option[(Option[T], Option[AbstractFile])] = + 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 6cdc3856cd..822396d4cf 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -11,39 +11,25 @@ import io.{ AbstractFile, Directory, File, Jar } import java.net.MalformedURLException import java.net.URL import java.util.regex.PatternSyntaxException -import scala.collection.{ mutable, immutable } -import scala.reflect.internal.util.StringOps.splitWhere -import scala.tools.nsc.classpath.FileUtils import File.pathSeparator -import FileUtils.endsClass -import FileUtils.endsScalaOrJava import Jar.isJarOrZip -/**

- * This module provides star expansion of '-classpath' option arguments, behaves the same as - * java, see [[http://docs.oracle.com/javase/6/docs/technotes/tools/windows/classpath.html]] - *

- * - * @author Stepan Koltsov - */ object ClassPath { - import scala.language.postfixOps - /** Expand single path entry */ private def expandS(pattern: String): List[String] = { val wildSuffix = File.separator + "*" /* Get all subdirectories, jars, zips out of a directory. */ def lsDir(dir: Directory, filt: String => Boolean = _ => true) = - dir.list filter (x => filt(x.name) && (x.isDirectory || isJarOrZip(x))) map (_.path) toList + dir.list.filter(x => filt(x.name) && (x.isDirectory || isJarOrZip(x))).map(_.path).toList if (pattern == "*") lsDir(Directory(".")) else if (pattern endsWith wildSuffix) lsDir(Directory(pattern dropRight 2)) else if (pattern contains '*') { try { val regexp = ("^" + pattern.replaceAllLiterally("""\*""", """.*""") + "$").r - lsDir(Directory(pattern).parent, regexp findFirstIn _ isDefined) + lsDir(Directory(pattern).parent, regexp.findFirstIn(_).isDefined) } catch { case _: PatternSyntaxException => List(pattern) } } @@ -51,7 +37,7 @@ object ClassPath { } /** Split classpath using platform-dependent path separator */ - def split(path: String): List[String] = (path split pathSeparator).toList filterNot (_ == "") distinct + def split(path: String): List[String] = (path split pathSeparator).toList.filterNot(_ == "").distinct /** Join classpath using platform-dependent path separator */ def join(paths: String*): String = paths filterNot (_ == "") mkString pathSeparator @@ -71,6 +57,7 @@ object ClassPath { case dir => dir filter (_.isClassContainer) map (x => new java.io.File(dir.file, x.name) getPath) toList } } + /** Expand manifest jar classpath entries: these are either urls, or paths * relative to the location of the jar. */ @@ -88,30 +75,6 @@ object ClassPath { try Some(new URL(spec)) catch { case _: MalformedURLException => None } - /** A class modeling aspects of a ClassPath which should be - * propagated to any classpaths it creates. - */ - abstract class ClassPathContext[T] extends classpath.ClassPathFactory[ClassPath[T]] { - /** A filter which can be used to exclude entities from the classpath - * based on their name. - */ - def isValidName(name: String): Boolean = true - - /** Filters for assessing validity of various entities. - */ - def validClassFile(name: String) = endsClass(name) && isValidName(name) - def validPackage(name: String) = (name != "META-INF") && (name != "") && (name.charAt(0) != '.') - def validSourceFile(name: String) = endsScalaOrJava(name) - - /** From the representation to its identifier. - */ - def toBinaryName(rep: T): String - - def sourcesInPath(path: String): List[ClassPath[T]] = - for (file <- expandPath(path, expandStar = false) ; dir <- Option(AbstractFile getDirectory file)) yield - new SourcePath[T](dir, this) - } - def manifests: List[java.net.URL] = { import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator Thread.currentThread().getContextClassLoader() @@ -119,271 +82,18 @@ object ClassPath { .filter(_.getProtocol == "jar").toList } - class JavaContext extends ClassPathContext[AbstractFile] { - def toBinaryName(rep: AbstractFile) = { - val name = rep.name - assert(endsClass(name), name) - FileUtils.stripClassExtension(name) - } - - def newClassPath(dir: AbstractFile) = new DirectoryClassPath(dir, this) - } - - object DefaultJavaContext extends JavaContext - - /** From the source file to its identifier. - */ - def toSourceName(f: AbstractFile): String = FileUtils.stripSourceExtension(f.name) -} - -import ClassPath._ - -/** - * Represents a package which contains classes and other packages - */ -abstract class ClassPath[T] extends ClassFileLookup[T] { - /** - * The short name of the package (without prefix) - */ - def name: String - - /** - * A String representing the origin of this classpath element, if known. - * For example, the path of the directory or jar. - */ - def origin: Option[String] = None - - /** Info which should be propagated to any sub-classpaths. - */ - def context: ClassPathContext[T] - - /** Lists of entities. - */ - def classes: IndexedSeq[ClassRepresentation[T]] - def packages: IndexedSeq[ClassPath[T]] - def sourcepaths: IndexedSeq[AbstractFile] - - /** The entries this classpath is composed of. In class `ClassPath` it's just the singleton list containing `this`. - * Subclasses such as `MergedClassPath` typically return lists with more elements. - */ - def entries: IndexedSeq[ClassPath[T]] = IndexedSeq(this) - - /** Merge classpath of `platform` and `urls` into merged classpath */ - def mergeUrlsIntoClassPath(urls: URL*): MergedClassPath[T] = { - // Collect our new jars/directories and add them to the existing set of classpaths - val allEntries = - (entries ++ - urls.map(url => context.newClassPath(io.AbstractFile.getURL(url))) - ).distinct - - // Combine all of our classpaths (old and new) into one merged classpath - new MergedClassPath(allEntries, context) - } - - /** - * Represents classes which can be loaded with a ClassfileLoader and/or SourcefileLoader. - */ - case class ClassRep(binary: Option[T], source: Option[AbstractFile]) extends ClassRepresentation[T] { - def name: String = binary match { - case Some(x) => context.toBinaryName(x) - case _ => - assert(source.isDefined) - toSourceName(source.get) - } - } - - /** Filters for assessing validity of various entities. - */ - def validClassFile(name: String) = context.validClassFile(name) - def validPackage(name: String) = context.validPackage(name) - def validSourceFile(name: String) = context.validSourceFile(name) - - /** - * Find a ClassRep given a class name of the form "package.subpackage.ClassName". - * Does not support nested classes on .NET - */ - override def findClass(name: String): Option[ClassRepresentation[T]] = - splitWhere(name, _ == '.', doDropIndex = true) match { - case Some((pkg, rest)) => - val rep = packages find (_.name == pkg) flatMap (_ findClass rest) - rep map { - case x: ClassRepresentation[T] => x - case x => throw new FatalError("Unexpected ClassRep '%s' found searching for name '%s'".format(x, name)) - } - case _ => - classes find (_.name == name) - } - - override def findClassFile(name: String): Option[AbstractFile] = - findClass(name) match { - case Some(ClassRepresentation(Some(x: AbstractFile), _)) => Some(x) - case _ => None - } - - override def asSourcePathString: String = sourcepaths.mkString(pathSeparator) - - def sortString = join(split(asClassPathString).sorted: _*) - override def equals(that: Any) = that match { - case x: ClassPath[_] => this.sortString == x.sortString - case _ => false - } - override def hashCode = sortString.hashCode() -} - -/** - * A Classpath containing source files - */ -class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends ClassPath[T] { - import FileUtils.AbstractFileOps + @deprecated("Shim for sbt's compiler interface", since = "2.12") + sealed abstract class ClassPathContext - def name = dir.name - override def origin = dir.underlyingSource map (_.path) - def asURLs = dir.toURLs() - def asClassPathString = dir.path - val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq(dir) - - private def traverse() = { - val classBuf = immutable.Vector.newBuilder[ClassRep] - val packageBuf = immutable.Vector.newBuilder[SourcePath[T]] - dir foreach { f => - if (!f.isDirectory && validSourceFile(f.name)) - classBuf += ClassRep(None, Some(f)) - else if (f.isDirectory && validPackage(f.name)) - packageBuf += new SourcePath[T](f, context) - } - (packageBuf.result(), classBuf.result()) - } - - lazy val (packages, classes) = traverse() - override def toString() = "sourcepath: "+ dir.toString() + @deprecated("Shim for sbt's compiler interface", since = "2.12") + sealed abstract class JavaContext } -/** - * A directory (or a .jar file) containing classfiles and packages - */ -class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[AbstractFile]) extends ClassPath[AbstractFile] { - import FileUtils.AbstractFileOps - - def name = dir.name - override def origin = dir.underlyingSource map (_.path) - def asURLs = dir.toURLs(default = Seq(new URL(name))) - def asClassPathString = dir.path - val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq() - - // calculates (packages, classes) in one traversal. - private def traverse() = { - val classBuf = immutable.Vector.newBuilder[ClassRep] - val packageBuf = immutable.Vector.newBuilder[DirectoryClassPath] - dir foreach { - f => - // Optimization: We assume the file was not changed since `dir` called - // `Path.apply` and categorized existent files as `Directory` - // or `File` (avoids IO operation JFile.isDirectory()). - val isDirectory = f match { - case pf: io.PlainFile => pf.givenPath match { - case _: io.Directory => true - case _: io.File => false - case _ => f.isDirectory - } - case _ => - f.isDirectory - } - if (!isDirectory && validClassFile(f.name)) - classBuf += ClassRep(Some(f), None) - else if (isDirectory && validPackage(f.name)) - packageBuf += new DirectoryClassPath(f, context) - } - (packageBuf.result(), classBuf.result()) - } - - lazy val (packages, classes) = traverse() - override def toString() = "directory classpath: "+ origin.getOrElse("?") -} - -/** - * A classpath unifying multiple class- and sourcepath entries. - */ -class MergedClassPath[T]( - override val entries: IndexedSeq[ClassPath[T]], - val context: ClassPathContext[T]) -extends ClassPath[T] { - - def this(entries: TraversableOnce[ClassPath[T]], context: ClassPathContext[T]) = - this(entries.toIndexedSeq, context) - - def name = entries.head.name - def asURLs = (entries flatMap (_.asURLs)).toList - lazy val sourcepaths: IndexedSeq[AbstractFile] = entries flatMap (_.sourcepaths) +@deprecated("Shim for sbt's compiler interface", since = "2.12") +sealed abstract class DirectoryClassPath - override def origin = Some(entries map (x => x.origin getOrElse x.name) mkString ("Merged(", ", ", ")")) - override def asClassPathString: String = join(entries map (_.asClassPathString) : _*) +@deprecated("Shim for sbt's compiler interface", since = "2.12") +sealed abstract class MergedClassPath - lazy val classes: IndexedSeq[ClassRepresentation[T]] = { - var count = 0 - val indices = mutable.HashMap[String, Int]() - val cls = new mutable.ArrayBuffer[ClassRepresentation[T]](1024) - - for (e <- entries; c <- e.classes) { - val name = c.name - if (indices contains name) { - val idx = indices(name) - val existing = cls(idx) - - if (existing.binary.isEmpty && c.binary.isDefined) - cls(idx) = ClassRep(binary = c.binary, source = existing.source) - if (existing.source.isEmpty && c.source.isDefined) - cls(idx) = ClassRep(binary = existing.binary, source = c.source) - } - else { - indices(name) = count - cls += c - count += 1 - } - } - cls.toIndexedSeq - } - - lazy val packages: IndexedSeq[ClassPath[T]] = { - var count = 0 - val indices = mutable.HashMap[String, Int]() - val pkg = new mutable.ArrayBuffer[ClassPath[T]](256) - - for (e <- entries; p <- e.packages) { - val name = p.name - if (indices contains name) { - val idx = indices(name) - pkg(idx) = addPackage(pkg(idx), p) - } - else { - indices(name) = count - pkg += p - count += 1 - } - } - pkg.toIndexedSeq - } - - private def addPackage(to: ClassPath[T], pkg: ClassPath[T]) = { - val newEntries: IndexedSeq[ClassPath[T]] = to match { - case cp: MergedClassPath[_] => cp.entries :+ pkg - case _ => IndexedSeq(to, pkg) - } - new MergedClassPath[T](newEntries, context) - } - - def show() { - println("ClassPath %s has %d entries and results in:\n".format(name, entries.size)) - asClassPathString split ':' foreach (x => println(" " + x)) - } - - override def toString() = "merged classpath "+ entries.mkString("(", "\n", ")") -} - -/** - * The classpath when compiling with target:jvm. Binary files (classfiles) are represented - * as AbstractFile. nsc.io.ZipArchive is used to view zip/jar archives as directories. - */ -class JavaClassPath( - containers: IndexedSeq[ClassPath[AbstractFile]], - context: JavaContext) -extends MergedClassPath[AbstractFile](containers, context) { } +@deprecated("Shim for sbt's compiler interface", since = "2.12") +sealed abstract class JavaClassPath diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 9decc99c8d..11b9766da4 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -10,9 +10,8 @@ package util import java.net.URL import scala.tools.reflect.WrappedProperties.AccessControl import scala.tools.nsc.Settings -import scala.tools.nsc.util.{ ClassFileLookup, ClassPath, JavaClassPath } +import scala.tools.nsc.util.{ClassFileLookup, ClassPath} import scala.reflect.io.{ File, Directory, Path, AbstractFile } -import ClassPath.{ JavaContext, DefaultJavaContext, split } import PartialFunction.condOpt import scala.tools.nsc.classpath.{ AggregateFlatClassPath, ClassPathFactory, FlatClassPath, FlatClassPathFactory } import scala.tools.nsc.settings.ClassPathRepresentationType @@ -40,7 +39,7 @@ object PathResolver { } /** pretty print class path */ - def ppcp(s: String) = split(s) match { + def ppcp(s: String) = ClassPath.split(s) match { case Nil => "" case Seq(x) => x case xs => xs.mkString(EOL, EOL, "") @@ -164,13 +163,6 @@ object PathResolver { |}""".asLines } - @deprecated("This method is no longer used be scalap and will be deleted", "2.11.5") - def fromPathString(path: String, context: JavaContext = DefaultJavaContext): JavaClassPath = { - val s = new Settings() - s.classpath.value = path - new PathResolver(s, context).result - } - /** With no arguments, show the interesting values in Environment and Defaults. * If there are arguments, show those in Calculated as if those options had been * given to a scala runner. @@ -187,8 +179,6 @@ object PathResolver { println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" "))) pr.result match { - case cp: JavaClassPath => - cp.show() case cp: AggregateFlatClassPath => println(s"ClassPath has ${cp.aggregates.size} entries and results in:\n${cp.asClassPathStrings}") } @@ -196,12 +186,12 @@ object PathResolver { } trait PathResolverResult { - def result: ClassFileLookup[AbstractFile] + def result: ClassFileLookup def resultAsURLs: Seq[URL] = result.asURLs } -abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup[AbstractFile], ResultClassPathType <: BaseClassPathType] +abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup, ResultClassPathType <: BaseClassPathType] (settings: Settings, classPathFactory: ClassPathFactory[BaseClassPathType]) extends PathResolverResult { @@ -301,15 +291,6 @@ abstract class PathResolverBase[BaseClassPathType <: ClassFileLookup[AbstractFil protected def computeResult(): ResultClassPathType } -class PathResolver(settings: Settings, context: JavaContext) - extends PathResolverBase[ClassPath[AbstractFile], JavaClassPath](settings, context) { - - def this(settings: Settings) = this(settings, DefaultJavaContext) - - override protected def computeResult(): JavaClassPath = - new JavaClassPath(containers.toIndexedSeq, context) -} - class FlatClassPathResolver(settings: Settings, flatClassPathFactory: ClassPathFactory[FlatClassPath]) extends PathResolverBase[FlatClassPath, AggregateFlatClassPath](settings, flatClassPathFactory) { @@ -319,10 +300,5 @@ class FlatClassPathResolver(settings: Settings, flatClassPathFactory: ClassPathF } object PathResolverFactory { - - def create(settings: Settings): PathResolverResult = - settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Flat => new FlatClassPathResolver(settings) - case ClassPathRepresentationType.Recursive => new PathResolver(settings) - } + 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 290b7b434e..bdb82605b6 100644 --- a/src/partest-extras/scala/tools/partest/BytecodeTest.scala +++ b/src/partest-extras/scala/tools/partest/BytecodeTest.scala @@ -1,10 +1,11 @@ package scala.tools.partest -import scala.tools.nsc.util.JavaClassPath +import scala.tools.nsc.util.ClassFileLookup import scala.collection.JavaConverters._ -import scala.tools.asm.{ClassWriter, ClassReader} +import scala.tools.asm.{ClassReader, ClassWriter} import scala.tools.asm.tree._ -import java.io.{File => JFile, InputStream} +import java.io.{InputStream, File => JFile} + import AsmNode._ /** @@ -125,12 +126,15 @@ abstract class BytecodeTest { cn } - protected lazy val classpath: JavaClassPath = { - import scala.tools.nsc.util.ClassPath.DefaultJavaContext + protected lazy val classpath: ClassFileLookup = { + import scala.tools.nsc.classpath.{FlatClassPathFactory, AggregateFlatClassPath} import scala.tools.util.PathResolver.Defaults + import scala.tools.nsc.Settings // logic inspired by scala.tools.util.PathResolver implementation - val containers = DefaultJavaContext.classesInExpandedPath(Defaults.javaUserClassPath) - new JavaClassPath(containers, DefaultJavaContext) + // `Settings` is used to check YdisableFlatCpCaching in ZipArchiveFlatClassPath + val factory = new FlatClassPathFactory(new Settings()) + val containers = factory.classesInExpandedPath(Defaults.javaUserClassPath) + new AggregateFlatClassPath(containers) } } diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala index e3dc72b717..cfefc3419c 100644 --- a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala +++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala @@ -8,8 +8,7 @@ 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.DefaultJavaContext -import scala.tools.nsc.util.{ClassPath, MergedClassPath, DirectoryClassPath} +import scala.tools.nsc.util.ClassPath import scala.tools.nsc.{interactive, Settings} import scala.tools.nsc.reporters.StoreReporter import scala.tools.nsc.classpath._ @@ -61,10 +60,6 @@ trait PresentationCompilation { val replOutClasspath = FlatClassPathFactory.newClassPath(replOutput.dir, settings) AggregateFlatClassPath(replOutClasspath :: global.platform.flatClassPath :: Nil) } - def mergedRecursiveClasspath = { - val replOutClasspath: DirectoryClassPath = new DirectoryClassPath(replOutput.dir, DefaultJavaContext) - new MergedClassPath[AbstractFile](replOutClasspath :: global.platform.classPath :: Nil, DefaultJavaContext) - } def copySettings: Settings = { val s = new Settings(_ => () /* ignores "bad option -nc" errors, etc */) s.processArguments(global.settings.recreateArgs, processAll = false) @@ -74,16 +69,9 @@ trait PresentationCompilation { val storeReporter: StoreReporter = new StoreReporter val interactiveGlobal = new interactive.Global(copySettings, storeReporter) { self => override lazy val platform: ThisPlatform = { - if (settings.YclasspathImpl.value == ClassPathRepresentationType.Flat) { - new JavaPlatform { - val global: self.type = self - override private[nsc] lazy val flatClassPath: FlatClassPath = mergedFlatClasspath - } - } else { - new JavaPlatform { - val global: self.type = self - override def classPath: ClassPath[AbstractFile] = mergedRecursiveClasspath - } + new JavaPlatform { + val global: self.type = self + override private[nsc] lazy val flatClassPath: FlatClassPath = mergedFlatClasspath } } } diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 3d2bfd7251..2ae43306a7 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -16,8 +16,6 @@ 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.nsc.util.ClassPath.DefaultJavaContext -import scala.tools.nsc.util.JavaClassPath import scala.tools.util.PathResolverFactory import scalax.rules.scalasig._ @@ -101,7 +99,7 @@ class Main { /** Executes scalap with the given arguments and classpath for the * class denoted by `classname`. */ - def process(args: Arguments, path: ClassFileLookup[AbstractFile])(classname: String): Unit = { + def process(args: Arguments, path: ClassFileLookup)(classname: String): Unit = { // find the classfile val encName = classname match { case "scala.AnyRef" => "java.lang.Object" @@ -145,7 +143,6 @@ object Main extends Main { val verbose = "-verbose" val version = "-version" - val classPathImplType = "-YclasspathImpl" val disableFlatClassPathCaching = "-YdisableFlatCpCaching" val logClassPath = "-Ylog-classpath" } @@ -183,7 +180,6 @@ object Main extends Main { val settings = new Settings() - arguments getArgument opts.classPathImplType foreach settings.YclasspathImpl.tryToSetFromPropertyValue settings.YdisableFlatCpCaching.value = arguments contains opts.disableFlatClassPathCaching settings.Ylogcp.value = arguments contains opts.logClassPath @@ -205,19 +201,14 @@ object Main extends Main { .withOption(opts.help) .withOptionalArg(opts.classpath) .withOptionalArg(opts.cp) - // TODO three temporary, hidden options to be able to test different classpath representations - .withOptionalArg(opts.classPathImplType) + // TODO two temporary, hidden options to be able to test different classpath representations .withOption(opts.disableFlatClassPathCaching) .withOption(opts.logClassPath) .parse(args) private def createClassPath(cpArg: Option[String], settings: Settings) = cpArg match { - case Some(cp) => settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Flat => - AggregateFlatClassPath(new FlatClassPathFactory(settings).classesInExpandedPath(cp)) - case ClassPathRepresentationType.Recursive => - new JavaClassPath(DefaultJavaContext.classesInExpandedPath(cp), DefaultJavaContext) - } + case Some(cp) => + AggregateFlatClassPath(new FlatClassPathFactory(settings).classesInExpandedPath(cp)) case _ => settings.classpath.value = "." // include '.' in the default classpath SI-6669 PathResolverFactory.create(settings).result diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala index dffb0e2f98..2a52474e5d 100644 --- a/test/files/run/t6502.scala +++ b/test/files/run/t6502.scala @@ -14,14 +14,6 @@ object Test extends StoreReporterDirectTest { compileString(newCompiler("-cp", classpath, "-d", s"${testOutput.path}/$jarFileName"))(code) } - var classPathKind: String = "" - - override def settings = { - val settings = new Settings - settings.YclasspathImpl.value = classPathKind - settings - } - def app1 = """ package test @@ -155,7 +147,7 @@ object Test extends StoreReporterDirectTest { assert(output.contains("created test6.Z"), output) } - def testAll(): Unit = { + def show(): Unit = { test1() test2() test3() @@ -163,11 +155,4 @@ object Test extends StoreReporterDirectTest { test5() test6() } - - def show(): Unit = { - classPathKind = ClassPathRepresentationType.Flat - testAll() - classPathKind = ClassPathRepresentationType.Recursive - testAll() - } } diff --git a/test/files/run/various-flat-classpath-types.scala b/test/files/run/various-flat-classpath-types.scala index d39019e885..527f22fc8b 100644 --- a/test/files/run/various-flat-classpath-types.scala +++ b/test/files/run/various-flat-classpath-types.scala @@ -80,7 +80,6 @@ object Test { private val compiler = new scala.tools.nsc.MainClass private val appRunner = new scala.tools.nsc.MainGenericRunner - private val classPathImplFlag = "-YclasspathImpl:flat" private val javaClassPath = sys.props("java.class.path") // creates a test dir in a temporary dir containing compiled files of this test @@ -166,13 +165,13 @@ object Test { val classPath = mkPath(javaClassPath, binDir.path, zipsDir.path + "/Bin.zip", jarsDir.path + "/Bin.jar") val sourcePath = mkPath(srcDir.path, zipsDir.path + "/Src.zip", jarsDir.path + "/Src.jar") - compiler.process(Array(classPathImplFlag, "-cp", classPath, "-sourcepath", sourcePath, + compiler.process(Array("-cp", classPath, "-sourcepath", sourcePath, "-d", outDir.path, s"${srcDir.path}/Main.scala")) } private def runApp(): Unit = { val classPath = mkPath(javaClassPath, outDir.path, binDir.path, zipsDir.path + "/Bin.zip", jarsDir.path + "/Bin.jar") - appRunner.process(Array(classPathImplFlag, "-cp", classPath, "Main")) + appRunner.process(Array("-cp", classPath, "Main")) } private def createStandardSrcHierarchy(baseFileName: String): Unit = @@ -200,7 +199,7 @@ object Test { private def compileSrc(baseFileName: String, destination: JFile = outDir): Unit = { val srcDirPath = srcDir.path - compiler.process(Array(classPathImplFlag, "-cp", javaClassPath, "-d", destination.path, + compiler.process(Array("-cp", javaClassPath, "-d", destination.path, s"$srcDirPath/$baseFileName.scala", s"$srcDirPath/nested/Nested$baseFileName.scala")) } diff --git a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala index 5dee488285..97c3200fc2 100644 --- a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala +++ b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala @@ -95,52 +95,6 @@ class FlatClassPathResolverTest { packagesToTest foreach compareEntriesInPackage } - @Test - def testCreatedEntriesAgainstRecursiveClassPath: Unit = { - val flatClassPath = createFlatClassPath(settings) - val recursiveClassPath = new PathResolver(settings).result - - def compareEntriesInPackage(inPackage: String): Unit = { - - @tailrec - def traverseToPackage(packageNameParts: Seq[String], cp: ClassPath[AbstractFile]): ClassPath[AbstractFile] = { - packageNameParts match { - case Nil => cp - case h :: t => - cp.packages.find(_.name == h) match { - case Some(nestedCp) => traverseToPackage(t, nestedCp) - case _ => throw new Exception(s"There's no package $inPackage in recursive classpath - error when searching for '$h'") - } - } - } - - val packageNameParts = if (inPackage == FlatClassPath.RootPackage) Nil else inPackage.split('.').toList - val recursiveClassPathInPackage = traverseToPackage(packageNameParts, recursiveClassPath) - - val flatCpPackages = flatClassPath.packages(inPackage).map(_.name) - val pkgPrefix = PackageNameUtils.packagePrefix(inPackage) - val recursiveCpPackages = recursiveClassPathInPackage.packages.map(pkgPrefix + _.name) - assertEquals(s"Packages in package '$inPackage' on flat cp should be the same as on the recursive cp", - recursiveCpPackages, flatCpPackages) - - val flatCpSources = flatClassPath.sources(inPackage).map(_.name).sorted - val recursiveCpSources = recursiveClassPathInPackage.classes - .filter(_.source.nonEmpty) - .map(_.name).sorted - assertEquals(s"Source entries in package '$inPackage' on flat cp should be the same as on the recursive cp", - recursiveCpSources, flatCpSources) - - val flatCpClasses = flatClassPath.classes(inPackage).map(_.name).sorted - val recursiveCpClasses = recursiveClassPathInPackage.classes - .filter(_.binary.nonEmpty) - .map(_.name).sorted - assertEquals(s"Class entries in package '$inPackage' on flat cp should be the same as on the recursive cp", - recursiveCpClasses, flatCpClasses) - } - - packagesToTest foreach compareEntriesInPackage - } - @Test def testFindClassFile: Unit = { val classPath = createFlatClassPath(settings) diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala index 812c298c48..45cded6d43 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala @@ -30,7 +30,6 @@ class SymbolTableForUnitTesting extends SymbolTable { override def isCompilerUniverse: Boolean = true - def classPath = platform.classPath def flatClassPath: FlatClassPath = platform.flatClassPath object platform extends backend.Platform { @@ -39,22 +38,12 @@ class SymbolTableForUnitTesting extends SymbolTable { def platformPhases: List[SubComponent] = Nil - lazy val classPath: ClassPath[AbstractFile] = { - assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Recursive, - "It's not possible to use the recursive classpath representation, when it's not the chosen classpath scanning method") - new PathResolver(settings).result - } - - private[nsc] lazy val flatClassPath: FlatClassPath = { - assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Flat, - "It's not possible to use the flat classpath representation, when it's not the chosen classpath scanning method") - new FlatClassPathResolver(settings).result - } + private[nsc] lazy val flatClassPath: FlatClassPath = new FlatClassPathResolver(settings).result def isMaybeBoxed(sym: Symbol): Boolean = ??? def needCompile(bin: AbstractFile, src: AbstractFile): Boolean = ??? def externalEquals: Symbol = ??? - def updateClassPath(subst: Map[ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile]]): Unit = ??? + def updateClassPath(subst: Map[FlatClassPath, FlatClassPath]): Unit = ??? } object loaders extends symtab.SymbolLoaders { @@ -69,10 +58,7 @@ class SymbolTableForUnitTesting extends SymbolTable { class GlobalMirror extends Roots(NoSymbol) { val universe: SymbolTableForUnitTesting.this.type = SymbolTableForUnitTesting.this - def rootLoader: LazyType = settings.YclasspathImpl.value match { - case ClassPathRepresentationType.Flat => new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) - case ClassPathRepresentationType.Recursive => new loaders.PackageLoader(classPath) - } + def rootLoader: LazyType = new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) override def toString = "compiler mirror" } diff --git a/test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala b/test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala deleted file mode 100644 index f2926e3e17..0000000000 --- a/test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2014 Contributor. All rights reserved. - */ -package scala.tools.nsc.util - -import scala.reflect.io.AbstractFile -import scala.tools.nsc.Settings -import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.util.PathResolverFactory - -/** - * Simple application to compare efficiency of the recursive and the flat classpath representations - */ -object ClassPathImplComparator { - - private class TestSettings extends Settings { - val checkClasses = PathSetting("-checkClasses", "Specify names of classes which should be found separated with ;", "") - val requiredIterations = IntSetting("-requiredIterations", - "Repeat tests specified number of times (to check e.g. impact of caches)", 1, Some((1, Int.MaxValue)), (_: String) => None) - val cpCreationRepetitions = IntSetting("-cpCreationRepetitions", - "Repeat tests specified number of times (to check e.g. impact of caches)", 1, Some((1, Int.MaxValue)), (_: String) => None) - val cpLookupRepetitions = IntSetting("-cpLookupRepetitions", - "Repeat tests specified number of times (to check e.g. impact of caches)", 1, Some((1, Int.MaxValue)), (_: String) => None) - } - - private class DurationStats(name: String) { - private var sum = 0L - private var iterations = 0 - - def noteMeasuredTime(millis: Long): Unit = { - sum += millis - iterations += 1 - } - - def printResults(): Unit = { - val avg = if (iterations == 0) 0 else sum.toDouble / iterations - println(s"$name - total duration: $sum ms; iterations: $iterations; avg: $avg ms") - } - } - - private lazy val defaultClassesToFind = List( - "scala.collection.immutable.List", - "scala.Option", - "scala.Int", - "scala.collection.immutable.Vector", - "scala.util.hashing.MurmurHash3" - ) - - private val oldCpCreationStats = new DurationStats("Old classpath - create") - private val oldCpSearchingStats = new DurationStats("Old classpath - search") - - private val flatCpCreationStats = new DurationStats("Flat classpath - create") - private val flatCpSearchingStats = new DurationStats("Flat classpath - search") - - def main(args: Array[String]): Unit = { - - if (args contains "-help") - usage() - else { - val oldCpSettings = loadSettings(args.toList, ClassPathRepresentationType.Recursive) - val flatCpSettings = loadSettings(args.toList, ClassPathRepresentationType.Flat) - - val classesToCheck = oldCpSettings.checkClasses.value - val classesToFind = - if (classesToCheck.isEmpty) defaultClassesToFind - else classesToCheck.split(";").toList - - def doTest(classPath: => ClassFileLookup[AbstractFile], cpCreationStats: DurationStats, cpSearchingStats: DurationStats, - cpCreationRepetitions: Int, cpLookupRepetitions: Int)= { - - def createClassPaths() = (1 to cpCreationRepetitions).map(_ => classPath).last - def testClassLookup(cp: ClassFileLookup[AbstractFile]): Boolean = (1 to cpCreationRepetitions).foldLeft(true) { - case (a, _) => a && checkExistenceOfClasses(classesToFind)(cp) - } - - val cp = withMeasuredTime("Creating classpath", createClassPaths(), cpCreationStats) - val result = withMeasuredTime("Searching for specified classes", testClassLookup(cp), cpSearchingStats) - println(s"The end of the test case. All expected classes found = $result \n") - } - - (1 to oldCpSettings.requiredIterations.value) foreach { iteration => - if (oldCpSettings.requiredIterations.value > 1) - println(s"Iteration no $iteration") - - println("Recursive (old) classpath representation:") - doTest(PathResolverFactory.create(oldCpSettings).result, oldCpCreationStats, oldCpSearchingStats, - oldCpSettings.cpCreationRepetitions.value, oldCpSettings.cpLookupRepetitions.value) - - println("Flat classpath representation:") - doTest(PathResolverFactory.create(flatCpSettings).result, flatCpCreationStats, flatCpSearchingStats, - flatCpSettings.cpCreationRepetitions.value, flatCpSettings.cpLookupRepetitions.value) - } - - if (oldCpSettings.requiredIterations.value > 1) { - println("\nOld classpath - summary") - oldCpCreationStats.printResults() - oldCpSearchingStats.printResults() - - println("\nFlat classpath - summary") - flatCpCreationStats.printResults() - flatCpSearchingStats.printResults() - } - } - } - - /** - * Prints usage information - */ - private def usage(): Unit = - println("""Use classpath and sourcepath options like in the case of e.g. 'scala' command. - | There are also two additional options: - | -checkClasses Specify names of classes which should be found - | -requiredIterations Repeat tests specified count of times (to check e.g. impact of caches) - | Note: Option -YclasspathImpl will be set automatically for each case. - """.stripMargin.trim) - - private def loadSettings(args: List[String], implType: String) = { - val settings = new TestSettings() - settings.processArguments(args, processAll = true) - settings.YclasspathImpl.value = implType - if (settings.classpath.isDefault) - settings.classpath.value = sys.props("java.class.path") - settings - } - - private def withMeasuredTime[T](operationName: String, f: => T, durationStats: DurationStats): T = { - val startTime = System.currentTimeMillis() - val res = f - val elapsed = System.currentTimeMillis() - startTime - durationStats.noteMeasuredTime(elapsed) - println(s"$operationName - elapsed $elapsed ms") - res - } - - private def checkExistenceOfClasses(classesToCheck: Seq[String])(classPath: ClassFileLookup[AbstractFile]): Boolean = - classesToCheck.foldLeft(true) { - case (res, classToCheck) => - val found = classPath.findClass(classToCheck).isDefined - if (!found) - println(s"Class $classToCheck not found") // of course in this case the measured time will be affected by IO operation - found - } -} -- cgit v1.2.3