mirror of https://github.com/sbt/sbt.git
Make sbt aware of Dotty
This small set of changes, together with the compiler-bridge I wrote (https://github.com/smarter/dotty-bridge) enables us to compile code using Dotty in sbt, see https://github.com/smarter/dotty-example-project for an example.
This commit is contained in:
parent
bcb98ab6bb
commit
10265efd9c
|
|
@ -30,7 +30,11 @@ final class CompilerArguments(scalaInstance: xsbti.compile.ScalaInstance, cp: xs
|
|||
}
|
||||
def finishClasspath(classpath: Seq[File]): Seq[File] =
|
||||
filterLibrary(classpath) ++ include(cp.compiler, scalaInstance.compilerJar) ++ include(cp.extra, scalaInstance.otherJars: _*)
|
||||
private[this] def include(flag: Boolean, jars: File*) = if (flag) jars else Nil
|
||||
private[this] def include(flag: Boolean, jars: File*) =
|
||||
if (flag || ScalaInstance.isDotty(scalaInstance.version))
|
||||
jars
|
||||
else
|
||||
Nil
|
||||
private[this] def abs(files: Seq[File]) = files.map(_.getAbsolutePath).sortWith(_ < _)
|
||||
private[this] def checkScalaHomeUnset(): Unit = {
|
||||
val scalaHome = System.getProperty("scala.home")
|
||||
|
|
|
|||
|
|
@ -21,16 +21,29 @@ class RawCompiler(val scalaInstance: xsbti.compile.ScalaInstance, cp: ClasspathO
|
|||
|
||||
val arguments = compilerArguments(sources, classpath, Some(outputDirectory), options)
|
||||
log.debug("Plain interface to Scala compiler " + scalaInstance.actualVersion + " with arguments: " + arguments.mkString("\n\t", "\n\t", ""))
|
||||
val mainClass = Class.forName("scala.tools.nsc.Main", true, scalaInstance.loader)
|
||||
val process = mainClass.getMethod("process", classOf[Array[String]])
|
||||
process.invoke(null, arguments.toArray)
|
||||
checkForFailure(mainClass, arguments.toArray)
|
||||
val args = arguments.toArray
|
||||
val reporter =
|
||||
if (ScalaInstance.isDotty(scalaInstance.version)) {
|
||||
val mainClass = Class.forName("dotty.tools.dotc.Main", true, scalaInstance.loader)
|
||||
val process = mainClass.getMethod("process", classOf[Array[String]])
|
||||
process.invoke(null, args)
|
||||
} else {
|
||||
val mainClass = Class.forName("scala.tools.nsc.Main", true, scalaInstance.loader)
|
||||
val process = mainClass.getMethod("process", classOf[Array[String]])
|
||||
process.invoke(null, arguments.toArray)
|
||||
mainClass.getMethod("reporter").invoke(null)
|
||||
}
|
||||
checkForFailure(reporter, arguments.toArray)
|
||||
}
|
||||
def compilerArguments = new CompilerArguments(scalaInstance, cp)
|
||||
protected def checkForFailure(mainClass: Class[_], args: Array[String]): Unit = {
|
||||
val reporter = mainClass.getMethod("reporter").invoke(null)
|
||||
protected def checkForFailure(reporter: AnyRef, args: Array[String]): Unit = {
|
||||
val failed = reporter.getClass.getMethod("hasErrors").invoke(reporter).asInstanceOf[Boolean]
|
||||
if (failed) throw new CompileFailed(args, "Plain compile failed", Array())
|
||||
}
|
||||
@deprecated("Use `checkForFailure(AnyRef, Array[String])`", "0.13.10")
|
||||
protected def checkForFailure(mainClass: Class[_], args: Array[String]): Unit = {
|
||||
val reporter = mainClass.getMethod("reporter").invoke(null)
|
||||
checkForFailure(reporter, args)
|
||||
}
|
||||
}
|
||||
class CompileFailed(val arguments: Array[String], override val toString: String, val problems: Array[xsbti.Problem]) extends xsbti.CompileFailed with FeedbackProvidedException
|
||||
|
|
|
|||
|
|
@ -17,12 +17,20 @@ object ScalaArtifacts {
|
|||
val LibraryID = ScalaLibraryID
|
||||
val CompilerID = ScalaCompilerID
|
||||
val ReflectID = "scala-reflect"
|
||||
val DottyIDPrefix = "dotty"
|
||||
|
||||
def dottyID(binaryVersion: String): String = s"${DottyIDPrefix}_${binaryVersion}"
|
||||
|
||||
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
|
||||
|
||||
private[sbt] def toolDependencies(org: String, version: String): Seq[ModuleID] = Seq(
|
||||
scalaToolDependency(org, ScalaArtifacts.CompilerID, version),
|
||||
scalaToolDependency(org, ScalaArtifacts.LibraryID, version)
|
||||
)
|
||||
private[sbt] def toolDependencies(org: String, version: String, isDotty: Boolean = false): Seq[ModuleID] =
|
||||
if (isDotty)
|
||||
Seq(ModuleID(org, DottyIDPrefix, version, Some(Configurations.ScalaTool.name + "->compile"),
|
||||
crossVersion = CrossVersion.binary))
|
||||
else
|
||||
Seq(scalaToolDependency(org, ScalaArtifacts.CompilerID, version),
|
||||
scalaToolDependency(org, ScalaArtifacts.LibraryID, version))
|
||||
|
||||
private[this] def scalaToolDependency(org: String, id: String, version: String): ModuleID =
|
||||
ModuleID(org, id, version, Some(Configurations.ScalaTool.name + "->default,optional(default)"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -390,7 +390,11 @@ object Defaults extends BuildCommon {
|
|||
def file(id: String) = files(id).headOption getOrElse sys.error(s"Missing ${id}.jar")
|
||||
val allFiles = toolReport.modules.flatMap(_.artifacts.map(_._2))
|
||||
val libraryJar = file(ScalaArtifacts.LibraryID)
|
||||
val compilerJar = file(ScalaArtifacts.CompilerID)
|
||||
val compilerJar =
|
||||
if (ScalaInstance.isDotty(scalaVersion.value))
|
||||
file(ScalaArtifacts.dottyID(scalaBinaryVersion.value))
|
||||
else
|
||||
file(ScalaArtifacts.CompilerID)
|
||||
val otherJars = allFiles.filterNot(x => x == libraryJar || x == compilerJar)
|
||||
ScalaInstance(scalaVersion.value, libraryJar, compilerJar, otherJars: _*)(makeClassLoader(state.value))
|
||||
}
|
||||
|
|
@ -1250,8 +1254,11 @@ object Classpaths {
|
|||
val pluginAdjust = if (sbtPlugin.value) sbtDependency.value.copy(configurations = Some(Provided.name)) +: base else base
|
||||
if (scalaHome.value.isDefined || ivyScala.value.isEmpty || !managedScalaInstance.value)
|
||||
pluginAdjust
|
||||
else
|
||||
ScalaArtifacts.toolDependencies(scalaOrganization.value, scalaVersion.value) ++ pluginAdjust
|
||||
else {
|
||||
val version = scalaVersion.value
|
||||
val isDotty = ScalaInstance.isDotty(version)
|
||||
ScalaArtifacts.toolDependencies(scalaOrganization.value, version, isDotty) ++ pluginAdjust
|
||||
}
|
||||
}
|
||||
)
|
||||
@deprecated("Split into ivyBaseSettings and jvmBaseSettings.", "0.13.2")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
[Dotty]: https://github.com/lampepfl/dotty
|
||||
[@smarter]: https://github.com/smarter
|
||||
|
||||
### Fixes with compatibility implications
|
||||
|
||||
### Improvements
|
||||
|
||||
- sbt is now aware of [Dotty][Dotty], it will assume
|
||||
that Dotty is used when `scalaVersion` starts with `0.`, the sbt
|
||||
compiler-bridge does not support Dotty but a separate compiler-bridge is being
|
||||
developed at https://github.com/smarter/dotty-bridge and an example project
|
||||
that uses it is available at https://github.com/smarter/dotty-example-project
|
||||
by [@smarter][@smarter].
|
||||
|
||||
### Bug fixes
|
||||
|
|
@ -41,6 +41,11 @@ object ScalaInstance {
|
|||
val ScalaOrg = ScalaOrganization
|
||||
val VersionPrefix = "version "
|
||||
|
||||
def isDotty(version: String): Boolean =
|
||||
// We rely on the fact that the first public version of Scala was 1.0 and
|
||||
// that Dotty will keep being version 0.x for a long time.
|
||||
version.startsWith("0.")
|
||||
|
||||
def apply(org: String, version: String, launcher: xsbti.Launcher): ScalaInstance =
|
||||
// Due to incompatibility with previous launchers if scalaOrg has default value revert to an existing method
|
||||
if (org == ScalaOrg)
|
||||
|
|
|
|||
Loading…
Reference in New Issue