summaryrefslogtreecommitdiff
path: root/scalalib
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2018-08-05 23:23:12 +0900
committerLi Haoyi <haoyi.sg@gmail.com>2018-08-05 22:23:12 +0800
commitb9824967392e4b674881e5dcec4c4fbb05e6cd9b (patch)
tree40c67dff4ffb26f085ef52b1ec3e2341f33d27be /scalalib
parent66c133a2ff58823c43ddfa7643fb74b8cf2bd0a6 (diff)
downloadmill-b9824967392e4b674881e5dcec4c4fbb05e6cd9b.tar.gz
mill-b9824967392e4b674881e5dcec4c4fbb05e6cd9b.tar.bz2
mill-b9824967392e4b674881e5dcec4c4fbb05e6cd9b.zip
Add support for Dotty projects (#397)
* Abstract over the scala compiler organization * Support using a locally published compiler Publishing locally with sbt means publishing ivy-style, which uses a different naming convention than maven, we now handle both cases. * Add minimal support for Dotty projects * Rewrite scalalib.Dep, introduce scalalib.CrossVersion Instead of Dep being a trait with three cases (Java/Scala/Point), it is now a case class where the cross field is an instance of the CrossVersion trait which has three cases (Constant/Binary/Full). This is more versatile since it allows for non-empty constant suffixes which will be used to implement withDottyCompat in the next commit. It's also a cleaner separation of concerns. We also deduplicate various pieces of codes that computed the artifact name: this is now always handled in Dep and CrossVersion. * Add simple way to use Scala 2 deps in a Dotty project This is similar to the withDottyCompat method in the sbt-dotty plugin. * Turn off the Dotty test on Java >= 9
Diffstat (limited to 'scalalib')
-rw-r--r--scalalib/src/mill/scalalib/Dep.scala148
-rw-r--r--scalalib/src/mill/scalalib/Lib.scala71
-rw-r--r--scalalib/src/mill/scalalib/ScalaModule.scala50
-rw-r--r--scalalib/src/mill/scalalib/publish/settings.scala52
-rw-r--r--scalalib/test/resources/hello-dotty/foo/src/Main.scala17
-rw-r--r--scalalib/test/src/mill/scalalib/HelloWorldTests.scala26
-rw-r--r--scalalib/worker/src/mill/scalalib/worker/ScalaWorker.scala23
7 files changed, 236 insertions, 151 deletions
diff --git a/scalalib/src/mill/scalalib/Dep.scala b/scalalib/src/mill/scalalib/Dep.scala
index 9719bd2d..b419462c 100644
--- a/scalalib/src/mill/scalalib/Dep.scala
+++ b/scalalib/src/mill/scalalib/Dep.scala
@@ -1,32 +1,60 @@
package mill.scalalib
import mill.util.JsonFormatters._
import upickle.default.{macroRW, ReadWriter => RW}
-sealed trait Dep {
- def configure(attributes: coursier.Attributes): Dep
- def force: Boolean
- def forceVersion(): Dep = this match {
- case dep : Dep.Java => dep.copy(force = true)
- case dep : Dep.Scala => dep.copy(force = true)
- case dep : Dep.Point => dep.copy(force = true)
- }
- def exclude(exclusions: (String, String)*): Dep = this match {
- case dep : Dep.Java => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
- case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
- case dep : Dep.Point => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+
+import CrossVersion._
+
+case class Dep(dep: coursier.Dependency, cross: CrossVersion, force: Boolean) {
+ import Dep.isDotty
+
+ def artifactName(binaryVersion: String, fullVersion: String, platformSuffix: String) = {
+ val suffix = cross.suffixString(binaryVersion, fullVersion, platformSuffix)
+ dep.module.name + suffix
}
+ def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
+ def forceVersion(): Dep = copy(force = true)
+ def exclude(exclusions: (String, String)*) = copy(dep = dep.copy(exclusions = dep.exclusions ++ exclusions))
def excludeOrg(organizations: String*): Dep = exclude(organizations.map(_ -> "*"): _*)
def excludeName(names: String*): Dep = exclude(names.map("*" -> _): _*)
- def withConfiguration(configuration: String): Dep = this match {
- case dep : Dep.Java => dep.copy(dep = dep.dep.copy(configuration = configuration))
- case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(configuration = configuration))
- case dep : Dep.Point => dep.copy(dep = dep.dep.copy(configuration = configuration))
- }
+ def toDependency(binaryVersion: String, fullVersion: String, platformSuffix: String) =
+ dep.copy(module = dep.module.copy(name = artifactName(binaryVersion, fullVersion, platformSuffix)))
+ def withConfiguration(configuration: String): Dep = copy(dep = dep.copy(configuration = configuration))
+
+ /**
+ * If scalaVersion is a Dotty version, replace the cross-version suffix
+ * by the Scala 2.x version that the Dotty version is retro-compatible with,
+ * otherwise do nothing.
+ *
+ * This setting is useful when your build contains dependencies that have only
+ * been published with Scala 2.x, if you have:
+ * {{{
+ * def ivyDeps = Agg(ivy"a::b:c")
+ * }}}
+ * you can replace it by:
+ * {{{
+ * def ivyDeps = Agg(ivy"a::b:c".withDottyCompat(scalaVersion()))
+ * }}}
+ * This will have no effect when compiling with Scala 2.x, but when compiling
+ * with Dotty this will change the cross-version to a Scala 2.x one. This
+ * works because Dotty is currently retro-compatible with Scala 2.x.
+ */
+ def withDottyCompat(scalaVersion: String): Dep =
+ cross match {
+ case cross: Binary if isDotty(scalaVersion) =>
+ copy(cross = Constant(value = "_2.12", platformed = cross.platformed))
+ case _ =>
+ this
+ }
}
-object Dep{
+
+object Dep {
val DefaultConfiguration = "default(compile)"
- implicit def parse(signature: String) = {
+ def isDotty(scalaVersion: String) =
+ scalaVersion.startsWith("0.")
+
+ implicit def parse(signature: String): Dep = {
val parts = signature.split(';')
val module = parts.head
val attributes = parts.tail.foldLeft(coursier.Attributes()) { (as, s) =>
@@ -37,48 +65,60 @@ object Dep{
}
}
(module.split(':') match {
- case Array(a, b, c) => Dep.Java(a, b, c, cross = false, force = false)
- case Array(a, b, "", c) => Dep.Java(a, b, c, cross = true, force = false)
- case Array(a, "", b, c) => Dep.Scala(a, b, c, cross = false, force = false)
- case Array(a, "", b, "", c) => Dep.Scala(a, b, c, cross = true, force = false)
- case Array(a, "", "", b, c) => Dep.Point(a, b, c, cross = false, force = false)
- case Array(a, "", "", b, "", c) => Dep.Point(a, b, c, cross = true, force = false)
+ case Array(a, b, c) => Dep(a, b, c, cross = empty(platformed = false))
+ case Array(a, b, "", c) => Dep(a, b, c, cross = empty(platformed = true))
+ case Array(a, "", b, c) => Dep(a, b, c, cross = Binary(platformed = false))
+ case Array(a, "", b, "", c) => Dep(a, b, c, cross = Binary(platformed = true))
+ case Array(a, "", "", b, c) => Dep(a, b, c, cross = Full(platformed = false))
+ case Array(a, "", "", b, "", c) => Dep(a, b, c, cross = Full(platformed = true))
case _ => throw new Exception(s"Unable to parse signature: [$signature]")
}).configure(attributes = attributes)
}
- def apply(org: String, name: String, version: String, cross: Boolean): Dep = {
- this(coursier.Dependency(coursier.Module(org, name), version, DefaultConfiguration), cross)
- }
- case class Java(dep: coursier.Dependency, cross: Boolean, force: Boolean) extends Dep {
- def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
+ def apply(org: String, name: String, version: String, cross: CrossVersion, force: Boolean = false): Dep = {
+ apply(coursier.Dependency(coursier.Module(org, name), version, DefaultConfiguration), cross, force)
}
- object Java{
- implicit def rw: RW[Java] = macroRW
- def apply(org: String, name: String, version: String, cross: Boolean, force: Boolean): Dep = {
- Java(coursier.Dependency(coursier.Module(org, name), version, DefaultConfiguration), cross, force)
+ implicit def rw: RW[Dep] = macroRW
+}
+
+sealed trait CrossVersion {
+ /** If true, the cross-version suffix should start with a platform suffix if it exists */
+ def platformed: Boolean
+
+ def isBinary: Boolean =
+ this.isInstanceOf[Binary]
+ def isConstant: Boolean =
+ this.isInstanceOf[Constant]
+ def isFull: Boolean =
+ this.isInstanceOf[Full]
+
+ /** The string that should be appended to the module name to get the artifact name */
+ def suffixString(binaryVersion: String, fullVersion: String, platformSuffix: String): String = {
+ val firstSuffix = if (platformed) platformSuffix else ""
+ this match {
+ case cross: Constant =>
+ s"${firstSuffix}${cross.value}"
+ case cross: Binary =>
+ s"${firstSuffix}_${binaryVersion}"
+ case cross: Full =>
+ s"${firstSuffix}_${fullVersion}"
}
}
- implicit def default(dep: coursier.Dependency): Dep = new Java(dep, false, false)
- def apply(dep: coursier.Dependency, cross: Boolean) = Scala(dep, cross, false)
- case class Scala(dep: coursier.Dependency, cross: Boolean, force: Boolean) extends Dep {
- def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
- }
- object Scala{
- implicit def rw: RW[Scala] = macroRW
- def apply(org: String, name: String, version: String, cross: Boolean, force: Boolean): Dep = {
- Scala(coursier.Dependency(coursier.Module(org, name), version, DefaultConfiguration), cross, force)
- }
+}
+object CrossVersion {
+ case class Constant(value: String, platformed: Boolean) extends CrossVersion
+ object Constant {
+ implicit def rw: RW[Constant] = macroRW
}
- case class Point(dep: coursier.Dependency, cross: Boolean, force: Boolean) extends Dep {
- def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
+ case class Binary(platformed: Boolean) extends CrossVersion
+ object Binary {
+ implicit def rw: RW[Binary] = macroRW
}
- object Point{
- implicit def rw: RW[Point] = macroRW
- def apply(org: String, name: String, version: String, cross: Boolean, force: Boolean): Dep = {
- Point(coursier.Dependency(coursier.Module(org, name), version, DefaultConfiguration), cross, force)
- }
+ case class Full(platformed: Boolean) extends CrossVersion
+ object Full {
+ implicit def rw: RW[Full] = macroRW
}
- implicit def rw = RW.merge[Dep](
- Java.rw, Scala.rw, Point.rw
- )
+
+ def empty(platformed: Boolean) = Constant(value = "", platformed)
+
+ implicit def rw: RW[CrossVersion] = RW.merge(Constant.rw, Binary.rw, Full.rw)
}
diff --git a/scalalib/src/mill/scalalib/Lib.scala b/scalalib/src/mill/scalalib/Lib.scala
index b69409a6..e890caaf 100644
--- a/scalalib/src/mill/scalalib/Lib.scala
+++ b/scalalib/src/mill/scalalib/Lib.scala
@@ -10,6 +10,7 @@ import javax.tools.ToolProvider
import ammonite.ops._
import ammonite.util.Util
import coursier.{Cache, Dependency, Fetch, Repository, Resolution}
+import Dep.isDotty
import mill.Agg
import mill.eval.{PathRef, Result}
import mill.modules.Jvm
@@ -56,58 +57,37 @@ object Lib{
private val ReleaseVersion = raw"""(\d+)\.(\d+)\.(\d+)""".r
private val MinorSnapshotVersion = raw"""(\d+)\.(\d+)\.([1-9]\d*)-SNAPSHOT""".r
+ private val DottyVersion = raw"""0\.(\d+)\.(\d+).*""".r
def scalaBinaryVersion(scalaVersion: String) = {
scalaVersion match {
case ReleaseVersion(major, minor, _) => s"$major.$minor"
case MinorSnapshotVersion(major, minor, _) => s"$major.$minor"
+ case DottyVersion(minor, _) => s"0.$minor"
case _ => scalaVersion
}
}
- def grepJar(classPath: Agg[Path], s: String) = {
+ def grepJar(classPath: Agg[Path], name: String, version: String) = {
+ val mavenStylePath = s"$name-$version.jar"
+ val ivyStylePath = s"$version/$name.jar"
+
classPath
- .find(_.toString.endsWith(s))
- .getOrElse(throw new Exception("Cannot find " + s))
- .toIO
+ .find(p => p.toString.endsWith(mavenStylePath) || p.toString.endsWith(ivyStylePath))
+ .getOrElse(throw new Exception(s"Cannot find $mavenStylePath or $ivyStylePath"))
}
-
def depToDependencyJava(dep: Dep, platformSuffix: String = ""): Dependency = {
- dep match {
- case Dep.Java(dep, cross, force) =>
- dep.copy(
- module = dep.module.copy(
- name =
- dep.module.name +
- (if (!cross) "" else platformSuffix)
- )
- )
- }
+ assert(dep.cross.isConstant, s"Not a Java dependency: $dep")
+ depToDependency(dep, "", platformSuffix)
}
- def depToDependency(dep: Dep, scalaVersion: String, platformSuffix: String = ""): Dependency =
- dep match {
- case d: Dep.Java => depToDependencyJava(dep)
- case Dep.Scala(dep, cross, force) =>
- dep.copy(
- module = dep.module.copy(
- name =
- dep.module.name +
- (if (!cross) "" else platformSuffix) +
- "_" + scalaBinaryVersion(scalaVersion)
- )
- )
- case Dep.Point(dep, cross, force) =>
- dep.copy(
- module = dep.module.copy(
- name =
- dep.module.name +
- (if (!cross) "" else platformSuffix) +
- "_" + scalaVersion
- )
- )
- }
+ def depToDependency(dep: Dep, scalaVersion: String, platformSuffix: String = ""): Dependency =
+ dep.toDependency(
+ binaryVersion = scalaBinaryVersion(scalaVersion),
+ fullVersion = scalaVersion,
+ platformSuffix = platformSuffix
+ )
def resolveDependenciesMetadata(repositories: Seq[Repository],
depToDependency: Dep => coursier.Dependency,
@@ -142,12 +122,17 @@ object Lib{
mapDependencies
)
}
- def scalaCompilerIvyDeps(scalaVersion: String) = Agg[Dep](
- ivy"org.scala-lang:scala-compiler:$scalaVersion".forceVersion(),
- ivy"org.scala-lang:scala-reflect:$scalaVersion".forceVersion()
- )
- def scalaRuntimeIvyDeps(scalaVersion: String) = Agg[Dep](
- ivy"org.scala-lang:scala-library:$scalaVersion".forceVersion()
+ def scalaCompilerIvyDeps(scalaOrganization: String, scalaVersion: String) =
+ if (isDotty(scalaVersion))
+ Agg(ivy"$scalaOrganization::dotty-compiler:$scalaVersion".forceVersion())
+ else
+ Agg(
+ ivy"$scalaOrganization:scala-compiler:$scalaVersion".forceVersion(),
+ ivy"$scalaOrganization:scala-reflect:$scalaVersion".forceVersion()
+ )
+
+ def scalaRuntimeIvyDeps(scalaOrganization: String, scalaVersion: String) = Agg[Dep](
+ ivy"$scalaOrganization:scala-library:$scalaVersion".forceVersion()
)
def listClassFiles(base: Path): Iterator[String] = {
diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala
index 3cea7fab..1899ee14 100644
--- a/scalalib/src/mill/scalalib/ScalaModule.scala
+++ b/scalalib/src/mill/scalalib/ScalaModule.scala
@@ -8,6 +8,7 @@ import mill.define.TaskModule
import mill.eval.{PathRef, Result}
import mill.modules.Jvm
import mill.modules.Jvm.{createJar, subprocess}
+import Dep.isDotty
import Lib._
import mill.util.Loose.Agg
import mill.util.DummyInputStream
@@ -17,6 +18,7 @@ import mill.util.DummyInputStream
*/
trait ScalaModule extends JavaModule { outer =>
trait Tests extends TestModule with ScalaModule{
+ override def scalaOrganization = outer.scalaOrganization()
def scalaVersion = outer.scalaVersion()
override def repositories = outer.repositories
override def scalacPluginIvyDeps = outer.scalacPluginIvyDeps
@@ -25,12 +27,24 @@ trait ScalaModule extends JavaModule { outer =>
override def scalaWorker = outer.scalaWorker
override def moduleDeps: Seq[JavaModule] = Seq(outer)
}
+
+ def scalaOrganization: T[String] = T {
+ if (isDotty(scalaVersion()))
+ "ch.epfl.lamp"
+ else
+ "org.scala-lang"
+ }
+
def scalaVersion: T[String]
override def mapDependencies = T.task{ d: coursier.Dependency =>
- val artifacts = Set("scala-library", "scala-compiler", "scala-reflect")
- if (d.module.organization != "org.scala-lang" || !artifacts(d.module.name)) d
- else d.copy(version = scalaVersion())
+ val artifacts =
+ if (isDotty(scalaVersion()))
+ Set("dotty-library", "dotty-compiler")
+ else
+ Set("scala-library", "scala-compiler", "scala-reflect")
+ if (!artifacts(d.module.name)) d
+ else d.copy(module = d.module.copy(organization = scalaOrganization()), version = scalaVersion())
}
override def resolveCoursierDependency: Task[Dep => coursier.Dependency] = T.task{
@@ -77,25 +91,41 @@ trait ScalaModule extends JavaModule { outer =>
case _ => (scalaVersion(), Lib.scalaBinaryVersion(scalaVersion()))
}
+ val (bridgeDep, bridgeName, bridgeVersion) =
+ if (isDotty(scalaVersion0)) {
+ val org = scalaOrganization()
+ val name = "dotty-sbt-bridge"
+ val version = scalaVersion()
+ (ivy"$org:$name:$version", name, version)
+ } else {
+ val org = "org.scala-sbt"
+ val name = "compiler-bridge"
+ val version = Versions.zinc
+ (ivy"$org::$name:$version", s"${name}_$scalaBinaryVersion0", version)
+ }
+
resolveDependencies(
repositories,
Lib.depToDependency(_, scalaVersion0, platformSuffix()),
- Seq(ivy"org.scala-sbt::compiler-bridge:${Versions.zinc}"),
+ Seq(bridgeDep),
sources = true
- ).map(_.find(_.path.last == s"compiler-bridge_${scalaBinaryVersion0}-${Versions.zinc}-sources.jar").map(_.path).get)
+ ).map(deps =>
+ grepJar(deps.map(_.path), bridgeName, s"$bridgeVersion-sources")
+ )
}
def scalacPluginClasspath: T[Agg[PathRef]] = T {
resolveDeps(scalacPluginIvyDeps)()
}
- def scalaLibraryIvyDeps = T{ scalaRuntimeIvyDeps(scalaVersion()) }
+ def scalaLibraryIvyDeps = T{ scalaRuntimeIvyDeps(scalaOrganization(), scalaVersion()) }
/**
* Classpath of the Scala Compiler & any compiler plugins
*/
def scalaCompilerClasspath: T[Agg[PathRef]] = T{
resolveDeps(
- T.task{scalaCompilerIvyDeps(scalaVersion()) ++ scalaRuntimeIvyDeps(scalaVersion())}
+ T.task{scalaCompilerIvyDeps(scalaOrganization(), scalaVersion()) ++
+ scalaRuntimeIvyDeps(scalaOrganization(), scalaVersion())}
)()
}
override def compileClasspath = T{
@@ -155,7 +185,11 @@ trait ScalaModule extends JavaModule { outer =>
Result.Failure("repl needs to be run with the -i/--interactive flag")
}else{
Jvm.interactiveSubprocess(
- mainClass = "scala.tools.nsc.MainGenericRunner",
+ mainClass =
+ if (isDotty(scalaVersion()))
+ "dotty.tools.repl.Main"
+ else
+ "scala.tools.nsc.MainGenericRunner",
classPath = runClasspath().map(_.path) ++ scalaCompilerClasspath().map(_.path),
mainArgs = Seq("-usejavacp"),
workingDir = pwd
diff --git a/scalalib/src/mill/scalalib/publish/settings.scala b/scalalib/src/mill/scalalib/publish/settings.scala
index 9a59f09d..bca81cf0 100644
--- a/scalalib/src/mill/scalalib/publish/settings.scala
+++ b/scalalib/src/mill/scalalib/publish/settings.scala
@@ -8,45 +8,29 @@ case class Artifact(group: String, id: String, version: String) {
object Artifact {
def fromDepJava(dep: Dep) = {
- dep match {
- case Dep.Java(dep, cross, force) =>
- Dependency(
- Artifact(dep.module.organization, dep.module.name, dep.version),
- Scope.Compile,
- if (dep.configuration == "") None else Some(dep.configuration),
- dep.exclusions.toList
- )
- }
+ assert(dep.cross.isConstant, s"Not a Java dependency: $dep")
+ fromDep(dep, "", "", "")
}
+
def fromDep(dep: Dep,
scalaFull: String,
scalaBin: String,
platformSuffix: String): Dependency = {
- dep match {
- case d: Dep.Java => fromDepJava(d)
- case Dep.Scala(dep, cross, force) =>
- Dependency(
- Artifact(
- dep.module.organization,
- s"${dep.module.name}${platformSuffix}_${scalaBin}",
- dep.version
- ),
- Scope.Compile,
- if (dep.configuration == "") None else Some(dep.configuration),
- dep.exclusions.toList
- )
- case Dep.Point(dep, cross, force) =>
- Dependency(
- Artifact(
- dep.module.organization,
- s"${dep.module.name}${platformSuffix}_${scalaFull}",
- dep.version
- ),
- Scope.Compile,
- if (dep.configuration == "") None else Some(dep.configuration),
- dep.exclusions.toList
- )
- }
+ val name = dep.artifactName(
+ binaryVersion = scalaBin,
+ fullVersion = scalaFull,
+ platformSuffix = platformSuffix
+ )
+ Dependency(
+ Artifact(
+ dep.dep.module.organization,
+ name,
+ dep.dep.version
+ ),
+ Scope.Compile,
+ if (dep.dep.configuration == "") None else Some(dep.dep.configuration),
+ dep.dep.exclusions.toList
+ )
}
}
diff --git a/scalalib/test/resources/hello-dotty/foo/src/Main.scala b/scalalib/test/resources/hello-dotty/foo/src/Main.scala
new file mode 100644
index 00000000..3fe80342
--- /dev/null
+++ b/scalalib/test/resources/hello-dotty/foo/src/Main.scala
@@ -0,0 +1,17 @@
+import cats._, cats.data._, cats.implicits._
+
+trait Context
+
+object Main {
+ def foo(f: implicit Int => Int): Int = {
+ implicit val x: Int = 1
+ f
+ }
+
+ def main(args: Array[String]): Unit = {
+ val x = Applicative[List].pure(1)
+ assert(x == List(1))
+ val value = foo(implicit x => x + 1)
+ assert(value == 2)
+ }
+}
diff --git a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
index 7a1dd6df..1a89a0e3 100644
--- a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
+++ b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
@@ -14,6 +14,7 @@ import utest._
import utest.framework.TestPath
import scala.collection.JavaConverters._
+import scala.util.Properties.isJavaAtLeast
object HelloWorldTests extends TestSuite {
@@ -190,11 +191,7 @@ object HelloWorldTests extends TestSuite {
object HelloWorldTypeLevel extends HelloBase{
object foo extends ScalaModule {
def scalaVersion = "2.11.8"
- override def mapDependencies = T.task{ d: coursier.Dependency =>
- val artifacts = Set("scala-library", "scala-compiler", "scala-reflect")
- if (d.module.organization != "org.scala-lang" || !artifacts(d.module.name)) d
- else d.copy(module = d.module.copy(organization = "org.typelevel"))
- }
+ override def scalaOrganization = "org.typelevel"
def ivyDeps = Agg(
ivy"com.github.julien-truffaut::monocle-macro::1.4.0"
@@ -238,6 +235,13 @@ object HelloWorldTests extends TestSuite {
}
}
+ object HelloDotty extends HelloBase{
+ object foo extends ScalaModule {
+ def scalaVersion = "0.9.0-RC1"
+ def ivyDeps = Agg(ivy"org.typelevel::cats-core:1.2.0".withDottyCompat(scalaVersion()))
+ }
+ }
+
val resourcePath = pwd / 'scalalib / 'test / 'resources / "hello-world"
def jarMainClass(jar: JarFile): Option[String] = {
@@ -815,5 +819,17 @@ object HelloWorldTests extends TestSuite {
)
}
+ 'dotty - workspaceTest(
+ HelloDotty,
+ resourcePath = pwd / 'scalalib / 'test / 'resources / "hello-dotty"
+ ){ eval =>
+ if (isJavaAtLeast("9")) {
+ // Skip the test because Dotty does not support Java >= 9 yet
+ // (see https://github.com/lampepfl/dotty/pull/3138)
+ } else {
+ val Right((_, evalCount)) = eval.apply(HelloDotty.foo.run())
+ assert(evalCount > 0)
+ }
+ }
}
}
diff --git a/scalalib/worker/src/mill/scalalib/worker/ScalaWorker.scala b/scalalib/worker/src/mill/scalalib/worker/ScalaWorker.scala
index 76f185c5..98b40889 100644
--- a/scalalib/worker/src/mill/scalalib/worker/ScalaWorker.scala
+++ b/scalalib/worker/src/mill/scalalib/worker/ScalaWorker.scala
@@ -9,7 +9,8 @@ import mill.Agg
import mill.eval.PathRef
import mill.scalalib.{CompilationResult, Lib, TestRunner}
import xsbti.compile.{CompilerCache => _, FileAnalysisStore => _, ScalaInstance => _, _}
-import mill.scalalib.Lib.grepJar
+import mill.scalalib.Dep.isDotty
+import mill.scalalib.Lib.{grepJar, scalaBinaryVersion}
import mill.util.{Ctx, PrintLogger}
import sbt.internal.inc._
import sbt.internal.util.{ConsoleOut, MainAppender}
@@ -44,15 +45,18 @@ class ScalaWorker(ctx0: mill.util.Ctx,
val sourceFolder = mill.modules.Util.unpackZip(sourcesJar)(workingDir)
val classloader = mill.util.ClassLoader.create(compilerJars.map(_.toURI.toURL), null)(ctx0)
- val scalacMain = classloader.loadClass("scala.tools.nsc.Main")
+ val compilerMain = classloader.loadClass(
+ if (isDotty(scalaVersion))
+ "dotty.tools.dotc.Main"
+ else
+ "scala.tools.nsc.Main"
+ )
val argsArray = Array[String](
"-d", compiledDest.toString,
"-classpath", (compilerJars ++ compilerBridgeClasspath).mkString(File.pathSeparator)
) ++ ls.rec(sourceFolder.path).filter(_.ext == "scala").map(_.toString)
- scalacMain.getMethods
- .find(_.getName == "process")
- .get
+ compilerMain.getMethod("process", classOf[Array[String]])
.invoke(null, argsArray)
}
compiledDest
@@ -97,11 +101,16 @@ class ScalaWorker(ctx0: mill.util.Ctx,
val compilers = compilersCache match {
case Some((k, v)) if k == compilersSig => v
case _ =>
+ val compilerName =
+ if (isDotty(scalaVersion))
+ s"dotty-compiler_${scalaBinaryVersion(scalaVersion)}"
+ else
+ "scala-compiler"
val scalaInstance = new ScalaInstance(
version = scalaVersion,
loader = mill.util.ClassLoader.create(compilerJars.map(_.toURI.toURL), null),
- libraryJar = grepJar(compilerClasspath, s"scala-library-$scalaVersion.jar"),
- compilerJar = grepJar(compilerClasspath, s"scala-compiler-$scalaVersion.jar"),
+ libraryJar = grepJar(compilerClasspath, "scala-library", scalaVersion).toIO,
+ compilerJar = grepJar(compilerClasspath, compilerName, scalaVersion).toIO,
allJars = compilerJars,
explicitActual = None
)