diff options
author | Som Snytt <som.snytt@gmail.com> | 2014-10-04 12:33:11 -0700 |
---|---|---|
committer | Som Snytt <som.snytt@gmail.com> | 2014-10-06 08:00:22 -0700 |
commit | 964a197cd90e561d05c9d725cc13895f18b6a6d0 (patch) | |
tree | 51a80e3c486ad12b6b4f97920c696bdf167d54b4 /src/repl | |
parent | 7b2c3cb8bb0f5f96f3182f551eb82cb1c59d460c (diff) | |
download | scala-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.scala | 34 |
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 { |