summaryrefslogtreecommitdiff
path: root/src/repl
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-10-04 12:33:11 -0700
committerSom Snytt <som.snytt@gmail.com>2014-10-06 08:00:22 -0700
commit964a197cd90e561d05c9d725cc13895f18b6a6d0 (patch)
tree51a80e3c486ad12b6b4f97920c696bdf167d54b4 /src/repl
parent7b2c3cb8bb0f5f96f3182f551eb82cb1c59d460c (diff)
downloadscala-964a197cd90e561d05c9d725cc13895f18b6a6d0.tar.gz
scala-964a197cd90e561d05c9d725cc13895f18b6a6d0.tar.bz2
scala-964a197cd90e561d05c9d725cc13895f18b6a6d0.zip
SI-8843 AbsFileCL acts like a CL
Let the AbstractFileClassLoader override just the usual suspects. Normal delegation behavior should ensue. That's instead of overriding `getResourceAsStream`, which was intended that "The repl classloader now works more like you'd expect a classloader to." (Workaround for "Don't know how to construct an URL for something which exists only in memory.") Also override `findResources` so that `getResources` does the obvious thing, namely, return one iff `getResource` does. The translating class loader for REPL only special-cases `foo.class`: as a fallback, take `foo` as `$line42.$read$something$foo` and try that class file. That's the use case for "works like you'd expect it to." There was a previous fix to ensure `getResource` doesn't take a class name. The convenience behavior, that `classBytes` takes either a class name or a resource path ending in ".class", has been promoted to `ScalaClassLoader`.
Diffstat (limited to 'src/repl')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index 6e30b73e0e..20b5a79aaa 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -295,22 +295,38 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
def originalPath(name: Name): String = typerOp path name
def originalPath(sym: Symbol): String = typerOp path sym
def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName
+
def translatePath(path: String) = {
val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path)
sym.toOption map flatPath
}
+
+ /** If path represents a class resource in the default package,
+ * see if the corresponding symbol has a class file that is a REPL artifact
+ * residing at a different resource path. Translate X.class to $line3/$read$$iw$$iw$X.class.
+ */
+ def translateSimpleResource(path: String): Option[String] = {
+ if (!(path contains '/') && (path endsWith ".class")) {
+ val name = path stripSuffix ".class"
+ val sym = if (name endsWith "$") symbolOfTerm(name.init) else symbolOfIdent(name)
+ def pathOf(s: String) = s"${s.replace('.', '/')}.class"
+ sym.toOption map (s => pathOf(flatPath(s)))
+ } else {
+ None
+ }
+ }
def translateEnclosingClass(n: String) = symbolOfTerm(n).enclClass.toOption map flatPath
+ /** If unable to find a resource foo.class, try taking foo as a symbol in scope
+ * and use its java class name as a resource to load.
+ *
+ * $intp.classLoader classBytes "Bippy" or $intp.classLoader getResource "Bippy.class" just work.
+ */
private class TranslatingClassLoader(parent: ClassLoader) extends util.AbstractFileClassLoader(replOutput.dir, parent) {
- /** Overridden here to try translating a simple name to the generated
- * class name if the original attempt fails. This method is used by
- * getResourceAsStream as well as findClass.
- */
- override protected def findAbstractFile(name: String): AbstractFile =
- super.findAbstractFile(name) match {
- case null if _initializeComplete => translatePath(name) map (super.findAbstractFile(_)) orNull
- case file => file
- }
+ override protected def findAbstractFile(name: String): AbstractFile = super.findAbstractFile(name) match {
+ case null if _initializeComplete => translateSimpleResource(name) map super.findAbstractFile orNull
+ case file => file
+ }
}
private def makeClassLoader(): util.AbstractFileClassLoader =
new TranslatingClassLoader(parentClassLoader match {