aboutsummaryrefslogtreecommitdiff
path: root/bridge/src/main/scala
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-10-11 17:28:39 +0200
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:06 +0100
commit2d10c87ce537fb42fdb134efcae53dca7305a7b7 (patch)
treea3629c9a3ad6db3e9d07df8fa8621f8c8211076c /bridge/src/main/scala
parent34d64f381362b12a595fd26690c7c9b1c26d16f7 (diff)
downloaddotty-2d10c87ce537fb42fdb134efcae53dca7305a7b7.tar.gz
dotty-2d10c87ce537fb42fdb134efcae53dca7305a7b7.tar.bz2
dotty-2d10c87ce537fb42fdb134efcae53dca7305a7b7.zip
Move sbt-bridge
Diffstat (limited to 'bridge/src/main/scala')
-rw-r--r--bridge/src/main/scala/xsbt/CompilerClassLoader.scala90
-rw-r--r--bridge/src/main/scala/xsbt/CompilerInterface.scala72
-rw-r--r--bridge/src/main/scala/xsbt/ConsoleInterface.scala73
-rw-r--r--bridge/src/main/scala/xsbt/DelegatingReporter.scala48
-rw-r--r--bridge/src/main/scala/xsbt/Log.scala10
-rw-r--r--bridge/src/main/scala/xsbt/Message.scala8
-rw-r--r--bridge/src/main/scala/xsbt/ScaladocInterface.scala72
7 files changed, 0 insertions, 373 deletions
diff --git a/bridge/src/main/scala/xsbt/CompilerClassLoader.scala b/bridge/src/main/scala/xsbt/CompilerClassLoader.scala
deleted file mode 100644
index 3cb3f344f..000000000
--- a/bridge/src/main/scala/xsbt/CompilerClassLoader.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-package xsbt
-
-import java.net.{URL, URLClassLoader}
-
-/** A classloader to run the compiler
- *
- * A CompilerClassLoader is constructed from a list of `urls` that need to be on
- * the classpath to run the compiler and the classloader used by sbt.
- *
- * To understand why a custom classloader is needed for the compiler, let us
- * describe some alternatives that wouldn't work.
- * - `new URLClassLoader(urls)`:
- * The compiler contains sbt phases that callback to sbt using the `xsbti.*`
- * interfaces. If `urls` does not contain the sbt interfaces we'll get a
- * `ClassNotFoundException` in the compiler when we try to use them, if
- * `urls` does contain the interfaces we'll get a `ClassCastException` or a
- * `LinkageError` because if the same class is loaded by two different
- * classloaders, they are considered distinct by the JVM.
- * - `new URLClassLoader(urls, sbtLoader)`:
- * Because of the JVM delegation model, this means that we will only load
- * a class from `urls` if it's not present in the parent `sbtLoader`, but
- * sbt uses its own version of the scala compiler and scala library which
- * is not the one we need to run the compiler.
- *
- * Our solution is to implement a subclass of URLClassLoader with no parent, instead
- * we override `loadClass` to load the `xsbti.*` interfaces from `sbtLoader`.
- */
-class CompilerClassLoader(urls: Array[URL], sbtLoader: ClassLoader)
- extends URLClassLoader(urls, null) {
- override def loadClass(className: String, resolve: Boolean): Class[_] =
- if (className.startsWith("xsbti.")) {
- // We can't use the loadClass overload with two arguments because it's
- // protected, but we can do the same by hand (the classloader instance
- // from which we call resolveClass does not matter).
- val c = sbtLoader.loadClass(className)
- if (resolve)
- resolveClass(c)
- c
- } else {
- super.loadClass(className, resolve)
- }
-}
-
-object CompilerClassLoader {
- /** Fix the compiler bridge ClassLoader
- *
- * Soundtrack: https://www.youtube.com/watch?v=imamcajBEJs
- *
- * The classloader that we get from sbt looks like:
- *
- * URLClassLoader(bridgeURLs,
- * DualLoader(scalaLoader, notXsbtiFilter, sbtLoader, xsbtiFilter))
- *
- * DualLoader will load the `xsbti.*` interfaces using `sbtLoader` and
- * everything else with `scalaLoader`. Once we have loaded the dotty Main
- * class using `scalaLoader`, subsequent classes in the dotty compiler will
- * also be loaded by `scalaLoader` and _not_ by the DualLoader. But the sbt
- * compiler phases are part of dotty and still need access to the `xsbti.*`
- * interfaces in `sbtLoader`, therefore DualLoader does not work for us
- * (this issue is not present with scalac because the sbt phases are
- * currently defined in the compiler bridge itself, not in scalac).
- *
- * CompilerClassLoader is a replacement for DualLoader. Until we can fix
- * this in sbt proper, we need to use reflection to construct our own
- * fixed classloader:
- *
- * URLClassLoader(bridgeURLs,
- * CompilerClassLoader(scalaLoader.getURLs, sbtLoader))
- *
- * @param bridgeLoader The classloader that sbt uses to load the compiler bridge
- * @return A fixed classloader that works with dotty
- */
- def fixBridgeLoader(bridgeLoader: ClassLoader) = bridgeLoader match {
- case bridgeLoader: URLClassLoader =>
- val dualLoader = bridgeLoader.getParent
- val dualLoaderClass = dualLoader.getClass
-
- // DualLoader#parentA and DualLoader#parentB are private
- val parentAField = dualLoaderClass.getDeclaredField("parentA")
- parentAField.setAccessible(true)
- val parentBField = dualLoaderClass.getDeclaredField("parentB")
- parentBField.setAccessible(true)
- val scalaLoader = parentAField.get(dualLoader).asInstanceOf[URLClassLoader]
- val sbtLoader = parentBField.get(dualLoader).asInstanceOf[URLClassLoader]
-
- val bridgeURLs = bridgeLoader.getURLs
- new URLClassLoader(bridgeURLs,
- new CompilerClassLoader(scalaLoader.getURLs, sbtLoader))
- }
-}
diff --git a/bridge/src/main/scala/xsbt/CompilerInterface.scala b/bridge/src/main/scala/xsbt/CompilerInterface.scala
deleted file mode 100644
index bf1488dad..000000000
--- a/bridge/src/main/scala/xsbt/CompilerInterface.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package xsbt
-
-import xsbti.{ AnalysisCallback, Logger, Problem, Reporter, Severity, DependencyContext }
-import xsbti.api.SourceAPI
-import xsbti.compile._
-import Log.debug
-import java.io.File
-
-import dotty.tools.dotc.core.Contexts.ContextBase
-import dotty.tools.dotc.{ Main => DottyMain }
-import dotty.tools.dotc.interfaces._
-
-import java.net.URLClassLoader
-
-final class CompilerInterface {
- def newCompiler(options: Array[String], output: Output, initialLog: Logger,
- initialDelegate: Reporter, resident: Boolean): CachedCompiler = {
- // The classloader that sbt uses to load the compiler bridge is broken
- // (see CompilerClassLoader#fixBridgeLoader for details). To workaround
- // this we construct our own ClassLoader and then run the following code
- // with it:
- // new CachedCompilerImpl(options, output, resident)
-
- val bridgeLoader = getClass.getClassLoader
- val fixedLoader = CompilerClassLoader.fixBridgeLoader(bridgeLoader)
- val cciClass = fixedLoader.loadClass("xsbt.CachedCompilerImpl")
- cciClass.getConstructors.head
- .newInstance(options, output, resident: java.lang.Boolean)
- .asInstanceOf[CachedCompiler]
- }
-
- def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger,
- delegate: Reporter, progress: CompileProgress, cached: CachedCompiler): Unit =
- cached.run(sources, changes, callback, log, delegate, progress)
-}
-
-class CachedCompilerImpl(args: Array[String], output: Output, resident: Boolean) extends CachedCompiler {
- val outputArgs =
- output match {
- case multi: MultipleOutput =>
- ???
- case single: SingleOutput =>
- List("-d", single.outputDirectory.getAbsolutePath.toString)
- }
-
- def commandArguments(sources: Array[File]): Array[String] =
- (outputArgs ++ args.toList ++ sources.map(_.getAbsolutePath).sortWith(_ < _)).toArray[String]
-
- def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, progress: CompileProgress): Unit = synchronized {
- run(sources.toList, changes, callback, log, delegate, progress)
- }
- private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, compileProgress: CompileProgress): Unit = {
- debug(log, args.mkString("Calling Dotty compiler with arguments (CompilerInterface):\n\t", "\n\t", ""))
- val ctx = (new ContextBase).initialCtx.fresh
- .setSbtCallback(callback)
- .setReporter(new DelegatingReporter(delegate))
-
- val cl = getClass.getClassLoader.asInstanceOf[URLClassLoader]
-
- val reporter = DottyMain.process(commandArguments(sources.toArray), ctx)
- if (reporter.hasErrors) {
- throw new InterfaceCompileFailed(args, Array())
- }
- }
-}
-
-class InterfaceCompileFailed(override val arguments: Array[String], override val problems: Array[Problem]) extends xsbti.CompileFailed {
- override val toString = "Compilation failed"
-}
diff --git a/bridge/src/main/scala/xsbt/ConsoleInterface.scala b/bridge/src/main/scala/xsbt/ConsoleInterface.scala
deleted file mode 100644
index f56918113..000000000
--- a/bridge/src/main/scala/xsbt/ConsoleInterface.scala
+++ /dev/null
@@ -1,73 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package xsbt
-
-import xsbti.Logger
-import scala.tools.nsc.{ GenericRunnerCommand, Interpreter, InterpreterLoop, ObjectRunner, Settings }
-import scala.tools.nsc.interpreter.InteractiveReader
-import scala.tools.nsc.reporters.Reporter
-import scala.tools.nsc.util.ClassPath
-
-import dotty.tools.dotc.core.Contexts.Context
-import dotty.tools.dotc.repl.REPL
-import dotty.tools.dotc.repl.REPL.Config
-
-class ConsoleInterface {
- def commandArguments(
- args: Array[String],
- bootClasspathString: String,
- classpathString: String,
- log: Logger
- ): Array[String] = args
-
- def run(args: Array[String],
- bootClasspathString: String,
- classpathString: String,
- initialCommands: String,
- cleanupCommands: String,
- loader: ClassLoader,
- bindNames: Array[String],
- bindValues: Array[Any],
- log: Logger
- ): Unit = {
- val completeArgs =
- args :+
- "-bootclasspath" :+ bootClasspathString :+
- "-classpath" :+ classpathString
-
- println("Starting dotty interpreter...")
- val repl = ConsoleInterface.customRepl(
- initialCommands :: Nil,
- cleanupCommands :: Nil,
- bindNames zip bindValues,
- loader
- )
- repl.process(completeArgs)
- }
-}
-
-object ConsoleInterface {
- def customConfig(
- initCmds: List[String],
- cleanupCmds: List[String],
- boundVals: Array[(String, Any)],
- loader: ClassLoader
- ) = new Config {
- override val initialCommands: List[String] = initCmds
- override val cleanupCommands: List[String] = cleanupCmds
- override val boundValues: Array[(String, Any)] = boundVals
- override val classLoader: Option[ClassLoader] = Option(loader)
- }
-
- def customRepl(cfg: Config): REPL = new REPL {
- override lazy val config = cfg
- }
-
- def customRepl(
- initCmds: List[String],
- cleanupCmds: List[String],
- boundVals: Array[(String, Any)],
- loader: ClassLoader
- ): REPL = customRepl(customConfig(initCmds, cleanupCmds, boundVals, loader))
-}
diff --git a/bridge/src/main/scala/xsbt/DelegatingReporter.scala b/bridge/src/main/scala/xsbt/DelegatingReporter.scala
deleted file mode 100644
index 770d6b2c7..000000000
--- a/bridge/src/main/scala/xsbt/DelegatingReporter.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package xsbt
-
-import dotty.tools._
-import dotc._
-import reporting._
-import reporting.diagnostic.MessageContainer
-import reporting.diagnostic.messages
-import core.Contexts._
-import xsbti.{Maybe, Position}
-
-final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
- with UniqueMessagePositions
- with HideNonSensicalMessages
- with MessageRendering {
- import MessageContainer._
-
- override def printSummary(implicit ctx: Context): Unit = delegate.printSummary()
-
- def doReport(cont: MessageContainer)(implicit ctx: Context): Unit = {
- val severity =
- cont match {
- case _: messages.Error => xsbti.Severity.Error
- case _: messages.Warning => xsbti.Severity.Warn
- case _ => xsbti.Severity.Info
- }
-
- val position = new Position {
- def line: Maybe[Integer] = Maybe.nothing()
- def lineContent: String = ""
- def offset: Maybe[Integer] = Maybe.nothing()
- def pointer: Maybe[Integer] = Maybe.nothing()
- def pointerSpace: Maybe[String] = Maybe.nothing()
- def sourceFile: Maybe[java.io.File] = Maybe.nothing()
- def sourcePath: Maybe[String] = Maybe.nothing()
- }
-
- val sb = new StringBuilder()
- sb.append(messageAndPos(cont.contained, cont.pos, diagnosticLevel(cont)))
- if (ctx.shouldExplain(cont) && cont.contained.explanation.nonEmpty) {
- sb.append(explanation(cont.contained))
- }
-
- delegate.log(position, sb.toString(), severity)
- }
-}
diff --git a/bridge/src/main/scala/xsbt/Log.scala b/bridge/src/main/scala/xsbt/Log.scala
deleted file mode 100644
index e514d7abb..000000000
--- a/bridge/src/main/scala/xsbt/Log.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package xsbt
-
-object Log {
- def debug(log: xsbti.Logger, msg: => String) = log.debug(Message(msg))
- def settingsError(log: xsbti.Logger): String => Unit =
- s => log.error(Message(s))
-}
diff --git a/bridge/src/main/scala/xsbt/Message.scala b/bridge/src/main/scala/xsbt/Message.scala
deleted file mode 100644
index 48f24f533..000000000
--- a/bridge/src/main/scala/xsbt/Message.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package xsbt
-
-object Message {
- def apply[T](s: => T) = new xsbti.F0[T] { def apply() = s }
-}
diff --git a/bridge/src/main/scala/xsbt/ScaladocInterface.scala b/bridge/src/main/scala/xsbt/ScaladocInterface.scala
deleted file mode 100644
index 3ad9c7941..000000000
--- a/bridge/src/main/scala/xsbt/ScaladocInterface.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package xsbt
-
-import xsbti.Logger
-import dotty.tools.dottydoc.api.scala.Dottydoc
-import java.net.URL
-
-class ScaladocInterface {
- def run(args: Array[String], log: Logger, delegate: xsbti.Reporter) =
- (new DottydocRunner(args, log, delegate)).run()
-}
-
-class DottydocRunner(args: Array[String], log: Logger, delegate: xsbti.Reporter) extends Dottydoc {
- def run(): Unit = getOutputFolder(args).map { outputFolder =>
- val index = createIndex(args)
- val resources = getResources(args)
- val template = getTemplate(resources)
-
- template.fold(writeJson(index, outputFolder)) { tpl =>
- buildDocs(outputFolder, tpl, resources, index)
- }
- } getOrElse {
- delegate.log(
- NoPosition,
- "No output folder set for API documentation (\"-d\" parameter should be passed to the documentation tool)",
- xsbti.Severity.Error
- )
- }
-
- private[this] val NoPosition = new xsbti.Position {
- val line = xsbti.Maybe.nothing[Integer]
- val lineContent = ""
- val offset = xsbti.Maybe.nothing[Integer]
- val sourcePath = xsbti.Maybe.nothing[String]
- val sourceFile = xsbti.Maybe.nothing[java.io.File]
- val pointer = xsbti.Maybe.nothing[Integer]
- val pointerSpace = xsbti.Maybe.nothing[String]
- }
-
- private def getStringSetting(name: String): Option[String] =
- args find (_.startsWith(name)) map (_.drop(name.length))
-
- private def getOutputFolder(args: Array[String]): Option[String] =
- args sliding(2) find { case Array(x, _) => x == "-d" } map (_.tail.head.trim)
-
- private def getTemplate(resources: List[URL]): Option[URL] =
- resources.find(_.getFile.endsWith("template.html"))
-
- private def getResources(args: Array[String]): List[URL] = {
- val cp = args sliding (2) find { case Array(x, _) => x == "-classpath" } map (_.tail.head.trim) getOrElse ""
-
- cp.split(":").find(_.endsWith("dottydoc-client.jar")).map { resourceJar =>
- import java.util.jar.JarFile
- val jarEntries = (new JarFile(resourceJar)).entries
- var entries: List[URL] = Nil
-
- while (jarEntries.hasMoreElements) {
- val entry = jarEntries.nextElement()
-
- if (!entry.isDirectory()) {
- val path = s"jar:file:$resourceJar!/${entry.getName}"
- val url = new URL(path)
- entries = url :: entries
- }
- }
-
- entries
- } getOrElse (Nil)
- }
-}