Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Scoverage for Scala 3 #2016

Merged
merged 4 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ object Deps {

val testScala213Version = "2.13.8"
val testScala212Version = "2.12.6"
val testScala211Version = "2.11.12"
val testScala30Version = "3.0.2"
val testScala31Version = "3.1.3"
val testScala32Version = "3.2.0"

val testScalaJs06Version = "0.6.33"

Expand Down Expand Up @@ -304,7 +307,10 @@ trait MillScalaModule extends ScalaModule with MillCoursierModule { outer =>
s"-DMILL_SCALA_2_12_VERSION=${Deps.workerScalaVersion212}",
s"-DTEST_SCALA_2_13_VERSION=${Deps.testScala213Version}",
s"-DTEST_SCALA_2_12_VERSION=${Deps.testScala212Version}",
s"-DTEST_SCALA_2_11_VERSION=${Deps.testScala211Version}",
s"-DTEST_SCALA_3_0_VERSION=${Deps.testScala30Version}",
s"-DTEST_SCALA_3_1_VERSION=${Deps.testScala31Version}",
s"-DTEST_SCALA_3_2_VERSION=${Deps.testScala32Version}",
s"-DTEST_UTEST_VERSION=${Deps.utest.dep.version}",
s"-DTEST_SCALAJS_0_6_VERSION=${Deps.testScalaJs06Version}"
) ++ outer.testArgs()
Expand Down
111 changes: 85 additions & 26 deletions contrib/scoverage/src/ScoverageModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import mill.contrib.scoverage.api.ScoverageReportWorkerApi.ReportType
import mill.define.{Command, Persistent, Sources, Target, Task}
import mill.scalalib.api.ZincWorkerUtil
import mill.scalalib.{Dep, DepSyntax, JavaModule, ScalaModule}
import mill.api.Result

/**
* Adds targets to a [[mill.scalalib.ScalaModule]] to create test coverage reports.
Expand Down Expand Up @@ -59,35 +60,61 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>

private def isScoverage2: Task[Boolean] = T.task { scoverageVersion().startsWith("2.") }

private def isScala3: Task[Boolean] = T.task { ZincWorkerUtil.isScala3(outer.scalaVersion()) }

private def isScala2: Task[Boolean] = T.task { !isScala3() }

/** Binary compatibility shim. */
@deprecated("Use scoverageRuntimeDeps instead.", "Mill after 0.10.7")
def scoverageRuntimeDep: T[Dep] = T {
T.log.error("scoverageRuntimeDep is no longer used. To customize your module, use scoverageRuntimeDeps.")
scoverageRuntimeDeps().toIndexedSeq.head
T.log.error(
"scoverageRuntimeDep is no longer used. To customize your module, use scoverageRuntimeDeps."
)
val result: Result[Dep] = if (isScala3()) {
Result.Failure("When using Scala 3 there is no external runtime dependency")
} else {
scoverageRuntimeDeps().toIndexedSeq.head
}
result
}

def scoverageRuntimeDeps: T[Agg[Dep]] = T {
Agg(ivy"org.scoverage::scalac-scoverage-runtime:${outer.scoverageVersion()}")
if (isScala3()) {
Agg.empty
} else {
Agg(ivy"org.scoverage::scalac-scoverage-runtime:${outer.scoverageVersion()}")
}
}

/** Binary compatibility shim. */
@deprecated("Use scoveragePluginDeps instead.", "Mill after 0.10.7")
def scoveragePluginDep: T[Dep] = T {
T.log.error("scoveragePluginDep is no longer used. To customize your module, use scoverageRuntimeDeps.")
scoveragePluginDeps().toIndexedSeq.head
T.log.error(
"scoveragePluginDep is no longer used. To customize your module, use scoverageRuntimeDeps."
)
val result: Result[Dep] = if (isScala3()) {
Result.Failure("When using Scala 3 there is no external plugin dependency")
} else {
scoveragePluginDeps().toIndexedSeq.head
}
result
}

def scoveragePluginDeps: T[Agg[Dep]] = T {
val sv = scoverageVersion()
if (isScoverage2()) {
Agg(
ivy"org.scoverage:::scalac-scoverage-plugin:${sv}",
ivy"org.scoverage::scalac-scoverage-domain:${sv}",
ivy"org.scoverage::scalac-scoverage-serializer:${sv}",
ivy"org.scoverage::scalac-scoverage-reporter:${sv}"
)
if (isScala3()) {
Agg.empty
} else {
Agg(ivy"org.scoverage:::scalac-scoverage-plugin:${sv}")
if (isScoverage2()) {
Agg(
ivy"org.scoverage:::scalac-scoverage-plugin:${sv}",
ivy"org.scoverage::scalac-scoverage-domain:${sv}",
ivy"org.scoverage::scalac-scoverage-serializer:${sv}",
ivy"org.scoverage::scalac-scoverage-reporter:${sv}"
)
} else {
Agg(ivy"org.scoverage:::scalac-scoverage-plugin:${sv}")
}
}
}

Expand All @@ -96,23 +123,47 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>
scoverageToolsClasspath()
}

private def checkVersions = T.task {
val sv = scalaVersion()
val isSov2 = scoverageVersion().startsWith("2.")
(sv.split('.'), isSov2) match {
case (Array("3", "0" | "1", _*), _) => Result.Failure(
"Scala 3.0 and 3.1 is not supported by Scoverage. You have to update to at least Scala 3.2 and Scoverage 2.0"
)
case (Array("3", _*), false) => Result.Failure(
"Scoverage 1.x does not support Scala 3. You have to update to at least Scala 3.2 and Scoverage 2.0"
)
case (Array("2", "11", _*), true) => Result.Failure(
"Scoverage 2.x is not compatible with Scala 2.11. Consider using Scoverage 1.x or switch to a newer Scala version."
)
case _ =>
}
}

def scoverageToolsClasspath: T[Agg[PathRef]] = T {
checkVersions()

scoverageReportWorkerClasspath() ++
resolveDeps(T.task {
// we need to resolve with same Scala version used for Mill, not the project Scala version
val scalaBinVersion = ZincWorkerUtil.scalaBinaryVersion(BuildInfo.scalaVersion)
val sv = scoverageVersion()
if (isScoverage2()) {
Agg(
ivy"org.scoverage:scalac-scoverage-plugin_${mill.BuildInfo.scalaVersion}:${sv}",
ivy"org.scoverage:scalac-scoverage-domain_${scalaBinVersion}:${sv}",
ivy"org.scoverage:scalac-scoverage-serializer_${scalaBinVersion}:${sv}",
ivy"org.scoverage:scalac-scoverage-reporter_${scalaBinVersion}:${sv}"
)

val baseDeps = Agg(
ivy"org.scoverage:scalac-scoverage-domain_${scalaBinVersion}:${sv}",
ivy"org.scoverage:scalac-scoverage-serializer_${scalaBinVersion}:${sv}",
ivy"org.scoverage:scalac-scoverage-reporter_${scalaBinVersion}:${sv}"
)

val pluginDep =
Agg(ivy"org.scoverage:scalac-scoverage-plugin_${mill.BuildInfo.scalaVersion}:${sv}")

if (isScala3() && isScoverage2()) {
baseDeps
} else if (isScoverage2()) {
baseDeps ++ pluginDep
} else {
Agg(
ivy"org.scoverage:scalac-scoverage-plugin_${mill.BuildInfo.scalaVersion}:${sv}"
)
pluginDep
}
})()
}
Expand Down Expand Up @@ -141,6 +192,7 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>
}

val scoverage: ScoverageData = new ScoverageData(implicitly)

class ScoverageData(ctx0: mill.define.Ctx) extends Module()(ctx0) with ScalaModule {

def doReport(reportType: ReportType): Task[Unit] = T.task {
Expand Down Expand Up @@ -180,9 +232,16 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>
/** Add the scoverage specific plugin settings (`dataDir`). */
override def scalacOptions: Target[Seq[String]] =
T {
outer.scalacOptions() ++
Seq(s"-P:scoverage:dataDir:${data().path.toIO.getPath()}") ++
(if (isScoverage2()) Seq(s"-P:scoverage:sourceRoot:${T.workspace}") else Seq())
val extras =
if (isScala3()) {
Seq(s"-coverage-out:${data().path.toIO.getPath()}")
} else {
val base = s"-P:scoverage:dataDir:${data().path.toIO.getPath()}"
if (isScoverage2()) Seq(base, s"-P:scoverage:sourceRoot:${T.workspace}")
else Seq(base)
}

outer.scalacOptions() ++ extras
}

def htmlReport(): Command[Unit] = T.command { doReport(ReportType.Html) }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import org.scalatest._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class GreetSpec extends WordSpec with Matchers {
class GreetSpec extends AnyWordSpec with Matchers {
"Greet" should {
"work" in {
Greet.greet("Nik", None) shouldBe ("Hello, Nik!")
Expand Down
Loading