Skip to content

Instantly share code, notes, and snippets.

@razie
Created June 2, 2017 16:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save razie/d3668c6c4f7f9568f2cb2b0db9e9609a to your computer and use it in GitHub Desktop.
Save razie/d3668c6c4f7f9568f2cb2b0db9e9609a to your computer and use it in GitHub Desktop.
/**
* To run the Scala compiler programatically, we need to provide it with a
* classpath, as we would if we invoked it from the command line. We need
* to introspect our classloader (accounting for differences between execution
* environments like IntelliJ, SBT, or WebStart), and find the paths to JAR
* files on disk.
*/
final class ReplClassloader(parent: ClassLoader) extends ClassLoader(parent) with razie.Logging {
override def getResource(name: String): URL = {
// Rather pass `settings.usejavacp.value = true` (which doesn't work
// under SBT) we do the same as SBT and respond to a resource request
// by the compiler for the magic name "app.classpath", write the JAR files
// from our classloader to a temporary file, and return that as the resource.
if (name == "app.class.path") {
def writeTemp(content: String): File = {
val f = File.createTempFile("classpath", ".txt")
// IO.writeFile(f, content)
val p = new java.io.PrintWriter(f)
p.print(content)
p.close
f
}
info("Attempting to configure Scala classpath based on classloader: " + getClass.getClassLoader)
val superResource = super.getResource(name)
if (superResource != null) superResource // In SBT, let it do it's thing
else getClass.getClassLoader match {
case u: URLClassLoader =>
// Rather pass `settings.usejavacp.value = true` (which doesn't work
// under SBT) we do the same as SBT and respond to a resource request
// by the compiler for the magic name "app.classpath"
info("yay...")
val files = u.getURLs.map(x => new java.io.File(x.toURI))
val f = writeTemp(files.mkString(File.pathSeparator))
f.toURI.toURL
case _ =>
// We're hosed here.
info("uh-oh")
null
}
} else super.getResource(name)
}
}
/** make a new parser/interpreter instance using the given error logger */
override def mkParser(errLogger: String => Unit) = {
// when in managed class loaders we can't just use the javacp
// TODO make this work for any managed classloader - it's hardcoded for sbt
val env = {
val settings = new nsc.Settings(errLogger)
// the repl uses the same thread
settings.Yreplsync.value = true
if(razie.wiki.Services.config.isLocalhost) {
val myLoader = new ReplClassloader(getClass.getClassLoader)
settings.embeddedDefaults(myLoader)
settings.bootclasspath.append("/Users/raz/w/racerkidz/lib_managed/jars/org.scala-lang/scala-library/scala-library-2.11.8.jar")
//todo figure out why the heck and remove this hardcoded bs
// RAZ WAS COMMENTED OUT
val cl = this.getClass.getClassLoader // or getClassLoader.getParent, or one more getParent...
val urls = cl match {
// HE HE HE started working when I collected this and parent
case cl: java.net.URLClassLoader => cl.getURLs.toList //++
///*pre-2.4.6 */ cl.getParent.asInstanceOf[java.net.URLClassLoader].getURLs.toList
case a => sys.error("oops: I was expecting an URLClassLoader, found a " + a.getClass)
}
val classpath = (urls map { _.toString })
razie.cout << "=================CLASSPATH: " + classpath
settings.bootclasspath.value = classpath.distinct.mkString(java.io.File.pathSeparator)
settings.classpath.value = classpath.distinct.mkString(java.io.File.pathSeparator)
settings.embeddedDefaults(cl) // or getClass.getClassLoader
} else {
// production - javacp is enough
settings.usejavacp.value = true
settings embeddedDefaults getClass.getClassLoader
}
settings
}
println ("mkParser")
val p = new RazieInterpreter(env)
p.setContextClassLoader
p
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment