using some of the embedding interfaces

This commit is contained in:
Mark Harrah 2012-01-09 08:00:35 -05:00
parent 4a53ace752
commit d837f869bd
14 changed files with 74 additions and 44 deletions

View File

@ -3,7 +3,7 @@
*/
package sbt
final case class ClasspathOptions(bootLibrary: Boolean, compiler: Boolean, extra: Boolean, autoBoot: Boolean, filterLibrary: Boolean)
final case class ClasspathOptions(bootLibrary: Boolean, compiler: Boolean, extra: Boolean, autoBoot: Boolean, filterLibrary: Boolean) extends xsbti.compile.ClasspathOptions
object ClasspathOptions
{
def manual = ClasspathOptions(false, false, false, true, false)

View File

@ -9,14 +9,25 @@ import java.io.{File, PrintWriter}
abstract class JavacContract(val name: String, val clazz: String) {
def exec(args: Array[String], writer: PrintWriter): Int
}
trait JavaCompiler
trait JavaCompiler extends xsbti.compile.JavaCompiler
{
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) {
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger)
def compile(sources: Array[File], classpath: Array[File], outputDirectory: File, options: Array[String], maxErrors: Int, log: xsbti.Logger): Unit =
apply(sources, classpath, outputDirectory, options)(log)
}
trait Javadoc
{
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger)
}
trait JavaTool extends Javadoc with JavaCompiler
{
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) =
compile(JavaCompiler.javac, sources, classpath, outputDirectory, options)(log)
}
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger) {
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger) =
compile(JavaCompiler.javadoc, sources, classpath, outputDirectory, options)(log)
}
def compile(contract: JavacContract, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger): Unit
}
object JavaCompiler
@ -36,8 +47,8 @@ object JavaCompiler
}
}
def construct(f: Fork, cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler =
new JavaCompiler {
def construct(f: Fork, cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaTool =
new JavaTool {
def compile(contract: JavacContract, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) {
val augmentedClasspath = if(cp.autoBoot) classpath ++ Seq(scalaInstance.libraryJar) else classpath
val javaCp = ClasspathOptions.javac(cp.compiler)
@ -48,13 +59,13 @@ object JavaCompiler
if( code != 0 ) throw new CompileFailed(arguments.toArray, contract.name + " returned nonzero exit code")
}
}
def directOrFork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaCompiler =
def directOrFork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaTool =
construct(directOrForkJavac, cp, scalaInstance)
def direct(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler =
def direct(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaTool =
construct(directJavac, cp, scalaInstance)
def fork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaCompiler =
def fork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaTool =
construct(forkJavac, cp, scalaInstance)
def directOrForkJavac(implicit doFork: Fork) = (contract: JavacContract, arguments: Seq[String], log: Logger) =>

View File

@ -3,24 +3,20 @@
*/
package sbt
import xsbti.compile.CompileOrder
import java.io.File
object CompileOrder extends Enumeration
{
val Mixed, JavaThenScala, ScalaThenJava = Value
}
// this class exists because of Scala's restriction on implicit parameter search.
// We cannot require an implicit parameter Equiv[Seq[String]] to construct Equiv[CompileSetup]
// because complexity(Equiv[Seq[String]]) > complexity(Equiv[CompileSetup])
// (6 > 4)
final class CompileOptions(val options: Seq[String], val javacOptions: Seq[String])
final class CompileSetup(val outputDirectory: File, val options: CompileOptions, val compilerVersion: String, val order: CompileOrder.Value)
final class CompileSetup(val outputDirectory: File, val options: CompileOptions, val compilerVersion: String, val order: CompileOrder)
object CompileSetup
{
// Equiv[CompileOrder.Value] dominates Equiv[CompileSetup]
implicit def equivCompileSetup(implicit equivFile: Equiv[File], equivOpts: Equiv[CompileOptions], equivComp: Equiv[String]/*, equivOrder: Equiv[CompileOrder.Value]*/): Equiv[CompileSetup] = new Equiv[CompileSetup] {
implicit def equivCompileSetup(implicit equivFile: Equiv[File], equivOpts: Equiv[CompileOptions], equivComp: Equiv[String]/*, equivOrder: Equiv[CompileOrder]*/): Equiv[CompileSetup] = new Equiv[CompileSetup] {
def equiv(a: CompileSetup, b: CompileSetup) =
equivFile.equiv(a.outputDirectory, b.outputDirectory) &&
equivOpts.equiv(a.options, b.options) &&
@ -39,7 +35,7 @@ object CompileSetup
def equiv(a: String, b: String) = a == b
}
implicit val equivOrder: Equiv[CompileOrder.Value] = new Equiv[CompileOrder.Value] {
def equiv(a: CompileOrder.Value, b: CompileOrder.Value) = a == b
implicit val equivOrder: Equiv[CompileOrder] = new Equiv[CompileOrder] {
def equiv(a: CompileOrder, b: CompileOrder) = a == b
}
}

View File

@ -10,11 +10,13 @@ import inc._
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 CompileOrder.{JavaThenScala, Mixed, ScalaThenJava}
import sbinary.DefaultProtocol.{ immutableMapFormat, immutableSetFormat, StringFormat }
import Types.const
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,
@ -22,7 +24,7 @@ final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File
class AggressiveCompile(cacheFile: File)
{
def apply(compiler: AnalyzingCompiler, javac: JavaCompiler, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String] = Nil, javacOptions: Seq[String] = Nil, analysisMap: Map[File, Analysis] = Map.empty, definesClass: DefinesClass = Locate.definesClass _, maxErrors: Int = 100, compileOrder: CompileOrder.Value = Mixed, skip: Boolean = false)(implicit log: Logger): Analysis =
def apply(compiler: AnalyzingCompiler, javac: 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 =
{
val setup = new CompileSetup(outputDirectory, new CompileOptions(options, javacOptions), compiler.scalaInstance.actualVersion, compileOrder)
compile1(sources, classpath, setup, store, analysisMap, definesClass, compiler, javac, maxErrors, skip)
@ -31,13 +33,13 @@ class AggressiveCompile(cacheFile: File)
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: Map[File, Analysis], definesClass: DefinesClass, compiler: AnalyzingCompiler, javac: 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: JavaCompiler, maxErrors: Int, skip: Boolean)(implicit log: Logger): Analysis =
{
val (previousAnalysis, previousSetup) = extract(store.get())
if(skip)
previousAnalysis
else {
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup, analysis.get _, definesClass, maxErrors, compiler, javac)
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup, analysis, definesClass, maxErrors, compiler, javac)
val (modified, result) = compile2(config)
if(modified)
store.set(result, setup)
@ -122,7 +124,7 @@ object AggressiveCompile
}
}
def directOrFork(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File]): JavaCompiler =
def directOrFork(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File]): JavaTool =
if(javaHome.isDefined)
JavaCompiler.fork(cpOptions, instance)(forkJavac(javaHome))
else

View File

@ -6,6 +6,7 @@ package inc
import xsbti.api.Source
import xsbti.{Position,Problem,Severity}
import xsbti.compile.CompileOrder
import java.io.File
import sbinary._
import DefaultProtocol._
@ -63,8 +64,8 @@ object AnalysisFormats
wrap[Severity, Byte]( _.ordinal.toByte, b => Severity.values.apply(b.toInt) )
implicit def setupFormat(implicit outDirF: Format[File], optionF: Format[CompileOptions], compilerVersion: Format[String], orderF: Format[CompileOrder.Value]): Format[CompileSetup] =
asProduct4[CompileSetup, File, CompileOptions, String, CompileOrder.Value]( (a,b,c,d) => new CompileSetup(a,b,c,d) )(s => (s.outputDirectory, s.options, s.compilerVersion, s.order))(outDirF, optionF, compilerVersion, orderF)
implicit def setupFormat(implicit outDirF: Format[File], optionF: Format[CompileOptions], compilerVersion: Format[String], orderF: Format[CompileOrder]): Format[CompileSetup] =
asProduct4[CompileSetup, File, CompileOptions, String, CompileOrder]( (a,b,c,d) => new CompileSetup(a,b,c,d) )(s => (s.outputDirectory, s.options, s.compilerVersion, s.order))(outDirF, optionF, compilerVersion, orderF)
implicit def stampsFormat(implicit prodF: Format[Map[File, Stamp]], srcF: Format[Map[File, Stamp]], binF: Format[Map[File, Stamp]], nameF: Format[Map[File, String]]): Format[Stamps] =
asProduct4( Stamps.apply _ )( s => (s.products, s.sources, s.binaries, s.classNames) )(prodF, srcF, binF, nameF)
@ -88,7 +89,11 @@ object AnalysisFormats
implicit def optsFormat(implicit strF: Format[String]): Format[CompileOptions] =
wrap[CompileOptions, (Seq[String],Seq[String])](co => (co.options, co.javacOptions), os => new CompileOptions(os._1, os._2))
implicit val orderFormat: Format[CompileOrder.Value] = enumerationFormat(CompileOrder)
implicit val orderFormat: Format[CompileOrder] =
{
val values = CompileOrder.values
wrap[CompileOrder, Int](_.ordinal, values)
}
implicit def seqFormat[T](implicit optionFormat: Format[T]): Format[Seq[T]] = viaSeq[Seq[T], T](x => x)
implicit def hashStampFormat: Format[Hash] = wrap[Hash, Array[Byte]](_.value, new Hash(_))

View File

@ -24,10 +24,10 @@ public interface ScalaInstance
File compilerJar();
/** Jars provided by this Scala instance other than the compiler and library jars. */
File[] extraJars();
File[] otherJars();
/** All jar files provided by this Scala instance.*/
File[] jars();
File[] allJars();
/** The unique identifier for this Scala instance. An implementation should usually obtain this from the compiler.properties file in the compiler jar. */
String actualVersion();

View File

@ -6,6 +6,7 @@ package sbt
import Build.data
import Scope.{fillTaskAxis, GlobalScope, ThisScope}
import xsbt.api.Discovery
import xsbti.compile.CompileOrder
import Project.{inConfig, Initialize, inScope, inTask, ScopedKey, Setting, SettingsDefinition}
import Load.LoadedBuild
import Artifact.{DocClassifier, SourceClassifier}
@ -43,8 +44,11 @@ object Defaults extends BuildCommon
def extractAnalysis[T](a: Attributed[T]): (T, inc.Analysis) =
(a.data, a.metadata get Keys.analysis getOrElse inc.Analysis.Empty)
def analysisMap[T](cp: Seq[Attributed[T]]): Map[T, inc.Analysis] =
(for(a <- cp; an <- a.metadata get Keys.analysis) yield (a.data, an) ).toMap
def analysisMap[T](cp: Seq[Attributed[T]]): T => Option[inc.Analysis] =
{
val m = (for(a <- cp; an <- a.metadata get Keys.analysis) yield (a.data, an) ).toMap
m.get _
}
def buildCore: Seq[Setting[_]] = thisBuildCore ++ globalCore
def thisBuildCore: Seq[Setting[_]] = inScope(GlobalScope.copy(project = Select(ThisBuild)))(Seq(

View File

@ -10,6 +10,7 @@ package sbt
import inc.Analysis
import inc.Locate.DefinesClass
import std.TaskExtra._
import xsbti.compile.CompileOrder
import scala.xml.{Node => XNode, NodeSeq}
import org.apache.ivy.core.module.{descriptor, id}
import descriptor.ModuleDescriptor, id.ModuleRevisionId
@ -129,7 +130,7 @@ object Keys
val scaladocOptions = TaskKey[Seq[String]]("scaladoc-options", "Options for Scaladoc.", DTask)
val scalacOptions = TaskKey[Seq[String]]("scalac-options", "Options for the Scala compiler.", BPlusTask)
val javacOptions = TaskKey[Seq[String]]("javac-options", "Options for the Java compiler.", BPlusTask)
val compileOrder = SettingKey[CompileOrder.Value]("compile-order", "Configures the order in which Java and sources within a single compilation are compiled. Valid values are: JavaThenScala, ScalaThenJava, or Mixed.", BPlusSetting)
val compileOrder = SettingKey[CompileOrder]("compile-order", "Configures the order in which Java and sources within a single compilation are compiled. Valid values are: JavaThenScala, ScalaThenJava, or Mixed.", BPlusSetting)
val initialCommands = SettingKey[String]("initial-commands", "Initial commands to execute when starting up the Scala interpreter.", AMinusSetting)
val cleanupCommands = SettingKey[String]("cleanup-commands", "Commands to execute before the Scala interpreter exits.", BMinusSetting)
val compileInputs = TaskKey[Compiler.Inputs]("compile-inputs", "Collects all inputs needed for compilation.", DTask)

View File

@ -7,6 +7,7 @@ package sbt
import java.net.{URI,URL}
import compiler.{Eval,EvalImports}
import xsbt.api.{Discovered,Discovery}
import xsbti.compile.CompileOrder
import classpath.ClasspathUtilities
import scala.annotation.tailrec
import collection.mutable

View File

@ -4,6 +4,8 @@
package sbt
import xsbti.{Logger => _,_}
import xsbti.compile.CompileOrder
import CompileOrder.{JavaThenScala, Mixed, ScalaThenJava}
import compiler._
import inc._
import Locate.DefinesClass
@ -14,12 +16,12 @@ object Compiler
val DefaultMaxErrors = 100
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.Value)
final case class IncSetup(analysisMap: Map[File, Analysis], definesClass: DefinesClass, skip: Boolean, cacheFile: File)
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaCompiler)
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 Compilers(scalac: AnalyzingCompiler, javac: JavaTool)
@deprecated("Use the other inputs variant.", "0.12.0")
def inputs(classpath: Seq[File], sources: Seq[File], outputDirectory: File, options: Seq[String], javacOptions: Seq[String], definesClass: DefinesClass, maxErrors: Int, order: CompileOrder.Value)(implicit compilers: Compilers, log: Logger): Inputs =
def inputs(classpath: Seq[File], sources: Seq[File], outputDirectory: File, options: Seq[String], javacOptions: Seq[String], definesClass: DefinesClass, maxErrors: Int, order: CompileOrder)(implicit compilers: Compilers, log: Logger): Inputs =
{
import Path._
val classesDirectory = outputDirectory / "classes"
@ -28,7 +30,7 @@ object Compiler
val incSetup = IncSetup(Map.empty, definesClass, false, cacheFile)
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.Value)(implicit compilers: Compilers, incSetup: IncSetup, log: Logger): Inputs =
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 =
new Inputs(
compilers,
new Options(classpath, sources, classesDirectory, options, javacOptions, maxErrors, order),
@ -54,7 +56,7 @@ object Compiler
val javaCompiler = JavaCompiler.fork(cpOptions, instance)(javac)
compilers(instance, cpOptions, javaCompiler)
}
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: JavaCompiler)(implicit app: AppConfiguration, log: Logger): Compilers =
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: JavaTool)(implicit app: AppConfiguration, log: Logger): Compilers =
{
val scalac = scalaCompiler(instance, cpOptions)
new Compilers(scalac, javac)

View File

@ -17,7 +17,7 @@ package sbt
object Doc {
def apply(maximumErrors: Int, compiler: AnalyzingCompiler) = new Scaladoc(maximumErrors, compiler)
def apply(maximumErrors: Int, compiler: JavaCompiler) = new Javadoc(maximumErrors, compiler)
def apply(maximumErrors: Int, compiler: sbt.compiler.Javadoc) = new Javadoc(maximumErrors, compiler)
}
sealed trait Doc {
type Gen = (Seq[File], Seq[File], File, Seq[String], Int, Logger) => Unit
@ -62,11 +62,11 @@ final class Scaladoc(maximumErrors: Int, compiler: AnalyzingCompiler) extends Do
generate("Scala", label, compiler.doc, sources, classpath, outputDirectory, options, maximumErrors, log)
}
}
final class Javadoc(maximumErrors: Int, compiler: JavaCompiler) extends Doc
final class Javadoc(maximumErrors: Int, doc: sbt.compiler.Javadoc) extends Doc
{
def apply(label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger)
{
// javadoc doesn't handle *.scala properly, so we evict them from javadoc sources list.
generate("Java", label, compiler.doc, sources.filterNot(_.name.endsWith(".scala")), classpath, outputDirectory, options, maximumErrors, log)
generate("Java", label, doc.doc, sources.filterNot(_.name.endsWith(".scala")), classpath, outputDirectory, options, maximumErrors, log)
}
}

View File

@ -58,7 +58,7 @@ object Sbt extends Build
// Path, IO (formerly FileUtilities), NameFilter and other I/O utility classes
lazy val ioSub = testedBaseProject(utilPath / "io", "IO") dependsOn(controlSub)
// Utilities related to reflection, managing Scala versions, and custom class loaders
lazy val classpathSub = baseProject(utilPath / "classpath", "Classpath") dependsOn(launchInterfaceSub, ioSub) settings(scalaCompiler)
lazy val classpathSub = baseProject(utilPath / "classpath", "Classpath") dependsOn(launchInterfaceSub, interfaceSub, ioSub) settings(scalaCompiler)
// Command line-related utilities.
lazy val completeSub = testedBaseProject(utilPath / "complete", "Completion") dependsOn(collectionSub, controlSub, ioSub) settings(jline)
// logging

View File

@ -20,6 +20,10 @@ 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
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

View File

@ -10,8 +10,12 @@ package sbt
* for the compiler itself.
* The 'version' field is the version used to obtain the Scala classes. This is typically the version for the maven repository.
* The 'actualVersion' field should be used to uniquely identify the compiler. It is obtained from the compiler.properties file.*/
final class ScalaInstance(val version: String, val loader: ClassLoader, val libraryJar: File, val compilerJar: File, val extraJars: Seq[File], val explicitActual: Option[String])
final class ScalaInstance(val version: String, val loader: ClassLoader, val libraryJar: File, val compilerJar: File, val extraJars: Seq[File], val explicitActual: Option[String]) extends xsbti.compile.ScalaInstance
{
// These are to implement xsbti.ScalaInstance
def otherJars: Array[File] = extraJars.toArray
def allJars: Array[File] = jars.toArray
require(version.indexOf(' ') < 0, "Version cannot contain spaces (was '" + version + "')")
def jars = libraryJar :: compilerJar :: extraJars.toList
/** Gets the version of Scala in the compiler.properties file from the loader. This version may be different than that given by 'version'*/