Skip to content

Commit

Permalink
Cleanup the ConsoleInterface API & AnalyzingCompiler
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed May 4, 2017
1 parent ffa533a commit fd323ab
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 100 deletions.
15 changes: 11 additions & 4 deletions internal/compiler-bridge/src/main/java/xsbti/ConsoleFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@
package xsbti;

public interface ConsoleFactory {
ConsoleInterface createConsole(String[] args, String bootClasspathString,
String classpathString, String initialCommands, String cleanupCommands,
ClassLoader loader, String[] bindNames, Object[] bindValues,
Logger log);
ConsoleInterface createConsole(
String[] args,
String bootClasspathString,
String classpathString,
String initialCommands,
String cleanupCommands,
ClassLoader loader,
String[] bindNames,
Object[] bindValues,
Logger log
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ public interface ConsoleResponse {

String output();
}

Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ public enum ConsoleResult {
Incomplete,
Error
}

40 changes: 22 additions & 18 deletions internal/compiler-bridge/src/main/scala/xsbt/ConsoleFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@ package xsbt
import xsbti.Logger

class ConsoleFactory extends xsbti.ConsoleFactory {
def createConsole(args: Array[String],
bootClasspathString: String,
classpathString: String,
initialCommands: String,
cleanupCommands: String,
loader: ClassLoader,
bindNames: Array[String],
bindValues: Array[AnyRef],
log: Logger): xsbti.ConsoleInterface =
new ConsoleInterface(args,
bootClasspathString,
classpathString,
initialCommands,
cleanupCommands,
loader,
bindNames,
bindValues,
log)
def createConsole(
args: Array[String],
bootClasspathString: String,
classpathString: String,
initialCommands: String,
cleanupCommands: String,
loader: ClassLoader,
bindNames: Array[String],
bindValues: Array[AnyRef],
log: Logger
): xsbti.ConsoleInterface =
new ConsoleInterface(
args,
bootClasspathString,
classpathString,
initialCommands,
cleanupCommands,
loader,
bindNames,
bindValues,
log
)
}
69 changes: 36 additions & 33 deletions internal/compiler-bridge/src/main/scala/xsbt/ConsoleInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,45 @@ package xsbt

import java.io.{ PrintWriter, StringWriter }

import scala.tools.nsc.interpreter.IMain
import scala.tools.nsc.{ GenericRunnerCommand, Settings }

import xsbti.Logger

import ConsoleHelper._

import scala.tools.nsc.interpreter.IMain
import scala.tools.nsc.{ GenericRunnerCommand, Settings }
class ConsoleInterface(
args: Array[String],
bootClasspathString: String,
classpathString: String,
initialCommands: String,
cleanupCommands: String,
loader: ClassLoader,
bindNames: Array[String],
bindValues: Array[AnyRef],
log: Logger
) extends xsbti.ConsoleInterface {

lazy val interpreterSettings: Settings = MakeSettings.sync(args.toList, onError)

val useJavaCp = "-usejavacp" // we need rt.jar from JDK, so java classpath is required

val compilerSettings: Settings =
MakeSettings.sync(args :+ useJavaCp, bootClasspathString, classpathString, onError)

class ConsoleInterface(args: Array[String],
bootClasspathString: String,
classpathString: String,
initialCommands: String,
cleanupCommands: String,
loader: ClassLoader,
bindNames: Array[String],
bindValues: Array[AnyRef],
log: Logger)
extends xsbti.ConsoleInterface {
lazy val interpreterSettings = MakeSettings.sync(args.toList, { message =>
log.error(Message(message))
})
// we need rt.jar from JDK, so java classpath is required
val useJavaCp = "-usejavacp"
val compilerSettings =
MakeSettings.sync(args :+ useJavaCp, bootClasspathString, classpathString, { message =>
log.error(Message(message))
})
if (!bootClasspathString.isEmpty)
compilerSettings.bootclasspath.value = bootClasspathString
compilerSettings.classpath.value = classpathString
val outWriter: StringWriter = new StringWriter
val poutWriter: PrintWriter = new PrintWriter(outWriter)

val interpreter: IMain = new IMain(compilerSettings, new PrintWriter(outWriter)) {
def lastReq = prevRequestList.last
def lastReq: Request = prevRequestList.last
}

override def interpret(line: String, synthetic: Boolean): ConsoleResponse = {
def interpret(line: String, synthetic: Boolean): ConsoleResponse = {
clearBuffer()
val r = interpreter.interpret(line, synthetic)
ConsoleResponse(r, outWriter.toString)
}

def clearBuffer(): Unit = {
// errorWriter.getBuffer.setLength(0)
outWriter.getBuffer.setLength(0)
Expand All @@ -58,28 +57,32 @@ class ConsoleInterface(args: Array[String],
clearBuffer()
interpreter.reset()
}

private def onError(str: String) = log error Message(str)
}

object MakeSettings {
def apply(args: List[String], onError: String => Unit) = {
val command = new GenericRunnerCommand(args, onError(_))
def apply(args: List[String], onError: String => Unit): Settings = {
val command = new GenericRunnerCommand(args, onError)
if (command.ok) command.settings
// TODO: Provide better exception
else throw new Exception(command.usageMsg)
}

def sync(args: Array[String],
bootClasspathString: String,
classpathString: String,
onError: String => Unit): Settings = {
def sync(
args: Array[String],
bootClasspathString: String,
classpathString: String,
onError: String => Unit
): Settings = {
val compilerSettings = sync(args.toList, onError)
if (!bootClasspathString.isEmpty)
compilerSettings.bootclasspath.value = bootClasspathString
compilerSettings.classpath.value = classpathString
compilerSettings
}

def sync(options: List[String], onError: String => Unit) = {
def sync(options: List[String], onError: String => Unit): Settings = {
val settings = apply(options, onError)
settings.Yreplsync.value = true
settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@ package sbt
package internal
package inc

import java.lang.reflect.InvocationTargetException
import java.io.File
import java.net.URLClassLoader

import sbt.util.Logger
import sbt.io.syntax._
import sbt.internal.inc.classpath.ClassLoaderCache
import sbt.internal.util.ManagedLogger
import xsbti.{ AnalysisCallback, Logger => xLogger, Maybe, Reporter }
import xsbti.{ AnalysisCallback, Maybe, Reporter, Logger => xLogger }
import xsbti.compile.{
CachedCompiler,
CachedCompilerProvider,
ClasspathOptions,
CompileProgress,
DependencyChanges,
GlobalsCache,
CompileProgress,
Output,
ScalaCompiler,
ClasspathOptions
ScalaCompiler
}

/**
Expand All @@ -49,13 +50,7 @@ final class AnalyzingCompiler(
with ScalaCompiler {

def onArgs(f: Seq[String] => Unit): AnalyzingCompiler =
new AnalyzingCompiler(
scalaInstance,
provider,
classpathOptions,
f,
classLoaderCache
)
new AnalyzingCompiler(scalaInstance, provider, classpathOptions, f, classLoaderCache)

def withClassLoaderCache(classLoaderCache: ClassLoaderCache) =
new AnalyzingCompiler(
Expand All @@ -81,17 +76,8 @@ final class AnalyzingCompiler(
val arguments = compArgs(Nil, classpath, None, options)
val output = CompileOutput(singleOutput)
val reporter = new LoggerReporter(maximumErrors, log, p => p)
compile(
sources,
changes,
arguments.toArray,
output,
callback,
reporter,
cache,
log,
Maybe.nothing[CompileProgress]
)
val progress = Maybe.nothing[CompileProgress]
compile(sources, changes, arguments.toArray, output, callback, reporter, cache, log, progress)
}

def compile(
Expand All @@ -106,8 +92,7 @@ final class AnalyzingCompiler(
progressOpt: Maybe[CompileProgress]
): Unit = {
val cached = cache(options, output, !changes.isEmpty, this, log, reporter)
val progress =
if (progressOpt.isDefined) progressOpt.get else IgnoreProgress
val progress = if (progressOpt.isDefined) progressOpt.get else IgnoreProgress
compile(sources, changes, callback, log, reporter, progress, cached)
}

Expand All @@ -132,6 +117,7 @@ final class AnalyzingCompiler(
)(sources, changes, callback, log, reporter, progress, compiler)
()
}

def newCachedCompiler(
arguments: Array[String],
output: Output,
Expand Down Expand Up @@ -170,6 +156,7 @@ final class AnalyzingCompiler(
val reporter = new LoggerReporter(maximumErrors, log)
doc(sources, classpath, outputDirectory, options, log, reporter)
}

def doc(
sources: Seq[File],
classpath: Seq[File],
Expand All @@ -189,16 +176,14 @@ final class AnalyzingCompiler(
)(arguments.toArray[String], log, reporter)
()
}

def console(
classpath: Seq[File],
options: Seq[String],
initialCommands: String,
cleanupCommands: String,
log: Logger
)(
loader: Option[ClassLoader] = None,
bindings: Seq[(String, Any)] = Nil
): Unit = {
)(loader: Option[ClassLoader] = None, bindings: Seq[(String, Any)] = Nil): Unit = {
onArgsHandler(consoleCommandArguments(classpath, options, log))
val (classpathString, bootClasspath) = consoleClasspaths(classpath)
val (names, values) = bindings.unzip
Expand Down Expand Up @@ -228,14 +213,12 @@ final class AnalyzingCompiler(

private[this] def consoleClasspaths(classpath: Seq[File]): (String, String) = {
val arguments = new CompilerArguments(scalaInstance, classpathOptions)
val classpathString =
CompilerArguments.absString(arguments.finishClasspath(classpath))
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath))
val bootClasspath =
if (classpathOptions.autoBoot)
arguments.createBootClasspathFor(classpath)
else ""
if (classpathOptions.autoBoot) arguments.createBootClasspathFor(classpath) else ""
(classpathString, bootClasspath)
}

def consoleCommandArguments(
classpath: Seq[File],
options: Seq[String],
Expand All @@ -250,7 +233,9 @@ final class AnalyzingCompiler(
)(options.toArray[String], bootClasspath, classpathString, log)
argsObj.asInstanceOf[Array[String]].toSeq
}

def force(log: Logger): Unit = { provider(scalaInstance, log); () }

private def call(
interfaceClassName: String,
methodName: String,
Expand All @@ -259,15 +244,17 @@ final class AnalyzingCompiler(
val interfaceClass = getInterfaceClass(interfaceClassName, log)
val interface = interfaceClass.newInstance.asInstanceOf[AnyRef]
val method = interfaceClass.getMethod(methodName, argTypes: _*)
try { method.invoke(interface, args: _*) } catch {
case e: java.lang.reflect.InvocationTargetException =>
try method.invoke(interface, args: _*)
catch {
case e: InvocationTargetException =>
e.getCause match {
case c: xsbti.CompileFailed =>
throw new CompileFailed(c.arguments, c.toString, c.problems)
case t => throw t
}
}
}

private[this] def loader(log: Logger) = {
val interfaceJar = provider(scalaInstance, log)
def createInterfaceLoader =
Expand Down Expand Up @@ -298,15 +285,14 @@ final class AnalyzingCompiler(
new classpath.DualLoader(
scalaLoader,
notXsbtiFilter,
x => true,
_ => true,
sbtLoader,
xsbtiFilter,
x => false
_ => false
)
}

override def toString =
"Analyzing compiler (Scala " + scalaInstance.actualVersion + ")"
override def toString = s"Analyzing compiler (Scala ${scalaInstance.actualVersion})"
}

object AnalyzingCompiler {
Expand Down Expand Up @@ -342,10 +328,7 @@ object AnalyzingCompiler {
def generateJar(outputDir: File, dir: File, resources: Seq[File], targetJar: File) = {
import sbt.io.Path._
copy(resources.pair(rebase(dir, outputDir)))
val toBeZipped = outputDir.allPaths.pair(
relativeTo(outputDir),
errorIfNone = false
)
val toBeZipped = outputDir.allPaths.pair(relativeTo(outputDir), errorIfNone = false)
zip(toBeZipped, targetJar)
}

Expand Down

0 comments on commit fd323ab

Please sign in to comment.