diff --git a/main/actions/src/main/scala/sbt/Compiler.scala b/main/actions/src/main/scala/sbt/Compiler.scala index 277d9a0a8..de1d5d660 100644 --- a/main/actions/src/main/scala/sbt/Compiler.scala +++ b/main/actions/src/main/scala/sbt/Compiler.scala @@ -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) diff --git a/main/actions/src/main/scala/sbt/Doc.scala b/main/actions/src/main/scala/sbt/Doc.scala index 6100a5b79..21bae974e 100644 --- a/main/actions/src/main/scala/sbt/Doc.scala +++ b/main/actions/src/main/scala/sbt/Doc.scala @@ -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)) + // } } diff --git a/main/src/main/scala/sbt/ConsoleProject.scala b/main/src/main/scala/sbt/ConsoleProject.scala index 33cb4c6e5..04ece2800 100644 --- a/main/src/main/scala/sbt/ConsoleProject.scala +++ b/main/src/main/scala/sbt/ConsoleProject.scala @@ -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 } } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 227ade923..84faf5d74 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -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) diff --git a/main/src/main/scala/sbt/Load.scala b/main/src/main/scala/sbt/Load.scala index 880a7e76c..0e3599282 100755 --- a/main/src/main/scala/sbt/Load.scala +++ b/main/src/main/scala/sbt/Load.scala @@ -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) +: