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

Initial work for scoverage 2.0 #1547

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ object Deps {
val scalafmtDynamic = ivy"org.scalameta::scalafmt-dynamic:3.0.6"
val scalametaTrees = ivy"org.scalameta::trees:4.4.29"
def scalaReflect(scalaVersion: String) = ivy"org.scala-lang:scala-reflect:${scalaVersion}"
def scalacScoveragePlugin = ivy"org.scoverage:::scalac-scoverage-plugin:1.4.9"
def scalacScoverageReporter = ivy"org.scoverage::scalac-scoverage-reporter:2.0.0-M2"
val sourcecode = ivy"com.lihaoyi::sourcecode:0.2.7"
val upickle = ivy"com.lihaoyi::upickle:1.4.2"
val utest = ivy"com.lihaoyi::utest:0.7.10"
Expand Down Expand Up @@ -573,7 +573,7 @@ object contrib extends MillModule {
override def compileIvyDeps = T{
Agg(
// compile-time only, need to provide the correct scoverage version runtime
Deps.scalacScoveragePlugin,
Deps.scalacScoverageReporter,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't fully understand this. Is this only being used to pull the version? I switched this to the reporter just to test it and it worked as well, but probably won't leave it as the reporter.

Copy link
Member

@lefou lefou Nov 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The contrib.scoverage.worker is loaded by the contrib.scoverage module in an isolated classloader. The contrib.scoverage.api module is shared between both. So we can load the scoverage jars only when needed and isolated from other mill plugins. Technically, this allows us to use different scoverage versions in the same build. As Scoverage 2.x has an incompatible API, we need to create a new worker module working with Scoverage 2.x. We also do this in other plugin, e.g. contrib.playlib.

// provided by mill runtime
Deps.osLib
)
Expand Down
7 changes: 6 additions & 1 deletion contrib/scoverage/api/src/ScoverageReportWorkerApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import mill.api.Ctx
trait ScoverageReportWorkerApi {
import ScoverageReportWorkerApi._

def report(reportType: ReportType, sources: Seq[os.Path], dataDirs: Seq[os.Path])(implicit
def report(
reportType: ReportType,
sources: Seq[os.Path],
dataDirs: Seq[os.Path],
sourceRoot: os.Path
)(implicit
Comment on lines +8 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the worker API is shared between all worker implementations, we need to keep/support the sourceRoot parameter, in case we decide to keep the Scoverage 1.x worker.

ctx: Ctx
): Unit
}
Expand Down
31 changes: 23 additions & 8 deletions contrib/scoverage/src/ScoverageModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>
def scoverageRuntimeDep: T[Dep] = T {
ivy"org.scoverage::scalac-scoverage-runtime:${outer.scoverageVersion()}"
}
def scoveragePluginDep: T[Dep] = T {
ivy"org.scoverage:::scalac-scoverage-plugin:${outer.scoverageVersion()}"
def scoveragePluginDep: T[Agg[Dep]] = T {
Agg(
ivy"org.scoverage:::scalac-scoverage-plugin:${outer.scoverageVersion()}",
ivy"org.scoverage::scalac-scoverage-domain:${outer.scoverageVersion()}",
ivy"org.scoverage::scalac-scoverage-serializer:${outer.scoverageVersion()}"
)
}

@deprecated("Use scoverageToolsClasspath instead.", "mill after 0.10.0-M1")
Expand All @@ -72,13 +76,15 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>
scoverageReportWorkerClasspath() ++
resolveDeps(T.task {
Agg(
ivy"org.scoverage:scalac-scoverage-plugin_${mill.BuildInfo.scalaVersion}:${outer.scoverageVersion()}"
ivy"org.scoverage::scalac-scoverage-domain:${outer.scoverageVersion()}",
ivy"org.scoverage::scalac-scoverage-serializer:${outer.scoverageVersion()}",
ivy"org.scoverage::scalac-scoverage-reporter:${outer.scoverageVersion()}"
)
})()
}

def scoverageClasspath: T[Agg[PathRef]] = T {
resolveDeps(T.task { Agg(scoveragePluginDep()) })()
resolveDeps(T.task { scoveragePluginDep() })()
}

def scoverageReportWorkerClasspath: T[Agg[PathRef]] = T {
Expand All @@ -98,7 +104,7 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>
ScoverageReportWorker
.scoverageReportWorker()
.bridge(scoverageToolsClasspath().map(_.path))
.report(reportType, allSources().map(_.path), Seq(data().path))
.report(reportType, allSources().map(_.path), Seq(data().path), T.workspace)
}

/**
Expand Down Expand Up @@ -126,11 +132,20 @@ trait ScoverageModule extends ScalaModule { outer: ScalaModule =>

/** Add the scoverage scalac plugin. */
override def scalacPluginIvyDeps: Target[Loose.Agg[Dep]] =
T { outer.scalacPluginIvyDeps() ++ Agg(outer.scoveragePluginDep()) }
T { outer.scalacPluginIvyDeps() ++ outer.scoveragePluginDep() }

/** Add the scoverage specific plugin settings (`dataDir`). */
/**
* Add the scoverage specific plugin settings
* - `dataDir` - where the coverage data files should go
* - `sourceRoot` - used for path relativization.
*/
override def scalacOptions: Target[Seq[String]] =
T { outer.scalacOptions() ++ Seq(s"-P:scoverage:dataDir:${data().path.toIO.getPath()}") }
T {
outer.scalacOptions() ++ Seq(
s"-P:scoverage:dataDir:${data().path.toIO.getPath()}",
s"-P:scoverage:sourceRoot:${T.workspace}"
)
}

def htmlReport(): Command[Unit] = T.command { doReport(ReportType.Html) }
def xmlReport(): Command[Unit] = T.command { doReport(ReportType.Xml) }
Expand Down
2 changes: 1 addition & 1 deletion contrib/scoverage/src/ScoverageReport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ trait ScoverageReport extends Module {
scoverageReportWorkerModule
.scoverageReportWorker()
.bridge(workerModule.scoverageToolsClasspath().map(_.path))
.report(reportType, sourcePaths, dataPaths)
.report(reportType, sourcePaths, dataPaths, T.workspace)
PathRef(T.dest)
}
}
Expand Down
11 changes: 6 additions & 5 deletions contrib/scoverage/worker/src/ScoverageReportWorkerImpl.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mill.contrib.scoverage.worker

import mill.contrib.scoverage.api.ScoverageReportWorkerApi
import _root_.scoverage.report.{CoverageAggregator, ScoverageHtmlWriter, ScoverageXmlWriter}
import _root_.scoverage.reporter.{CoverageAggregator, ScoverageHtmlWriter, ScoverageXmlWriter}
import mill.api.Ctx
import mill.contrib.scoverage.api.ScoverageReportWorkerApi.ReportType

Expand All @@ -10,11 +10,12 @@ class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi {
override def report(
reportType: ReportType,
sources: Seq[os.Path],
dataDirs: Seq[os.Path]
dataDirs: Seq[os.Path],
sourceRoot: os.Path
)(implicit ctx: Ctx): Unit =
try {
ctx.log.info(s"Processing coverage data for ${dataDirs.size} data locations")
CoverageAggregator.aggregate(dataDirs.map(_.toIO)) match {
CoverageAggregator.aggregate(dataDirs.map(_.toIO), sourceRoot.toIO) match {
case Some(coverage) =>
val sourceFolders = sources.map(_.toIO)
val folder = ctx.dest
Expand All @@ -24,7 +25,7 @@ class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi {
new ScoverageHtmlWriter(sourceFolders, folder.toIO, None)
.write(coverage)
case ReportType.Xml =>
new ScoverageXmlWriter(sourceFolders, folder.toIO, false)
new ScoverageXmlWriter(sourceFolders, folder.toIO, false, None)
.write(coverage)
case ReportType.Console =>
ctx.log.info(s"Statement coverage.: ${coverage.statementCoverageFormatted}%")
Expand All @@ -34,7 +35,7 @@ class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi {
ctx.log.error(s"No coverage data found in [${dataDirs.mkString(", ")}]")
}
} catch {
case e =>
case e: Throwable =>
ctx.log.error(s"Exception while building coverage report. ${e.getMessage()}")
e.printStackTrace()
throw e
Expand Down