From 917a024333de3e598c0722b910265f19541000dd Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 17 Sep 2024 10:58:48 +0200 Subject: [PATCH] WIP: rework scoverage worker --- contrib/package.mill | 22 ++--- .../contrib/scoverage/api/FileReportType.java | 27 ++++++ .../contrib/scoverage/api/ReportType.java | 18 ++++ .../api/ScoverageReportWorkerApi.scala | 82 +++++++++---------- .../api/ScoverageReportWorkerApi2.java | 32 ++++++++ .../worker/ScoverageReportWorkerImpl.scala | 32 ++++---- .../worker/ScoverageReportWorkerImpl.scala | 32 ++++---- 7 files changed, 165 insertions(+), 80 deletions(-) create mode 100644 contrib/scoverage/api/src/mill/contrib/scoverage/api/FileReportType.java create mode 100644 contrib/scoverage/api/src/mill/contrib/scoverage/api/ReportType.java create mode 100644 contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi2.java diff --git a/contrib/package.mill b/contrib/package.mill index 1eee3b7a636..541f1ef298e 100644 --- a/contrib/package.mill +++ b/contrib/package.mill @@ -130,17 +130,17 @@ object `package` extends RootModule { // TODO: (Scala 3) temporarily disable until decision on compatibility with Scala 3 // Worker for Scoverage 1.x - // object worker extends build.MillPublishScalaModule { - // // scoverage is on an old Scala version which doesnt support scalafix - // def fix(args: String*): Command[Unit] = T.command {} - // def compileModuleDeps = Seq(build.main.api) - // def moduleDeps = Seq(scoverage.api) - // def testDepPaths = T { Seq(compile().classes) } - - // // compile-time only, need to provide the correct scoverage version at runtime - // def compileIvyDeps = Agg(build.Deps.scalacScoveragePlugin) - // def scalaVersion = build.Deps.scalaVersionForScoverageWorker1 - // } + object worker extends build.MillPublishScalaModule { + // scoverage is on an old Scala version which doesnt support scalafix + def fix(args: String*): Command[Unit] = T.command {} + def compileModuleDeps = Seq(build.main.api) + def moduleDeps = Seq(scoverage.api) + def testDepPaths = T { Seq(compile().classes) } + + // compile-time only, need to provide the correct scoverage version at runtime + def compileIvyDeps = Agg(build.Deps.scalacScoveragePlugin) + def scalaVersion = build.Deps.scalaVersionForScoverageWorker1 + } // Worker for Scoverage 2.0 object worker2 extends build.MillPublishScalaModule { diff --git a/contrib/scoverage/api/src/mill/contrib/scoverage/api/FileReportType.java b/contrib/scoverage/api/src/mill/contrib/scoverage/api/FileReportType.java new file mode 100644 index 00000000000..be2a7644527 --- /dev/null +++ b/contrib/scoverage/api/src/mill/contrib/scoverage/api/FileReportType.java @@ -0,0 +1,27 @@ +package mill.contrib.scoverage.api; + +public abstract class FileReportType extends ReportType { + private final String folderName; + + /*private[api]*/ + FileReportType(String name, String folderName) { + super(name); + this.folderName = folderName; + } + + public String folderName() { + return folderName; + } + + /* private[api]*/ + static final FileReportType _Html = + new FileReportType("Html", "htmlReport") {}; + + /* private[api]*/ + static final FileReportType _Xml = + new FileReportType("Xml", "xmlReport") {}; + + /* private[api]*/ + static final FileReportType _XmlCobertura = + new FileReportType("XmlCobertura", "xmlCoberturaReport") {}; +} diff --git a/contrib/scoverage/api/src/mill/contrib/scoverage/api/ReportType.java b/contrib/scoverage/api/src/mill/contrib/scoverage/api/ReportType.java new file mode 100644 index 00000000000..523ddbe9513 --- /dev/null +++ b/contrib/scoverage/api/src/mill/contrib/scoverage/api/ReportType.java @@ -0,0 +1,18 @@ +package mill.contrib.scoverage.api; + +public abstract class ReportType { + private String name; + + /*private[api]*/ + ReportType(String name) {} + + public static final ReportType Console = new ReportType("Console") {}; + public static final FileReportType Html = FileReportType._Html; + public static final FileReportType Xml = FileReportType._Xml; + public static final FileReportType XmlCobertura = FileReportType._XmlCobertura; + + @Override + public String toString() { + return name; + } +} diff --git a/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi.scala b/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi.scala index 55fc01d3dc7..98169531452 100644 --- a/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi.scala +++ b/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi.scala @@ -1,46 +1,46 @@ -package mill.contrib.scoverage.api +// package mill.contrib.scoverage.api -import mill.api.Ctx +// import mill.api.Ctx -trait ScoverageReportWorkerApi { - import ScoverageReportWorkerApi._ +// trait ScoverageReportWorkerApi { +// import ScoverageReportWorkerApi._ - @deprecated("Use other overload instead.", "Mill after 0.10.7") - def report( - reportType: ReportType, - sources: Seq[os.Path], - dataDirs: Seq[os.Path] - )(implicit - ctx: Ctx - ): Unit = { - report(reportType, sources, dataDirs, ctx.workspace) - } +// @deprecated("Use other overload instead.", "Mill after 0.10.7") +// def report( +// reportType: ReportType, +// sources: Seq[os.Path], +// dataDirs: Seq[os.Path] +// )(implicit +// ctx: Ctx +// ): Unit = { +// report(reportType, sources, dataDirs, ctx.workspace) +// } - def report( - reportType: ReportType, - sources: Seq[os.Path], - dataDirs: Seq[os.Path], - sourceRoot: os.Path - )(implicit - ctx: Ctx - ): Unit = { - // FIXME: We only call the deprecated version here, to preserve binary compatibility. Remove when appropriate. - ctx.log.error( - "Binary compatibility stub may cause infinite loops with StackOverflowError. You need to implement: def report(ReportType, Seq[Path], Seq[Path], os.Path): Unit" - ) - report(reportType, sources, dataDirs) - } -} +// def report( +// reportType: ReportType, +// sources: Seq[os.Path], +// dataDirs: Seq[os.Path], +// sourceRoot: os.Path +// )(implicit +// ctx: Ctx +// ): Unit = { +// // FIXME: We only call the deprecated version here, to preserve binary compatibility. Remove when appropriate. +// ctx.log.error( +// "Binary compatibility stub may cause infinite loops with StackOverflowError. You need to implement: def report(ReportType, Seq[Path], Seq[Path], os.Path): Unit" +// ) +// report(reportType, sources, dataDirs) +// } +// } -object ScoverageReportWorkerApi { - sealed trait ReportType - sealed trait FileReportType extends ReportType { def folderName: String } - object ReportType { - final case object Html extends FileReportType { val folderName: String = "htmlReport" } - final case object Xml extends FileReportType { val folderName: String = "xmlReport" } - final case object XmlCobertura extends FileReportType { - val folderName: String = "xmlCoberturaReport" - } - final case object Console extends ReportType - } -} +// object ScoverageReportWorkerApi { +// sealed trait ReportType +// sealed trait FileReportType extends ReportType { def folderName: String } +// object ReportType { +// final case object Html extends FileReportType { val folderName: String = "htmlReport" } +// final case object Xml extends FileReportType { val folderName: String = "xmlReport" } +// final case object XmlCobertura extends FileReportType { +// val folderName: String = "xmlCoberturaReport" +// } +// final case object Console extends ReportType +// } +// } diff --git a/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi2.java b/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi2.java new file mode 100644 index 00000000000..4f17f09bc4d --- /dev/null +++ b/contrib/scoverage/api/src/mill/contrib/scoverage/api/ScoverageReportWorkerApi2.java @@ -0,0 +1,32 @@ +package mill.contrib.scoverage.api; + +import java.nio.file.Path; +import java.nio.file.Files; +import java.io.IOException; + +public interface ScoverageReportWorkerApi2 { + + interface Logger { + void info(String msg); + void error(String msg); + void debug(String msg); + void warn(String msg); + } + + interface Ctx { + Logger log(); + Path dest(); + } + + void report(ReportType reportType, Path[] sources, Path[] dataDirs, Path sourceRoot, Ctx ctx); + + static void makeAllDirs(Path path) throws IOException { + // Replicate behavior of `os.makeDir.all(path)` + if (Files.isDirectory(path) && Files.isSymbolicLink(path)) { + // do nothing + } else { + Files.createDirectories(path); + } + } + +} diff --git a/contrib/scoverage/worker/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala b/contrib/scoverage/worker/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala index 836c0387f17..847e23614b4 100644 --- a/contrib/scoverage/worker/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala +++ b/contrib/scoverage/worker/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala @@ -1,43 +1,47 @@ package mill.contrib.scoverage.worker -import mill.contrib.scoverage.api.ScoverageReportWorkerApi import _root_.scoverage.report.{ CoberturaXmlWriter, CoverageAggregator, ScoverageHtmlWriter, ScoverageXmlWriter } -import mill.api.Ctx -import mill.contrib.scoverage.api.ScoverageReportWorkerApi.ReportType + +import mill.contrib.scoverage.api.ScoverageReportWorkerApi2 +import mill.contrib.scoverage.api.ReportType +import ScoverageReportWorkerApi2.Ctx + +import java.nio.file.Path /** * Scoverage Worker for Scoverage 1.x */ -class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi { +class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi2 { override def report( reportType: ReportType, - sources: Seq[os.Path], - dataDirs: Seq[os.Path], + sources: Array[Path], + dataDirs: Array[Path], // ignored in Scoverage 1.x - sourceRoot: os.Path - )(implicit ctx: Ctx): Unit = + sourceRoot: Path, + 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(_.toFile).toIndexedSeq) match { case Some(coverage) => - val sourceFolders = sources.map(_.toIO) + val sourceFolders = sources.map(_.toFile).toIndexedSeq val folder = ctx.dest - os.makeDir.all(folder) + ScoverageReportWorkerApi2.makeAllDirs(folder) reportType match { case ReportType.Html => - new ScoverageHtmlWriter(sourceFolders, folder.toIO, None) + new ScoverageHtmlWriter(sourceFolders, folder.toFile, None) .write(coverage) case ReportType.Xml => - new ScoverageXmlWriter(sourceFolders, folder.toIO, false) + new ScoverageXmlWriter(sourceFolders, folder.toFile, false) .write(coverage) case ReportType.XmlCobertura => - new CoberturaXmlWriter(sourceFolders, folder.toIO) + new CoberturaXmlWriter(sourceFolders, folder.toFile) .write(coverage) case ReportType.Console => ctx.log.info(s"Statement coverage.: ${coverage.statementCoverageFormatted}%") diff --git a/contrib/scoverage/worker2/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala b/contrib/scoverage/worker2/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala index a478a91c533..64da275013c 100644 --- a/contrib/scoverage/worker2/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala +++ b/contrib/scoverage/worker2/src/mill/contrib/scoverage/worker/ScoverageReportWorkerImpl.scala @@ -1,42 +1,46 @@ package mill.contrib.scoverage.worker -import mill.contrib.scoverage.api.ScoverageReportWorkerApi import _root_.scoverage.reporter.{ CoberturaXmlWriter, CoverageAggregator, ScoverageHtmlWriter, ScoverageXmlWriter } -import mill.api.Ctx -import mill.contrib.scoverage.api.ScoverageReportWorkerApi.ReportType + +import mill.contrib.scoverage.api.ScoverageReportWorkerApi2 +import mill.contrib.scoverage.api.ReportType +import ScoverageReportWorkerApi2.Ctx + +import java.nio.file.Path /** * Scoverage Worker for Scoverage 2.x */ -class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi { +class ScoverageReportWorkerImpl extends ScoverageReportWorkerApi2 { override def report( reportType: ReportType, - sources: Seq[os.Path], - dataDirs: Seq[os.Path], - sourceRoot: os.Path - )(implicit ctx: Ctx): Unit = + sources: Array[Path], + dataDirs: Array[Path], + sourceRoot: Path, + ctx: Ctx + ): Unit = try { ctx.log.info(s"Processing coverage data for ${dataDirs.size} data locations") - CoverageAggregator.aggregate(dataDirs.map(_.toIO), sourceRoot.toIO) match { + CoverageAggregator.aggregate(dataDirs.map(_.toFile).toIndexedSeq, sourceRoot.toFile) match { case Some(coverage) => - val sourceFolders = sources.map(_.toIO) + val sourceFolders = sources.map(_.toFile).toIndexedSeq val folder = ctx.dest - os.makeDir.all(folder) + ScoverageReportWorkerApi2.makeAllDirs(folder) reportType match { case ReportType.Html => - new ScoverageHtmlWriter(sourceFolders, folder.toIO, None) + new ScoverageHtmlWriter(sourceFolders, folder.toFile, None) .write(coverage) case ReportType.Xml => - new ScoverageXmlWriter(sourceFolders, folder.toIO, false, None) + new ScoverageXmlWriter(sourceFolders, folder.toFile, false, None) .write(coverage) case ReportType.XmlCobertura => - new CoberturaXmlWriter(sourceFolders, folder.toIO, None) + new CoberturaXmlWriter(sourceFolders, folder.toFile, None) .write(coverage) case ReportType.Console => ctx.log.info(s"Statement coverage.: ${coverage.statementCoverageFormatted}%")