diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-11-29 10:40:53 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-29 10:40:53 +1000 |
commit | 2bc92e0b2fa9f6de2b2a6c8f9ef4b85492e7df4d (patch) | |
tree | 929108e6ac5c31964be3dd13bdbf197a0281e146 /src | |
parent | 57d98fda843d3b23757b48e0c6eebb7bd8eedc5d (diff) | |
parent | 1b2cd1be9790bf9c14fd68c78f784d6cb4f7c907 (diff) | |
download | scala-2bc92e0b2fa9f6de2b2a6c8f9ef4b85492e7df4d.tar.gz scala-2bc92e0b2fa9f6de2b2a6c8f9ef4b85492e7df4d.tar.bz2 scala-2bc92e0b2fa9f6de2b2a6c8f9ef4b85492e7df4d.zip |
Merge pull request #5544 from retronym/ticket/8779
SI-8779 Enable inlining of code within a REPL session
Diffstat (limited to 'src')
6 files changed, 39 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index a7880c72d7..e58d2d3b43 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -95,6 +95,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) type ThisPlatform = JavaPlatform { val global: Global.this.type } lazy val platform: ThisPlatform = new GlobalPlatform + /* A hook for the REPL to add a classpath entry containing products of previous runs to inliner's bytecode repository*/ + // Fixes SI-8779 + def optimizerClassPath(base: ClassPath): ClassPath = base def classPath: ClassPath = platform.classPath diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index edb75514e8..f7ee36c1ba 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -37,7 +37,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { val coreBTypes = new CoreBTypesProxy[this.type](this) import coreBTypes._ - val byteCodeRepository: ByteCodeRepository[this.type] = new ByteCodeRepository(global.classPath, this) + val byteCodeRepository: ByteCodeRepository[this.type] = new ByteCodeRepository(global.optimizerClassPath(global.classPath), this) val localOpt: LocalOpt[this.type] = new LocalOpt(this) diff --git a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala index 8df0c3743d..6fefaf0da0 100644 --- a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryClassPath.scala @@ -1,9 +1,11 @@ package scala.tools.nsc.classpath import scala.tools.nsc.util.ClassRepresentation -import scala.reflect.io.{Path, PlainFile, VirtualDirectory, AbstractFile} +import scala.reflect.io.{AbstractFile, Path, PlainFile, VirtualDirectory} import FileUtils._ import java.net.URL + +import scala.reflect.internal.util.AbstractFileClassLoader import scala.tools.nsc.util.ClassPath case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath with DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { @@ -11,7 +13,7 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi protected def emptyFiles: Array[AbstractFile] = Array.empty protected def getSubDir(packageDirName: String): Option[AbstractFile] = - Option(dir.lookupName(packageDirName, directory = true)) + Option(AbstractFileClassLoader.lookupPath(dir)(packageDirName.split('/'), 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 @@ -27,10 +29,8 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi 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 + val relativePath = FileUtils.dirPath(className) + ".class" + Option(AbstractFileClassLoader.lookupPath(dir)(relativePath split '/', directory = false)) } private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) diff --git a/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala b/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala index b5030460b8..3cede1b3c5 100644 --- a/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala +++ b/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala @@ -12,6 +12,20 @@ import java.security.cert.Certificate import java.security.{ ProtectionDomain, CodeSource } import java.util.{ Collections => JCollections, Enumeration => JEnumeration } +object AbstractFileClassLoader { + // should be a method on AbstractFile, but adding in `internal.util._` for now as we're in a minor release + private[scala] final def lookupPath(base: AbstractFile)(pathParts: Seq[String], directory: Boolean): AbstractFile = { + var file: AbstractFile = base + for (dirPart <- pathParts.init) { + file = file.lookupName(dirPart, directory = true) + if (file == null) + return null + } + + file.lookupName(pathParts.last, directory = directory) + } +} + /** A class loader that loads files from a [[scala.reflect.io.AbstractFile]]. * * @author Lex Spoon @@ -25,19 +39,7 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader) else s"${name.replace('.', '/')}.class" protected def findAbstractFile(name: String): AbstractFile = { - var file: AbstractFile = root - val pathParts = name split '/' - - for (dirPart <- pathParts.init) { - file = file.lookupName(dirPart, directory = true) - if (file == null) - return null - } - - file.lookupName(pathParts.last, directory = false) match { - case null => null - case file => file - } + AbstractFileClassLoader.lookupPath(root)(name split '/', directory = false) } protected def dirNameToPath(name: String): String = diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 65f2c95f73..99acc34811 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -889,7 +889,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } class ClassBasedWrapper extends Wrapper { - def preambleHeader = "class %s extends _root_.java.io.Serializable { " + def preambleHeader = "sealed class %s extends _root_.java.io.Serializable { " /** Adds an object that instantiates the outer wrapping class. */ def postamble = s""" diff --git a/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala index cf055e0758..0bb9eb6a0b 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala @@ -6,6 +6,9 @@ package scala.tools.nsc package interpreter +import scala.tools.nsc.backend.JavaPlatform +import scala.tools.nsc.classpath.{AggregateClassPath, ClassPathFactory} +import scala.tools.nsc.util.ClassPath import typechecker.Analyzer /** A layer on top of Global so I can guarantee some extra @@ -31,4 +34,14 @@ trait ReplGlobal extends Global { new util.AbstractFileClassLoader(virtualDirectory, loader) {} } } + + override def optimizerClassPath(base: ClassPath): ClassPath = { + settings.outputDirs.getSingleOutput match { + case None => base + case Some(out) => + // Make bytecode of previous lines available to the inliner + val replOutClasspath = ClassPathFactory.newClassPath(settings.outputDirs.getSingleOutput.get, settings) + AggregateClassPath.createAggregate(platform.classPath, replOutClasspath) + } + } } |