Fix Compiler.compilers

This commit is contained in:
Eugene Yokota 2015-09-14 21:59:36 -04:00
parent 076ccd7b90
commit 21a027c487
5 changed files with 99 additions and 87 deletions

View File

@ -13,12 +13,15 @@ import Locate.DefinesClass
import java.io.File
import sbt.internal.librarymanagement.{ ComponentManager, IvyConfiguration }
import sbt.librarymanagement.ModuleID
import sbt.librarymanagement.{ ModuleID, CrossVersion }
import sbt.util.Logger
object Compiler {
val DefaultMaxErrors = 100
private[sbt] def scalaCompilerBridgeSource(sbtver: String): ModuleID =
ModuleID(xsbti.ArtifactInfo.SbtOrganization, "compiler-bridge", sbtver, Some("component")).cross(CrossVersion.binary).sources()
/** Inputs necessary to run the incremental compiler. */
final case class Inputs(compilers: Compilers, config: Options, incSetup: IncSetup)
/** The inputs for the copiler *and* the previous analysis of source dependecnies. */
@ -29,13 +32,8 @@ object Compiler {
def newJavac: IncrementalCompilerJavaTools
}
/** The instances of Scalac/Javac used to compile the current project. */
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaTool) {
final def newJavac: Option[IncrementalCompilerJavaTools] =
javac match {
case x: JavaToolWithNewInterface => Some(x.newJavac)
case _ => None
}
}
final case class Compilers(scalac: AnalyzingCompiler, javac: IncrementalCompilerJavaTools)
/** The previous source dependency analysis result from compilation. */
final case class PreviousAnalysis(analysis: Analysis, setup: Option[CompileSetup])
type CompileResult = IC.Result
@ -49,15 +47,6 @@ object Compiler {
incSetup
)
// def compilers(cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
// {
// val scalaProvider = app.provider.scalaProvider
// compilers(ScalaInstance(scalaProvider.version, scalaProvider.launcher), cpOptions)
// }
// def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
// compilers(instance, cpOptions, None)
// @deprecated("Use `compilers(ScalaInstance, ClasspathOptions, Option[File], IvyConfiguration)`.", "0.13.10")
// def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File])(implicit app: AppConfiguration, log: Logger): Compilers =
// {
@ -109,10 +98,22 @@ object Compiler {
// new AnalyzingCompiler(instance, provider, cpOptions)
// }
def compilers(cpOptions: ClasspathOptions, ivyConfiguration: IvyConfiguration)(implicit app: AppConfiguration, log: Logger): Compilers =
{
val scalaProvider = app.provider.scalaProvider
val instance = ScalaInstance(scalaProvider.version, scalaProvider.launcher)
val sourceModule = scalaCompilerBridgeSource(app.provider.id.version)
compilers(instance, cpOptions, None, ivyConfiguration, sourceModule)
}
// def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
// compilers(instance, cpOptions, None)
// TODO: Get java compiler
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File], ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID)(implicit app: AppConfiguration, log: Logger): Compilers = {
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File],
ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID)(implicit app: AppConfiguration, log: Logger): Compilers = {
val scalac = scalaCompiler(instance, cpOptions, javaHome, ivyConfiguration, sourcesModule)
val javac = ???
val javac = JavaTools.directOrFork(instance, cpOptions, javaHome)
new Compilers(scalac, javac)
}
def scalaCompiler(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File], ivyConfiguration: IvyConfiguration, sourcesModule: ModuleID)(implicit app: AppConfiguration, log: Logger): AnalyzingCompiler =
@ -123,26 +124,6 @@ object Compiler {
new AnalyzingCompiler(instance, provider, cpOptions)
}
// @deprecated("Use the `compile` method instead.", "0.13.8")
// def apply(in: Inputs, log: Logger): Analysis = {
// import in.config._
// apply(in, log, new LoggerReporter(maxErrors, log, sourcePositionMapper))
// }
// @deprecated("Use the `compile` method instead.", "0.13.8")
// def apply(in: Inputs, log: Logger, reporter: xsbti.Reporter): Analysis = {
// import in.compilers._
// import in.config._
// import in.incSetup._
// // Here we load the previous analysis since the new paths don't.
// val (previousAnalysis, previousSetup) = {
// MixedAnalyzingCompiler.staticCachedStore(cacheFile).get().map {
// case (a, s) => (a, Some(s))
// } getOrElse {
// (Analysis.empty(nameHashing = incOptions.nameHashing), None)
// }
// }
// compile(InputsWithPrevious(in, PreviousAnalysis(previousAnalysis, previousSetup)), log, reporter).analysis
// }
def compile(in: InputsWithPrevious, log: Logger): CompileResult =
{
import in.inputs.config._
@ -157,7 +138,7 @@ object Compiler {
// than the previously defined versions.
// TODO - Remove this hackery in sbt 1.0.
val javacChosen: xsbti.compile.JavaCompiler =
in.inputs.compilers.newJavac.map(_.xsbtiCompiler).getOrElse(in.inputs.compilers.javac)
in.inputs.compilers.javac.xsbtiCompiler // ).getOrElse(in.inputs.compilers.javac)
// TODO - Why are we not using the IC interface???
IC.incrementalCompile(scalac, javacChosen, sources, classpath, CompileOutput(classesDirectory), cache, None, options, javacOptions,
in.previousAnalysis.analysis, in.previousAnalysis.setup, analysisMap, definesClass, reporter, order, skip, incOptions)(log)

View File

@ -16,6 +16,7 @@ import sbt.internal.util.Cache.{ defaultEquiv, hConsCache, hNilCache, seqCache,
import sbt.internal.util.Tracked.{ inputChanged, outputChanged }
import sbt.internal.util.{ FilesInfo, HashFileInfo, HNil, ModifiedFileInfo, PlainFileInfo }
import sbt.internal.util.FilesInfo.{ exists, hash, lastModified }
import xsbti.Reporter
import sbt.util.Logger
@ -25,26 +26,42 @@ object Doc {
scaladoc(label, cache, compiler, Seq())
def scaladoc(label: String, cache: File, compiler: AnalyzingCompiler, fileInputOptions: Seq[String]): Gen =
cached(cache, fileInputOptions, prepare(label + " Scala API documentation", compiler.doc))
def javadoc(label: String, cache: File, doc: sbt.compiler.Javadoc): Gen =
javadoc(label, cache, doc, Seq())
def javadoc(label: String, cache: File, doc: sbt.compiler.Javadoc, fileInputOptions: Seq[String]): Gen =
cached(cache, fileInputOptions, prepare(label + " Java API documentation", filterSources(javaSourcesOnly, doc.doc)))
def javadoc(label: String, cache: File, doc: sbt.compiler.javac.JavaTools, log: Logger, reporter: Reporter): Gen =
javadoc(label, cache, doc, log, reporter, Seq())
def javadoc(label: String, cache: File, doc: sbt.compiler.javac.JavaTools, log: Logger, reporter: Reporter, fileInputOptions: Seq[String]): Gen =
cached(cache, fileInputOptions, prepare(label + " Java API documentation", filterSources(javaSourcesOnly,
(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maxErrors: Int, log: Logger) => {
// doc.doc
???
})))
val javaSourcesOnly: File => Boolean = _.getName.endsWith(".java")
@deprecated("Use `scaladoc`", "0.13.0")
def apply(maximumErrors: Int, compiler: AnalyzingCompiler) = new Scaladoc(maximumErrors, compiler)
// @deprecated("Use `scaladoc`", "0.13.0")
// def apply(maximumErrors: Int, compiler: AnalyzingCompiler) = new Scaladoc(maximumErrors, compiler)
@deprecated("Use `javadoc`", "0.13.0")
def apply(maximumErrors: Int, compiler: sbt.compiler.Javadoc) = new Javadoc(maximumErrors, compiler)
// @deprecated("Use `javadoc`", "0.13.0")
// def apply(maximumErrors: Int, compiler: sbt.compiler.Javadoc) = new Javadoc(maximumErrors, compiler)
private[sbt] final class Scaladoc(maximumErrors: Int, compiler: AnalyzingCompiler) extends Doc {
def apply(label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger) {
generate("Scala", label, compiler.doc, sources, classpath, outputDirectory, options, maximumErrors, log)
}
}
private[sbt] 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, doc.doc, sources.filterNot(_.name.endsWith(".scala")), classpath, outputDirectory, options, maximumErrors, log)
}
}
}
@deprecated("No longer used. See `Doc.javadoc` or `Doc.scaladoc`", "0.13.0")
// @deprecated("No longer used. See `Doc.javadoc` or `Doc.scaladoc`", "0.13.0")
sealed trait Doc {
type Gen = (Seq[File], Seq[File], File, Seq[String], Int, Logger) => Unit
def apply(label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger): Unit
// def apply(label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger): Unit
final def generate(variant: String, label: String, docf: Gen, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maxErrors: Int, log: Logger) {
private[sbt] final def generate(variant: String, label: String, docf: Gen, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maxErrors: Int, log: Logger) {
val logSnip = variant + " API documentation"
if (sources.isEmpty)
log.info("No sources available, skipping " + logSnip + "...")
@ -57,32 +74,19 @@ sealed trait Doc {
}
}
def cached(cache: File, label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger) {
type Inputs = FilesInfo[HashFileInfo] :+: FilesInfo[ModifiedFileInfo] :+: String :+: File :+: Seq[String] :+: HNil
val inputs: Inputs = hash(sources.toSet) :+: lastModified(classpath.toSet) :+: classpath.absString :+: outputDirectory :+: options :+: HNil
implicit val stringEquiv: Equiv[String] = defaultEquiv
implicit val fileEquiv: Equiv[File] = defaultEquiv
val cachedDoc = inputChanged(cache / "inputs") { (inChanged, in: Inputs) =>
outputChanged(cache / "output") { (outChanged, outputs: FilesInfo[PlainFileInfo]) =>
if (inChanged || outChanged)
apply(label, sources, classpath, outputDirectory, options, log)
else
log.debug("Doc uptodate: " + outputDirectory.getAbsolutePath)
}
}
cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet))
}
}
@deprecated("No longer used. See `Doc.scaladoc`", "0.13.0")
final class Scaladoc(maximumErrors: Int, compiler: AnalyzingCompiler) extends Doc {
def apply(label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger) {
generate("Scala", label, compiler.doc, sources, classpath, outputDirectory, options, maximumErrors, log)
}
}
@deprecated("No longer used. See `Doc.javadoc`", "0.13.0")
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, doc.doc, sources.filterNot(_.name.endsWith(".scala")), classpath, outputDirectory, options, maximumErrors, log)
}
// def cached(cache: File, label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger) {
// type Inputs = FilesInfo[HashFileInfo] :+: FilesInfo[ModifiedFileInfo] :+: String :+: File :+: Seq[String] :+: HNil
// val inputs: Inputs = hash(sources.toSet) :+: lastModified(classpath.toSet) :+: classpath.absString :+: outputDirectory :+: options :+: HNil
// implicit val stringEquiv: Equiv[String] = defaultEquiv
// implicit val fileEquiv: Equiv[File] = defaultEquiv
// val cachedDoc = inputChanged(cache / "inputs") { (inChanged, in: Inputs) =>
// outputChanged(cache / "output") { (outChanged, outputs: FilesInfo[PlainFileInfo]) =>
// if (inChanged || outChanged)
// apply(label, sources, classpath, outputDirectory, options, log)
// else
// log.debug("Doc uptodate: " + outputDirectory.getAbsolutePath)
// }
// }
// cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet))
// }
}

View File

@ -5,6 +5,8 @@ package sbt
import sbt.util.Logger
import java.io.File
import sbt.librarymanagement.Resolver
import sbt.internal.librarymanagement.{ InlineIvyConfiguration, IvyPaths }
object ConsoleProject {
def apply(state: State, extra: String, cleanupCommands: String = "", options: Seq[String] = Nil)(implicit log: Logger): Unit = {
@ -12,8 +14,13 @@ object ConsoleProject {
val cpImports = new Imports(extracted, state)
val bindings = ("currentState" -> state) :: ("extracted" -> extracted) :: ("cpHelpers" -> cpImports) :: Nil
val unit = extracted.currentUnit
// TODO: Fix this
val compiler: sbt.compiler.AnalyzingCompiler = ??? //Compiler.compilers(ClasspathOptions.repl)(state.configuration, log).scalac
val localOnly = false
val lock = None
val checksums = Nil
val ivyPaths = new IvyPaths(unit.unit.localBase, bootIvyHome(state.configuration))
val ivyConfiguration = new InlineIvyConfiguration(ivyPaths, Resolver.withDefaultResolvers(Nil),
Nil, Nil, localOnly, lock, checksums, None, log)
val compiler: sbt.compiler.AnalyzingCompiler = Compiler.compilers(ClasspathOptions.repl, ivyConfiguration)(state.configuration, log).scalac
val imports = BuildUtil.getImports(unit.unit) ++ BuildUtil.importAll(bindings.map(_._1))
val importString = imports.mkString("", ";\n", ";\n\n")
val initCommands = importString + extra
@ -29,4 +36,7 @@ object ConsoleProject {
implicit def settingKeyEvaluate[T](s: SettingKey[T]): Evaluate[T] = new Evaluate(get(s))
}
final class Evaluate[T] private[sbt] (val eval: T)
private def bootIvyHome(app: xsbti.AppConfiguration): Option[File] =
try { Option(app.provider.scalaProvider.launcher.ivyHome) }
catch { case _: NoSuchMethodError => None }
}

View File

@ -246,7 +246,7 @@ object Defaults extends BuildCommon {
val _ = clean.value
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
},
scalaCompilerBridgeSource := ModuleID(xsbti.ArtifactInfo.SbtOrganization, "compiler-interface", sbtVersion.value, Some("component")).sources()
scalaCompilerBridgeSource := Compiler.scalaCompilerBridgeSource(sbtVersion.value)
)
// must be a val: duplication detected by object identity
private[this] lazy val compileBaseGlobal: Seq[Setting[_]] = globalDefaults(Seq(
@ -797,13 +797,21 @@ object Defaults extends BuildCommon {
val cp = data(dependencyClasspath.value).toList
val label = nameForSrc(configuration.value.name)
val fiOpts = fileInputOptions.value
val logger: Logger = s.log
val maxer = maxErrors.value
val spms = sourcePositionMappers.value
val reporter: xsbti.Reporter =
(compilerReporter in compile).value match {
case Some(r) => r
case _ => new LoggerReporter(maxer, logger, Compiler.foldMappers(spms))
}
val (options, runDoc) =
if (hasScala)
(sOpts ++ Opts.doc.externalAPI(xapis), // can't put the .value calls directly here until 2.10.2
Doc.scaladoc(label, s.cacheDirectory / "scala", cs.scalac.onArgs(exported(s, "scaladoc")), fiOpts))
else if (hasJava)
(jOpts,
Doc.javadoc(label, s.cacheDirectory / "java", cs.javac.onArgs(exported(s, "javadoc")), fiOpts))
Doc.javadoc(label, s.cacheDirectory / "java", cs.javac, logger, reporter, fiOpts))
else
(Nil, RawCompileLike.nop)
runDoc(srcs, cp, out, options, maxErrors.value, s.log)
@ -859,7 +867,7 @@ object Defaults extends BuildCommon {
private[this] def compileIncrementalTaskImpl(s: TaskStreams, ci: Compiler.Inputs, previous: Compiler.PreviousAnalysis, reporter: Option[xsbti.Reporter]): Compiler.CompileResult =
{
lazy val x = s.text(ExportStream)
def onArgs(cs: Compiler.Compilers) = cs.copy(scalac = cs.scalac.onArgs(exported(x, "scalac")), javac = cs.javac.onArgs(exported(x, "javac")))
def onArgs(cs: Compiler.Compilers) = cs.copy(scalac = cs.scalac.onArgs(exported(x, "scalac")), javac = cs.javac /*.onArgs(exported(x, "javac"))*/ )
val i = InputsWithPrevious(ci.copy(compilers = onArgs(ci.compilers)), previous)
try reporter match {
case Some(reporter) => Compiler.compile(i, s.log, reporter)

View File

@ -4,7 +4,8 @@
package sbt
import sbt.internal.util.{ Settings, Show, ~> }
import sbt.librarymanagement.{ Configuration, Configurations }
import sbt.librarymanagement.{ Configuration, Configurations, Resolver }
import sbt.internal.librarymanagement.{ InlineIvyConfiguration, IvyPaths }
import java.io.File
import java.net.{ URI, URL }
@ -51,8 +52,13 @@ object Load {
val stagingDirectory = getStagingDirectory(state, globalBase).getCanonicalFile
val loader = getClass.getClassLoader
val classpath = Attributed.blankSeq(provider.mainClasspath ++ scalaProvider.jars)
// TODO: Fix this
val compilers = ??? //Compiler.compilers(ClasspathOptions.boot)(state.configuration, log)
val localOnly = false
val lock = None
val checksums = Nil
val ivyPaths = new IvyPaths(baseDirectory, bootIvyHome(state.configuration))
val ivyConfiguration = new InlineIvyConfiguration(ivyPaths, Resolver.withDefaultResolvers(Nil),
Nil, Nil, localOnly, lock, checksums, None, log)
val compilers = Compiler.compilers(ClasspathOptions.boot, ivyConfiguration)(state.configuration, log)
val evalPluginDef = EvaluateTask.evalPluginDef(log) _
val delegates = defaultDelegates
val initialID = baseDirectory.getName
@ -61,6 +67,9 @@ object Load {
new sbt.LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, definesClass, delegates,
EvaluateTask.injectStreams, pluginMgmt, inject, None, Nil, log)
}
private def bootIvyHome(app: xsbti.AppConfiguration): Option[File] =
try { Option(app.provider.scalaProvider.launcher.ivyHome) }
catch { case _: NoSuchMethodError => None }
def injectGlobal(state: State): Seq[Setting[_]] =
(appConfiguration in GlobalScope :== state.configuration) +:
LogManager.settingsLogger(state) +: