mirror of https://github.com/sbt/sbt.git
basis for a resident compiler
unstable, but can be tested with -Dsbt.resident.limit=n n is the maximum Globals kept around
This commit is contained in:
parent
0566a61689
commit
6769c94208
|
|
@ -5,6 +5,7 @@ package sbt
|
|||
package compiler
|
||||
|
||||
import xsbti.{AnalysisCallback, Logger => xLogger, Reporter}
|
||||
import xsbti.compile.{CachedCompiler, CachedCompilerProvider, DependencyChanges, GlobalsCache}
|
||||
import java.io.File
|
||||
import java.net.{URL, URLClassLoader}
|
||||
|
||||
|
|
@ -12,22 +13,37 @@ package compiler
|
|||
* provided by scalaInstance. This class requires a ComponentManager in order to obtain the interface code to scalac and
|
||||
* the analysis plugin. Because these call Scala code for a different Scala version than the one used for this class, they must
|
||||
* be compiled for the version of Scala being used.*/
|
||||
class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, val provider: CompilerInterfaceProvider, val cp: xsbti.compile.ClasspathOptions, log: Logger)
|
||||
final class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, val provider: CompilerInterfaceProvider, val cp: xsbti.compile.ClasspathOptions, log: Logger) extends CachedCompilerProvider
|
||||
{
|
||||
def this(scalaInstance: ScalaInstance, provider: CompilerInterfaceProvider, log: Logger) = this(scalaInstance, provider, ClasspathOptions.auto, log)
|
||||
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger)
|
||||
def apply(sources: Seq[File], changes: DependencyChanges, classpath: Seq[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, cache: GlobalsCache, log: Logger)
|
||||
{
|
||||
val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options)
|
||||
compile(arguments, callback, maximumErrors, log)
|
||||
val arguments = (new CompilerArguments(scalaInstance, cp))(Nil, classpath, outputDirectory, options)
|
||||
compile(sources, changes, arguments, callback, maximumErrors, cache, log)
|
||||
}
|
||||
|
||||
def compile(arguments: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger): Unit =
|
||||
compile(arguments, callback, log, new LoggerReporter(maximumErrors, log))
|
||||
def compile(arguments: Seq[String], callback: AnalysisCallback, log: Logger, reporter: Reporter)
|
||||
def compile(sources: Seq[File], changes: DependencyChanges, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, cache: GlobalsCache, log: Logger): Unit =
|
||||
{
|
||||
call("xsbt.CompilerInterface", log)(
|
||||
classOf[Array[String]], classOf[AnalysisCallback], classOf[xLogger], classOf[Reporter] ) (
|
||||
arguments.toArray[String] : Array[String], callback, log, reporter )
|
||||
val reporter = new LoggerReporter(maximumErrors, log)
|
||||
val cached = cache(options.toArray, !changes.isEmpty, this, log, reporter)
|
||||
compile(sources, changes, callback, log, reporter, cached)
|
||||
}
|
||||
|
||||
def compile(sources: Seq[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, reporter: Reporter, compiler: CachedCompiler)
|
||||
{
|
||||
call("xsbt.CompilerInterface", "run", log)(
|
||||
classOf[Array[File]], classOf[DependencyChanges], classOf[AnalysisCallback], classOf[xLogger], classOf[Reporter], classOf[CachedCompiler]) (
|
||||
sources.toArray, changes, callback, log, reporter, compiler )
|
||||
}
|
||||
def newCachedCompiler(arguments: Array[String], log: xLogger, reporter: Reporter): CachedCompiler =
|
||||
newCachedCompiler(arguments: Seq[String], log, reporter)
|
||||
|
||||
def newCachedCompiler(arguments: Seq[String], log: xLogger, reporter: Reporter): CachedCompiler =
|
||||
{
|
||||
call("xsbt.CompilerInterface", "newCompiler", log)(
|
||||
classOf[Array[String]], classOf[xLogger], classOf[Reporter] ) (
|
||||
arguments.toArray[String] : Array[String], log, reporter ).
|
||||
asInstanceOf[CachedCompiler]
|
||||
}
|
||||
|
||||
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger): Unit =
|
||||
|
|
@ -35,7 +51,7 @@ class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, val prov
|
|||
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger, reporter: Reporter): Unit =
|
||||
{
|
||||
val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options)
|
||||
call("xsbt.ScaladocInterface", log) (classOf[Array[String]], classOf[xLogger], classOf[Reporter]) (
|
||||
call("xsbt.ScaladocInterface", "run", log) (classOf[Array[String]], classOf[xLogger], classOf[Reporter]) (
|
||||
arguments.toArray[String] : Array[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 =
|
||||
|
|
@ -44,16 +60,16 @@ class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, val prov
|
|||
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath))
|
||||
val bootClasspath = if(cp.autoBoot) arguments.createBootClasspath else ""
|
||||
val (names, values) = bindings.unzip
|
||||
call("xsbt.ConsoleInterface", log)(
|
||||
call("xsbt.ConsoleInterface", "run", log)(
|
||||
classOf[Array[String]], classOf[String], classOf[String], classOf[String], classOf[String], classOf[ClassLoader], classOf[Array[String]], classOf[Array[Any]], classOf[xLogger])(
|
||||
options.toArray[String]: Array[String], bootClasspath, classpathString, initialCommands, cleanupCommands, loader.orNull, names.toArray[String], values.toArray[Any], log)
|
||||
}
|
||||
def force(log: Logger): Unit = provider(scalaInstance, log)
|
||||
private def call(interfaceClassName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*)
|
||||
private def call(interfaceClassName: String, methodName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*): AnyRef =
|
||||
{
|
||||
val interfaceClass = getInterfaceClass(interfaceClassName, log)
|
||||
val interface = interfaceClass.newInstance.asInstanceOf[AnyRef]
|
||||
val method = interfaceClass.getMethod("run", argTypes : _*)
|
||||
val method = interfaceClass.getMethod(methodName, argTypes : _*)
|
||||
try { method.invoke(interface, args: _*) }
|
||||
catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
package sbt
|
||||
package compiler
|
||||
|
||||
import xsbti.{Logger => xLogger, Reporter}
|
||||
import xsbti.compile.{CachedCompiler, CachedCompilerProvider, GlobalsCache}
|
||||
import Logger.f0
|
||||
import java.io.File
|
||||
import java.util.{LinkedHashMap,Map}
|
||||
|
||||
private final class CompilerCache(val maxInstances: Int) extends GlobalsCache
|
||||
{
|
||||
private[this] val cache = lru[CompilerKey, CachedCompiler](maxInstances)
|
||||
private[this] def lru[A,B](max: Int) = new LinkedHashMap[A,B](8, 0.75f, true) {
|
||||
override def removeEldestEntry(eldest: Map.Entry[A,B]): Boolean = size > max
|
||||
}
|
||||
def apply(args: Array[String], forceNew: Boolean, c: CachedCompilerProvider, log: xLogger, reporter: Reporter): CachedCompiler = synchronized
|
||||
{
|
||||
val key = CompilerKey(dropSources(args.toList), c.scalaInstance.actualVersion)
|
||||
if(forceNew) cache.remove(key)
|
||||
cache.get(key) match {
|
||||
case null =>
|
||||
log.debug(f0("Compiler cache miss. " + key.toString))
|
||||
put(key, c.newCachedCompiler(args, log, reporter))
|
||||
case cc =>
|
||||
log.debug(f0("Compiler cache hit (" + cc.hashCode.toHexString + "). " + key.toString))
|
||||
cc
|
||||
}
|
||||
}
|
||||
def clear(): Unit = synchronized { cache.clear() }
|
||||
|
||||
private[this] def dropSources(args: Seq[String]): Seq[String] =
|
||||
args.filterNot(arg => arg.endsWith(".scala") || arg.endsWith(".java"))
|
||||
|
||||
private[this] def put(key: CompilerKey, cc: CachedCompiler): CachedCompiler =
|
||||
{
|
||||
cache.put(key, cc)
|
||||
cc
|
||||
}
|
||||
private[this] final case class CompilerKey(args: Seq[String], scalaVersion: String) {
|
||||
override def toString = "scala " + scalaVersion + ", args: " + args.mkString(" ")
|
||||
}
|
||||
}
|
||||
object CompilerCache
|
||||
{
|
||||
def apply(maxInstances: Int): GlobalsCache = new CompilerCache(maxInstances)
|
||||
|
||||
val fresh: GlobalsCache = new GlobalsCache {
|
||||
def clear() {}
|
||||
def apply(args: Array[String], forceNew: Boolean, c: CachedCompilerProvider, log: xLogger, reporter: Reporter): CachedCompiler =
|
||||
c.newCachedCompiler(args, log, reporter)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,22 +5,23 @@ package sbt
|
|||
package inc
|
||||
|
||||
import xsbti.api.{Source, SourceAPI}
|
||||
import xsbti.compile.DependencyChanges
|
||||
import xsbti.{Position,Problem,Severity}
|
||||
import Logger.{m2o, problem}
|
||||
import java.io.File
|
||||
|
||||
object IncrementalCompile
|
||||
{
|
||||
def apply(sources: Set[File], entry: String => Option[File], compile: (Set[File], xsbti.AnalysisCallback) => Unit, previous: Analysis, forEntry: File => Option[Analysis], outputPath: File, log: Logger): (Boolean, Analysis) =
|
||||
def apply(sources: Set[File], entry: String => Option[File], compile: (Set[File], DependencyChanges, xsbti.AnalysisCallback) => Unit, previous: Analysis, forEntry: File => Option[Analysis], outputPath: File, log: Logger): (Boolean, Analysis) =
|
||||
{
|
||||
val current = Stamps.initial(Stamp.exists, Stamp.hash, Stamp.lastModified)
|
||||
val internalMap = (f: File) => previous.relations.produced(f).headOption
|
||||
val externalAPI = getExternalAPI(entry, forEntry)
|
||||
Incremental.compile(sources, entry, previous, current, forEntry, doCompile(compile, internalMap, externalAPI, current, outputPath), log)
|
||||
}
|
||||
def doCompile(compile: (Set[File], xsbti.AnalysisCallback) => Unit, internalMap: File => Option[File], externalAPI: (File, String) => Option[Source], current: ReadStamps, outputPath: File) = (srcs: Set[File]) => {
|
||||
def doCompile(compile: (Set[File], DependencyChanges, xsbti.AnalysisCallback) => Unit, internalMap: File => Option[File], externalAPI: (File, String) => Option[Source], current: ReadStamps, outputPath: File) = (srcs: Set[File], changes: DependencyChanges) => {
|
||||
val callback = new AnalysisCallback(internalMap, externalAPI, current, outputPath)
|
||||
compile(srcs, callback)
|
||||
compile(srcs, changes, callback)
|
||||
callback.get
|
||||
}
|
||||
def getExternalAPI(entry: String => Option[File], forEntry: File => Option[Analysis]): (File, String) => Option[Source] =
|
||||
|
|
|
|||
|
|
@ -7,30 +7,36 @@ package inc
|
|||
import xsbt.api.{NameChanges, SameAPI, TopLevel}
|
||||
import annotation.tailrec
|
||||
import xsbti.api.{Compilation, Source}
|
||||
import xsbti.compile.DependencyChanges
|
||||
import java.io.File
|
||||
|
||||
object Incremental
|
||||
{
|
||||
def debug(s: => String) = if(java.lang.Boolean.getBoolean("xsbt.inc.debug")) println(s) else ()
|
||||
def compile(sources: Set[File], entry: String => Option[File], previous: Analysis, current: ReadStamps, forEntry: File => Option[Analysis], doCompile: Set[File] => Analysis, log: Logger)(implicit equivS: Equiv[Stamp]): (Boolean, Analysis) =
|
||||
def compile(sources: Set[File], entry: String => Option[File], previous: Analysis, current: ReadStamps, forEntry: File => Option[Analysis], doCompile: (Set[File], DependencyChanges) => Analysis, log: Logger)(implicit equivS: Equiv[Stamp]): (Boolean, Analysis) =
|
||||
{
|
||||
val initialChanges = changedInitial(entry, sources, previous, current, forEntry)
|
||||
val binaryChanges = new DependencyChanges {
|
||||
val modifiedBinaries = initialChanges.binaryDeps.toArray
|
||||
val modifiedClasses = initialChanges.external.modified.toArray
|
||||
def isEmpty = modifiedBinaries.isEmpty && modifiedClasses.isEmpty
|
||||
}
|
||||
val initialInv = invalidateInitial(previous.relations, initialChanges, log)
|
||||
log.debug("Initially invalidated: " + initialInv)
|
||||
val analysis = cycle(initialInv, previous, doCompile, log)
|
||||
val analysis = cycle(initialInv, binaryChanges, previous, doCompile, log)
|
||||
(!initialInv.isEmpty, analysis)
|
||||
}
|
||||
|
||||
// TODO: the Analysis for the last successful compilation should get returned + Boolean indicating success
|
||||
// TODO: full external name changes, scopeInvalidations
|
||||
def cycle(invalidated: Set[File], previous: Analysis, doCompile: Set[File] => Analysis, log: Logger): Analysis =
|
||||
def cycle(invalidated: Set[File], binaryChanges: DependencyChanges, previous: Analysis, doCompile: (Set[File], DependencyChanges) => Analysis, log: Logger): Analysis =
|
||||
if(invalidated.isEmpty)
|
||||
previous
|
||||
else
|
||||
{
|
||||
val pruned = prune(invalidated, previous)
|
||||
debug("********* Pruned: \n" + pruned.relations + "\n*********")
|
||||
val fresh = doCompile(invalidated)
|
||||
val fresh = doCompile(invalidated, binaryChanges)
|
||||
debug("********* Fresh: \n" + fresh.relations + "\n*********")
|
||||
val merged = pruned ++ fresh//.copy(relations = pruned.relations ++ fresh.relations, apis = pruned.apis ++ fresh.apis)
|
||||
debug("********* Merged: \n" + merged.relations + "\n*********")
|
||||
|
|
@ -38,8 +44,13 @@ object Incremental
|
|||
debug("Changes:\n" + incChanges)
|
||||
val incInv = invalidateIncremental(merged.relations, incChanges, invalidated, log)
|
||||
log.debug("Incrementally invalidated: " + incInv)
|
||||
cycle(incInv, merged, doCompile, log)
|
||||
cycle(incInv, emptyChanges, merged, doCompile, log)
|
||||
}
|
||||
private[this] def emptyChanges: DependencyChanges = new DependencyChanges {
|
||||
val modifiedBinaries = new Array[File](0)
|
||||
val modifiedClasses = new Array[String](0)
|
||||
def isEmpty = true
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,37 +9,38 @@ import inc._
|
|||
import java.io.File
|
||||
import classpath.ClasspathUtilities
|
||||
import classfile.Analyze
|
||||
import xsbti.api.Source
|
||||
import xsbti.compile.CompileOrder
|
||||
import CompileOrder.{JavaThenScala, Mixed, ScalaThenJava}
|
||||
import xsbti.AnalysisCallback
|
||||
import inc.Locate.DefinesClass
|
||||
import CompileSetup._
|
||||
import sbinary.DefaultProtocol.{ immutableMapFormat, immutableSetFormat, StringFormat }
|
||||
import Types.const
|
||||
|
||||
import xsbti.AnalysisCallback
|
||||
import xsbti.api.Source
|
||||
import xsbti.compile.{CompileOrder, DependencyChanges, GlobalsCache}
|
||||
import CompileOrder.{JavaThenScala, Mixed, ScalaThenJava}
|
||||
|
||||
final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File],
|
||||
val previousAnalysis: Analysis, val previousSetup: Option[CompileSetup], val currentSetup: CompileSetup, val getAnalysis: File => Option[Analysis], val definesClass: DefinesClass,
|
||||
val maxErrors: Int, val compiler: AnalyzingCompiler, val javac: xsbti.compile.JavaCompiler)
|
||||
val maxErrors: Int, val compiler: AnalyzingCompiler, val javac: xsbti.compile.JavaCompiler, val cache: GlobalsCache)
|
||||
|
||||
class AggressiveCompile(cacheFile: File)
|
||||
{
|
||||
def apply(compiler: AnalyzingCompiler, javac: xsbti.compile.JavaCompiler, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String] = Nil, javacOptions: Seq[String] = Nil, analysisMap: File => Option[Analysis] = const(None), definesClass: DefinesClass = Locate.definesClass _, maxErrors: Int = 100, compileOrder: CompileOrder = Mixed, skip: Boolean = false)(implicit log: Logger): Analysis =
|
||||
def apply(compiler: AnalyzingCompiler, javac: xsbti.compile.JavaCompiler, sources: Seq[File], classpath: Seq[File], outputDirectory: File, cache: GlobalsCache, options: Seq[String] = Nil, javacOptions: Seq[String] = Nil, analysisMap: File => Option[Analysis] = const(None), definesClass: DefinesClass = Locate.definesClass _, maxErrors: Int = 100, compileOrder: CompileOrder = Mixed, skip: Boolean = false)(implicit log: Logger): Analysis =
|
||||
{
|
||||
val setup = new CompileSetup(outputDirectory, new CompileOptions(options, javacOptions), compiler.scalaInstance.actualVersion, compileOrder)
|
||||
compile1(sources, classpath, setup, store, analysisMap, definesClass, compiler, javac, maxErrors, skip)
|
||||
compile1(sources, classpath, setup, store, analysisMap, definesClass, compiler, javac, maxErrors, skip, cache)
|
||||
}
|
||||
|
||||
def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
|
||||
args.bootClasspath ++ args.finishClasspath(classpath)
|
||||
|
||||
def compile1(sources: Seq[File], classpath: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: File => Option[Analysis], definesClass: DefinesClass, compiler: AnalyzingCompiler, javac: xsbti.compile.JavaCompiler, maxErrors: Int, skip: Boolean)(implicit log: Logger): Analysis =
|
||||
def compile1(sources: Seq[File], classpath: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: File => Option[Analysis], definesClass: DefinesClass, compiler: AnalyzingCompiler, javac: xsbti.compile.JavaCompiler, maxErrors: Int, skip: Boolean, cache: GlobalsCache)(implicit log: Logger): Analysis =
|
||||
{
|
||||
val (previousAnalysis, previousSetup) = extract(store.get())
|
||||
if(skip)
|
||||
previousAnalysis
|
||||
else {
|
||||
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup, analysis, definesClass, maxErrors, compiler, javac)
|
||||
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup, analysis, definesClass, maxErrors, compiler, javac, cache)
|
||||
val (modified, result) = compile2(config)
|
||||
if(modified)
|
||||
store.set(result, setup)
|
||||
|
|
@ -56,7 +57,7 @@ class AggressiveCompile(cacheFile: File)
|
|||
val searchClasspath = explicitBootClasspath(options.options) ++ withBootclasspath(cArgs, absClasspath)
|
||||
val entry = Locate.entry(searchClasspath, definesClass)
|
||||
|
||||
val compile0 = (include: Set[File], callback: AnalysisCallback) => {
|
||||
val compile0 = (include: Set[File], changes: DependencyChanges, callback: AnalysisCallback) => {
|
||||
IO.createDirectory(outputDirectory)
|
||||
val incSrc = sources.filter(include)
|
||||
val (javaSrcs, scalaSrcs) = incSrc partition javaOnly
|
||||
|
|
@ -65,8 +66,8 @@ class AggressiveCompile(cacheFile: File)
|
|||
if(!scalaSrcs.isEmpty)
|
||||
{
|
||||
val sources = if(order == Mixed) incSrc else scalaSrcs
|
||||
val arguments = cArgs(sources, absClasspath, outputDirectory, options.options)
|
||||
compiler.compile(arguments, callback, maxErrors, log)
|
||||
val arguments = cArgs(Nil, absClasspath, outputDirectory, options.options)
|
||||
compiler.compile(sources, changes, arguments, callback, maxErrors, cache, log)
|
||||
}
|
||||
def compileJava() =
|
||||
if(!javaSrcs.isEmpty)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ object IC extends IncrementalCompiler[Analysis, AnalyzingCompiler]
|
|||
val agg = new AggressiveCompile(setup.cacheFile)
|
||||
val aMap = (f: File) => m2o(analysisMap(f))
|
||||
val defClass = (f: File) => { val dc = definesClass(f); (name: String) => dc.apply(name) }
|
||||
agg(scalac, javac, sources, classpath, classesDirectory, scalacOptions, javacOptions, aMap, defClass, maxErrors, order, skip)(log)
|
||||
agg(scalac, javac, sources, classpath, classesDirectory, cache, scalacOptions, javacOptions, aMap, defClass, maxErrors, order, skip)(log)
|
||||
}
|
||||
|
||||
private[this] def m2o[S](opt: Maybe[S]): Option[S] = if(opt.isEmpty) None else Some(opt.get)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ object API
|
|||
val name = "xsbt-api"
|
||||
}
|
||||
|
||||
final class API(val global: Global, val callback: xsbti.AnalysisCallback) extends Compat
|
||||
final class API(val global: CallbackGlobal) extends Compat
|
||||
{
|
||||
import global._
|
||||
def error(msg: String) = throw new RuntimeException(msg)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ object Analyzer
|
|||
{
|
||||
def name = "xsbt-analyzer"
|
||||
}
|
||||
final class Analyzer(val global: Global, val callback: AnalysisCallback) extends Compat
|
||||
final class Analyzer(val global: CallbackGlobal) extends Compat
|
||||
{
|
||||
import global._
|
||||
|
||||
|
|
@ -35,10 +35,12 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
// build dependencies structure
|
||||
val sourceFile = unit.source.file.file
|
||||
callback.beginSource(sourceFile)
|
||||
println("Dependencies of " + sourceFile)
|
||||
for(on <- unit.depends)
|
||||
{
|
||||
def binaryDependency(file: File, className: String) = callback.binaryDependency(file, className, sourceFile)
|
||||
val onSource = on.sourceFile
|
||||
println("\t" + on + ", src: " + onSource + ", class: " + classFile(on))
|
||||
if(onSource == null)
|
||||
{
|
||||
classFile(on) match
|
||||
|
|
@ -82,7 +84,6 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
}
|
||||
|
||||
private[this] final val classSeparator = '.'
|
||||
private[this] def findClass(name: String): Option[AbstractFile] = classPath.findClass(name).flatMap(_.binary.asInstanceOf[Option[AbstractFile]])
|
||||
private[this] def classFile(sym: Symbol): Option[(AbstractFile, String)] =
|
||||
{
|
||||
import scala.tools.nsc.symtab.Flags
|
||||
|
|
|
|||
|
|
@ -4,101 +4,227 @@
|
|||
package xsbt
|
||||
|
||||
import xsbti.{AnalysisCallback,Logger,Problem,Reporter,Severity}
|
||||
import scala.tools.nsc.{Phase, SubComponent}
|
||||
import xsbti.compile.{CachedCompiler, DependencyChanges}
|
||||
import scala.tools.nsc.{io, reporters, util, Phase, Global, Settings, SubComponent}
|
||||
import util.{ClassPath,DirectoryClassPath,MergedClassPath,JavaClassPath}
|
||||
import ClassPath.{ClassPathContext,JavaContext}
|
||||
import io.AbstractFile
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable
|
||||
import Log.debug
|
||||
import java.io.File
|
||||
|
||||
class CompilerInterface
|
||||
final class CompilerInterface
|
||||
{
|
||||
def run(args: Array[String], callback: AnalysisCallback, log: Logger, delegate: Reporter)
|
||||
def newCompiler(options: Array[String], initialLog: Logger, initialDelegate: Reporter): CachedCompiler =
|
||||
new CachedCompiler0(options, new WeakLog(initialLog, initialDelegate))
|
||||
def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, cached: CachedCompiler): Unit =
|
||||
cached.run(sources, changes, callback, log, delegate)
|
||||
}
|
||||
sealed abstract class CallbackGlobal(settings: Settings, reporter: reporters.Reporter) extends Global(settings, reporter) {
|
||||
def callback: AnalysisCallback
|
||||
def findClass(name: String): Option[AbstractFile]
|
||||
}
|
||||
class InterfaceCompileFailed(val arguments: Array[String], val problems: Array[Problem], override val toString: String) extends xsbti.CompileFailed
|
||||
|
||||
private final class WeakLog(private[this] var log: Logger, private[this] var delegate: Reporter)
|
||||
{
|
||||
def apply(message: String) {
|
||||
assert(log ne null, "Stale reference to logger")
|
||||
log.error(Message(message))
|
||||
}
|
||||
def logger: Logger = log
|
||||
def reporter: Reporter = delegate
|
||||
def clear() {
|
||||
log = null
|
||||
delegate = null
|
||||
}
|
||||
}
|
||||
|
||||
private final class CachedCompiler0(args: Array[String], initialLog: WeakLog) extends CachedCompiler
|
||||
{
|
||||
val settings = new Settings(s => initialLog(s))
|
||||
val command = Command(args.toList, settings)
|
||||
private[this] val dreporter = DelegatingReporter(settings, initialLog.reporter)
|
||||
try {
|
||||
compiler // force compiler internal structures
|
||||
if(!noErrors(dreporter)) {
|
||||
dreporter.printSummary()
|
||||
handleErrors(dreporter, initialLog.logger)
|
||||
}
|
||||
} finally
|
||||
initialLog.clear()
|
||||
|
||||
def noErrors(dreporter: DelegatingReporter) = !dreporter.hasErrors && command.ok
|
||||
|
||||
def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter): Unit = synchronized
|
||||
{
|
||||
import scala.tools.nsc.{Global, Settings}
|
||||
|
||||
println("Running cached compiler " + hashCode.toHexString)
|
||||
debug(log, "Interfacing (CompilerInterface) with Scala compiler " + scala.tools.nsc.Properties.versionString)
|
||||
|
||||
val settings = new Settings(Log.settingsError(log))
|
||||
val command = Command(args.toList, settings)
|
||||
val dreporter = DelegatingReporter(settings, delegate)
|
||||
def noErrors = !dreporter.hasErrors && command.ok
|
||||
|
||||
object compiler extends Global(command.settings, dreporter)
|
||||
{
|
||||
object dummy // temporary fix for #4426
|
||||
object sbtAnalyzer extends
|
||||
{
|
||||
val global: compiler.type = compiler
|
||||
val phaseName = Analyzer.name
|
||||
val runsAfter = List("jvm")
|
||||
override val runsBefore = List("terminal")
|
||||
val runsRightAfter = None
|
||||
}
|
||||
with SubComponent
|
||||
{
|
||||
val analyzer = new Analyzer(global, callback)
|
||||
def newPhase(prev: Phase) = analyzer.newPhase(prev)
|
||||
def name = phaseName
|
||||
}
|
||||
object apiExtractor extends
|
||||
{
|
||||
val global: compiler.type = compiler
|
||||
val phaseName = API.name
|
||||
val runsAfter = List("typer")
|
||||
override val runsBefore = List("erasure")
|
||||
val runsRightAfter = Some("typer")
|
||||
}
|
||||
with SubComponent
|
||||
{
|
||||
val api = new API(global, callback)
|
||||
def newPhase(prev: Phase) = api.newPhase(prev)
|
||||
def name = phaseName
|
||||
}
|
||||
|
||||
override lazy val phaseDescriptors =
|
||||
{
|
||||
phasesSet += sbtAnalyzer
|
||||
phasesSet += apiExtractor
|
||||
superComputePhaseDescriptors
|
||||
}
|
||||
// Required because computePhaseDescriptors is private in 2.8 (changed to protected sometime later).
|
||||
private def superComputePhaseDescriptors() =
|
||||
{
|
||||
val meth = classOf[Global].getDeclaredMethod("computePhaseDescriptors")
|
||||
meth.setAccessible(true)
|
||||
meth.invoke(this).asInstanceOf[List[SubComponent]]
|
||||
}
|
||||
def logUnreportedWarnings(seq: List[(Position,String)]): Unit = // Scala 2.10.x and later
|
||||
{
|
||||
for( (pos, msg) <- seq) yield
|
||||
callback.problem(dreporter.convert(pos), msg, Severity.Warn, false)
|
||||
}
|
||||
def logUnreportedWarnings(count: Boolean): Unit = () // for source compatibility with Scala 2.8.x
|
||||
def logUnreportedWarnings(count: Int): Unit = () // for source compatibility with Scala 2.9.x
|
||||
}
|
||||
def processUnreportedWarnings(run: compiler.Run)
|
||||
{
|
||||
implicit def listToBoolean[T](l: List[T]): Boolean = error("source compatibility only, should never be called")
|
||||
implicit def listToInt[T](l: List[T]): Int = error("source compatibility only, should never be called")
|
||||
compiler.logUnreportedWarnings(run.deprecationWarnings)
|
||||
compiler.logUnreportedWarnings(run.uncheckedWarnings)
|
||||
}
|
||||
try { run(sources.toList, changes, callback, log, dreporter) }
|
||||
finally { dreporter.dropDelegate() }
|
||||
}
|
||||
private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, dreporter: DelegatingReporter)
|
||||
{
|
||||
if(command.shouldStopWithInfo)
|
||||
{
|
||||
dreporter.info(null, command.getInfoMessage(compiler), true)
|
||||
throw new InterfaceCompileFailed(args, Array(), "Compiler option supplied that disabled actual compilation.")
|
||||
}
|
||||
if(noErrors)
|
||||
if(noErrors(dreporter))
|
||||
{
|
||||
val run = new compiler.Run
|
||||
debug(log, args.mkString("Calling Scala compiler with arguments (CompilerInterface):\n\t", "\n\t", ""))
|
||||
run compile command.files
|
||||
processUnreportedWarnings(run)
|
||||
compiler.set(callback, dreporter)
|
||||
try {
|
||||
val run = new compiler.Run
|
||||
compiler.reload(changes)
|
||||
val sortedSourceFiles = sources.map(_.getAbsolutePath).sortWith(_ < _)
|
||||
run compile sortedSourceFiles
|
||||
processUnreportedWarnings(run)
|
||||
} finally {
|
||||
compiler.clear()
|
||||
}
|
||||
dreporter.problems foreach { p => callback.problem(p.position, p.message, p.severity, true) }
|
||||
}
|
||||
dreporter.printSummary()
|
||||
if(!noErrors)
|
||||
{
|
||||
debug(log, "Compilation failed (CompilerInterface)")
|
||||
throw new InterfaceCompileFailed(args, dreporter.problems, "Compilation failed")
|
||||
}
|
||||
if(!noErrors(dreporter)) handleErrors(dreporter, log)
|
||||
}
|
||||
}
|
||||
class InterfaceCompileFailed(val arguments: Array[String], val problems: Array[Problem], override val toString: String) extends xsbti.CompileFailed
|
||||
def handleErrors(dreporter: DelegatingReporter, log: Logger): Nothing =
|
||||
{
|
||||
debug(log, "Compilation failed (CompilerInterface)")
|
||||
throw new InterfaceCompileFailed(args, dreporter.problems, "Compilation failed")
|
||||
}
|
||||
def processUnreportedWarnings(run: compiler.Run)
|
||||
{
|
||||
implicit def listToBoolean[T](l: List[T]): Boolean = error("source compatibility only, should never be called")
|
||||
implicit def listToInt[T](l: List[T]): Int = error("source compatibility only, should never be called")
|
||||
compiler.logUnreportedWarnings(run.deprecationWarnings)
|
||||
compiler.logUnreportedWarnings(run.uncheckedWarnings)
|
||||
}
|
||||
object compiler extends CallbackGlobal(command.settings, dreporter)
|
||||
{
|
||||
object dummy // temporary fix for #4426
|
||||
object sbtAnalyzer extends
|
||||
{
|
||||
val global: compiler.type = compiler
|
||||
val phaseName = Analyzer.name
|
||||
val runsAfter = List("jvm")
|
||||
override val runsBefore = List("terminal")
|
||||
val runsRightAfter = None
|
||||
}
|
||||
with SubComponent
|
||||
{
|
||||
val analyzer = new Analyzer(global)
|
||||
def newPhase(prev: Phase) = analyzer.newPhase(prev)
|
||||
def name = phaseName
|
||||
}
|
||||
object apiExtractor extends
|
||||
{
|
||||
val global: compiler.type = compiler
|
||||
val phaseName = API.name
|
||||
val runsAfter = List("typer")
|
||||
override val runsBefore = List("erasure")
|
||||
val runsRightAfter = Some("typer")
|
||||
}
|
||||
with SubComponent
|
||||
{
|
||||
val api = new API(global)
|
||||
def newPhase(prev: Phase) = api.newPhase(prev)
|
||||
def name = phaseName
|
||||
}
|
||||
|
||||
val out = new File(settings.outdir.value)
|
||||
override lazy val phaseDescriptors =
|
||||
{
|
||||
phasesSet += sbtAnalyzer
|
||||
phasesSet += apiExtractor
|
||||
superComputePhaseDescriptors
|
||||
}
|
||||
// Required because computePhaseDescriptors is private in 2.8 (changed to protected sometime later).
|
||||
private[this] def superComputePhaseDescriptors() = superCall("computePhaseDescriptors").asInstanceOf[List[SubComponent]]
|
||||
private[this] def superDropRun(): Unit = superCall("dropRun")
|
||||
private[this] def superCall(methodName: String): AnyRef =
|
||||
{
|
||||
val meth = classOf[Global].getDeclaredMethod(methodName)
|
||||
meth.setAccessible(true)
|
||||
meth.invoke(this)
|
||||
}
|
||||
def logUnreportedWarnings(seq: List[(Position,String)]): Unit = // Scala 2.10.x and later
|
||||
{
|
||||
for( (pos, msg) <- seq) yield
|
||||
callback.problem(reporter.asInstanceOf[DelegatingReporter].convert(pos), msg, Severity.Warn, false)
|
||||
}
|
||||
def logUnreportedWarnings(count: Boolean): Unit = () // for source compatibility with Scala 2.8.x
|
||||
def logUnreportedWarnings(count: Int): Unit = () // for source compatibility with Scala 2.9.x
|
||||
|
||||
def set(callback: AnalysisCallback, dreporter: DelegatingReporter)
|
||||
{
|
||||
this.callback0 = callback
|
||||
reporter = dreporter
|
||||
}
|
||||
def clear()
|
||||
{
|
||||
callback0 = null
|
||||
atPhase(currentRun.namerPhase) { forgetAll() }
|
||||
superDropRun()
|
||||
reporter = null
|
||||
}
|
||||
|
||||
override def registerTopLevelSym(sym: Symbol) = toForget += sym
|
||||
|
||||
def findClass(name: String): Option[AbstractFile] =
|
||||
getOutputClass(name) orElse findOnClassPath(name)
|
||||
|
||||
def getOutputClass(name: String): Option[AbstractFile] =
|
||||
{
|
||||
val f = new File(out, name.replace('.', '/') + ".class")
|
||||
if(f.exists) Some(AbstractFile.getFile(f)) else None
|
||||
}
|
||||
|
||||
def findOnClassPath(name: String): Option[AbstractFile] = classPath.findClass(name).flatMap(_.binary.asInstanceOf[Option[AbstractFile]])
|
||||
|
||||
final def unlinkAll(m: Symbol) {
|
||||
val scope = m.owner.info.decls
|
||||
scope unlink m
|
||||
scope unlink m.companionSymbol
|
||||
// if(scope.isEmpty && m.owner != definitions.EmptyPackageClass && m.owner != definitions.RootClass)
|
||||
// emptyPackages += m.owner
|
||||
}
|
||||
def reloadClass(pkg: Symbol, simpleName: String, bin: AbstractFile)
|
||||
{
|
||||
val loader = new loaders.ClassfileLoader(bin)
|
||||
toForget += loaders.enterClass(pkg, simpleName, loader)
|
||||
toForget += loaders.enterModule(pkg, simpleName, loader)
|
||||
}
|
||||
|
||||
def forgetAll()
|
||||
{
|
||||
for(sym <- toForget) {
|
||||
unlinkAll(sym)
|
||||
toReload.put(sym.fullName, (sym.owner, sym.name.toString))
|
||||
}
|
||||
toForget = mutable.Set()
|
||||
}
|
||||
|
||||
// fine-control over external changes is unimplemented:
|
||||
// must drop whole CachedCompiler when !changes.isEmpty
|
||||
def reload(changes: DependencyChanges)
|
||||
{
|
||||
for {
|
||||
(fullName,(pkg,simpleName)) <- toReload
|
||||
classFile <- getOutputClass(fullName)
|
||||
}
|
||||
reloadClass(pkg, simpleName, classFile)
|
||||
|
||||
toReload = newReloadMap()
|
||||
}
|
||||
|
||||
private [this] def newReloadMap() = mutable.Map[String,(Symbol,String)]()
|
||||
private[this] var emptyPackages = mutable.Set[Symbol]()
|
||||
private[this] var toReload = newReloadMap()
|
||||
private[this] var toForget = mutable.Set[Symbol]()
|
||||
private[this] var callback0: AnalysisCallback = null
|
||||
def callback: AnalysisCallback = callback0
|
||||
}
|
||||
}
|
||||
|
|
@ -15,10 +15,11 @@ private object DelegatingReporter
|
|||
// The following code is based on scala.tools.nsc.reporters.{AbstractReporter, ConsoleReporter}
|
||||
// Copyright 2002-2009 LAMP/EPFL
|
||||
// Original author: Martin Odersky
|
||||
private final class DelegatingReporter(warnFatal: Boolean, delegate: xsbti.Reporter) extends scala.tools.nsc.reporters.Reporter
|
||||
private final class DelegatingReporter(warnFatal: Boolean, private[this] var delegate: xsbti.Reporter) extends scala.tools.nsc.reporters.Reporter
|
||||
{
|
||||
import scala.tools.nsc.util.{FakePos,NoPosition,Position}
|
||||
|
||||
def dropDelegate() { delegate = null }
|
||||
def error(msg: String) { error(FakePos("scalac"), msg) }
|
||||
|
||||
def printSummary() = delegate.printSummary()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package xsbti.compile;
|
||||
|
||||
import xsbti.AnalysisCallback;
|
||||
import xsbti.Logger;
|
||||
import xsbti.Reporter;
|
||||
import java.io.File;
|
||||
|
||||
public interface CachedCompiler
|
||||
{
|
||||
public void run(File[] sources, DependencyChanges cpChanges, AnalysisCallback callback, Logger log, Reporter delegate);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package xsbti.compile;
|
||||
|
||||
import xsbti.Logger;
|
||||
import xsbti.Reporter;
|
||||
|
||||
public interface CachedCompilerProvider
|
||||
{
|
||||
ScalaInstance scalaInstance();
|
||||
CachedCompiler newCachedCompiler(String[] arguments, Logger log, Reporter reporter);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package xsbti.compile;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
// only includes changes to dependencies outside of the project
|
||||
public interface DependencyChanges
|
||||
{
|
||||
boolean isEmpty();
|
||||
// class files or jar files
|
||||
File[] modifiedBinaries();
|
||||
// class names
|
||||
String[] modifiedClasses();
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package xsbti.compile;
|
||||
|
||||
import xsbti.Logger;
|
||||
import xsbti.Reporter;
|
||||
|
||||
public interface GlobalsCache
|
||||
{
|
||||
public CachedCompiler apply(String[] args, boolean forceNew, CachedCompilerProvider provider, Logger log, Reporter reporter);
|
||||
public void clear();
|
||||
}
|
||||
|
|
@ -21,4 +21,6 @@ public interface Setup<Analysis>
|
|||
* This file can be removed to force a full recompilation.
|
||||
* The file should be unique and not shared between compilations. */
|
||||
File cacheFile();
|
||||
|
||||
GlobalsCache cache();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ object Defaults extends BuildCommon
|
|||
managedDirectory <<= baseDirectory(_ / "lib_managed")
|
||||
))
|
||||
def globalCore: Seq[Setting[_]] = inScope(GlobalScope)(defaultTestTasks(test) ++ defaultTestTasks(testOnly) ++ defaultTestTasks(testQuick) ++ Seq(
|
||||
compilerCache <<= state map { _ get Keys.stateCompilerCache getOrElse compiler.CompilerCache.fresh },
|
||||
crossVersion :== CrossVersion.Disabled,
|
||||
scalaOrganization :== ScalaArtifacts.Organization,
|
||||
buildDependencies <<= buildDependencies or Classpaths.constructBuildDependencies,
|
||||
|
|
@ -574,8 +575,8 @@ object Defaults extends BuildCommon
|
|||
|
||||
def compileTask = (compileInputs in compile, streams) map { (i,s) => Compiler(i,s.log) }
|
||||
def compileIncSetupTask =
|
||||
(dependencyClasspath, cacheDirectory, skip in compile, definesClass) map { (cp, cacheDir, skip, definesC) =>
|
||||
Compiler.IncSetup(analysisMap(cp), definesC, skip, cacheDir / "inc_compile")
|
||||
(dependencyClasspath, cacheDirectory, skip in compile, definesClass, compilerCache) map { (cp, cacheDir, skip, definesC, cache) =>
|
||||
Compiler.IncSetup(analysisMap(cp), definesC, skip, cacheDir / "inc_compile", cache)
|
||||
}
|
||||
def compileInputsSettings: Seq[Setting[_]] = {
|
||||
val optionsPair = TaskKey.local[(Seq[String], Seq[String])]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ package sbt
|
|||
import inc.Analysis
|
||||
import inc.Locate.DefinesClass
|
||||
import std.TaskExtra._
|
||||
import xsbti.compile.CompileOrder
|
||||
import xsbti.compile.{CompileOrder, GlobalsCache}
|
||||
import scala.xml.{Node => XNode, NodeSeq}
|
||||
import org.apache.ivy.core.module.{descriptor, id}
|
||||
import descriptor.ModuleDescriptor, id.ModuleRevisionId
|
||||
|
|
@ -153,6 +153,8 @@ object Keys
|
|||
val compile = TaskKey[Analysis]("compile", "Compiles sources.", APlusTask)
|
||||
val compilers = TaskKey[Compiler.Compilers]("compilers", "Defines the Scala and Java compilers to use for compilation.", DTask)
|
||||
val compileIncSetup = TaskKey[Compiler.IncSetup]("inc-compile-setup", "Configures aspects of incremental compilation.", DTask)
|
||||
val compilerCache = TaskKey[GlobalsCache]("compiler-cache", "Cache of scala.tools.nsc.Global instances. This should typically be cached so that it isn't recreated every task run.", DTask)
|
||||
val stateCompilerCache = AttributeKey[GlobalsCache]("compiler-cache", "Internal use: Global cache.")
|
||||
val definesClass = TaskKey[DefinesClass]("defines-class", "Internal use: provides a function that determines whether the provided file contains a given class.", Invisible)
|
||||
val doc = TaskKey[File]("doc", "Generates API documentation.", AMinusTask)
|
||||
val copyResources = TaskKey[Seq[(File,File)]]("copy-resources", "Copies resources to the output directory.", AMinusTask)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
package sbt
|
||||
|
||||
import complete.{DefaultParsers, Parser}
|
||||
import compiler.EvalImports
|
||||
import compiler.{CompilerCache,EvalImports}
|
||||
import Types.{const,idFun}
|
||||
import Aggregation.AnyKeys
|
||||
import Project.LoadAction
|
||||
|
|
@ -394,11 +394,27 @@ object BuiltinCommands
|
|||
def loadProjectImpl = Command(LoadProjectImpl)(_ => Project.loadActionParser)( doLoadProject )
|
||||
def doLoadProject(s0: State, action: LoadAction.Value): State =
|
||||
{
|
||||
val (s, base) = Project.loadAction(SessionVar.clear(s0), action)
|
||||
val (s1, base) = Project.loadAction(SessionVar.clear(s0), action)
|
||||
IO.createDirectory(base)
|
||||
val s = if(s1 has Keys.stateCompilerCache) s1 else registerCompilerCache(s1)
|
||||
val (eval, structure) = Load.defaultLoad(s, base, s.log, Project.inPluginProject(s), Project.extraBuilds(s))
|
||||
val session = Load.initialSession(structure, eval, s0)
|
||||
SessionSettings.checkSession(session, s)
|
||||
Project.setProject(session, structure, s)
|
||||
}
|
||||
def registerCompilerCache(s: State): State =
|
||||
{
|
||||
val maxCompilers = System.getProperty("sbt.resident.limit")
|
||||
val cache =
|
||||
if(maxCompilers == null)
|
||||
CompilerCache.fresh
|
||||
else
|
||||
{
|
||||
val num = try maxCompilers.toInt catch {
|
||||
case e: NumberFormatException => throw new RuntimeException("Resident compiler limit must be an integer.", e)
|
||||
}
|
||||
if(num <= 0) CompilerCache.fresh else CompilerCache(num)
|
||||
}
|
||||
s.put(Keys.stateCompilerCache, cache)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
package sbt
|
||||
|
||||
import xsbti.{Logger => _,_}
|
||||
import xsbti.compile.CompileOrder
|
||||
import xsbti.compile.{CompileOrder,GlobalsCache}
|
||||
import CompileOrder.{JavaThenScala, Mixed, ScalaThenJava}
|
||||
import compiler._
|
||||
import inc._
|
||||
|
|
@ -17,7 +17,7 @@ object Compiler
|
|||
|
||||
final case class Inputs(compilers: Compilers, config: Options, incSetup: IncSetup)
|
||||
final case class Options(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, order: CompileOrder)
|
||||
final case class IncSetup(analysisMap: File => Option[Analysis], definesClass: DefinesClass, skip: Boolean, cacheFile: File)
|
||||
final case class IncSetup(analysisMap: File => Option[Analysis], definesClass: DefinesClass, skip: Boolean, cacheFile: File, cache: GlobalsCache)
|
||||
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaTool)
|
||||
|
||||
@deprecated("Use the other inputs variant.", "0.12.0")
|
||||
|
|
@ -27,7 +27,7 @@ object Compiler
|
|||
val classesDirectory = outputDirectory / "classes"
|
||||
val cacheFile = outputDirectory / "cache_old_style"
|
||||
val augClasspath = classesDirectory.asFile +: classpath
|
||||
val incSetup = IncSetup(Map.empty, definesClass, false, cacheFile)
|
||||
val incSetup = IncSetup(Map.empty, definesClass, false, cacheFile, CompilerCache.fresh)
|
||||
inputs(augClasspath, sources, classesDirectory, options, javacOptions, maxErrors, order)(compilers, incSetup, log)
|
||||
}
|
||||
def inputs(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, order: CompileOrder)(implicit compilers: Compilers, incSetup: IncSetup, log: Logger): Inputs =
|
||||
|
|
@ -76,6 +76,6 @@ object Compiler
|
|||
import in.incSetup._
|
||||
|
||||
val agg = new AggressiveCompile(cacheFile)
|
||||
agg(scalac, javac, sources, classpath, classesDirectory, options, javacOptions, analysisMap, definesClass, maxErrors, order, skip)(log)
|
||||
agg(scalac, javac, sources, classpath, classesDirectory, cache, options, javacOptions, analysisMap, definesClass, maxErrors, order, skip)(log)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,13 @@ package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtr
|
|||
type File = java.io.File
|
||||
type URI = java.net.URI
|
||||
type URL = java.net.URL
|
||||
|
||||
object CompileOrder {
|
||||
val JavaThenScala = xsbti.compile.CompileOrder.JavaThenScala
|
||||
val ScalaThenJava = xsbti.compile.CompileOrder.ScalaThenJava
|
||||
val Mixed = xsbti.compile.CompileOrder.Mixed
|
||||
}
|
||||
type CompileOrder = xsbti.compile.CompileOrder
|
||||
val JavaThenScala = xsbti.compile.CompileOrder.JavaThenScala
|
||||
val ScalaThenJava = xsbti.compile.CompileOrder.ScalaThenJava
|
||||
val Mixed = xsbti.compile.CompileOrder.Mixed
|
||||
|
||||
implicit def maybeToOption[S](m: xsbti.Maybe[S]): Option[S] =
|
||||
if(m.isDefined) Some(m.get) else None
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
package example
|
||||
|
||||
object A
|
||||
{
|
||||
val x: Int = 3
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
package example
|
||||
|
||||
object A
|
||||
{
|
||||
val x: Int = B.y
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
package example
|
||||
|
||||
object A
|
||||
{
|
||||
val x: String = B.y
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
package example
|
||||
|
||||
object B
|
||||
{
|
||||
val y: String = "4"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
package example
|
||||
|
||||
object B
|
||||
{
|
||||
val y: Int = 5
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
package clear
|
||||
|
||||
object A
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
package clear
|
||||
|
||||
object A
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
package clear
|
||||
|
||||
object B
|
||||
|
|
|
|||
Loading…
Reference in New Issue