
org.pantsbuild.zinc.compiler.InputUtils.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zinc-compiler_2.11 Show documentation
Show all versions of zinc-compiler_2.11 Show documentation
The SBT incremental compiler for nailgun
The newest version!
/**
* Copyright (C) 2012 Typesafe, Inc.
*/
package org.pantsbuild.zinc.compiler
import java.io.{File}
import java.util.function.{ Function => JFunction }
import scala.compat.java8.OptionConverters._
import sbt.internal.inc.ZincUtil
import sbt.io.IO
import sbt.util.Logger
import xsbti.{Position, Problem, Severity, ReporterConfig, ReporterUtil}
import xsbti.compile.{
AnalysisStore,
ClasspathOptionsUtil,
CompileOptions,
CompileOrder,
Compilers,
Inputs,
PreviousResult,
Setup
}
import org.pantsbuild.zinc.analysis.AnalysisMap
import org.pantsbuild.zinc.scalautil.ScalaUtils
import org.pantsbuild.zinc.compiler.CompilerUtils.newScalaCompiler
object InputUtils {
/**
* Create Inputs based on command-line settings.
*/
def create(
settings: Settings,
analysisMap: AnalysisMap,
previousResult: PreviousResult,
log: Logger
): Inputs = {
import settings._
val scalaJars = InputUtils.selectScalaJars(settings.scala)
val instance = ScalaUtils.scalaInstance(scalaJars.compiler, scalaJars.extra, scalaJars.library)
val compilers = ZincUtil.compilers(instance, ClasspathOptionsUtil.auto, settings.javaHome, newScalaCompiler(instance, settings.compiledBridgeJar.get))
// TODO: Remove duplication once on Scala 2.12.x.
val positionMapper =
new JFunction[Position, Position] {
override def apply(p: Position): Position = p
}
val compileOptions =
CompileOptions
.create()
.withClasspath(
autoClasspath(
classesDirectory,
compilers.scalac().scalaInstance().allJars,
javaOnly,
classpath
).toArray
)
.withSources(sources.toArray)
.withClassesDirectory(classesDirectory)
.withScalacOptions(scalacOptions.toArray)
.withJavacOptions(javacOptions.toArray)
.withOrder(compileOrder)
val reporter =
ReporterUtil.getDefault(
ReporterUtil.getDefaultReporterConfig()
.withMaximumErrors(Int.MaxValue)
.withUseColor(settings.consoleLog.color)
.withMsgFilters(settings.consoleLog.msgPredicates.toArray)
.withFileFilters(settings.consoleLog.filePredicates.toArray)
.withLogLevel(settings.consoleLog.javaLogLevel)
.withPositionMapper(positionMapper)
)
val setup =
Setup.create(
analysisMap.getPCELookup,
false,
settings.analysis.cache,
CompilerUtils.getGlobalsCache,
incOptions.options(log),
reporter,
None.asJava,
Array()
)
Inputs.create(
compilers,
compileOptions,
setup,
previousResult
)
}
/**
* Load the analysis for the destination, creating it if necessary.
*/
def loadDestinationAnalysis(
settings: Settings,
analysisMap: AnalysisMap,
log: Logger
): (AnalysisStore, PreviousResult) = {
def load() = {
val analysisStore = analysisMap.cachedStore(settings.analysis.cache)
analysisStore.get().asScala match {
case Some(a) => (analysisStore, Some(a.getAnalysis), Some(a.getMiniSetup))
case _ => (analysisStore, None, None)
}
}
// Try loading, and optionally remove/retry on failure.
val (analysisStore, previousAnalysis, previousSetup) =
try {
load()
} catch {
case e: Throwable if settings.analysis.clearInvalid =>
// Remove the corrupted analysis and output directory.
log.warn(s"Failed to load analysis from ${settings.analysis.cache} ($e): will execute a clean compile.")
IO.delete(settings.analysis.cache)
IO.delete(settings.classesDirectory)
load()
}
(analysisStore, PreviousResult.create(previousAnalysis.asJava, previousSetup.asJava))
}
/**
* Automatically add the output directory and scala library to the classpath.
*/
def autoClasspath(classesDirectory: File, allScalaJars: Seq[File], javaOnly: Boolean, classpath: Seq[File]): Seq[File] = {
if (javaOnly) classesDirectory +: classpath
else splitScala(allScalaJars) match {
case Some(scalaJars) => classesDirectory +: scalaJars.library +: classpath
case None => classesDirectory +: classpath
}
}
/**
* Select the scala jars.
*
* Prefer the explicit scala-compiler, scala-library, and scala-extra settings,
* then the scala-path setting, then the scala-home setting. Default to bundled scala.
*/
def selectScalaJars(scala: ScalaLocation): ScalaJars = {
val jars = splitScala(scala.path) getOrElse Defaults.scalaJars
ScalaJars(
scala.compiler getOrElse jars.compiler,
scala.library getOrElse jars.library,
scala.extra ++ jars.extra
)
}
/**
* Distinguish the compiler and library jars.
*/
def splitScala(jars: Seq[File], excluded: Set[String] = Set.empty): Option[ScalaJars] = {
val filtered = jars filterNot (excluded contains _.getName)
val (compiler, other) = filtered partition (_.getName matches ScalaCompiler.pattern)
val (library, extra) = other partition (_.getName matches ScalaLibrary.pattern)
if (compiler.nonEmpty && library.nonEmpty) Some(ScalaJars(compiler(0), library(0), extra)) else None
}
//
// Default setup
//
val ScalaCompiler = JarFile("scala-compiler")
val ScalaLibrary = JarFile("scala-library")
val ScalaReflect = JarFile("scala-reflect")
// TODO: The default jar locations here are definitely not helpful, but the existence
// of "some" value for each of these is assumed in a few places. Should remove and make
// them optional to more cleanly support Java-only compiles.
object Defaults {
val scalaCompiler = ScalaCompiler.default
val scalaLibrary = ScalaLibrary.default
val scalaExtra = Seq(ScalaReflect.default)
val scalaJars = ScalaJars(scalaCompiler, scalaLibrary, scalaExtra)
val scalaExcluded = Set("jansi.jar", "jline.jar", "scala-partest.jar", "scala-swing.jar", "scalacheck.jar", "scalap.jar")
}
/**
* Jar file description for locating jars.
*/
case class JarFile(name: String, classifier: Option[String] = None) {
val versionPattern = "(-.*)?"
val classifierString = classifier map ("-" + _) getOrElse ""
val extension = "jar"
val pattern = name + versionPattern + classifierString + "." + extension
val default = new File(name + classifierString + "." + extension)
}
object JarFile {
def apply(name: String, classifier: String): JarFile = JarFile(name, Some(classifier))
}
/**
* The scala jars split into compiler, library, and extra.
*/
case class ScalaJars(compiler: File, library: File, extra: Seq[File])
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy